propertylist/Propertylist: added loadProperties_top() and marked loadHashtable_top...
[metux-java.git] / propertylist / Propertylist.java
blob2decc2e5cbef6898272b6a4a878202b96d1d07df
2 //
3 // FIXME: replace Hashtable by Properties
4 //
6 package org.de.metux.propertylist;
8 import java.io.*;
9 import java.util.Enumeration;
10 import java.util.Hashtable;
11 import java.util.Properties;
13 import java.lang.NumberFormatException;
15 import org.de.metux.util.StrSplit;
16 import org.de.metux.util.TextDB;
17 import org.de.metux.util.UniqueNameList;
18 import org.de.metux.util.LoadFile;
19 import org.de.metux.util.StrUtil;
20 import org.de.metux.util.CachedDatasource;
22 import java.net.URLEncoder;
24 import java.net.URL;
26 public class Propertylist implements IPropertylist
28 Properties db = new Properties();
29 Properties cache = new Properties();
30 IPostprocessor postprocessor;
32 public boolean enable_datasource_cache = false;
33 public static Hashtable db_recycling = null;
34 public static CachedDatasource datasource_cache = new CachedDatasource();
36 private class dbcache_ent
38 public Properties proplist;
39 public String text;
42 /* this method loads data from a hashtable into the propertysheet
43 with low priority, means that existing fields are not touched.
45 the opposite would be high priority meaning existing fields
46 will be overwritten.
49 public void setPostprocessor(IPostprocessor p)
51 postprocessor = p;
54 public void runPostprocessor()
55 throws EIllegalValue
57 if (postprocessor==null)
58 return;
60 /* run as long as it returns true */
61 while(postprocessor.propertylist_postprocess((IPropertylist)this));
64 /* get a really raw string, directly from database */
65 public String db_get(String field)
67 return (String)db.get(field);
70 @Deprecated
71 public void loadHash_sub(Hashtable h)
73 for (Enumeration e = h.keys(); e.hasMoreElements(); )
75 String key = (String) e.nextElement();
77 /* fields with !! always have precedence */
78 if (key.startsWith("!!"))
79 db.put(key.substring(2),(String)h.get(key));
81 /* fields with ++ are always added, not just overwritten */
82 else if (key.startsWith("++"))
83 add(key.substring(2),(String)h.get(key));
85 /* in this loading mode we do not overwrite existing fields */
86 else if (!db.containsKey(key))
87 set(key,(String)h.get(key));
89 cache.clear();
92 public void loadProperties_sub(Properties pr)
94 for (Enumeration e = pr.keys(); e.hasMoreElements(); )
96 String key = (String) e.nextElement();
98 /* fields with !! always have precedence */
99 if (key.startsWith("!!"))
100 db.put(key.substring(2),(String)pr.get(key));
102 /* fields with ++ are always added, not just overwritten */
103 else if (key.startsWith("++"))
104 add(key.substring(2),(String)pr.get(key));
106 /* in this loading mode we do not overwrite existing fields */
107 else if (!db.containsKey(key))
108 set(key,(String)pr.get(key));
110 cache.clear();
113 public void loadHash_low(Hashtable h)
114 throws EIllegalValue
116 loadHash_sub(h);
117 runPostprocessor();
120 @Deprecated
121 public void loadHash_top(Hashtable h)
123 for (Enumeration e = h.keys(); e.hasMoreElements(); )
125 String key = (String) e.nextElement();
126 if (key.startsWith("!!"))
127 set(key.substring(2),(String)h.get(key));
128 else if (key.startsWith("++"))
129 add(key.substring(2),(String)h.get(key));
130 else
131 set(key,(String)h.get(key));
135 public void loadProperties_top(Properties pr)
137 for (Enumeration e = pr.keys(); e.hasMoreElements(); )
139 String key = (String) e.nextElement();
140 if (key.startsWith("!!"))
141 set(key.substring(2),(String)pr.get(key));
142 else if (key.startsWith("++"))
143 add(key.substring(2),(String)pr.get(key));
144 else
145 set(key,(String)pr.get(key));
149 private Properties _load_properties(String filename)
151 if (enable_datasource_cache)
153 if (db_recycling==null)
154 db_recycling = new Hashtable();
156 dbcache_ent ent = (dbcache_ent)db_recycling.get(filename);
157 if (ent!=null)
159 // System.err.println("Found in cache: "+filename);
160 return ent.proplist;
163 ent = new dbcache_ent();
164 ent.proplist = new Properties();
165 if (!TextDB.LoadIntoHashtable(filename,ent.proplist))
167 // System.err.println("Could not load: "+filename);
168 ent.proplist = null;
170 // else
171 // System.err.println("Loaded: "+filename);
173 db_recycling.put(filename,ent);
174 return ent.proplist;
176 else
178 Properties pr = new Properties();
179 if (!TextDB.LoadIntoHashtable(filename,pr))
180 return null;
181 else
182 return pr;
186 public boolean loadTextDB_low(String filename)
187 throws EIllegalValue
189 Properties pr = _load_properties(filename);
190 if (pr == null)
191 return false;
192 loadHash_low(pr);
193 return true;
196 public boolean loadTextDB_sub(String filename)
198 Properties pr = _load_properties(filename);
199 if (pr==null)
201 // System.err.println("Couldnt load properties from: "+filename);
202 return false;
204 loadHash_sub(pr);
205 return true;
208 public boolean loadTextDB_top(File filename)
210 return loadTextDB_top(filename.toString());
213 public boolean loadTextDB_top(String filename)
215 Properties pr = _load_properties(filename);
217 if (pr==null)
218 return false;
220 loadHash_top(pr);
221 return true;
224 public void remove ( String key )
226 db.remove(key);
227 cache.clear();
230 public void set ( String key, String value )
232 db.put(key,value);
233 cache.clear();
236 public void add ( String key, String value )
238 String got;
239 if ((key==null)||(value==null)) return;
241 if ((got=db_get(key))!=null)
242 db.put(key,got+"\n"+value);
243 else
244 db.put(key,value);
247 // can be overwritten, ie for namespace handling, hierachies, etc
248 public String get_raw(String name)
249 throws EIllegalValue
251 if (name.startsWith(":URLENCODE:"))
253 name = name.substring(11);
254 return URLEncoder.encode(get_str(name));
257 return db_get(name);
260 public String get_str(String name)
261 throws EIllegalValue
263 return get_str_rec(name,100);
266 public String[] get_list(String name)
267 throws EIllegalValue
269 return StrSplit.split(get_str(name));
272 /* can be overwritten in order to handle special things like exec()
273 returns null if nothing happened */
274 public String handle_special_str(String key)
276 return null;
279 public boolean get_bool(String name, boolean def)
283 return get_bool(name);
285 catch (EIllegalValue e)
287 return def;
291 public boolean get_bool(String name) throws EIllegalValue
293 String val=get_str(name);
296 return StrUtil.toBool(val);
298 catch (NumberFormatException e)
300 throw new EIllegalValue(name,val);
304 private final String get_str_rec(String key, int depth)
305 throws EIllegalValue
307 if (depth<1)
308 throw new EInfiniteRecursion(key,get_raw(key));
310 /* if we someday want to add special vars/commands, this
311 would probably be the right point */
313 String value;
314 boolean notnull = false;
315 boolean notempty = false;
317 /* handle subclass-defined specials */
318 if ((value=handle_special_str(key))!=null)
319 return value;
321 /* -- parse special modifiers -- */
322 for (boolean parsing=true; parsing;)
324 if (key.startsWith("!notnull!"))
326 notnull = true;
327 key = key.substring(9);
329 else if (key.startsWith("!notempty!"))
331 notempty = true;
332 key = key.substring(10);
334 else
335 parsing = false;
338 if ((value=get_raw(key))==null)
340 if (notnull)
341 throw new EVariableNull(key,value);
342 else
343 return "";
346 /* --- now replace variables --- */
347 int start, end;
349 while ((start=value.indexOf("$("))!=-1) /* scan for $( */
351 if ((end=value.indexOf(')', start+2))!=-1)
353 String name = value.substring(start+2,end);
354 String newval =
355 value.substring(0,start)+
356 get_str_rec(name,depth-1)+
357 value.substring(end+1);
359 value = newval;
361 else
362 throw new EVariableParseError(key,value);
365 if (value.equals("") && notempty)
366 throw new EVariableEmpty(key,value);
368 return value;
371 public String dump()
373 String res = "";
374 for (Enumeration e = db.keys(); e.hasMoreElements(); )
376 String key = (String) e.nextElement();
377 res += key+"=\""+db_get(key)+"\"\n";
379 return res;
382 public boolean load_content(String field, File filename, boolean strip_comments)
384 String text = datasource_cache.loadContent(filename,strip_comments);
386 if (text==null)
387 return false;
388 set(field,text);
389 return true;
392 public boolean load_content(String field, URL url, boolean strip_comments)
394 String text = datasource_cache.loadContent(url,strip_comments);
395 if (text==null)
396 return false;
398 set(field,text);
399 return true;
402 public Enumeration propertyNames()
404 return db.keys();
407 public IPropertylist clone()
409 Propertylist pr = new Propertylist();
410 pr.db = (Properties)db.clone();
412 // copy the database
413 for (Enumeration keys = db.keys(); keys.hasMoreElements(); )
415 String k = (String)keys.nextElement();
416 pr.set(k,db_get(k));
418 return pr;
421 public String toString()
423 String str = "[PROPERTYLIST]\n";
424 for (Enumeration keys = db.keys(); keys.hasMoreElements(); )
426 String k = (String)keys.nextElement();
427 str += k+"=\""+db_get(k)+"\"\n";
429 return str;