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 this.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 = this.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 = this.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 = this.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 (this.classes == null) {
    166             return new IRI[0];
    167         }
    168         final Collection<IRI> iris = this.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 (this.properties == null) {
    177             return new IRI[0];
    178         }
    179         final Collection<IRI> iris = this.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(this.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 this.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 static 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 (this.classes == null) {
    231             this.classes = new HashMap<>(10);
    232         }
    233         this.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 (this.properties == null) {
    250             this.properties = new HashMap<>(10);
    251         }
    252         this.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 static IRI createIRI(String namespace, String localName) {
    265         return SimpleValueFactory.getInstance().createIRI(namespace, localName);
    266     }
    267
    268     private void fillResourceToCommentMap() {
    269         if (this.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         this.resourceToCommentMap = newMap;
    285     }
    286
    287 }