001/* 002 * Licensed to DuraSpace under one or more contributor license agreements. 003 * See the NOTICE file distributed with this work for additional information 004 * regarding copyright ownership. 005 * 006 * DuraSpace licenses this file to you under the Apache License, 007 * Version 2.0 (the "License"); you may not use this file except in 008 * compliance with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.fcrepo.kernel.modeshape.rdf.impl.mappings; 019 020import static com.google.common.base.Throwables.propagate; 021import static com.hp.hpl.jena.datatypes.xsd.XSDDatatype.XSDanyURI; 022import static com.hp.hpl.jena.datatypes.xsd.XSDDatatype.XSDboolean; 023import static com.hp.hpl.jena.datatypes.xsd.XSDDatatype.XSDdate; 024import static com.hp.hpl.jena.datatypes.xsd.XSDDatatype.XSDdecimal; 025import static com.hp.hpl.jena.datatypes.xsd.XSDDatatype.XSDlong; 026import static com.hp.hpl.jena.datatypes.xsd.XSDDatatype.XSDstring; 027import static com.hp.hpl.jena.graph.NodeFactory.createURI; 028import static com.hp.hpl.jena.graph.Triple.create; 029import static com.hp.hpl.jena.vocabulary.RDFS.range; 030import static java.util.stream.Stream.of; 031import static javax.jcr.PropertyType.BINARY; 032import static javax.jcr.PropertyType.BOOLEAN; 033import static javax.jcr.PropertyType.DATE; 034import static javax.jcr.PropertyType.DECIMAL; 035import static javax.jcr.PropertyType.DOUBLE; 036import static javax.jcr.PropertyType.LONG; 037import static javax.jcr.PropertyType.PATH; 038import static javax.jcr.PropertyType.REFERENCE; 039import static javax.jcr.PropertyType.STRING; 040import static javax.jcr.PropertyType.URI; 041import static javax.jcr.PropertyType.WEAKREFERENCE; 042import static javax.jcr.PropertyType.nameFromValue; 043import static org.fcrepo.kernel.api.RdfLexicon.REPOSITORY_NAMESPACE; 044import static org.slf4j.LoggerFactory.getLogger; 045 046import java.util.stream.Stream; 047import java.util.Map; 048 049import javax.jcr.RepositoryException; 050import javax.jcr.nodetype.PropertyDefinition; 051 052import org.slf4j.Logger; 053 054import com.google.common.collect.ImmutableMap; 055import com.hp.hpl.jena.datatypes.xsd.XSDDatatype; 056import com.hp.hpl.jena.graph.Node; 057import com.hp.hpl.jena.graph.Triple; 058 059/** 060 * Utility for moving Property Definitions into RDFS triples 061 * @author cbeer 062 */ 063public class PropertyDefinitionToTriples extends ItemDefinitionToTriples<PropertyDefinition> { 064 065 private static final Logger LOGGER = getLogger(PropertyDefinitionToTriples.class); 066 067 /** 068 * A JCR type for which we know no RDF equivalent. 069 */ 070 private static final Node UNMAPPED_TYPE = createURI(REPOSITORY_NAMESPACE 071 + "UnmappedType"); 072 073 /** 074 * A map from JCR types to RDF types. 075 */ 076 private static final Map<Integer, XSDDatatype> JCR_TYPE_TO_XSD_DATATYPE = 077 ImmutableMap.<Integer, XSDDatatype>builder() 078 .put(BOOLEAN, XSDboolean) 079 .put(DATE, XSDdate) 080 .put(DECIMAL, XSDdecimal) 081 .put(DOUBLE, XSDdecimal) 082 .put(LONG, XSDlong) 083 .put(URI, XSDanyURI) 084 .put(REFERENCE, XSDanyURI) 085 .put(WEAKREFERENCE, XSDanyURI) 086 .put(PATH, XSDanyURI) 087 .put(BINARY, XSDstring) 088 .put(STRING, XSDstring).build(); 089 090 /** 091 * Translate ItemDefinitions into triples. The definitions will hang off 092 * the provided RDF Node 093 * @param domain the given domain 094 */ 095 public PropertyDefinitionToTriples(final Node domain) { 096 super(domain); 097 } 098 099 @Override 100 public Stream<Triple> apply(final PropertyDefinition input) { 101 102 if (!input.getName().contains(":")) { 103 LOGGER.debug("Received property definition with no namespace: {}", 104 input.getName()); 105 LOGGER.debug("This cannot be serialized into several RDF formats, " + 106 "so we assume it is internal and discard it."); 107 return Stream.empty(); 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 Stream.concat(of(propertyTriple), 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}