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 <localname> 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 */