PageRenderTime 53ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/external/emma/core/java12/com/vladium/util/IProperties.java

https://bitbucket.org/rlyspn/androidrr
Java | 370 lines | 224 code | 78 blank | 68 comment | 42 complexity | 746f1bd783a2cb81ca3c9409a8789051 MD5 | raw file
  1. /* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
  2. *
  3. * This program and the accompanying materials are made available under
  4. * the terms of the Common Public License v1.0 which accompanies this distribution,
  5. * and is available at http://www.eclipse.org/legal/cpl-v10.html
  6. *
  7. * $Id: IProperties.java,v 1.1.1.1.2.1 2004/07/08 10:52:10 vlad_r Exp $
  8. */
  9. package com.vladium.util;
  10. import java.io.PrintStream;
  11. import java.io.PrintWriter;
  12. import java.util.ArrayList;
  13. import java.util.Enumeration;
  14. import java.util.HashMap;
  15. import java.util.Iterator;
  16. import java.util.List;
  17. import java.util.Properties;
  18. import java.util.Set;
  19. import java.util.TreeSet;
  20. // ----------------------------------------------------------------------------
  21. /**
  22. * @author Vlad Roubtsov, (C) 2003
  23. */
  24. public
  25. interface IProperties
  26. {
  27. // public: ................................................................
  28. /**
  29. * An IMapper is a stateless hook for mapping a arbitrary property key
  30. * to another (useful, for example, for property aliasing and defaulting).
  31. * Each IMapper must be completely stateless and could be shared between
  32. * multiple IProperties instances (and invoked from multiple concurrent threads).
  33. */
  34. interface IMapper
  35. {
  36. String getMappedKey (final String key);
  37. } // end of nested interface
  38. String getProperty (String key);
  39. String getProperty (String key, String dflt);
  40. boolean isOverridden (String key);
  41. IProperties copy ();
  42. Iterator /* String */ properties ();
  43. Properties toProperties ();
  44. /**
  45. * @param prefix [may not be null]
  46. */
  47. String [] toAppArgsForm (final String prefix);
  48. boolean isEmpty ();
  49. void list (PrintStream out);
  50. void list (PrintWriter out);
  51. String setProperty (String key, String value);
  52. abstract class Factory
  53. {
  54. /**
  55. * Creates an empty IProperties set with an optional property mapper.
  56. *
  57. * @param mapper [may be null]
  58. * @return an empty property set [never null]
  59. */
  60. public static IProperties create (final IMapper mapper)
  61. {
  62. return new PropertiesImpl (null, mapper);
  63. }
  64. /**
  65. * Converts a java.util.Properties instance to an IProperties instance,
  66. * with an optional property mapper. Note that 'properties' content is
  67. * shallowly cloned, so the result can be mutated independently from
  68. * the input.
  69. *
  70. * @param properties [may not be null]
  71. * @param mapper [may be null]
  72. * @return a property set based on 'properties' [never null]
  73. */
  74. public static IProperties wrap (final Properties properties, final IMapper mapper)
  75. {
  76. final HashMap map = new HashMap ();
  77. // always use propertyNames() for traversing java.util.Properties:
  78. for (Enumeration names = properties.propertyNames (); names.hasMoreElements (); )
  79. {
  80. final String n = (String) names.nextElement ();
  81. final String v = properties.getProperty (n);
  82. map.put (n, v);
  83. }
  84. return new PropertiesImpl (map, mapper); // note: map is a defensive clone
  85. }
  86. /**
  87. * Combines two property sets by creating a property set that chains 'overrides'
  88. * to 'base' for property delegation. Note that 'overrides' are cloned
  89. * defensively and so the result can be mutated independently of both inputs.
  90. *
  91. * @param overrides [may be null]
  92. * @param base [may be null]
  93. * @return [never null; an empty property set with a null mapper is created
  94. * if both inputs are null]
  95. */
  96. public static IProperties combine (final IProperties overrides, final IProperties base)
  97. {
  98. final IProperties result = overrides != null
  99. ? overrides.copy ()
  100. : create (null);
  101. // [assertion: result != null]
  102. ((PropertiesImpl) result).getLastProperties ().setDelegate ((PropertiesImpl) base);
  103. return result;
  104. }
  105. /*
  106. * Not MT-safe
  107. */
  108. private static final class PropertiesImpl implements IProperties, Cloneable
  109. {
  110. // ACCESSORS (IProperties):
  111. public String getProperty (final String key)
  112. {
  113. return getProperty (key, null);
  114. }
  115. public String getProperty (final String key, final String dflt)
  116. {
  117. String value = (String) m_valueMap.get (key);
  118. // first, try to delegate horizontally:
  119. if ((value == null) && (m_mapper != null))
  120. {
  121. final String mappedKey = m_mapper.getMappedKey (key);
  122. if (mappedKey != null)
  123. value = (String) m_valueMap.get (mappedKey);
  124. }
  125. // next, try to delegate vertically:
  126. if ((value == null) && (m_delegate != null))
  127. {
  128. value = m_delegate.getProperty (key, null);
  129. }
  130. return value != null ? value : dflt;
  131. }
  132. public boolean isOverridden (final String key)
  133. {
  134. return m_valueMap.containsKey (key);
  135. }
  136. public IProperties copy ()
  137. {
  138. final PropertiesImpl _clone;
  139. try
  140. {
  141. _clone = (PropertiesImpl) super.clone ();
  142. }
  143. catch (CloneNotSupportedException cnse)
  144. {
  145. throw new Error (cnse.toString ()); // never happens
  146. }
  147. _clone.m_valueMap = (HashMap) m_valueMap.clone ();
  148. _clone.m_unmappedKeySet = null;
  149. // note: m_mapper field is not cloned by design (mappers are stateless/shareable)
  150. PropertiesImpl scan = _clone;
  151. for (PropertiesImpl delegate = m_delegate; delegate != null; delegate = delegate.m_delegate)
  152. {
  153. final PropertiesImpl _delegateClone;
  154. try
  155. {
  156. _delegateClone = (PropertiesImpl) delegate.clone ();
  157. }
  158. catch (CloneNotSupportedException cnse)
  159. {
  160. throw new Error (cnse.toString ()); // never happens
  161. }
  162. // note that the value map needs to be cloned not only for the
  163. // outermost IProperties set but for the inner ones as well
  164. // (to prevent independent mutation in them from showing through)
  165. _delegateClone.m_valueMap = (HashMap) delegate.m_valueMap.clone ();
  166. _delegateClone.m_unmappedKeySet = null; // ensure that the last delegate will have this field reset
  167. scan.setDelegate (_delegateClone);
  168. scan = _delegateClone;
  169. }
  170. return _clone;
  171. }
  172. public Iterator /* String */ properties ()
  173. {
  174. return unmappedKeySet ().iterator ();
  175. }
  176. public Properties toProperties ()
  177. {
  178. final Properties result = new Properties ();
  179. for (Iterator i = properties (); i.hasNext (); )
  180. {
  181. final String n = (String) i.next ();
  182. final String v = getProperty (n);
  183. result.setProperty (n, v);
  184. }
  185. return result;
  186. }
  187. public boolean isEmpty ()
  188. {
  189. return m_valueMap.isEmpty () && ((m_delegate == null) || ((m_delegate != null) && m_delegate.isEmpty ()));
  190. }
  191. public String [] toAppArgsForm (final String prefix)
  192. {
  193. if (isEmpty ())
  194. return IConstants.EMPTY_STRING_ARRAY;
  195. else
  196. {
  197. if (prefix == null)
  198. throw new IllegalArgumentException ("null input: prefix");
  199. final List _result = new ArrayList ();
  200. for (Iterator names = properties (); names.hasNext (); )
  201. {
  202. final String name = (String) names.next ();
  203. final String value = getProperty (name, "");
  204. _result.add (prefix.concat (name).concat ("=").concat (value));
  205. }
  206. final String [] result = new String [_result.size ()];
  207. _result.toArray (result);
  208. return result;
  209. }
  210. }
  211. public void list (final PrintStream out)
  212. {
  213. if (out != null)
  214. {
  215. for (Iterator i = properties (); i.hasNext (); )
  216. {
  217. final String n = (String) i.next ();
  218. final String v = getProperty (n);
  219. out.println (n + ":\t[" + v + "]");
  220. }
  221. }
  222. }
  223. public void list (final PrintWriter out)
  224. {
  225. if (out != null)
  226. {
  227. for (Iterator i = properties (); i.hasNext (); )
  228. {
  229. final String n = (String) i.next ();
  230. final String v = getProperty (n);
  231. out.println (n + ":\t[" + v + "]");
  232. }
  233. }
  234. }
  235. // MUTATORS:
  236. public String setProperty (final String key, final String value)
  237. {
  238. if (value == null)
  239. throw new IllegalArgumentException ("null input: value");
  240. m_unmappedKeySet = null;
  241. return (String) m_valueMap.put (key, value);
  242. }
  243. PropertiesImpl (final HashMap values, final IMapper mapper)
  244. {
  245. m_mapper = mapper;
  246. m_valueMap = values != null ? values : new HashMap ();
  247. m_delegate = null;
  248. }
  249. Set unmappedKeySet ()
  250. {
  251. Set result = m_unmappedKeySet;
  252. if (result == null)
  253. {
  254. result = new TreeSet ();
  255. result.addAll (m_valueMap.keySet ());
  256. if (m_delegate != null)
  257. result.addAll (m_delegate.unmappedKeySet ());
  258. m_unmappedKeySet = result;
  259. return result;
  260. }
  261. return result;
  262. }
  263. // ACCESSORS:
  264. PropertiesImpl getLastProperties ()
  265. {
  266. PropertiesImpl result = this;
  267. for (PropertiesImpl delegate = m_delegate; delegate != null; delegate = delegate.m_delegate)
  268. {
  269. // this does not detect all possible cycles:
  270. if (delegate == this)
  271. throw new IllegalStateException ("cyclic delegation detected");
  272. result = delegate;
  273. }
  274. return result;
  275. }
  276. // MUTATORS:
  277. void setDelegate (final PropertiesImpl delegate)
  278. {
  279. m_delegate = delegate;
  280. m_unmappedKeySet = null;
  281. }
  282. private final IMapper m_mapper;
  283. private /*final*/ HashMap m_valueMap; // never null
  284. private PropertiesImpl m_delegate;
  285. private transient Set m_unmappedKeySet;
  286. } // end of nested class
  287. } // end of nested class
  288. // protected: .............................................................
  289. // package: ...............................................................
  290. // private: ...............................................................
  291. } // end of class
  292. // ----------------------------------------------------------------------------