View Javadoc

1   /*
2    wsmo4j - a WSMO API and Reference Implementation
3    
4    Copyright (c) 2004-2005, OntoText Lab. / SIRMA
5                             University of Innsbruck, Austria
6    
7    This library is free software; you can redistribute it and/or modify it under
8    the terms of the GNU Lesser General Public License as published by the Free
9    Software Foundation; either version 2.1 of the License, or (at your option)
10   any later version.
11   This library is distributed in the hope that it will be useful, but WITHOUT
12   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13   FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14   details.
15   You should have received a copy of the GNU Lesser General Public License along
16   with this library; if not, write to the Free Software Foundation, Inc.,
17   59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18   */
19  package com.ontotext.wsmo4j.common;
20  
21  /**
22   * <p>Title: WSMO4J</p>
23   * <p>Description: WSMO API and a Reference Implementation</p>
24   * <p>Copyright:  Copyright (c) 2004-2005</p>
25   * <p>Company: OntoText Lab. / SIRMA </p>
26   * @author not attributable
27   * @version 1.0
28   *
29   */
30  
31  import java.io.Serializable;
32  
33  import org.omwg.logicalexpression.terms.Visitor;
34  import org.wsmo.common.IRI;
35  
36  public class IRIImpl implements IRI, Serializable {
37  
38  	private CharUtil util = new CharUtil();
39  	
40      private static final long serialVersionUID = 1L;
41      
42      /**
43       * actual string uri.
44       */
45      private String iri;
46      
47      /**
48       * indicating position in IRI string of namespace / localname split
49       */
50      private int seperator = -1;
51  
52      /**
53       * Creates IRI object, does heuristics for namespace/localname split
54       * @param iri String representation of IRI
55       * @throws IllegalArgumentException in case no legal IRI is supplied
56       */
57      public IRIImpl(String iri) throws IllegalArgumentException {
58          if (iri == null || iri.length() == 0) {
59              throw new IllegalArgumentException("IRI can not be emtpy");
60          }
61          checkAbsoluteIRI(iri);
62          seperator = getStartLocalName(iri);
63          this.iri = iri;
64      }
65      
66      /**
67       * Creates IRI with the knowledge of sepration between namespace and localname.
68       * 
69       * @param ns
70       *            String containing the part of the IRI that is the Namespace
71       * @param ln
72       *            String containing the part of the IRI that is the localname
73       * @throws IllegalArgumentExpression
74       *             <p>
75       *             in case the IRI is not legal according to the IRI spec.
76       *             </p>
77       */
78      public IRIImpl(String ns, String ln) throws IllegalArgumentException {
79          if (ns == null || ln == null || ns.length() == 0 || ln.length() == 0) {
80              throw new IllegalArgumentException(
81                      "both local name and namespace may not be empty");
82          }
83          if (!isLegalLocalName(ln)) {
84              throw new IllegalArgumentException("local name (" + ln
85                      + ") is not valid");
86          }
87          checkAbsoluteIRI(ns+ln);
88          seperator = ns.length();
89      }
90  
91      /**
92       * retrieve the &lt;localname&gt; part of the iri.
93       * 
94       * @return a localname as string
95       */
96      public String getLocalName() {
97          
98          int pos = iri.lastIndexOf('#');
99          
100         if (pos < 0) {
101             pos = iri.lastIndexOf('/');
102         }
103         
104         if (pos < 0) {
105             return iri;
106         }
107         return iri.substring(pos + 1);
108     }
109     
110 
111     /**
112      * retrieve the namespace part of iri
113      * @return the namespace or null in case the namespace is not known.
114      */
115     public String getNamespace() {
116         if (seperator == -1)
117             return null;
118         return iri.substring(0, seperator);
119     }
120     
121     public String toString() {
122         return iri;
123     }
124     
125     /**
126      * @see org.omwg.logicalexpression.terms.Term#accept(org.omwg.logicalexpression.terms.Visitor)
127      */
128 	public void accept(Visitor v) {
129         v.visitIRI(this);
130     }
131     
132     /**
133      * equality check.
134      * 
135      * @param object
136      *            to compare with
137      * @return true if object is lexical an identical IRI
138      * @see Object#equals(java.lang.Object)
139      */
140     public boolean equals(Object object) {
141         if (object == this) {
142             return true; // instance match
143         }
144         if (object == null
145                 || false == object instanceof IRI) {
146             return false;
147         }
148         return 0 == iri.compareTo(object.toString());
149     }
150     
151     public int hashCode() {
152         return iri.hashCode();
153     }
154     
155     private void checkAbsoluteIRI(String iri) throws IllegalArgumentException{
156         //scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
157         int schemeEnd = iri.indexOf(':');
158         if (schemeEnd<1){
159             throw new IllegalArgumentException("Only absolute IRIs allowed: "+iri);
160         }
161         if (!util.isAlpha(iri.charAt(0))){
162             throw new IllegalArgumentException("IRI scheme must start with alpha nummeric character: "+iri);
163         }
164         for (int i=1; i<schemeEnd;i++){
165             if (!isScheme(iri.charAt(i))){
166                 throw new IllegalArgumentException("Illegal Character in IRI scheme: "+ iri.charAt(i) +"("+iri+")");
167             }
168         }
169         //do not check scheme specific stuff (can't know all custom schemes).
170 
171     }
172     
173     /**
174      * Get the index that points to the position in the IRI where the localname
175      * starts. If this index is -1, no valid localname or no namespace is found.
176      * 
177      * @param iri
178      *            String representing the full IRI
179      * @return index that points to the position in the IRI where the localname
180      *         starts or -1, if namespace or localname are not found
181      * @see #isLegalLocalName(String)
182      */
183     private int getStartLocalName(String iri) {
184         int i = iri.length() - 1;
185         while (i > 0 && isLegalLocalNameChar(iri.charAt(i))) {
186             i--;
187         }
188         // no namespace found so -1
189         if (i == 0) {
190             i = -1;
191         }
192         // only '_' and Letter are allowed as first char of localname
193         else {
194             while (i < iri.length()
195                     && !(iri.charAt(i) == '_' || util.isLetter(iri.charAt(i)))) {
196                 i++;
197             }
198         }
199         // no local name found so -1
200         if (i == iri.length()) {
201             i = -1;
202         }
203         return i;
204     }
205 
206     private boolean isScheme(char chr){
207         return util.isAlpha(chr) || util.isDigit(chr) ||
208                 chr == '-' || chr == '+' || chr == '.';
209     }
210 
211     /**
212      * This method checks if a given character is a legal character for a
213      * localname. It must be either a valid letter, a digit or '_'.
214      * 
215      * @param chr
216      *            character
217      * @return <code>true</code> if chr is a letter, a numeral or '_', or
218      *         <code>false</code> otherwise
219      * @see #isLetter(char)
220      */
221     private boolean isLegalLocalNameChar(char chr) {
222         // letter || digit
223         if (util.isLetter(chr) || util.isDigit(chr))
224             return true;
225         if (chr == '_')
226             return true;
227         if (util.isCombiningChar(chr) || util.isExtender(chr))
228         	return true;
229         return false;
230     }
231     
232     /**
233      * This method checks if a given string is a legal localname. This is the
234      * case if every character of the string is either a valid letter, a digit
235      * or '_'. Also, only '_' and Letter are allowed as first char of a
236      * localname.
237      * 
238      * @param ln
239      *            String representing the localname part of an IRI
240      * @return <code>true</code> if ln is a legal localname;
241      *         <code>false</code> otherwise
242      * @see #isLegalLocalNameChar(char)
243      */
244     private boolean isLegalLocalName(String ln) {
245         boolean validLocalName = true;
246         for (int i = 0; i < ln.length(); i++) {
247             if (!isLegalLocalNameChar(ln.charAt(i))) {
248                 validLocalName = false;
249             }
250         }
251         return (validLocalName && (ln.charAt(0) == '_' || util.isLetter(ln.charAt(0))));
252     }
253     
254 }
255 
256 /*
257 * $Log$
258 * Revision 1.10  2006/11/17 16:40:14  nathaliest
259 * fixed wsml serializer to not serialize sqnames with unallowed characters and added util class to check characters
260 *
261 * Revision 1.9  2005/11/04 06:14:26  holgerlausen
262 * fixed unit tests relying on relative iris
263 *
264 * Revision 1.8  2005/11/03 18:15:34  holgerlausen
265 * included check in IRIImpl for absolute IRI
266 *
267 * Revision 1.7  2005/10/17 15:10:00  marin_dimitrov
268 * getNameSpace --> getNamespace
269 *
270 * Revision 1.6  2005/09/16 14:02:44  alex_simov
271 * Identifier.asString() removed, use Object.toString() instead
272 * (Implementations MUST override toString())
273 *
274 * Revision 1.5  2005/09/06 18:25:33  holgerlausen
275 * implemented namespace heurisitcs for IRI and additional type checks
276 *
277 * Revision 1.4  2005/09/02 13:32:44  ohamano
278 * move logicalexpression packages from ext to core
279 * move tests from logicalexpression.test to test module
280 *
281 * Revision 1.3  2005/09/02 09:43:32  ohamano
282 * integrate wsmo-api and le-api on api and reference implementation level; full parser, serializer and validator integration will be next step
283 *
284 * Revision 1.2  2005/06/22 14:20:15  alex_simov
285 * Copyright header added/updated
286 *
287 * Revision 1.1  2005/06/01 12:00:32  marin_dimitrov
288 * v0.4.0
289 *
290 * Revision 1.2  2005/05/30 15:06:37  alex
291 * toString() delegates to asString()
292 *
293 * Revision 1.1  2005/05/11 12:24:05  alex
294 * initial commit
295 *
296 */