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   * @version $Id$
38   */
39  public abstract class Vocabulary {
40  
41      /**
42       * Allows to add comments to <code>namespaces</code>,
43       * <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       * Constructor.
73       *
74       * @param namespace the namespace IRI prefix.
75       */
76      public Vocabulary(String namespace) {
77          try {
78          this.namespace =  SimpleValueFactory.getInstance().createIRI(namespace);
79          } catch (Exception e) {
80              throw new IllegalArgumentException("Invalid namespace '" + namespace + "'", e);
81          }
82      }
83  
84      /**
85       * @return the namespace associated to this vocabulary.
86       */
87      public IRI getNamespace() {
88          return namespace;
89      }
90  
91      /**
92       * Returns a class defined within this vocabulary.
93       *
94       * @param name class name.
95       * @return the IRI associated to such resource.
96       */
97      public IRI getClass(String name) {
98          IRI res = classes.get(name);
99          if (null == res) {
100             throw new IllegalArgumentException("Unknown resource name '" + name + "'");
101         }
102         return res;
103     }
104 
105     /**
106      * Returns a property defined within this vocabulary.
107      *
108      * @param name property name.
109      * @return the IRI associated to such property.
110      */
111     public IRI getProperty(String name) {
112         IRI prop = properties.get(name);
113         if (null == prop) {
114             throw new IllegalArgumentException("Unknown property name '" + name + "'");
115         }
116         return prop;
117     }
118 
119     /**
120      * Returns a property defined within this vocabulary, if not found the
121      * <code>defaultValue</code> will be returned.
122      *
123      * @param name property name.
124      * @param defaultValue the default value if property name not found.
125      * @return the IRI associated to such property.
126      */
127     public IRI getProperty(String name, IRI defaultValue) {
128         IRI prop = properties.get(name);
129         if (null == prop) {
130             return defaultValue;
131         }
132         return prop;
133     }
134 
135     /**
136      * Returns the property IRI for the specified property string.
137      * If the string contains a list of words separated by blank chars,
138      * such words are merged and camel case separated.
139      *
140      * @param property property name.
141      * @return property IRI.
142      */
143     public IRI getPropertyCamelCase(String property) {
144         String[] names = property.split("\\W");
145         String camelCase = names[0];
146         for (int i = 1; i < names.length; i++) {
147             String tmp = names[i];
148             camelCase += tmp.replaceFirst("(.)", tmp.substring(0, 1).toUpperCase());
149         }
150         return getProperty(camelCase);
151     }
152 
153     /**
154      * @return the list of all defined classes.
155      */
156     public IRI[] getClasses() {
157         if(classes == null) {
158             return new IRI[0];
159         }
160         final Collection<IRI> iris = classes.values();
161         return iris.toArray( new IRI[ iris.size() ] );
162     }
163 
164     /**
165      * @return the list of all defined properties.
166      */
167     public IRI[] getProperties() {
168         if(properties == null) {
169             return new IRI[0];
170         }
171         final Collection<IRI> iris = properties.values();
172         return iris.toArray( new IRI[ iris.size() ] );
173     }
174 
175     /**
176      * Returns all the defined comments for resources.
177      *
178      * @return unmodifiable list of comments.
179      */
180     public Map<IRI,String> getComments() {
181         fillResourceToCommentMap();
182         return Collections.unmodifiableMap(resourceToCommentMap);
183     }
184 
185     /**
186      * Returns the comment for the given resource.
187      *
188      * @param resource input resource to have a comment.
189      * @return the human readable comment associated to the
190      *         given resource.
191      */
192     public String getCommentFor(IRI resource) {
193         fillResourceToCommentMap();
194         return resourceToCommentMap.get(resource);
195     }
196     
197     /**
198      * Creates a IRI.
199      *
200      * @param iriStr the IRI string
201      * @return the IRI instance.
202      */
203     protected IRI createIRI(String iriStr) {
204         return SimpleValueFactory.getInstance().createIRI(iriStr);
205     }
206 
207     /**
208      * Creates a resource and register it to the {@link #classes} map.
209      *
210      * @param namespace vocabulary namespace.
211      * @param resource name of the resource.
212      * @return the created resource IRI.
213      */
214     protected IRI createClass(String namespace, String resource) {
215         IRI res = createIRI(namespace, resource);
216         if(classes == null) {
217             classes = new HashMap<>(10);
218         }
219         classes.put(resource, res);
220         return res;
221     }
222 
223     /**
224      * Creates a property and register it to the {@link #properties} map.
225      *
226      * @param namespace vocabulary namespace.
227      * @param property name of the property.
228      * @return the created property IRI.
229      */
230     protected IRI createProperty(String namespace, String property) {
231         IRI res = createIRI(namespace, property);
232         if(properties == null) {
233             properties = new HashMap<>(10);
234         }
235         properties.put(property, res);
236         return res;
237     }
238 
239     /**
240      * Creates a IRI.
241      *
242      * @param namespace
243      * @param localName
244      * @return
245      */
246     private IRI createIRI(String namespace, String localName) {
247         return SimpleValueFactory.getInstance().createIRI(namespace, localName);
248     }
249 
250     private void fillResourceToCommentMap() {
251         if(resourceToCommentMap != null)
252             return;
253         final Map<IRI,String> newMap = new HashMap<>();
254         for (Field field : this.getClass().getFields()) {
255             try {
256                 final Object value = field.get(this);
257                 if(value instanceof IRI) {
258                     final Comment comment = field.getAnnotation(Comment.class);
259                     if(comment != null)
260                         newMap.put((IRI) value, comment.value());
261                 }
262             } catch (IllegalAccessException iae) {
263                 throw new RuntimeException("Error while creating resource to comment map.", iae);
264             }
265         }
266         resourceToCommentMap = newMap;
267     }
268 
269 }