// OO jDREW - An Object Oriented extension of the Java Deductive Reasoning Engine for the Web // Copyright (C) 2005 Marcel Ball // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA package org.ruleml.oojdrew.parsing; import java.io.IOException; import java.util.Iterator; import java.util.Vector; import nu.xom.ParsingException; import nu.xom.ValidityException; import org.ruleml.oojdrew.util.DefiniteClause; import org.ruleml.oojdrew.util.Term; import org.ruleml.oojdrew.util.Types; /** * * This Class will implement the Subsumes Parser. This allows user to use the POSL * syntax subsumes(superClass, subClass) to implement a user defined taxonomy. * <p>Title: OO jDREW</p> * * <p>Description: Reasoning Engine for the Semantic Web - Supporting OO RuleML * 0.91</p> * * <p>Copyright: Copyright (c) 2007</p> * * @author Ben Craig * @version 0.93 */ public class SubsumesParser { String parseString; /** A Vector of the subsumes Objects in the system after parsing. */ Vector subsumeObjects = new Vector(); /** A Vector of Strings that contain all the classes in the type system after parsing. */ Vector allClasses = new Vector(); /** A Vector of RDFObjects in the type system after parsing. */ Vector RDFObjects = new Vector(); String finalRDFSString = ""; /** * This is the constructor for the subsumes parser. All it needs is a string to be * parsed. * * @param String - parseString this is the POSL representation of the type system to be * parsed */ public SubsumesParser(String parseString){ this.parseString = parseString; } public SubsumesParser() { this.parseString = ""; } /** * This method will parse the given String when the SubsumesParser was created. * * @throws SubsumesException - a Exception that could occur depending on invalid formatting * @throws IOException * @throws ParsingException * @throws ParseException * @throws ValidityException */ public void parseSubsumes() throws SubsumesException, ValidityException, ParseException, ParsingException, IOException{ this.buildSubsumeObjects(); this.buildRDFObjects(); RDFSParser.parseRDFSString(finalRDFSString); //this.buildTypes(); } public void parseSubsumes(String parseString) throws SubsumesException, ValidityException, ParseException, ParsingException, IOException { this.parseString = parseString; parseSubsumes(); } /** * This method will parse through all the given subsumes relations and create * objects for them. The objects contain a 2 strings one for the super class and one * for the sub class. * * @throws SubsumesException a Exception that could occur depending on invalid formatting */ public void buildSubsumeObjects() throws SubsumesException{ Vector rdfsObjects = new Vector(); //Parsing the POSL String given POSLParser pp = new POSLParser(); try{ pp.parseDefiniteClauses(parseString); }catch(Exception e){ throw new SubsumesException("Incorrect POSL syntax"); } //Obtaining the Parsed subsume objects Iterator it = pp.iterator(); //Iterating through all of the clauses to make sure they are of valid syntax //Once they have been validated then a subsumes Object is created to //store the parameters of the subsumes objects while (it.hasNext()) { DefiniteClause dc = (DefiniteClause) it.next(); Term[] atoms = dc.atoms; if(atoms.length != 1){ throw new SubsumesException("Types cannot contain a rule."); } Term t1 = atoms[0]; String predicate = t1.getSymbolString(); if(!predicate.equals("subsumes")){ throw new SubsumesException("Only subsumes facts can be in type definition."); } Term[] terms = t1.getSubTerms(); if(terms.length != 3){ throw new SubsumesException("Subsumes facts can only have 2 arguments."); } String[] varnames = dc.variableNames; String term1 = terms[1].toPOSLString(varnames,true); String term2 = terms[2].toPOSLString(varnames,true); //System.out.println(term1 + " " + term2); boolean t1Var = false; boolean t2Var = false; String term1Sub = term1.substring(0,1); String term2Sub = term2.substring(0,1); if(term1Sub.equals("?")){ throw new SubsumesException("Subsumes facts cannot contain variables in type definitions"); } if(term2Sub.equals("?")){ throw new SubsumesException("Subsumes facts cannot contain variables in type definitions"); } SubsumesObject so = new SubsumesObject(term1,term2); subsumeObjects.add(so); } } /** * Iterating through all of the subsume objects to create RDF Objects * RDF objects contain the the parent class and all of its sub classes. */ public void buildRDFObjects(){ String allRDFSObjects = ""; Iterator it = subsumeObjects.iterator(); String superClass; String subClass; String compare; boolean firstPass = true; boolean superDuplicate = false; boolean subDuplicate = false; //Looping through the subsume Objects to determine all of the classes in the //Type System duplicates must be removed. while(it.hasNext()){ superDuplicate = false; subDuplicate = false; Object b = it.next(); SubsumesObject so = (SubsumesObject) b; superClass = so.getSuperClass(); subClass = so.getSubClass() ; if(firstPass){ //System.out.println("First pass"); firstPass = false; allClasses.add(superClass); } int classSize = allClasses.size(); Iterator allClassIt = allClasses.iterator(); //checking for duplicates while(allClassIt.hasNext()){ Object comp = allClassIt.next(); compare = comp.toString(); if(superClass.equals(compare)){ //System.out.println("Found duplicate super"); superDuplicate = true; } if(subClass.equals(compare)){ //System.out.println("Found duplicate sub"); subDuplicate = true; } } if(!superDuplicate){ allClasses.add(superClass); } if(!subDuplicate){ allClasses.add(subClass); } } Iterator secondPass = allClasses.iterator(); //make all RDF objects for each class //This iteration will create all of the RDF Objects needed //We need to find all of the subClasses of every class collected in the //allClasses Vector. while(secondPass.hasNext()){ Object sup = secondPass.next(); String mainClass = sup.toString(); Iterator subObjects = subsumeObjects.iterator(); //find all parents of each rdf object Vector allParents = new Vector(); while(subObjects.hasNext()){ Object subObject = subObjects.next(); SubsumesObject so = (SubsumesObject)subObject; String superC = so.getSuperClass(); String subC = so.getSubClass(); if(mainClass.equals(subC)){ allParents.add(superC); } } int size = allParents.size(); String[] parents = new String[size]; for(int i = 0 ; i < size; i++){ Object parOb = allParents.elementAt(i); parents[i] = parOb.toString(); } RDFObject ro = new RDFObject(mainClass,parents); String rdfStringSingle = "<rdf:Description rdf:ID=\""+ro.getName()+"\">" +"\n" + "<rdf:type rdf:resource=\"http://www.w3.org/2000/01/rdf-schema#Class\"/>\n"; String[] parentz = ro.getParents(); for(int i = 0; i <parentz.length; i++){ rdfStringSingle = rdfStringSingle + "<rdfs:subClassOf rdf:resource=\"#" + parentz[i]+ "\"/>\n"; } rdfStringSingle = "\n" + rdfStringSingle + "</rdf:Description>\n"; allRDFSObjects = allRDFSObjects + rdfStringSingle; RDFObjects.add(ro); } finalRDFSString = "<rdf:RDF\n" + "xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n" + "xmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\"\n" + "xml:base=\"http://example.org/schemas/vehicles\">\n" + allRDFSObjects + "\n" + "</rdf:RDF>"; } /** * This method will create the RDFS Types. Once the RDF Objects have been created * all that is left to do is define them in the Type Graph. */ public void buildTypes(){ Iterator it = RDFObjects.iterator(); while(it.hasNext()){ Object ob = it.next(); RDFObject rdfsOb = (RDFObject)ob; String name = rdfsOb.getName(); String[] parents = rdfsOb.getParents(); Types.createType(name, parents); } } }//SubsumesParser Class /** * This class is used to create a subsumes Object, that contains a pair of strings. * * @author craigb */ class SubsumesObject{ String superClass; String subClass; /** * This is the constructor for a subsumes object * * @param superClass the super class of the object * @param subClass the sub class of the object */ SubsumesObject(String superClass, String subClass){ this.superClass = superClass; this.subClass = subClass; } /** * Method to return the super class of the object * @return String the super class */ String getSuperClass(){ return superClass; } /** * Method to return the sub class of the object * @return String the sub class */ String getSubClass(){ return subClass; } } /** * This class is used to construct an RDFObject * * @author craigb * */ class RDFObject{ String name; String[] parents; /** * Constructor for an RDFObject * * @param name the name of the sub class * @param parents of the sub class */ RDFObject(String name, String[] parents){ this.name = name; this.parents = parents; } /** * Get the name of the type to be created * * @return String the name of the type to be created */ String getName(){ return name; } /** * This method will return the array of hte parents * * @return String[] the parents */ String[] getParents(){ return parents; } }