View Javadoc

1   /*
2    * Copyright 2012-2013 smartics, Kronseder & Reiner GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package de.smartics.properties.spi.config.definition;
17  
18  import java.io.Serializable;
19  import java.util.Collections;
20  import java.util.HashMap;
21  import java.util.HashSet;
22  import java.util.Map;
23  import java.util.Map.Entry;
24  import java.util.Set;
25  
26  import javax.annotation.CheckForNull;
27  import javax.annotation.concurrent.ThreadSafe;
28  
29  import de.smartics.properties.api.config.domain.key.ConfigurationKey;
30  
31  /**
32   * Contains information from the <code>definition.xml</code> that is contained
33   * in archives providing property information.
34   */
35  @ThreadSafe
36  public final class PropertiesDefinitionContext implements Serializable
37  {
38    // ********************************* Fields *********************************
39  
40    // --- constants ------------------------------------------------------------
41  
42    /**
43     * The class version identifier.
44     */
45    private static final long serialVersionUID = 1L;
46  
47    /**
48     * The default top level domains to identify groups.
49     * <ol>
50     * <li><code>biz</code></li>
51     * <li><code>com</code></li>
52     * <li><code>edu</code></li>
53     * <li><code>gov</code></li>
54     * <li><code>info</code></li>
55     * <li><code>net</code></li>
56     * <li><code>org</code></li>
57     * </ol>
58     */
59    public static final Set<String> DEFAULT_TLDS;
60  
61    // --- members --------------------------------------------------------------
62  
63    /**
64     * The collection of top-level-domains (tlds). Country codes (two letters) are
65     * not necessarily mentioned here since they are dealt with generically.
66     *
67     * @serial
68     */
69    private final Set<String> tlds;
70  
71    /**
72     * The collection of registered environment names.
73     *
74     * @serial
75     */
76    private final Set<String> environments;
77  
78    /**
79     * The collection of registered node names.
80     *
81     * @serial
82     */
83    private final Set<String> nodes;
84  
85    /**
86     * The collection of registered group names.
87     *
88     * @serial
89     */
90    private final Set<String> groups;
91  
92    /**
93     * The mapping of properties file path names to a associated configuration
94     * key.
95     *
96     * @serial
97     */
98    private final Map<String, ConfigurationKey> files;
99  
100   // ****************************** Initializer *******************************
101 
102   static
103   {
104     final Set<String> defaults = new HashSet<String>();
105     defaults.add("biz");
106     defaults.add("com");
107     defaults.add("edu");
108     defaults.add("gov");
109     defaults.add("info");
110     defaults.add("net");
111     defaults.add("org");
112     DEFAULT_TLDS = Collections.unmodifiableSet(defaults);
113   }
114 
115   // ****************************** Constructors ******************************
116 
117   /**
118    * Convenience constructor using the default TLDs and not registering any
119    * environments, nodes or groups.
120    */
121   public PropertiesDefinitionContext()
122   {
123     this(DEFAULT_TLDS, null, null, null, null);
124   }
125 
126   /**
127    * Convenience constructor using the default TLDs and no explicit files.
128    *
129    * @param environments the collection of registered environment names.
130    * @param nodes the collection of registered node names.
131    * @param groups the collection of registered group names.
132    */
133   public PropertiesDefinitionContext(final Set<String> environments,
134       final Set<String> nodes, final Set<String> groups)
135   {
136     this(DEFAULT_TLDS, environments, nodes, groups);
137   }
138 
139   /**
140    * Convenience constructor without an explicit path to configuration key
141    * mapping.
142    *
143    * @param tlds the collection of top-level-domains (tlds).
144    * @param environments the collection of registered environment names.
145    * @param nodes the collection of registered node names.
146    * @param groups the collection of registered group names.
147    */
148   public PropertiesDefinitionContext(final Set<String> tlds,
149       final Set<String> environments, final Set<String> nodes,
150       final Set<String> groups)
151   {
152     this(tlds, environments, nodes, groups, null);
153   }
154 
155   /**
156    * Convenience constructor using the default TLDs.
157    *
158    * @param environments the collection of registered environment names.
159    * @param nodes the collection of registered node names.
160    * @param groups the collection of registered group names.
161    * @param files the mapping of properties file path names to a associated
162    *          configuration key.
163    */
164   public PropertiesDefinitionContext(final Set<String> environments,
165       final Set<String> nodes, final Set<String> groups,
166       final Map<String, ConfigurationKey> files)
167   {
168     this(DEFAULT_TLDS, environments, nodes, groups, files);
169   }
170 
171   /**
172    * Default constructor.
173    *
174    * @param tlds the collection of top-level-domains (tlds).
175    * @param environments the collection of registered environment names.
176    * @param nodes the collection of registered node names.
177    * @param groups the collection of registered group names.
178    * @param files the mapping of properties file path names to a associated
179    *          configuration key.
180    */
181   public PropertiesDefinitionContext(final Set<String> tlds,
182       final Set<String> environments, final Set<String> nodes,
183       final Set<String> groups, final Map<String, ConfigurationKey> files)
184   {
185     this.tlds = create(tlds);
186     this.environments = create(environments);
187     this.nodes = create(nodes);
188     this.groups = create(groups);
189     this.files = create(files);
190   }
191 
192   // ****************************** Inner Classes *****************************
193 
194   // ********************************* Methods ********************************
195 
196   // --- init -----------------------------------------------------------------
197 
198   private static Set<String> create(final Set<String> set)
199   {
200     return set != null ? new HashSet<String>(set) : new HashSet<String>();
201   }
202 
203   private static Map<String, ConfigurationKey> create(
204       final Map<String, ConfigurationKey> map)
205   {
206     return map != null ? new HashMap<String, ConfigurationKey>(map)
207         : new HashMap<String, ConfigurationKey>();
208   }
209 
210   // --- get&set --------------------------------------------------------------
211 
212   // --- business -------------------------------------------------------------
213 
214   /**
215    * Checks if the given string is a registered top level domain (tld) or
216    * contains only two letters.
217    *
218    * @param token the token to check.
219    * @return <code>true</code> if the {@code token} is not <code>null</code>, is
220    *         registered or contains exactly two letters, <code>false</code>
221    *         otherwise.
222    */
223   public boolean isRegisteredGroupTld(final String token)
224   {
225     return token != null && (tlds.contains(token) || isCountryTld(token));
226   }
227 
228   private static boolean isCountryTld(final String tld)
229   {
230     return tld.length() == 2 && Character.isLetter(tld.charAt(0))
231            && Character.isLetter(tld.charAt(1));
232   }
233 
234   /**
235    * Checks if the given token is a registered environment.
236    *
237    * @param token the token to check.
238    * @return <code>true</code> if the token is a registered environment,
239    *         <code>false</code> otherwise.
240    */
241   public boolean isRegisteredEnvironment(final String token)
242   {
243     return environments.contains(token);
244   }
245 
246   /**
247    * Checks if the given token is a registered node.
248    *
249    * @param token the token to check.
250    * @return <code>true</code> if the token is a registered node,
251    *         <code>false</code> otherwise.
252    */
253   public boolean isRegisteredNode(final String token)
254   {
255     return nodes.contains(token);
256   }
257 
258   /**
259    * Checks if the given token is a registered group.
260    *
261    * @param token the token to check.
262    * @return <code>true</code> if the token is a registered group,
263    *         <code>false</code> otherwise.
264    */
265   public boolean isRegisteredGroup(final String token)
266   {
267     return groups.contains(token);
268   }
269 
270   /**
271    * Returns the configuration key associated with the given {@code path}.
272    *
273    * @param path the path to fetch its configuration key. Note that a
274    *          <code>null</code> value is allowed.
275    * @return the configuration key for the given {@code path} or
276    *         <code>null</code> if no key is associated with it.
277    */
278   @CheckForNull
279   public ConfigurationKey getKey(final String path)
280   {
281     return files.get(path);
282   }
283 
284   /**
285    * Checks if the given token is a group. It is a group if it is either
286    * registered explicitly or the token starts with a registered TLD or it
287    * starts with two letters and a dot.
288    *
289    * @param token the token to check.
290    * @return <code>true</code> if the token is a group, <code>false</code>
291    *         otherwise.
292    */
293   public boolean isGroup(final String token)
294   {
295     if (!isRegisteredGroup(token))
296     {
297       final String tld = determineTld(token);
298       if (isRegisteredGroupTld(tld))
299       {
300         return true;
301       }
302 
303       return false;
304     }
305 
306     return true;
307   }
308 
309   private String determineTld(final String token)
310   {
311     final int index = token.indexOf('.');
312     if (index != -1)
313     {
314       return token.substring(0, index);
315     }
316     return null;
317   }
318 
319   // --- object basics --------------------------------------------------------
320 
321   @Override
322   public String toString()
323   {
324     final StringBuilder buffer = new StringBuilder(128);
325 
326     buffer.append("TLDs          :");
327     for (final String tld : tlds)
328     {
329       buffer.append(' ').append(tld);
330     }
331 
332     buffer.append("\nEnvironments  :");
333     for (final String environment : environments)
334     {
335       buffer.append(' ').append(environment);
336     }
337 
338     buffer.append("\nNodes         :");
339     for (final String node : nodes)
340     {
341       buffer.append(' ').append(node);
342     }
343 
344     buffer.append("\nGroups        :");
345     for (final String group : groups)
346     {
347       buffer.append(' ').append(group);
348     }
349 
350     buffer.append("\nExplicit Paths:");
351     for (final Entry<String, ConfigurationKey> entry : files.entrySet())
352     {
353       buffer.append(' ').append(entry.getKey()).append('=')
354           .append(entry.getValue());
355     }
356 
357     return buffer.toString();
358   }
359 }