blob: 7e4de653d2511aa8e0df47a957b6c0b41cfb6bfa [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.any23.vocab;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Base class for the definition of a vocabulary.
*
* @author Michele Mostarda ( michele.mostarda@gmail.com )
* @version $Id$
*/
public abstract class Vocabulary {
/**
* Allows to add comments to <code>namespaces</code>,
* <code>classes</code> and <code>properties</code>.
*/
@Target({FIELD})
@Retention(RUNTIME)
@interface Comment {
String value();
}
/**
* Vocabulary namespace.
*/
private final IRI namespace;
/**
* Map of vocabulary resources.
*/
private Map<String,IRI> classes;
/**
* Map of vocabulary properties.
*/
private Map<String,IRI> properties;
/**
* Map any resource with the relative comment.
*/
private Map<IRI,String> resourceToCommentMap;
/**
* Overloaded Constructor.
*
* @param namespace the namespace IRI prefix.
*/
public Vocabulary(String namespace) {
try {
this.namespace = SimpleValueFactory.getInstance().createIRI(namespace);
} catch (Exception e) {
throw new IllegalArgumentException("Invalid namespace '" + namespace + "'", e);
}
}
/**
* @return the namespace associated to this vocabulary.
*/
public IRI getNamespace() {
return namespace;
}
/**
* Returns a class defined within this vocabulary.
*
* @param name class name.
* @return the IRI associated to such resource.
*/
public IRI getClass(String name) {
IRI res = classes.get(name);
if (null == res) {
throw new IllegalArgumentException("Unknown resource name '" + name + "'");
}
return res;
}
/**
* Returns a property defined within this vocabulary.
*
* @param name property name.
* @return the IRI associated to such property.
*/
public IRI getProperty(String name) {
IRI prop = properties.get(name);
if (null == prop) {
throw new IllegalArgumentException("Unknown property name '" + name + "'");
}
return prop;
}
/**
* Returns a property defined within this vocabulary, if not found the
* <code>defaultValue</code> will be returned.
*
* @param name property name.
* @param defaultValue the default value if property name not found.
* @return the IRI associated to such property.
*/
public IRI getProperty(String name, IRI defaultValue) {
IRI prop = properties.get(name);
if (null == prop) {
return defaultValue;
}
return prop;
}
/**
* Returns the property IRI for the specified property string.
* If the string contains a list of words separated by blank chars,
* such words are merged and camel case separated.
*
* @param property property name.
* @return property IRI.
*/
public IRI getPropertyCamelCase(String property) {
String[] names = property.split("\\W");
String camelCase = names[0];
for (int i = 1; i < names.length; i++) {
String tmp = names[i];
camelCase += tmp.replaceFirst("(.)", tmp.substring(0, 1).toUpperCase(java.util.Locale.ROOT));
}
return getProperty(camelCase);
}
/**
* @return the list of all defined classes.
*/
public IRI[] getClasses() {
if(classes == null) {
return new IRI[0];
}
final Collection<IRI> iris = classes.values();
return iris.toArray( new IRI[ iris.size() ] );
}
/**
* @return the list of all defined properties.
*/
public IRI[] getProperties() {
if(properties == null) {
return new IRI[0];
}
final Collection<IRI> iris = properties.values();
return iris.toArray( new IRI[ iris.size() ] );
}
/**
* Returns all the defined comments for resources.
*
* @return unmodifiable list of comments.
*/
public Map<IRI,String> getComments() {
fillResourceToCommentMap();
return Collections.unmodifiableMap(resourceToCommentMap);
}
/**
* Returns the comment for the given resource.
*
* @param resource input resource to have a comment.
* @return the human readable comment associated to the
* given resource.
*/
public String getCommentFor(IRI resource) {
fillResourceToCommentMap();
return resourceToCommentMap.get(resource);
}
/**
* Creates a IRI.
*
* @param iriStr the IRI string
* @return the IRI instance.
*/
protected IRI createIRI(String iriStr) {
return SimpleValueFactory.getInstance().createIRI(iriStr);
}
/**
* Creates a resource and register it to the {@link #classes} map.
*
* @param namespace vocabulary namespace.
* @param resource name of the resource.
* @return the created resource IRI.
*/
protected IRI createClass(String namespace, String resource) {
IRI res = createIRI(namespace, resource);
if(classes == null) {
classes = new HashMap<>(10);
}
classes.put(resource, res);
return res;
}
/**
* Creates a property and register it to the {@link #properties} map.
*
* @param namespace vocabulary namespace.
* @param property name of the property.
* @return the created property IRI.
*/
protected IRI createProperty(String namespace, String property) {
IRI res = createIRI(namespace, property);
if(properties == null) {
properties = new HashMap<>(10);
}
properties.put(property, res);
return res;
}
/**
* Creates a IRI.
*
* @param namespace
* @param localName
* @return
*/
private IRI createIRI(String namespace, String localName) {
return SimpleValueFactory.getInstance().createIRI(namespace, localName);
}
private void fillResourceToCommentMap() {
if(resourceToCommentMap != null)
return;
final Map<IRI,String> newMap = new HashMap<>();
for (Field field : this.getClass().getFields()) {
try {
final Object value = field.get(this);
if(value instanceof IRI) {
final Comment comment = field.getAnnotation(Comment.class);
if(comment != null)
newMap.put((IRI) value, comment.value());
}
} catch (IllegalAccessException iae) {
throw new RuntimeException("Error while creating resource to comment map.", iae);
}
}
resourceToCommentMap = newMap;
}
}