3 // FIXME: replace Hashtable by Properties
6 package org
.de
.metux
.propertylist
;
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
;
26 public class Propertylist
implements IPropertylist
28 Properties db
= new Properties();
29 Properties cache
= new Properties();
30 IPostprocessor postprocessor
;
32 public static Hashtable db_recycling
= null;
33 public static CachedDatasource datasource_cache
= new CachedDatasource();
35 private class dbcache_ent
37 public Properties proplist
;
41 /* this method loads data from a hashtable into the propertysheet
42 with low priority, means that existing fields are not touched.
44 the opposite would be high priority meaning existing fields
48 public void setPostprocessor(IPostprocessor p
)
53 public void runPostprocessor()
56 if (postprocessor
==null)
59 /* run as long as it returns true */
60 while(postprocessor
.propertylist_postprocess((IPropertylist
)this));
63 /* get a really raw string, directly from database */
64 public String
db_get(String field
)
66 return (String
)db
.get(field
);
69 public void loadProperties_sub(Properties pr
)
71 for (Enumeration e
= pr
.keys(); e
.hasMoreElements(); )
73 String key
= (String
) e
.nextElement();
75 /* fields with !! always have precedence */
76 if (key
.startsWith("!!"))
77 db
.put(key
.substring(2),(String
)pr
.get(key
));
79 /* fields with ++ are always added, not just overwritten */
80 else if (key
.startsWith("++"))
81 add(key
.substring(2),(String
)pr
.get(key
));
83 /* in this loading mode we do not overwrite existing fields */
84 else if (!db
.containsKey(key
))
85 set(key
,(String
)pr
.get(key
));
90 public void loadProperties_top(Properties pr
)
92 for (Enumeration e
= pr
.keys(); e
.hasMoreElements(); )
94 String key
= (String
) e
.nextElement();
95 if (key
.startsWith("!!"))
96 set(key
.substring(2),(String
)pr
.get(key
));
97 else if (key
.startsWith("++"))
98 add(key
.substring(2),(String
)pr
.get(key
));
100 set(key
,(String
)pr
.get(key
));
104 public void remove ( String key
)
110 public void set ( String key
, String value
)
116 public void add ( String key
, String value
)
119 if ((key
==null)||(value
==null)) return;
121 if ((got
=db_get(key
))!=null)
122 db
.put(key
,got
+"\n"+value
);
127 // can be overwritten, ie for namespace handling, hierachies, etc
128 public String
get_raw(String name
)
131 if (name
.startsWith(":URLENCODE:"))
133 name
= name
.substring(11);
134 return URLEncoder
.encode(get_str(name
));
140 public String
get_str(String name
)
143 return get_str_rec(name
,100);
146 public String
[] get_list(String name
)
149 return StrSplit
.split(get_str(name
));
152 /* can be overwritten in order to handle special things like exec()
153 returns null if nothing happened */
154 public String
handle_special_str(String key
)
159 public boolean get_bool(String name
, boolean def
)
163 return get_bool(name
);
165 catch (EIllegalValue e
)
171 public boolean get_bool(String name
) throws EIllegalValue
173 String val
=get_str(name
);
176 return StrUtil
.toBool(val
);
178 catch (NumberFormatException e
)
180 throw new EIllegalValue(name
,val
);
184 private final String
get_str_rec(String key
, int depth
)
188 throw new EInfiniteRecursion(key
,get_raw(key
));
190 /* if we someday want to add special vars/commands, this
191 would probably be the right point */
194 boolean notnull
= false;
195 boolean notempty
= false;
197 /* handle subclass-defined specials */
198 if ((value
=handle_special_str(key
))!=null)
201 /* -- parse special modifiers -- */
202 for (boolean parsing
=true; parsing
;)
204 if (key
.startsWith("!notnull!"))
207 key
= key
.substring(9);
209 else if (key
.startsWith("!notempty!"))
212 key
= key
.substring(10);
218 if ((value
=get_raw(key
))==null)
221 throw new EVariableNull(key
,value
);
226 /* --- now replace variables --- */
229 while ((start
=value
.indexOf("$("))!=-1) /* scan for $( */
231 if ((end
=value
.indexOf(')', start
+2))!=-1)
233 String name
= value
.substring(start
+2,end
);
235 value
.substring(0,start
)+
236 get_str_rec(name
,depth
-1)+
237 value
.substring(end
+1);
242 throw new EVariableParseError(key
,value
);
245 if (value
.equals("") && notempty
)
246 throw new EVariableEmpty(key
,value
);
254 for (Enumeration e
= db
.keys(); e
.hasMoreElements(); )
256 String key
= (String
) e
.nextElement();
257 res
+= key
+"=\""+db_get(key
)+"\"\n";
262 public boolean load_content(String field
, File filename
, boolean strip_comments
)
264 String text
= datasource_cache
.loadContent(filename
,strip_comments
);
272 public boolean load_content(String field
, URL url
, boolean strip_comments
)
274 String text
= datasource_cache
.loadContent(url
,strip_comments
);
282 public Enumeration
propertyNames()
287 public IPropertylist
clone()
289 Propertylist pr
= new Propertylist();
290 pr
.db
= (Properties
)db
.clone();
293 for (Enumeration keys
= db
.keys(); keys
.hasMoreElements(); )
295 String k
= (String
)keys
.nextElement();
301 public String
toString()
303 String str
= "[PROPERTYLIST]\n";
304 for (Enumeration keys
= db
.keys(); keys
.hasMoreElements(); )
306 String k
= (String
)keys
.nextElement();
307 str
+= k
+"=\""+db_get(k
)+"\"\n";