View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *  http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.any23.vocab;
19  
20  import org.eclipse.rdf4j.model.IRI;
21  import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
22  import java.lang.annotation.Retention;
23  import java.lang.annotation.Target;
24  import java.lang.reflect.Field;
25  import java.util.Collection;
26  import java.util.Collections;
27  import java.util.HashMap;
28  import java.util.Map;
29  
30  import static java.lang.annotation.ElementType.FIELD;
31  import static java.lang.annotation.RetentionPolicy.RUNTIME;
32  
33  /**
34   * Base class for the definition of a vocabulary.
35   *
36   * @author Michele Mostarda ( michele.mostarda@gmail.com )
37   * 
38   * @version $Id$
39   */
40  public abstract class Vocabulary {
41  
42      /**
43       * Allows to add comments to <code>namespaces</code>, <code>classes</code> and <code>properties</code>.
44       */
45      @Target({ FIELD })
46      @Retention(RUNTIME)
47      @interface Comment {
48          String value();
49      }
50  
51      /**
52       * Vocabulary namespace.
53       */
54      private final IRI namespace;
55  
56      /**
57       * Map of vocabulary resources.
58       */
59      private Map<String, IRI> classes;
60  
61      /**
62       * Map of vocabulary properties.
63       */
64      private Map<String, IRI> properties;
65  
66      /**
67       * Map any resource with the relative comment.
68       */
69      private Map<IRI, String> resourceToCommentMap;
70  
71      /**
72       * Overloaded Constructor.
73       *
74       * @param namespace
75       *            the namespace IRI prefix.
76       */
77      public Vocabulary(String namespace) {
78          try {
79              this.namespace = SimpleValueFactory.getInstance().createIRI(namespace);
80          } catch (Exception e) {
81              throw new IllegalArgumentException("Invalid namespace '" + namespace + "'", e);
82          }
83      }
84  
85      /**
86       * @return the namespace associated to this vocabulary.
87       */
88      public IRI getNamespace() {
89          return namespace;
90      }
91  
92      /**
93       * Returns a class defined within this vocabulary.
94       *
95       * @param name
96       *            class name.
97       * 
98       * @return the IRI associated to such resource.
99       */
100     public IRI getClass(String name) {
101         IRI res = classes.get(name);
102         if (null == res) {
103             throw new IllegalArgumentException("Unknown resource name '" + name + "'");
104         }
105         return res;
106     }
107 
108     /**
109      * Returns a property defined within this vocabulary.
110      *
111      * @param name
112      *            property name.
113      * 
114      * @return the IRI associated to such property.
115      */
116     public IRI getProperty(String name) {
117         IRI prop = properties.get(name);
118         if (null == prop) {
119             throw new IllegalArgumentException("Unknown property name '" + name + "'");
120         }
121         return prop;
122     }
123 
124     /**
125      * Returns a property defined within this vocabulary, if not found the <code>defaultValue</code> will be returned.
126      *
127      * @param name
128      *            property name.
129      * @param defaultValue
130      *            the default value if property name not found.
131      * 
132      * @return the IRI associated to such property.
133      */
134     public IRI getProperty(String name, IRI defaultValue) {
135         IRI prop = properties.get(name);
136         if (null == prop) {
137             return defaultValue;
138         }
139         return prop;
140     }
141 
142     /**
143      * Returns the property IRI for the specified property string. If the string contains a list of words separated by
144      * blank chars, such words are merged and camel case separated.
145      *
146      * @param property
147      *            property name.
148      * 
149      * @return property IRI.
150      */
151     public IRI getPropertyCamelCase(String property) {
152         String[] names = property.split("\\W");
153         String camelCase = names[0];
154         for (int i = 1; i < names.length; i++) {
155             String tmp = names[i];
156             camelCase += tmp.replaceFirst("(.)", tmp.substring(0, 1).toUpperCase(java.util.Locale.ROOT));
157         }
158         return getProperty(camelCase);
159     }
160 
161     /**
162      * @return the list of all defined classes.
163      */
164     public IRI[] getClasses() {
165         if (classes == null) {
166             return new IRI[0];
167         }
168         final Collection<IRI> iris = classes.values();
169         return iris.toArray(new IRI[iris.size()]);
170     }
171 
172     /**
173      * @return the list of all defined properties.
174      */
175     public IRI[] getProperties() {
176         if (properties == null) {
177             return new IRI[0];
178         }
179         final Collection<IRI> iris = properties.values();
180         return iris.toArray(new IRI[iris.size()]);
181     }
182 
183     /**
184      * Returns all the defined comments for resources.
185      *
186      * @return unmodifiable list of comments.
187      */
188     public Map<IRI, String> getComments() {
189         fillResourceToCommentMap();
190         return Collections.unmodifiableMap(resourceToCommentMap);
191     }
192 
193     /**
194      * Returns the comment for the given resource.
195      *
196      * @param resource
197      *            input resource to have a comment.
198      * 
199      * @return the human readable comment associated to the given resource.
200      */
201     public String getCommentFor(IRI resource) {
202         fillResourceToCommentMap();
203         return resourceToCommentMap.get(resource);
204     }
205 
206     /**
207      * Creates a IRI.
208      *
209      * @param iriStr
210      *            the IRI string
211      * 
212      * @return the IRI instance.
213      */
214     protected IRI createIRI(String iriStr) {
215         return SimpleValueFactory.getInstance().createIRI(iriStr);
216     }
217 
218     /**
219      * Creates a resource and register it to the {@link #classes} map.
220      *
221      * @param namespace
222      *            vocabulary namespace.
223      * @param resource
224      *            name of the resource.
225      * 
226      * @return the created resource IRI.
227      */
228     protected IRI createClass(String namespace, String resource) {
229         IRI res = createIRI(namespace, resource);
230         if (classes == null) {
231             classes = new HashMap<>(10);
232         }
233         classes.put(resource, res);
234         return res;
235     }
236 
237     /**
238      * Creates a property and register it to the {@link #properties} map.
239      *
240      * @param namespace
241      *            vocabulary namespace.
242      * @param property
243      *            name of the property.
244      * 
245      * @return the created property IRI.
246      */
247     protected IRI createProperty(String namespace, String property) {
248         IRI res = createIRI(namespace, property);
249         if (properties == null) {
250             properties = new HashMap<>(10);
251         }
252         properties.put(property, res);
253         return res;
254     }
255 
256     /**
257      * Creates a IRI.
258      *
259      * @param namespace
260      * @param localName
261      * 
262      * @return
263      */
264     private IRI createIRI(String namespace, String localName) {
265         return SimpleValueFactory.getInstance().createIRI(namespace, localName);
266     }
267 
268     private void fillResourceToCommentMap() {
269         if (resourceToCommentMap != null)
270             return;
271         final Map<IRI, String> newMap = new HashMap<>();
272         for (Field field : this.getClass().getFields()) {
273             try {
274                 final Object value = field.get(this);
275                 if (value instanceof IRI) {
276                     final Comment comment = field.getAnnotation(Comment.class);
277                     if (comment != null)
278                         newMap.put((IRI) value, comment.value());
279                 }
280             } catch (IllegalAccessException iae) {
281                 throw new RuntimeException("Error while creating resource to comment map.", iae);
282             }
283         }
284         resourceToCommentMap = newMap;
285     }
286 
287 }