View Javadoc

1   /*
2    wsmo4j - a WSMO API and Reference Implementation
3    Copyright (c) 2004, University of Innsbruck, Institute of Computer Science
4    This library is free software; you can redistribute it and/or modify it under
5    the terms of the GNU Lesser General Public License as published by the Free
6    Software Foundation; either version 2.1 of the License, or (at your option)
7    any later version.
8    This library is distributed in the hope that it will be useful, but WITHOUT
9    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10   FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11   details.
12   You should have received a copy of the GNU Lesser General Public License along
13   with this library; if not, write to the Free Software Foundation, Inc.,
14   59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15   */
16  package org.deri.wsmo4j.io.parser.wsml;
17  
18  
19  import java.io.*;
20  import java.util.*;
21  
22  import org.deri.wsmo4j.io.parser.*;
23  import org.omwg.logicalexpression.*;
24  import org.omwg.logicalexpression.terms.Visitor;
25  import org.omwg.ontology.Axiom;
26  import org.wsmo.common.*;
27  import org.wsmo.common.exception.*;
28  import org.wsmo.factory.*;
29  import org.wsmo.wsml.ParserException;
30  import org.wsmo.wsml.compiler.analysis.*;
31  import org.wsmo.wsml.compiler.lexer.*;
32  import org.wsmo.wsml.compiler.node.*;
33  import org.wsmo.wsml.compiler.parser.Parser;
34  
35  import com.ontotext.wsmo4j.common.*;
36  import com.ontotext.wsmo4j.parser.wsml.*;
37  
38  
39  /**
40   * Accespoint for parsin LogicalExpressions (used by general wsml parser
41   * and to create objectmodels from arbitrary LE strings)
42   */
43  public class LogExprParserImpl {
44  
45      private ASTAnalysisContainer container;
46  
47      /**
48       *
49       * @param map optional set to factories to be used during parsing
50       * (PARSER_WSMO_FACTORY PARSER_LE_FACTORY PARSER_DATA_FACTORY)
51       * @param nsHolder gives available namespaces
52       */
53      public LogExprParserImpl(Map map, TopEntity nsHolder) {
54          if (map==null) map = new HashMap();
55          Object o = map.get(Factory.WSMO_FACTORY);
56          if (o == null || ! (o instanceof WsmoFactory)) {
57              o = Factory.createWsmoFactory(new HashMap <String, Object> ());
58          }
59          WsmoFactory factory = (WsmoFactory)o;
60          assert (factory != null);
61  
62          o = map.get(Factory.LE_FACTORY);
63          if (o == null || ! (o instanceof LogicalExpressionFactory)) {
64              o = Factory.createLogicalExpressionFactory(new HashMap <String, Object> ());
65          }
66          LogicalExpressionFactory leFactory = (LogicalExpressionFactory)o;
67          assert (leFactory != null);
68  
69          o = map.get(Factory.DATA_FACTORY);
70          if (o == null || ! (o instanceof DataFactory)) {
71              o = Factory.createDataFactory(new HashMap <String, Object> ());
72          }
73          DataFactory dataFactory = (DataFactory)o;
74          assert (dataFactory != null);
75  
76          container = new ASTAnalysisContainer();
77  
78          HashMap <String, String> ns = new HashMap <String, String>();
79          if (nsHolder!=null){
80              if (nsHolder.getDefaultNamespace()!=null &&
81                      nsHolder.getDefaultNamespace().getIRI()!=null){
82                  ns.put("_", nsHolder.getDefaultNamespace().getIRI().toString());
83              }
84              for (Iterator i = nsHolder.listNamespaces().iterator(); i.hasNext();){
85                  Namespace namespace = (Namespace) i.next();
86                  ns.put(namespace.getPrefix(),
87                          namespace.getIRI().toString());
88              }
89          }
90          new IdentifierAnalysis(container, factory).setNameSpaces(ns);
91          new ValueAnalysis(container, dataFactory, leFactory, factory);
92          new CompoundExpressionAnalysis(container, leFactory);
93          new VariableAnalysis(container, leFactory);
94          new AtomicExpressionAnalysis(container, factory, leFactory);
95      }
96  
97      /**
98       * This method parses a Node.
99       * @param node
100      *            SableCC Node that will be parsed, it expects a Node of the
101      *            type "PLogExpr"
102      * @return logical expression object model
103      * @throws RuntimeException in case node is not of Type PLogExpr
104      * @see org.omwg.logicalexpression.io.Parser#parse(java.lang.Object)
105      */
106     public LogicalExpression parse(Object node)
107             throws RuntimeException {
108         if (node instanceof PLogExpr) {
109             ((PLogExpr)node).apply(container);
110             return (LogicalExpression)container.getStack(LogicalExpression.class).remove(0);
111         }
112         throw new RuntimeException("WSML Parser Error: LogExprParser.parse requiers object of type " +
113                                    "org.wsmo.wsml.compiler.node.PLogExpr, found" + node.getClass());
114     }
115 
116     /**
117      * @param expr String
118      * @return logical expression object model
119      * @throws ParserException
120      * @throws InvalidModelException
121      * @see org.omwg.logicalexpression.io.Parser#parse(java.lang.String)
122      */
123     /* TODO This method looks like a good point of attack for optimization. It's eats up a lot more time for
124              * it's own computations (1709) than for it's callouts to subroutines (737) in the org.wsmo.wsml.compiler.*  packages.
125      *
126      * 100,0% - 2.446 ms - inherent 1.709 ms - 1 invocation org.deri.wsmo4j.io.parser.wsml.LogExprParserImpl.parse
127      * 15,1% - 369 ms - inherent 0 ms - 1 invocation org.wsmo.wsml.compiler.parser.Parser.<init>
128      * 6,2% - 151 ms - inherent 0 ms - 1 invocation org.wsmo.wsml.compiler.lexer.Lexer.<init>
129      * 5,9% - 143 ms - inherent 0 ms - 1 invocation org.wsmo.wsml.compiler.node.Start.apply
130      * 2,9% - 72 ms - inherent 0 ms - 1 invocation org.wsmo.wsml.compiler.parser.Parser.parse
131              * 0,0% - 0 ms - inherent 0 ms - 1 invocation org.deri.wsmo4j.io.parser.wsml.LogExprParserImpl$LogExpProcesser.<init>
132      * 0,0% - 0 ms - inherent 0 ms - 1 invocation java.io.StringReader.<init>
133      * 0,0% - 0 ms - inherent 0 ms - 1 invocation java.io.PushbackReader.<init>
134      * 0,0% - 0 ms - inherent 0 ms - 1 invocation java.util.Vector.<init>
135      * 0,0% - 0 ms - inherent 0 ms - 1 invocation java.lang.StringBuilder.<init>
136      * 0,0% - 0 ms - inherent 0 ms - 2 invocation java.lang.StringBuilder.append
137      * 0,0% - 0 ms - inherent 0 ms - 2 invocation java.lang.String.trim
138      * 0,0% - 0 ms - inherent 0 ms - 1 invocation java.lang.StringBuilder.toString
139      * 0,0% - 0 ms - inherent 0 ms - 1 invocation java.lang.String.lastIndexOf
140      * 0,0% - 0 ms - inherent 0 ms - 1 invocation java.util.Vector.firstElement
141      * 0,0% - 0 ms - inherent 0 ms - 1 invocation java.lang.String.length
142      */
143     public org.omwg.logicalexpression.LogicalExpression parse(String expr)
144             throws ParserException {
145         //System.out.println(expr.lastIndexOf(".")+"-"+(expr.length()-1));
146         if (expr.trim().lastIndexOf(".") != expr.trim().length() - 1) {
147             expr += ".";
148         }
149         
150         container.getStack(String.class).add(expr);
151         
152         expr = "ontology o987654321 axiom a987654321 definedBy \n" + expr + "  \n";
153 
154         //to avoid pushbackoverflow increase size of buffer.
155         Lexer lexer = new Lexer(new PushbackReader(new StringReader(expr),65536));
156         Parser parser = new Parser(lexer);
157         Vector axiom = new Vector();
158         Start head;
159         try {
160             head = parser.parse();
161         }
162         catch (org.wsmo.wsml.compiler.parser.ParserException pe) {
163             ParserException e = new ParserException(ParserException.NOT_VALID_PARSETREE, pe);
164             Token t = pe.getToken();
165             e.setErrorLine(t.getLine() - 1);
166             e.setErrorPos(t.getPos());
167             e.setFoundToken(t.getText());
168             try {
169                 e.setExpectedToken(pe.getMessage().split("expecting: ")[1].trim());
170             }
171             catch (IndexOutOfBoundsException iobE) {
172                 //if error message does not follow usual pattern
173                 e.setExpectedToken(pe.getMessage());
174             }
175             throw e;
176         }
177         catch (org.wsmo.wsml.compiler.lexer.LexerException le) {
178             ParserException e = new ParserException(ParserException.NOT_VALID_PARSETREE, le);
179             try {
180                 e.setErrorLine(Integer.parseInt(le.getMessage().split(",")[0].split("\\[")[1]));
181             }
182             catch (NumberFormatException nfE) {
183                 //could not find line so leave default
184             }
185             try {
186                 e.setErrorPos(Integer.parseInt(le.getMessage().split(",")[1].split("\\]")[0]));
187             }
188             catch (NumberFormatException nfE) {
189                 //could not find pos so leave default
190             }
191             throw e;
192         }
193         catch (IOException ioe) {
194             //should never happen logexp is never allone in a file
195             throw new RuntimeException(ioe);
196         }
197         try {
198             head.apply(new LogExpProcesser(
199                     axiom));
200         }
201         catch (WrappedParsingException e) {
202             if (e.getWrappedException()instanceof ParserException) {
203                 ParserException pe = (ParserException)e.getWrappedException();
204                 pe.setErrorLine(pe.getErrorLine() - 1);
205                 throw pe;
206             }
207             else if (e.getWrappedException()instanceof RuntimeException) {
208                 throw (RuntimeException)e.getWrappedException();
209             }
210             else {
211                 throw e;
212             }
213         }
214         return (LogicalExpression)axiom.firstElement();
215     }
216 
217     /*
218      * <p>Helper class for parsing logical expressions</p>
219      * @author reto.krummenacher@deri.org, holger.lausen@deri.org
220      *
221      */
222     private class LogExpProcesser
223             extends DepthFirstAdapter {
224 
225         private Vector <LogicalExpression> axioms;
226 
227         LogExpProcesser(Vector <LogicalExpression> axioms) {
228             this.axioms = axioms;
229         }
230 
231         public void inALogDefinition(ALogDefinition node) {
232             axioms.add(parse(node.getLogExpr().get(0)));
233         }
234     }
235 
236     static TopEntity copyNsHolder(TopEntity nsHolder){
237         //copy the nsHolder otherwise problems with still holding
238         //reference to some entities that do not garbage collected!
239         if (nsHolder==null){
240             return null;
241         }
242         Identifier dummyID = new UnnumberedAnonymousID(){public void accept(Visitor v){};};
243         TopEntity nsHolderCopy = new TopEntityImpl(dummyID);
244         nsHolderCopy.setDefaultNamespace(nsHolder.getDefaultNamespace());
245         Iterator i = nsHolder.listNamespaces().iterator();
246         while(i.hasNext()){
247             nsHolderCopy.addNamespace((Namespace)i.next());
248         }
249         return nsHolderCopy;
250     }
251     
252     
253     /*
254      * puts all Logical Expression Strings of a Reader on a Stack and 
255      * returns a new Reader (reading from beginning)
256      */
257     public static Reader findLogicalExpressions(Reader src, Stack allLogExp){
258         StringBuffer buffer = new StringBuffer();
259         try{
260             boolean inALineComment = false;
261             boolean inAString = false;
262             boolean inAIRI = false;
263             boolean inAComment = false;
264             boolean inALogexp = false;
265             char current = 0;
266             char previous = 0;
267             char preprevious = 0;
268             char[] r = new char[9];
269             char[] def = "definedBy".toCharArray();
270             StringBuffer logexp = new StringBuffer();
271             while(src.ready()){
272                 current = (char)src.read();
273                 if (current == 65535) break;
274                 buffer.append(current);
275                 
276                 if (!inAString && ! inAIRI && current=='/' && previous=='/'){
277                     inALineComment=true;
278                 }
279                 if (inALineComment && current=='\n'){
280                     inALineComment=false;
281                 }
282                 
283                 if (!inAString && ! inAIRI && current=='*' && previous=='/'){
284                     inAComment=true;
285                 }
286                 if (inAComment && current=='/' && previous=='*'){
287                     inAComment=false;
288                 }
289                 
290                 if (current=='"' && previous=='_'){
291                     inAIRI=true;
292                 }
293                 if (inAIRI && current=='"' && previous!='\\'){
294                     inAIRI=false;
295                 }
296                 
297                 if (current=='"' && previous!='_'  && previous!='\\'){
298                     inAString=true;
299                 }
300                 if (inAString && current=='"' && previous!='\\'){
301                     inAString=false;
302                 }
303                 
304                 r[0]=r[1];
305                 r[1]=r[2];
306                 r[2]=r[3];
307                 r[3]=r[4];
308                 r[4]=r[5];
309                 r[5]=r[6];
310                 r[6]=r[7];
311                 r[7]=r[8];
312                 r[8]=current;
313                 String str = r.toString();
314                 if (inALogexp){
315                     logexp.append(current);
316                 }
317                 
318                 if (!inAComment && !inAIRI && !inALineComment && !inAString && Arrays.equals(r, def)){
319                     inALogexp=true;
320                 }
321                 if (inALogexp && !inAComment && !inALineComment && current =='.' && previous != '\\'){
322                     allLogExp.add(logexp.toString().trim());
323                     logexp.delete(0, logexp.length());
324                 }
325                 if (inALogexp && !inAComment && !inALineComment && isAxiomOrRelationOrConceptOrInstance(r)){
326                     logexp.delete(0, logexp.length());
327                     inALogexp=false;
328                 }
329                 preprevious=previous;
330                 previous=current;
331             }
332         }catch (IOException e){
333             e.printStackTrace();
334         }
335         return new StringReader(buffer.toString());
336     }
337     
338     private static String[] words = new String[]{
339         "axiom","relation", "relationInstance",
340         "concept","instance",
341         "webService", "mediator", "ontology", "goal"};
342     
343     private static boolean isAxiomOrRelationOrConceptOrInstance(char[] c){
344         for (int i=0; i<words.length; i++){
345             boolean check=true;
346             int m=0;
347             for(int n=words[i].length()-1; n>=0 && 8-m>=0; n--){
348                 //System.out.println(words[i]+"-"+" i"+i+" n"+n);
349                 if(words[i].charAt(n)!=c[8-m++]){
350                     check=false;
351                     break;
352                 }
353             }
354             if (check) return true;
355         }
356         return false;
357     }
358 
359 }