Package edu.cmu.cs.fusion.xml

Source Code of edu.cmu.cs.fusion.xml.SchemaQueries

package edu.cmu.cs.fusion.xml;

import java.io.File;
import java.io.StringReader;
import java.util.LinkedList;
import java.util.List;

import javax.xml.namespace.QName;
import javax.xml.xquery.XQConnection;
import javax.xml.xquery.XQException;
import javax.xml.xquery.XQPreparedExpression;
import javax.xml.xquery.XQResultSequence;

import net.sf.saxon.Configuration;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.xqj.SaxonXQDataSource;

import org.eclipse.jdt.core.JavaModelException;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import edu.cmu.cs.crystal.util.TypeHierarchy;
import edu.cmu.cs.crystal.util.Utilities;
import edu.cmu.cs.fusion.FusionTypeCheckException;
import edu.cmu.cs.fusion.Relation;
import edu.cmu.cs.fusion.RelationsEnvironment;
import edu.cmu.cs.fusion.Relationship;
import edu.cmu.cs.fusion.alias.ObjectLabel;
import edu.cmu.cs.fusion.annot.Relation.Effect;
import edu.cmu.cs.fusion.constraint.XMLContext;
import edu.cmu.cs.fusion.relationship.RelationshipDelta;
import edu.cmu.cs.fusion.relationship.SevenPointLattice;

/**
* This class holds the XQuery from a particular schema. Given a file of that schema, and a type hierarchy,
* it can be used to query the data in the file and produce various results in the FUSION model.
*
* @author ciera
*
*/
public class SchemaQueries {
  private static String DOC = "doc";

  private RelationsEnvironment relEnv;
  private XMLContext context;
  private String topStr;
  private String localStr;
  private List<String> queryStrings; 
 
  /**
   * Create a new schema query based on the info from fusion file.
   * @param context The XMLContext, which contains all of our imports and classpath info
   * @param relEnv The relations environment
   * @param topElement The string representing the query for the top-level elements
   * @param localVal The string representing any local functions or namepsaces
   * @param queryStrings The list of query strings for relationships
   */
  public SchemaQueries(XMLContext context, RelationsEnvironment relEnv, String topElement, String localVal,
      List<String> queryStrings) {
    topStr = topElement;
    localStr = localVal;
    this.queryStrings = queryStrings;
    this.context = context;
    this.relEnv = relEnv;
   
    if (localStr == null)
      localStr = "";
  }

  /**
   * Run each of our queries on this file, and produce a list of relationship changes
   * @param file The XML file to run the queries on. This is assumed to have the same schema as the one that was used
   * to create this SchemaQueries object
   * @param types A type hierarchy to use for subtyping checks.
   * @return A representation of the changes to the starting context that should be made.
   * @throws FusionTypeCheckException
   */
  public RelationshipDelta runQueries(File file, TypeHierarchy types) throws FusionTypeCheckException {
    List<RelationshipDelta> deltas = new LinkedList<RelationshipDelta>();
    try {
      SaxonXQDataSource data = new SaxonXQDataSource();
      Configuration config = data.getConfiguration();
      XQConnection conn = data.getConnection();
      config.registerExtensionFunction(new TypeComparisonDefinition(types));

      for (String query : queryStrings) {
        RelationshipDelta result;
        String complete = localStr + query;
        StringReader reader = new StringReader(complete);
       
        XQPreparedExpression exp = conn.prepareExpression(reader);
        String filename = file.getAbsolutePath().replace('\\', '/');
        exp.bindString(new QName(DOC), filename, null);
       
        XQResultSequence queryResult = exp.executeQuery();
        result = processRelationshipResults(queryResult, types);
        deltas.add(result);
      }
     
    } catch (XQException e) {
      throw new FusionTypeCheckException(context.getFullyQualifiedName(), file, e);
    } catch (JavaModelException e) {
      throw new FusionTypeCheckException(context.getFullyQualifiedName(), file, e);
    } catch (XPathException e) {
      throw new FusionTypeCheckException(context.getFullyQualifiedName(), file, e);
    }
    return !deltas.isEmpty() ? RelationshipDelta.joinAlt(deltas) : new RelationshipDelta();
  }
 
  /**
   * Run the top query and produce a list of objects that are "top-level" objects in this file
   * @param file The XML file to run the top query on. This is assumed to have the same schema as the one that was used
   * to create this SchemaQueries object
   * @param types A type hierarchy to use for subtyping checks.
   * @return A list of ObjectLabels, which will have an associated type.
   * @throws FusionTypeCheckException
   */
  public List<ObjectLabel> findTopObjects(File file, TypeHierarchy types) throws FusionTypeCheckException {
    if (topStr == null)
      return new LinkedList<ObjectLabel>();
   
    try {
      SaxonXQDataSource data = new SaxonXQDataSource();
      Configuration config = data.getConfiguration();
      XQConnection conn = data.getConnection();
      config.registerExtensionFunction(new TypeComparisonDefinition(types));

      String complete = localStr + topStr;
      StringReader reader = new StringReader(complete);
       
      XQPreparedExpression exp = conn.prepareExpression(reader);
      exp.bindString(new QName(DOC), file.getAbsolutePath().replace('\\', '/'), null);
       
      XQResultSequence queryResult = exp.executeQuery();
      return processBindingResults(queryResult);
    } catch (XQException e) {
      throw new FusionTypeCheckException(e);
    } catch (XPathException e) {
      throw new FusionTypeCheckException(e);
    }
  }


  /**
   * Process the results, where results is a list of <Object name="??" type="??"/>
   */
  private List<ObjectLabel> processBindingResults(XQResultSequence results) throws XQException {
    List<ObjectLabel> tops = new LinkedList<ObjectLabel>();
    while (results.next()) {
      Element topElement = (Element)results.getObject();
      String labelName = topElement.getAttribute("name");
      String typeName = topElement.getAttribute("type");
      tops.add(new XMLObjectLabel(labelName, typeName));
    }
    return tops;
  }

  /**
   * Process the results, where results is a list of <Relationship name="??" effect="??"> with objects in them
   * @throws FusionTypeCheckException
   */
  private RelationshipDelta processRelationshipResults(XQResultSequence results, TypeHierarchy types) throws JavaModelException, XQException, FusionTypeCheckException {
    RelationshipDelta delta = new RelationshipDelta();
    while (results.next()) {
      Element relElement = (Element) results.getObject();
      String relName = relElement.getAttribute("name");
      Effect effect = Effect.valueOf(relElement.getAttribute("effect"));
      if (effect == null || effect == Effect.TEST)
        throw new FusionTypeCheckException(effect);
     
      relName = Utilities.resolveType(context, relName);
      Relation relType = relEnv.findRelation(relName);
      if (relType == null)
        throw new FusionTypeCheckException(relName);
     
      ObjectLabel[] labArr = getLabels(relElement, relType, types);
      Relationship rel = new Relationship(relType, labArr);
     
      delta.setRelationship(rel, effect == Effect.ADD ? SevenPointLattice.TRU : SevenPointLattice.FAL);
    }
    return delta;
  }

  /**
   * Process the objects within a relation element, given the associated relation.
   * Also do typechecking here.
   * @throws FusionTypeCheckException
   */
  private ObjectLabel[] getLabels(Element relElement, Relation relation, TypeHierarchy types) throws FusionTypeCheckException {
    NodeList nodes = relElement.getElementsByTagName("Object");
    String[] relTypes = relation.getFullyQualifiedTypes();
   
    if (relTypes.length != nodes.getLength())
      throw new FusionTypeCheckException(relation, relTypes.length, nodes.getLength());
    ObjectLabel[] labels = new ObjectLabel[relTypes.length];
   
    for (int ndx = 0; ndx < nodes.getLength(); ndx++) {
      Element node = (Element) nodes.item(ndx);
      String name = node.getAttribute("name");
      String type = node.getAttribute("type");
      labels[ndx] = createLabel(name, type);
     
      if (!(types.isSubtypeCompatible(type, relTypes[ndx])))
        throw new FusionTypeCheckException(relation, ndx, type, name);
    }
    return labels;
  }

  private ObjectLabel createLabel(String name, String type) {
    if (type.equals("java.lang.String")) {
      return new XMLLiteralLabel(name, type);
    }
    else if (type.indexOf('.') != -1) {
      return new XMLObjectLabel(name, type);
    }
    else if (type.equals("int")) {
      return new XMLLiteralLabel(Integer.parseInt(name), type);
    }
    else if (type.equals("double")) {
      return new XMLLiteralLabel(Double.parseDouble(name), type);
    }
    else if (type.equals("char")) {
      assert (name.length() == 1);
      return new XMLLiteralLabel(name.charAt(0), type);
    }
    else if (type.equals("boolean")) {
      return new XMLLiteralLabel(Boolean.parseBoolean(name), type);
    }
    else if (type.equals("short")) {
      return new XMLLiteralLabel(Short.parseShort(name), type);
    }
    else if (type.equals("long")) {
      return new XMLLiteralLabel(Long.parseLong(name), type);
    }
    else if (type.equals("float")) {
      return new XMLLiteralLabel(Float.parseFloat(name), type);
    }
    else
      return new XMLObjectLabel(name, type);
  }
}
TOP

Related Classes of edu.cmu.cs.fusion.xml.SchemaQueries

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.