View Javadoc

1   /*
2    wsmo4j - a WSMO API and Reference Implementation
3    Copyright (c) 2005, University of Innsbruck, Austria
4                        Ontotext Lab. / SIRMA Group
5    This library is free software; you can redistribute it and/or modify it under
6    the terms of the GNU Lesser General Public License as published by the Free
7    Software Foundation; either version 2.1 of the License, or (at your option)
8    any later version.
9    This library is distributed in the hope that it will be useful, but WITHOUT
10   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   details.
13   You should have received a copy of the GNU Lesser General Public License along
14   with this library; if not, write to the Free Software Foundation, Inc.,
15   59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16   */
17  package org.deri.wsmo4j.io.serializer.wsml;
18  
19  
20  import java.util.*;
21  
22  import org.deri.wsmo4j.io.parser.wsml.*;
23  import org.deri.wsmo4j.logicalexpression.*;
24  import org.omwg.logicalexpression.*;
25  import org.omwg.logicalexpression.terms.*;
26  import org.omwg.logicalexpression.terms.Visitor;
27  import org.omwg.ontology.*;
28  import org.wsmo.common.*;
29  import org.wsmo.factory.*;
30  import org.wsmo.wsml.*;
31  
32  import com.ontotext.wsmo4j.common.CharUtil;
33  
34  
35  /**
36   * Concrete Visitor class. For each visited term, a String is built.
37   * @see org.omwg.logicalexpression.terms.Visitor
38   */
39  public class VisitorSerializeWSMLTerms
40          implements Visitor {
41      
42      private Map atoms2ConstructedTerms;
43      
44      private Vector stack;
45  
46      private Namespace[] nsHolder;
47      
48      private CharUtil util;
49  
50      /**
51       * @param nsC TopEntity
52       * @see org.deri.wsmo4j.io.serializer.wsml.VisitorSerializeWSML#VisitorSerializeWSML(TopEntity)
53       */
54      public VisitorSerializeWSMLTerms(TopEntity nsC) {
55          
56          if (nsC != null) {
57              Set <Namespace> nsBuffer = new HashSet <Namespace> (nsC.listNamespaces());
58              if (nsC.getDefaultNamespace() != null) {
59                  nsBuffer.add(nsC.getDefaultNamespace());
60              }
61              if (nsBuffer.size() > 0) {
62                  nsHolder = nsBuffer.toArray(new Namespace[nsBuffer.size()]);
63                  Arrays.sort(nsHolder, new Comparator <Object>() {
64                      public int compare(Object o1, Object o2) {
65                          String ns1IRI = ((Namespace)o1).getIRI().toString();
66                          String ns2IRI = ((Namespace)o2).getIRI().toString();
67                          return ns1IRI.compareTo(ns2IRI);
68                      }
69                  });
70              }
71          }
72          stack = new Vector();
73          util = new CharUtil();
74      }
75      
76      public void setAtoms2ConstructedTerms(Map atoms2ConstructedTerms){
77          this.atoms2ConstructedTerms = atoms2ConstructedTerms;
78      }
79  
80      /**
81       * Builds a String representing the ConstructedTerm and adds it to a vector.
82       * @param t ConstructedTerm to be serialized
83               * @see org.omwg.logicalexpression.terms.Visitor#visitConstructedTerm(org.omwg.logicalexpression.terms.ConstructedTerm)
84       */
85      public void visitConstructedTerm(ConstructedTerm t) {
86          String iri = t.getFunctionSymbol().toString();
87          String s = "";
88          t.getFunctionSymbol().accept(this);
89          if (ConstantTransformer.getInstance().isInfix(iri)) {
90              String operator = (String)stack.remove(stack.size() - 1);
91              t.getParameter(0).accept(this);
92              t.getParameter(1).accept(this);
93              s = "("+ (String)stack.remove(stack.size() - 2)
94                  + operator + (String)stack.remove(stack.size() - 1) + ")";
95          }
96          else {
97              s = s + (String)stack.remove(stack.size() - 1);
98              int nbParams = t.getArity();
99              if (nbParams > 0) {
100                 s = s + "(";
101                 for (int i = 0; i < nbParams; i++) {
102                     t.getParameter(i).accept(this);
103                     s = s + (String)stack.remove(stack.size() - 1);
104                     if (i + 1 < nbParams) {
105                         s = s + ",";
106                     }
107                 }
108                 s = s + ")";
109             }
110         }
111         stack.add(s);
112     }
113 
114     /**
115      * Builds a String representing the Variable and adds it to a vector.
116      * @param t Variable to be serialized
117      * @see org.omwg.logicalexpression.terms.Visitor#visitVariable(org.omwg.logicalexpression.terms.Variable)
118      */
119     public void visitVariable(Variable t) {
120         if (t instanceof TempVariable){
121             Term term = (Term)atoms2ConstructedTerms.get(t);
122             if (term!=null) term.accept(this);
123             else stack.add(t.toString()+"<NonResolvableDependencyToBuiltInAtom>");
124             return;
125         }
126         stack.add(Constants.VARIABLE_DEL + t.getName());
127     }
128 
129     public void visitComplexDataValue(ComplexDataValue value) {
130         String s = "";
131         value.getType().getIRI().accept(this);
132         s = (String)stack.remove(stack.size() - 1);
133         int nbParams = value.getArity();
134         s = s + "(";
135         for (byte i = 0; i < nbParams; i++) {
136             ((Term)value.getArgumentValue(i)).accept(this);
137             s = s + (String)stack.remove(stack.size() - 1);
138             if (i + 1 < nbParams) {
139                 s = s + ",";
140             }
141         }
142         stack.add(s + ")");
143     }
144 
145     public void visitSimpleDataValue(SimpleDataValue value) {
146         if (value.getType().getIRI().toString().equals(WsmlDataType.WSML_STRING)) {
147             //escape \ and "
148             String content = (String)value.getValue();
149             content = content.replaceAll("\\\\", "\\\\\\\\");
150             content = content.replaceAll("\"", "\\\\\"");
151             stack.add(Constants.STRING_DEL_START + content + Constants.STRING_DEL_END);
152         }
153         else { // WSML_DECIMAL || WSML_INTEGER
154             stack.add("" + value.getValue());
155         }
156         String iri = value.getType().getIRI().toString();
157     }
158 
159     /**
160      * Builds a String representing the Unnumbered Anonymous ID
161      * and adds it to a vector.
162      * @param t UnNBAnonymousID to be serialized
163      * @see org.omwg.logicalexpression.terms.Visitor#visitAnonymousID(org.omwg.logicalexpression.terms.UnNbAnonymousID)
164      */
165     public void visitUnnumberedID(UnnumberedAnonymousID t) {
166         stack.add(Constants.ANONYMOUS_ID_NOTATION);
167     }
168 
169     /**
170      * Builds a String representing the Numbered Anonymous ID
171      * and adds it to a vector.
172      * @param t NbAnonymousID to be serialized
173      * @see org.omwg.logicalexpression.terms.Visitor#visitNbAnonymousID(org.omwg.logicalexpression.terms.NbAnonymousID)
174      */
175     public void visitNumberedID(NumberedAnonymousID t) {
176         stack.add(Constants.ANONYMOUS_ID_NOTATION + t.getNumber());
177     }
178 
179     /**
180      * Builds a String representing the IRI and adds it to a vector.
181      * @param t IRI to be serialized
182      * @see org.omwg.logicalexpression.terms.Visitor#visitIRI(org.omwg.logicalexpression.terms.IRI)
183      */
184     public void visitIRI(IRI t) {
185         String iri = t.toString();
186         String notion = ConstantTransformer.getInstance().findNotation(iri);
187         if (notion != null) {
188             stack.add(notion);
189             return;
190         }
191         stack.add(resolveIRI(iri));
192     }
193     
194     String resolveIRI(String iri) {
195 
196         Parser p = Factory.createParser(null);
197         if (nsHolder == null) { // no or empty namespace holder spacified
198             return Constants.IRI_DEL_START + iri + Constants.IRI_DEL_END;
199         }
200         
201         for(int i = nsHolder.length-1; i >= 0; i--) {
202             Namespace ns = nsHolder[i];
203             if (iri.startsWith(ns.getIRI().toString())) {
204                 
205                 // the namespace consumes the whole iri ?
206                 if (iri.length() == ns.getIRI().toString().length()) {
207                     continue;
208                 }
209                 // the new sQName would contain invalid characters
210                 if (checkChars(iri.substring(ns.getIRI().toString().length()))) {
211                     continue;
212                 }
213                 boolean isDefaultNSMatch = ns.getPrefix() == null 
214                                            || ns.getPrefix().equals("")
215                                            || ns.getPrefix().equals("_");
216                 // the raw sqname which might contain characters to be escaped
217                 String sqname = (isDefaultNSMatch) ? 
218                         iri.substring(ns.getIRI().toString().length()) // --> default namespace
219                         : (ns.getPrefix() + Constants.SQNAME_DEL // --> other namespace
220                             + iri.substring(ns.getIRI().toString().length()));
221                 
222                 sqname = escapeNonSQNameSymbols(sqname);
223                 
224                 if (isDefaultNSMatch // avoid using reserved terms as identifiers
225                         && p.listKeywords().contains(sqname)) {
226                     continue;
227                 }
228                 return sqname;
229             }
230         }
231         return Constants.IRI_DEL_START + iri + Constants.IRI_DEL_END;
232     }
233     
234     public static String escapeNonSQNameSymbols(String sqname) {
235         StringBuffer buf = new StringBuffer(sqname.length());
236         // escape all '.' and '-' symbols by '\'
237         for (int i = 0; i < sqname.length(); i++) {
238             if (sqname.charAt(i) == '-' || sqname.charAt(i) == '.') {
239                 buf.append('\\');
240             }
241             buf.append(sqname.charAt(i));
242         }
243         return buf.toString();
244     }
245 
246     /**
247      * All serialized elements are added to a vector. This method removes the
248      * first serialized object from this vector and shifts any subsequent
249      * objects to the left (subtracts one from their indices).
250      * @return the serialized String object that is the first element in this vector
251      */
252     public String getSerializedObject() {
253         return stack.remove(0).toString();
254     }
255     
256     /**
257      * Checks if the given string can NOT be encoded as a sQName
258      * @param iri
259      * @return true if the string contains symbols which can not be encoded in sQName
260      */
261     private boolean checkChars(String iri) { 
262     	for (int i=0; i<iri.length();i++) {
263     		char chr = iri.charAt(i);
264     		if (!util.isAlpha(chr) && !util.isDigit(chr) && !(chr == '_')) {
265     			if (!util.isCombiningChar(chr) && !util.isExtender(chr))
266     				return true;
267     		}
268     	}
269     	return false;
270     }
271 }
272 
273 /*
274  * $Log$
275  * Revision 1.22  2007/04/02 12:13:23  morcen
276  * Generics support added to wsmo-api, wsmo4j and wsmo-test
277  *
278  * Revision 1.21  2007/01/08 16:04:58  alex_simov
279  * no message
280  *
281  * Revision 1.20  2007/01/03 09:25:59  alex_simov
282  * IRI serializing bugfix: longer namespace IRIs are preferred when trying to
283  * transform full IRIs into sQNames
284  *
285  * Revision 1.19  2006/12/05 13:45:44  alex_simov
286  * bugfix: IRI serialization produced invalid SQNames
287  *
288  * Revision 1.18  2006/11/17 16:40:14  nathaliest
289  * fixed wsml serializer to not serialize sqnames with unallowed characters and added util class to check characters
290  *
291  * Revision 1.17  2006/10/31 15:50:26  vassil_momtchev
292  * when IRI is equal to namespace iri, do not use sqnames, but full IRI
293  *
294  * Revision 1.16  2006/05/04 14:17:09  alex_simov
295  * bugfix: invalid sQName parsing/serializing - illegal symbols not escaped
296  *
297  */