All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.semantictools.frame.api.ContextBuilder Maven / Gradle / Ivy

Go to download

A library used to generate documentation for media types associated with a JSON-LD context

The newest version!
/*******************************************************************************
 * Copyright 2012 Pearson Education
 * 
 * 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.semantictools.frame.api;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.semantictools.context.renderer.model.Container;
import org.semantictools.context.renderer.model.ContextProperties;
import org.semantictools.context.renderer.model.FrameConstraints;
import org.semantictools.context.renderer.model.JsonContext;
import org.semantictools.context.renderer.model.TermInfo;
import org.semantictools.context.renderer.model.TermInfo.TermCategory;
import org.semantictools.context.renderer.model.TermValue;
import org.semantictools.frame.model.BindVocabulary;
import org.semantictools.frame.model.Datatype;
import org.semantictools.frame.model.DublinCoreTerms;
import org.semantictools.frame.model.Enumeration;
import org.semantictools.frame.model.Field;
import org.semantictools.frame.model.Frame;
import org.semantictools.frame.model.NamedIndividual;
import org.semantictools.frame.model.OntologyInfo;
import org.semantictools.frame.model.RdfType;
import org.semantictools.frame.model.RestCategory;
import org.semantictools.frame.model.VannVocabulary;

import com.hp.hpl.jena.ontology.Individual;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntProperty;
import com.hp.hpl.jena.ontology.OntResource;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.vocabulary.OWL;
import com.hp.hpl.jena.vocabulary.OWL2;
import com.hp.hpl.jena.vocabulary.RDF;
import com.hp.hpl.jena.vocabulary.RDFS;
import com.hp.hpl.jena.vocabulary.XSD;

public class ContextBuilder {
  private static final String CONTAINER = "http://www.w3.org/ns/ldp#Container";
  private static final String PAGE = "http://www.w3.org/ns/ldp#Page";
  private static final String nextPage = "http://www.w3.org/ns/ldp#nextPage";
  private static final String NIL = "http://www.w3.org/1999/02/22-rdf-syntax-ns#nil";
  private OntModel model;
  private TypeManager typeManager;
  
  private OntProperty suggestedPrefix;
  
  private Set history;

  public ContextBuilder(TypeManager typeManager) {
    this.model = typeManager.getOntModel();
    this.typeManager = typeManager;
    
    suggestedPrefix = model.getOntProperty("http://purl.org/semantictools/v1/vocab/bind#suggestedPrefix");
  }



  public JsonContext createContext(ContextProperties properties) {
    history = new HashSet();
    JsonContext context = new JsonContext();
    context.setContextURI(properties.getContextURI());
    context.setMediaType(properties.getMediaType());
    context.setRootType(properties.getRdfTypeURI());
    
    String typeURI = properties.getRdfTypeURI();
    if (typeURI == null) {
      return null;
    }

    addGraphTypes(context, properties);
    Frame frame = typeManager.getFrameByUri(typeURI);
    if (frame == null) {
      throw new FrameNotFoundException(typeURI);
    }
    addType(properties, context, frame, false, true);
    if (frame.isSubclassOf(CONTAINER)) {
      Frame page = typeManager.getFrameByUri(PAGE);
      addType(properties, context, page, false, true);

      TermInfo term = new TermInfo("nil");
      term.setIriValue(NIL);
      context.add(term);
      
      properties.getIdRefList().add(nextPage);
      
      
    }
    context.expand();
    context.invertRewriteRules();
    
    updateFrameConstraints(properties, context);
    
    return context;
  }


  private void addGraphTypes(JsonContext context, ContextProperties properties) {
    List graphTypes = properties.getGraphTypes();
    if (!graphTypes.isEmpty()) {
      for (String uri : graphTypes) {
        Frame frame = typeManager.getFrameByUri(uri);
        if (frame == null) {
          throw new FrameNotFoundException(uri);
        }
        addType(properties, context, frame, false, true);
      }
    }
    
  }



  private void updateFrameConstraints(ContextProperties properties,  JsonContext context) {
    
    List list = properties.listFrameConstraints();
    for (FrameConstraints c : list) {
      String name = c.getClassURI();
      TermInfo term = context.getTermInfoByShortName(name);
      if (term != null) {
        String uri = term.getIri();
        uri = context.rewrite(uri);
        c.setClassURI(uri);
        properties.addFrameConstraints(c);
      }
    }
    
    
  }



  private boolean isStandard(String uri) {
    return uri != null && uri.startsWith("http://www.w3.org/2001/XMLSchema#");
   
//    return uri.startsWith("http://www.w3.org/2001/XMLSchema#") ||
//        uri.startsWith("http://www.w3.org/2002/07/owl#");
  }

  private void addType(ContextProperties properties, JsonContext context, RdfType rdfType, boolean stubbed, boolean allFields) {

    String typeURI = rdfType.getUri();
    if (properties.getExcludedTypes().contains(typeURI)) {
      return;
    }
    if (rdfType.canAsListType() && embedListMembers(properties)) {
//      rdfType = rdfType.asListType().getElementType();
      addType(properties, context, rdfType.asListType().getElementType(), stubbed, allFields);
    }
    
        
    if (isStandard(typeURI)) return;

    String localName = rdfType.getLocalName();
    
    String prefix = getPrefix(context, rdfType.getNamespace());
    
    
    String iri = (prefix == null) ? typeURI : prefix + ":" + localName;

    if (!context.containsTerm(localName)) {
      context.add(localName, iri).setCategory(TermCategory.TYPE);
    }
    

    if (stubbed || history.contains(typeURI)) return;
    
    Frame frame = typeManager.getFrameByUri(typeURI);
    if (frame == null) {
      // Since the frame was not found, the type is probably a Datatype.
      // Let's confirm that the datatype exists.
      
      Datatype datatype = typeManager.getDatatypeByUri(typeURI);
      if (datatype == null) {
        throw new FrameNotFoundException(typeURI);
      }
      return;
    }
    
    history.add(typeURI);
    
    if (typeURI.equals(RDFS.Resource.getURI())) {
    	return;
    }
    
    FrameConstraints constraints = properties.getFrameConstraints(localName);
    
    List fieldList = allFields ? frame.listAllFields() : frame.getDeclaredFields();
    for (Field field : fieldList) {
      if (constraints == null || constraints.isIncludedProperty(field.getURI())) {
        addField(properties, context, field, frame);
      }
    }
    
    addSubtypes(properties, context, frame);
    
  }


  /**
   * Returns true if rdf:member is not represented as an idref.
   */
  private boolean embedListMembers(ContextProperties properties) {
    properties.isIdRef("http://www.w3.org/2000/01/rdf-schema#member");
    return false;
  }



  private void addSubtypes(ContextProperties properties, JsonContext context, Frame frame) {
    
    FrameConstraints c = properties.getFrameConstraints(frame.getLocalName());
    
    List list = frame.listAllSubtypes();
    for (Frame sub : list) {
      if (properties.getExcludedTypes().contains(sub.getUri())) {
    	continue;
      }
    		
      if (c != null) {
        // If the supertype has constraints, then they must bubble down to 
        // subtypes.  This means that the constraints cannot be null on the subtypes...
        FrameConstraints cc = properties.getFrameConstraints(sub.getLocalName());
        if (cc == null) {
          cc = new FrameConstraints(sub.getLocalName());
          properties.addFrameConstraints(cc);
        }
        cc.copyAll(c);
      } 
      
      addType(properties, context, sub, false, false);
    }
    
  }



  private void addField(ContextProperties properties, JsonContext context, Field field, Frame declaringFrame) {
    OntProperty property = field.getProperty();
    
    if (!isIncluded(field, properties, declaringFrame)) return;
    
    
    boolean allFields = field.getDeclaringFrame() == declaringFrame;
    
    String localName = property.getLocalName();
    String propertyURI = property.getURI();
    String iriValue = iriRef(context, property.getNameSpace(), property.getLocalName(), propertyURI);
    TermInfo info = new TermInfo(localName);
    info.setCategory(TermCategory.PROPERTY);
    
   
    RdfType rdfType = field.getRdfType();
    TermValue value = null;
    if (rdfType == null) {
      throw new RuntimeException("RDF type not defined for property: " + field.getLocalName());
    }
    if (rdfType.canAsListType()) {
      value = new TermValue();
      value.setContainer(Container.LIST);
      
    } 
//    if (rdfType.canAsListType()) {
//      rdfType = rdfType.asListType().getElementType();
//    }
    boolean uriRef = properties.isIdRef(property.getURI());
    
    boolean enumerable = 
        rdfType != null && 
        rdfType.canAsFrame() && 
        (rdfType.asFrame().getCategory() == RestCategory.ENUMERABLE);
    
    boolean stubbed = false;
    // stubbed=true means that the object is stubbed out because it is coerced as an IRI reference only,
    //              or it is an enumerable type.
    

    if (enumerable || uriRef ) {
      if (value == null) {
        value = new TermValue();
      }
      value.setType("@id");
      stubbed = true;
      
    } 
    if (properties.getOptionalProperties().contains(property.getURI())) {
      if (value == null) {
        value = new TermValue();
      }
      value.setMinCardinality(0);
    }
    
    if (
        enumerable 
        || (rdfType!=null && rdfType.canAsFrame() && rdfType.asFrame().hasInstances())
    ) {
      addIndividuals(context, rdfType.asFrame());
    }
    
    addValueRestriction(context, field);
    
    
    if (value != null) {
      value.setId(iriValue);
      info.setObjectValue(value);
    } else {
      info.setIriValue(iriValue);
    }
    
    addNamespace(context, field, property);
    
   

    if (!context.containsTerm(localName)) {
      context.add(info);
    }
    
    
    if (value != null && value.getContainer() == Container.LIST) {
      addType(properties, context, rdfType, stubbed, allFields);
      
    } else if (rdfType.canAsFrame()) {
      addType(properties, context, rdfType, stubbed, allFields);
      
    } else {
      
      addNamespace(context, rdfType);
      addType(properties, context, rdfType, true, allFields);
      
      if (!properties.getExpandedValues().contains(propertyURI)) {
        String propertyTypeURI = rdfType.getUri();
        
        String typeIRI = iriRef(context, rdfType.getNamespace(), rdfType.getLocalName(), propertyTypeURI);
        if (value == null) {
          value = new TermValue();
        }
        value.setId(iriValue);
        value.setType(typeIRI);
        info.setObjectValue(value);
        addNamespace(context, rdfType);
      } else {
        System.out.println("expanded value: " + info.getTermName());
      }
      
      
    }
    
    coerceType(info, properties);
    
    if (field.getType().canAs(OntProperty.class)) {
      addPropertyHierarchy(context, field.getType().asProperty());
    }
  }
  
  
  private void addPropertyHierarchy(JsonContext context, OntProperty property) {
    
    String localName = property.getLocalName();
    TermInfo info = context.getTermInfoByShortName(localName);
    if (info == null) {
      info = new TermInfo(localName);
      String uri = property.getURI();
      info.setIriValue(uri);
      info.setCategory(TermCategory.PROPERTY);
      TermValue value = new TermValue();
      
      TermInfo namespace = addNamespace(context, property);
      
      StringBuilder id = new StringBuilder();
      id.append(namespace.getTermName());
      id.append(":");
      id.append(property.getLocalName());
      value.setId(id.toString());
     
      value.setType("@id");
      info.setObjectValue(value);
      context.add(info);
      context.put(uri, info);
    }
    
    List list = property.listSubProperties(true).toList();
    for (OntProperty p : list) {
      addPropertyHierarchy(context, p);
    }
    
  }



  private void addValueRestriction(JsonContext context, Field field) {
    
    NamedIndividual value = field.getValueRestriction();
    if (value != null) {
      String uri = value.getUri();
      TermInfo info = context.getTermInfoByURI(uri);
      if (info == null) {
        info = new TermInfo(value.getLocalName());
        info.setCategory(TermCategory.INDIVIDUAL);
        info.setIriValue(uri);
        context.add(info);
      }
    }
    
  }



  private void coerceType(TermInfo info, ContextProperties properties) {
    
    String key = info.getTermName() + ".@type";
    String typeURI = properties.getProperty(key);
    
    if (typeURI == null) return;
    
    
    
  }


  private TermInfo addNamespace(JsonContext context, NamedIndividual individual) {

    String namespace = individual.getNamespaceURI();
    TermInfo term = context.getTermInfoByURI(namespace);
    if (term != null) return term;
    
    String prefix = getPrefix(context, namespace);
    
    OntologyInfo info = typeManager.getOntologyByNamespaceUri(namespace);
   
    
    
    term = new TermInfo(prefix);
    term.setIriValue(namespace);
    term.setCategory(TermCategory.NAMESPACE);
    context.add(term);
    
    return term;
  }

  private TermInfo addNamespace(JsonContext context, RdfType rdfType) {
    
    String namespace = rdfType.getNamespace();
    TermInfo term = context.getTermInfoByURI(namespace);
    if (term != null) return term;
    
    OntologyInfo info = typeManager.getOntologyByNamespaceUri(namespace);
   
    
    String prefix = info==null ?
        TypeManager.getDefaultNamespacePrefix(namespace) :
        info.getPrefix();
    
    term = new TermInfo(prefix);
    term.setIriValue(namespace);
    term.setCategory(TermCategory.NAMESPACE);
    context.add(term);
    
    return term;
    
  }



  private boolean isIncluded(Field field, ContextProperties properties, Frame declaringFrame) {
    
    String fieldType = field.getRdfType().getUri();
    if (properties.getExcludedTypes().contains(fieldType)) return false;
    
    List superList = declaringFrame.getSupertypeList();
    for (Frame superFrame : superList) {
    	if (!isIncluded(field, properties, superFrame)) {
    		return false;
    	}
    }
    
    FrameConstraints constraints = properties.getFrameConstraints(declaringFrame.getLocalName());
   
    return (constraints == null) || constraints.isIncludedProperty(field.getURI());
  }



  private void addIndividuals(JsonContext context, Frame frame) {
    
    if (frame.getUri().startsWith("http://www.w3.org/1999/02/22-rdf-syntax-ns#") ||
        frame.getUri().startsWith("http://www.w3.org/2000/01/rdf-schema#") ||
        frame.getUri().startsWith("http://www.w3.org/2002/07/owl#")
    ) return;
    
    if (frame.canAsEnumeration()) {
      addIndividuals(context, frame.asEnumeration());
      
    } else {
      List list = frame.listInstances(false);
      for (NamedIndividual n : list) {
        String name = n.getLocalName();
        String uri = n.getUri();
        TermInfo term = context.getTermInfoByShortName(name);
        
        if (term != null) {
          String termURI = term.getIri();
          if (!uri.equals(termURI)) {
            // There is another entity with the same short name.
            // Check to see if this entity is registered by another name.
            
            term = context.getTermInfoByURI(uri);
            if (term == null) {
              // Not registered.  So create a new term using a CURIE.
              
              TermInfo nsTerm = addNamespace(context, n);
              String prefix = nsTerm.getTermName();
              name = prefix + ":" + name;
              
              term = new TermInfo(name);
              term.setIriValue(name);
              context.add(term);
            }
            
            
          }
        }
        
        if (term == null) {
          
          TermInfo nsTerm = addNamespace(context, n);
          uri = nsTerm.getTermName() + ":" + name;
          term = new TermInfo(name);
          term.setIriValue(uri);
          context.add(term);
        }
      }
    }
    
  }
  
  private void addIndividuals(JsonContext context, Enumeration e) {
    List list = e.getIndividualList();
    for (NamedIndividual n : list) {
      String name = n.getLocalName();
      TermInfo term = new TermInfo(name);
      term.setIriValue(n.getUri());
      context.add(term);
    }
  }



  private void addNamespace(JsonContext context, Field field, OntProperty property) {

    String namespace = field.getProperty().getNameSpace();
    String prefix = getPrefix(context, namespace);
    
    TermInfo term = context.getTermInfoByShortName(prefix);
    if (term != null) return;
    term = new TermInfo(prefix);
    term.setCategory(TermCategory.NAMESPACE);
    term.setIriValue(namespace);
    
    context.add(term);
  }
  
  private TermInfo addNamespace(JsonContext context, OntProperty property) {
    String namespace = property.getNameSpace();
    String prefix = getPrefix(context, namespace);
    TermInfo term = context.getTermInfoByShortName(prefix);
    
    if (term != null) {
      return term;
    }
    term = new TermInfo(prefix);
    term.setCategory(TermCategory.NAMESPACE);
    term.setIriValue(namespace);
    context.add(term);
    return term;
  }



  private String iriRef(JsonContext context, String namespaceURI, String localName, String uri) {
    if (typeManager.isStandardLiteralType(uri)) {
      namespaceURI = XSD.getURI();
      localName = XSD.xstring.getLocalName();
    }
    String prefix = getPrefix(context, namespaceURI);
    if (prefix == null) {
      return uri;
    }
    return prefix + ":" + localName;
  }

  private OntologyInfo createOntologyInfo(String namespaceURI) {
    Model tmp = ModelFactory.createDefaultModel();
    Resource namespaceResource = tmp.createResource(namespaceURI);
    String ontologyURI = null;
    String prefix = null;
    String label = null;
    
    // Check to see if the namespaceURI is listed as the subject in any statements
    StmtIterator sequence = model.listStatements(namespaceResource, null, (RDFNode) null);
    while (sequence.hasNext()) {
      Statement s = sequence.next();
      if (s.getPredicate().equals(RDF.type) && s.getObject().equals(OWL.Ontology)) {
        ontologyURI = namespaceURI;
      }
      if (s.getPredicate().equals(RDFS.label) ||
          s.getPredicate().equals(DublinCoreTerms.title)) {
        label = s.getObject().asLiteral().getString();
      }
      if (s.getPredicate().equals(BindVocabulary.suggestedPrefix) || 
          s.getPredicate().equals(VannVocabulary.preferredNamespacePrefix)) {
        prefix = s.getObject().asLiteral().getString();
      }
      if ((ontologyURI != null) && (prefix!=null) ) {
        break;
      }
    }
    
    if (ontologyURI == null) {
      // Check to see if the namespaceURI is referenced via the preferredNamespacePrefix
      Literal object = tmp.createLiteral(namespaceURI);
      sequence = model.listStatements(null, null, object);
      if (sequence.hasNext()) {
        Statement s = sequence.next();
        Resource subject = s.getSubject();
        ontologyURI = subject.getURI();
       
        s = subject.getProperty(VannVocabulary.preferredNamespacePrefix);
        if (s != null) {
          prefix = s.getObject().asLiteral().getString();
        } else {
          s = subject.getProperty(BindVocabulary.suggestedPrefix);
          if (s != null) {
            prefix =  s.getObject().asLiteral().getString();
          }
        }
        
        if (prefix != null) {
          s = subject.getProperty(DublinCoreTerms.title);
          if (s == null) {
            s = subject.getProperty(RDFS.label);
          }
          if (s == null) {
            s = subject.getProperty(DublinCoreElements.title);
          }
          if (s != null) {
            label = s.getObject().asLiteral().getString();
          }
          
        }
        
      }
    }
    
   OntologyInfo info = new OntologyInfo();
   
   info.setNamespaceUri(namespaceURI);
   info.setOntologyURI(ontologyURI);
   info.setPrefix(prefix);
   info.setLabel(label);
    
    return info;
  }

  private String getPrefix(JsonContext context, String namespaceURI) {

    String prefix = null;
    
    // Special handling for OWL namespace.
    if (OWL2.NS.equals(namespaceURI)) {
      OntologyInfo info = typeManager.getOntologyByNamespaceUri(namespaceURI);
      prefix = info.getPrefix();
                
    } else {
      
      OntologyInfo info = typeManager.getOntologyByNamespaceUri(namespaceURI);
      if (info == null) {
      
        info = createOntologyInfo(namespaceURI);
        typeManager.add(info);
        prefix = info.getPrefix();
      } else {
        prefix = info.getPrefix();
      }
    }
    if (prefix == null && namespaceURI.equals("http://www.w3.org/1999/02/22-rdf-syntax-ns#")) {
      prefix = "rdf";
    }

    if (prefix !=null && !context.containsTerm(prefix)) {
      String uri = namespaceURI;
      context.add(prefix, uri).setCategory(TermCategory.NAMESPACE);
    }
    
    
    return prefix;
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy