001/** 002 * Copyright 2015 DuraSpace, Inc. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.fcrepo.kernel.modeshape.rdf.impl.mappings; 017 018import static com.google.common.base.Throwables.propagate; 019import static com.hp.hpl.jena.datatypes.xsd.XSDDatatype.XSDanyURI; 020import static com.hp.hpl.jena.datatypes.xsd.XSDDatatype.XSDboolean; 021import static com.hp.hpl.jena.datatypes.xsd.XSDDatatype.XSDdate; 022import static com.hp.hpl.jena.datatypes.xsd.XSDDatatype.XSDdecimal; 023import static com.hp.hpl.jena.datatypes.xsd.XSDDatatype.XSDlong; 024import static com.hp.hpl.jena.datatypes.xsd.XSDDatatype.XSDstring; 025import static com.hp.hpl.jena.graph.NodeFactory.createURI; 026import static com.hp.hpl.jena.graph.Triple.create; 027import static com.hp.hpl.jena.vocabulary.RDFS.range; 028import static java.util.Collections.emptyIterator; 029import static javax.jcr.PropertyType.BINARY; 030import static javax.jcr.PropertyType.BOOLEAN; 031import static javax.jcr.PropertyType.DATE; 032import static javax.jcr.PropertyType.DECIMAL; 033import static javax.jcr.PropertyType.DOUBLE; 034import static javax.jcr.PropertyType.LONG; 035import static javax.jcr.PropertyType.PATH; 036import static javax.jcr.PropertyType.REFERENCE; 037import static javax.jcr.PropertyType.STRING; 038import static javax.jcr.PropertyType.URI; 039import static javax.jcr.PropertyType.WEAKREFERENCE; 040import static javax.jcr.PropertyType.nameFromValue; 041import static org.fcrepo.kernel.api.RdfLexicon.REPOSITORY_NAMESPACE; 042import static org.slf4j.LoggerFactory.getLogger; 043 044import java.util.Iterator; 045import java.util.Map; 046 047import javax.jcr.RepositoryException; 048import javax.jcr.nodetype.PropertyDefinition; 049 050import org.fcrepo.kernel.api.utils.iterators.RdfStream; 051import org.slf4j.Logger; 052 053import com.google.common.collect.ImmutableMap; 054import com.hp.hpl.jena.datatypes.xsd.XSDDatatype; 055import com.hp.hpl.jena.graph.Node; 056import com.hp.hpl.jena.graph.Triple; 057 058/** 059 * Utility for moving Property Definitions into RDFS triples 060 * @author cbeer 061 */ 062public class PropertyDefinitionToTriples extends ItemDefinitionToTriples<PropertyDefinition> { 063 064 private static final Logger LOGGER = getLogger(PropertyDefinitionToTriples.class); 065 066 /** 067 * A JCR type for which we know no RDF equivalent. 068 */ 069 private static final Node UNMAPPED_TYPE = createURI(REPOSITORY_NAMESPACE 070 + "UnmappedType"); 071 072 /** 073 * A map from JCR types to RDF types. 074 */ 075 private static final Map<Integer, XSDDatatype> JCR_TYPE_TO_XSD_DATATYPE = 076 ImmutableMap.<Integer, XSDDatatype>builder() 077 .put(BOOLEAN, XSDboolean) 078 .put(DATE, XSDdate) 079 .put(DECIMAL, XSDdecimal) 080 .put(DOUBLE, XSDdecimal) 081 .put(LONG, XSDlong) 082 .put(URI, XSDanyURI) 083 .put(REFERENCE, XSDanyURI) 084 .put(WEAKREFERENCE, XSDanyURI) 085 .put(PATH, XSDanyURI) 086 .put(BINARY, XSDstring) 087 .put(STRING, XSDstring).build(); 088 089 /** 090 * Translate ItemDefinitions into triples. The definitions will hang off 091 * the provided RDF Node 092 * @param domain the given domain 093 */ 094 public PropertyDefinitionToTriples(final Node domain) { 095 super(domain); 096 } 097 098 @Override 099 public Iterator<Triple> apply(final PropertyDefinition input) { 100 101 if (!input.getName().contains(":")) { 102 LOGGER.debug("Received property definition with no namespace: {}", 103 input.getName()); 104 LOGGER.debug("This cannot be serialized into several RDF formats, " + 105 "so we assume it is internal and discard it."); 106 // TODO find a better way... 107 return emptyIterator(); 108 } 109 110 try { 111 // skip range declaration for unknown types 112 final int requiredType = input.getRequiredType(); 113 114 final Node rangeForJcrType = getRangeForJcrType(requiredType); 115 116 if (!rangeForJcrType.equals(UNMAPPED_TYPE)) { 117 LOGGER.trace("Adding RDFS:range for property: {} with required type: {} as: {}", 118 input.getName(), nameFromValue(requiredType), rangeForJcrType.getURI()); 119 final Triple propertyTriple = 120 create(getResource(input).asNode(), range.asNode(), 121 rangeForJcrType); 122 return new RdfStream(propertyTriple).concat(super.apply(input)); 123 } 124 LOGGER.trace( 125 "Skipping RDFS:range for property: {} with unmappable type: {}", 126 input.getName(), nameFromValue(requiredType)); 127 return super.apply(input); 128 } catch (final RepositoryException e) { 129 throw propagate(e); 130 } 131 } 132 133 /** 134 * Convert a JCR type to an RDF data type. 135 * 136 * @param requiredType a JCR PropertyType 137 * @return rdf node of data type 138 */ 139 private static Node getRangeForJcrType(final int requiredType) { 140 return JCR_TYPE_TO_XSD_DATATYPE.containsKey(requiredType) 141 ? createURI(JCR_TYPE_TO_XSD_DATATYPE.get(requiredType).getURI()) 142 : UNMAPPED_TYPE; 143 } 144}