| /* |
| * Copyright 2008 Michael Hunger. |
| * |
| * Licensed 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.qi4j.index.rdf.query.internal; |
| |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| import org.qi4j.api.common.QualifiedName; |
| import org.qi4j.api.entity.Identity; |
| import org.qi4j.api.query.grammar.AssociationFunction; |
| import org.qi4j.api.query.grammar.ManyAssociationFunction; |
| import org.qi4j.api.query.grammar.PropertyFunction; |
| import org.qi4j.api.util.Classes; |
| |
| import static java.lang.String.format; |
| |
| public class Triples |
| implements Iterable<Triples.Triple> |
| { |
| private int valueCounter = 0; |
| private final List<Triple> triples = new ArrayList<>(); |
| private final Namespaces namespaces; |
| |
| public Triples( Namespaces namespaces ) |
| { |
| this.namespaces = namespaces; |
| } |
| |
| public void addDefaultTriples( String resultType ) |
| { |
| triples.add( |
| new Triple( |
| "?entityType", |
| "rdfs:subClassOf", |
| "<" + Classes.toURI( resultType ) + ">", |
| false ) |
| ); |
| triples.add( |
| new Triple( |
| "?entity", |
| "rdf:type", |
| "?entityType", |
| false ) |
| ); |
| triples.add( |
| new Triple( |
| "?entity", |
| addNamespace( QualifiedName.fromClass( Identity.class, "identity" ).toNamespace() ) + ":identity", |
| "?identity", |
| false |
| ) |
| ); |
| } |
| |
| private String addNamespace( String namespace ) |
| { |
| return namespaces.addNamespace( namespace ); |
| } |
| |
| public Triple addTriple( final PropertyFunction<?> propertyFunction, boolean optional ) |
| { |
| String subject = "?entity"; |
| if( propertyFunction.traversedAssociation() != null ) |
| { |
| subject = addTripleAssociation( propertyFunction.traversedAssociation(), false ).value; |
| } |
| else if( propertyFunction.traversedProperty() != null ) |
| { |
| subject = addTriple( propertyFunction.traversedProperty(), false ).value; |
| } |
| QualifiedName qualifiedName = QualifiedName.fromAccessor( propertyFunction.accessor() ); |
| String prefix = addNamespace( qualifiedName.toNamespace() ); |
| return addTriple( subject, prefix + ":" + qualifiedName.name(), optional ); |
| } |
| |
| public Triple addTripleAssociation( AssociationFunction<?> associationReference, boolean optional ) |
| { |
| String subject = "?entity"; |
| if( associationReference.traversedAssociation() != null ) |
| { |
| subject = addTripleAssociation( associationReference.traversedAssociation(), false ).value; |
| } |
| QualifiedName qualifiedName = QualifiedName.fromAccessor( associationReference.accessor() ); |
| String prefix = addNamespace( qualifiedName.toNamespace() ); |
| return addTriple( subject, prefix + ":" + qualifiedName.name(), optional ); |
| } |
| |
| public Triple addTripleManyAssociation( final ManyAssociationFunction<?> manyAssociationReference, |
| final boolean optional |
| ) |
| { |
| AssociationFunction<?> traversedAssociation = manyAssociationReference.traversedAssociation(); |
| String subject = "?entity"; |
| if( traversedAssociation != null ) |
| { |
| subject = addTripleAssociation( traversedAssociation, false ).value; |
| } |
| QualifiedName qualifiedName = QualifiedName.fromAccessor( manyAssociationReference.accessor() ); |
| String predicatePrefix = addNamespace( qualifiedName.toNamespace() ); |
| String predicate = predicatePrefix + ":" + qualifiedName.name(); |
| Triple collectionTriple = addTriple( subject, predicate, optional ); |
| |
| String liSubject = collectionTriple.value; |
| return addTriple( liSubject, "rdf:li", false ); |
| } |
| |
| private Triple addTriple( final String subject, |
| final String predicate, |
| final boolean optional |
| ) |
| { |
| Triple triple = getTriple( subject, predicate ); |
| if( triple == null ) |
| { |
| final String value = "?v" + valueCounter++; |
| triple = new Triple( subject, predicate, value, optional ); |
| triples.add( triple ); |
| } |
| if( !optional && triple.optional ) |
| { |
| triple.optional = false; |
| } |
| return triple; |
| } |
| |
| private Triple getTriple( final String subject, |
| final String predicate |
| ) |
| { |
| for( Triple triple : triples ) |
| { |
| if( triple.subject.equals( subject ) |
| && triple.predicate.equals( predicate ) ) |
| { |
| return triple; |
| } |
| } |
| return null; |
| } |
| |
| public boolean hasTriples() |
| { |
| return !triples.isEmpty(); |
| } |
| |
| @Override |
| public Iterator<Triple> iterator() |
| { |
| return triples.iterator(); |
| } |
| |
| public String toSparql() |
| { |
| StringBuilder sparql = new StringBuilder(); |
| for( Triple triple : triples ) |
| { |
| sparql.append( triple.toSparql() ); |
| } |
| return sparql.toString(); |
| } |
| |
| public static class Triple |
| { |
| private final String subject; |
| private final String predicate; |
| private String value; |
| private boolean optional; |
| |
| private Triple( final String subject, |
| final String predicate, |
| final String value, |
| final boolean optional |
| ) |
| { |
| this.subject = subject; |
| this.predicate = predicate; |
| this.value = value; |
| this.optional = optional; |
| } |
| |
| @Override |
| public boolean equals( Object otherObject ) |
| { |
| if( this == otherObject ) |
| { |
| return true; |
| } |
| if( otherObject == null || getClass() != otherObject.getClass() ) |
| { |
| return false; |
| } |
| |
| Triple other = (Triple) otherObject; |
| |
| if( predicate != null ? !predicate.equals( other.predicate ) : other.predicate != null ) |
| { |
| return false; |
| } |
| if( subject != null ? !subject.equals( other.subject ) : other.subject != null ) |
| { |
| return false; |
| } |
| if( value != null ) |
| { |
| return value.equals( other.value ); |
| } |
| else |
| { |
| return other.value == null; |
| } |
| } |
| |
| @Override |
| public int hashCode() |
| { |
| int result; |
| result = ( subject != null ? subject.hashCode() : 0 ); |
| result = 31 * result + ( predicate != null ? predicate.hashCode() : 0 ); |
| result = 31 * result + ( value != null ? value.hashCode() : 0 ); |
| return result; |
| } |
| |
| @Override |
| public String toString() |
| { |
| return toSparql(); |
| } |
| |
| public String toSparql() |
| { |
| |
| if( optional ) |
| { |
| return format( "OPTIONAL {%s %s %s}.", subject, predicate, value ); |
| } |
| return format( "%s %s %s.", subject, predicate, value ); |
| } |
| |
| public String subject() |
| { |
| return subject; |
| } |
| |
| public String predicate() |
| { |
| return predicate; |
| } |
| |
| public String value() |
| { |
| return value; |
| } |
| |
| public void setValue( String value ) |
| { |
| this.value = value; |
| } |
| |
| public boolean isOptional() |
| { |
| return optional; |
| } |
| } |
| |
| @Override |
| public String toString() |
| { |
| return triples.toString(); |
| } |
| } |