You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by cl...@apache.org on 2014/10/15 20:50:35 UTC
[03/51] [partial] reverting accidentally deleted files
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/AbsIRIFactoryImpl.java
----------------------------------------------------------------------
diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/AbsIRIFactoryImpl.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/AbsIRIFactoryImpl.java
new file mode 100644
index 0000000..4a048bb
--- /dev/null
+++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/AbsIRIFactoryImpl.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.iri.impl;
+
+
+import org.apache.jena.iri.IRI ;
+import org.apache.jena.iri.IRIException ;
+import org.apache.jena.iri.IRIFactoryI ;
+
+abstract public class AbsIRIFactoryImpl implements IRIFactoryI {
+
+ protected abstract IRIFactoryImpl getFactory();
+ public AbsIRIFactoryImpl() {
+ }
+
+// public IRI create(String s) {
+// return create(s);
+// }
+
+ @Override
+ public IRI create(String s) {
+ return create(new IRIImpl(getFactory(),s )
+// ,
+// throwEx?AbsIRIImpl.ALL_EXCEPTIONS:
+// AbsIRIImpl.NO_EXCEPTIONS)
+ );
+ }
+
+ //@Override
+ @Override
+ public IRI construct(String s) throws IRIException {
+ return throwAnyErrors(create(s));
+ }
+
+ //@Override
+ @Override
+ public IRI construct(IRI i) throws IRIException {
+ return throwAnyErrors(create(i));
+
+//
+// try {
+// return create(i,true);
+// } catch (Violation e) {
+// throw new IRIImplException(e);
+// }
+ }
+ protected IRI throwAnyErrors(IRI rslt) throws IRIException {
+ if (rslt.hasViolation(false)) {
+ throw new IRIImplException(rslt.violations(false).next());
+// Iterator it = rslt.exceptions();
+// while (it.hasNext()){
+// Violation v = (Violation)it.next();
+// if (v.isError())
+// throw new IRIImplException(v);
+// }
+ }
+ return rslt;
+ }
+// public IRI create(IRI i) {
+// return create(i);
+// }
+ @Override
+ abstract public IRI create(IRI i);
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/AbsIRIImpl.java
----------------------------------------------------------------------
diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/AbsIRIImpl.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/AbsIRIImpl.java
new file mode 100644
index 0000000..fec96ef
--- /dev/null
+++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/AbsIRIImpl.java
@@ -0,0 +1,787 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.iri.impl;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import java.net.IDN;
+
+import org.apache.jena.iri.* ;
+/*
+import com.vgrs.xcode.idna.Idna;
+import com.vgrs.xcode.idna.Nameprep;
+import com.vgrs.xcode.idna.Punycode;
+import com.vgrs.xcode.util.XcodeException;
+*/
+abstract public class AbsIRIImpl extends IRI implements
+ ViolationCodes, IRIComponents {
+
+ private static final int defaultRelative = ABSOLUTE | SAMEDOCUMENT | CHILD
+ | PARENT | GRANDPARENT;
+
+ static String removeDotSegments(String path) {
+ // 5.2.4 step 1.
+ int inputBufferStart = 0;
+ int inputBufferEnd = path.length();
+ StringBuffer output = new StringBuffer();
+ // 5.2.4 step 2.
+ while (inputBufferStart < inputBufferEnd) {
+ String in = path.substring(inputBufferStart);
+ // 5.2.4 step 2A
+ if (in.startsWith("./")) {
+ inputBufferStart += 2;
+ continue;
+ }
+ if (in.startsWith("../")) {
+ inputBufferStart += 3;
+ continue;
+ }
+ // 5.2.4 2 B.
+ if (in.startsWith("/./")) {
+ inputBufferStart += 2;
+ continue;
+ }
+ if (in.equals("/.")) {
+ in = "/"; // don't continue, process below.
+ inputBufferStart += 2; // force end of loop
+ }
+ // 5.2.4 2 C.
+ if (in.startsWith("/../")) {
+ inputBufferStart += 3;
+ removeLastSeqment(output);
+ continue;
+ }
+ if (in.equals("/..")) {
+ in = "/"; // don't continue, process below.
+ inputBufferStart += 3; // force end of loop
+ removeLastSeqment(output);
+ }
+ // 5.2.4 2 D.
+ if (in.equals(".")) {
+ inputBufferStart += 1;
+ continue;
+ }
+ if (in.equals("..")) {
+ inputBufferStart += 2;
+ continue;
+ }
+ // 5.2.4 2 E.
+ int nextSlash = in.indexOf('/', 1);
+ if (nextSlash == -1)
+ nextSlash = in.length();
+ inputBufferStart += nextSlash;
+ output.append(in.substring(0, nextSlash));
+ }
+ // 5.2.4 3
+ return output.toString();
+ }
+
+ private static void removeLastSeqment(StringBuffer output) {
+ int ix = output.length();
+ while (ix > 0) {
+ ix--;
+ if (output.charAt(ix) == '/')
+ break;
+ }
+ output.setLength(ix);
+ }
+
+ private long foundExceptionMask;
+
+ long allErrors;
+
+ abstract long errors(int field);
+
+ abstract SchemeSpecificPart getSchemeSpec();
+ abstract Exception getIDNAException();
+
+ // void throwExceptions(IRIFactoryImpl f, boolean includeRelative) {
+ // long mask = f.exceptions;
+ // if (!includeRelative)
+ // mask &= ~(1l << RELATIVE_URI);
+ // if (hasExceptionMask(mask)) {
+ // throw (IRIImplUncheckedException) exceptionsMask(mask).next();
+ // }
+ // }
+
+ boolean hasExceptionMask(long mask) {
+ return (allErrors & mask) != 0;
+ }
+
+ private ArrayList<Violation> foundExceptions;
+
+ protected String path;
+/*
+ static private Idna idna;
+ static {
+ try {
+ idna = new Idna(new Punycode(), new Nameprep());
+ } catch (XcodeException e) {
+ System.err.println("Internal error in IDN setup");
+ e.printStackTrace();
+ }
+ }
+*/
+ static final private char hex[] = "0123456789ABCDEF".toCharArray();
+
+ static final Iterator<Violation> nullIterator = new ArrayList<Violation>(0).iterator();
+
+ protected static final int NO_EXCEPTIONS = 1;
+
+ protected static final int ALL_EXCEPTIONS = 2;
+
+ protected static final int NOT_RELATIVE_EXCEPTIONS = 3;
+
+ protected static final int PATH_INDEX = Parser.invFields[PATH];
+
+ public AbsIRIImpl() {
+ super();
+ }
+
+ Iterator<Violation> exceptionsMask(final long mask) {
+ createExceptions(mask);
+ return foundExceptions == null ? nullIterator :
+ new Iterator<Violation>() {
+ private Iterator<Violation> underlying = foundExceptions.iterator();
+
+ private Violation next;
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (next==null) {
+ while (underlying.hasNext()) {
+ next = underlying.next();
+ if (((1l << (next).getViolationCode())
+ & mask) != 0)
+ return true;
+ }
+ next = null;
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public Violation next() {
+ if (hasNext()) {
+ Violation rslt = next;
+ next = null;
+ return rslt;
+ }
+ throw new NoSuchElementException();
+ }
+
+ };
+ }
+
+ private void createExceptions(long m) {
+ m &= ~foundExceptionMask;
+ if ((allErrors & m) != 0) {
+ if (foundExceptions == null) {
+ foundExceptions = new ArrayList<>();
+ }
+ for (int i = 0; i < Parser.fields.length; i++) {
+ int f = Parser.fields[i];
+ if ((errors(f) & m) != 0) {
+ for (int e = 0; e < 64; e++)
+ if (((1l << e) & m & errors(f)) != 0) {
+ foundExceptions.add(new ViolationImpl(this, f, e));
+ }
+
+ }
+ }
+
+ }
+ foundExceptionMask |= m;
+ }
+
+ @Override
+ public boolean isAbsolute() {
+ return has(SCHEME);
+ }
+
+ abstract boolean has(int component);
+
+ @Override
+ public boolean isRelative() {
+ return !has(SCHEME);
+ }
+
+ /*
+ * public boolean isRDFURIReference() { return !hasException(RDF); }
+ *
+ * public boolean isIRI() { return !hasException(IRI); }
+ *
+ * public boolean isURIinASCII() { return !hasException(URI); }
+ */
+ // public boolean isVeryBad() {
+ // return false;
+ // }
+ // public boolean isXSanyURI() {
+ // return !hasException(XMLSchema);
+ // }
+ /*
+ public boolean hasException(int conformance) {
+ return hasExceptionMask(getFactory().recsToMask(conformance));
+ }
+
+ public Iterator exceptions(int conformance) {
+ return exceptionsMask(getFactory().recsToMask(conformance));
+ }
+ */
+
+ @Override
+ public boolean hasViolation(boolean includeWarnings) {
+ return hasExceptionMask(getSchemeSpec().getMask(includeWarnings));
+ }
+
+ @Override
+ public Iterator<Violation> violations(boolean includeWarnings) {
+ return exceptionsMask(getSchemeSpec().getMask(includeWarnings));
+ }
+
+ @Override
+ public URL toURL() throws MalformedURLException {
+ return new URL(toASCIIString());
+ }
+
+ // TODO ToAsciiMask
+ static long ToAsciiMask =
+ ~0l;
+ /*
+ (1l << LTR_CHAR) | (1l << ILLEGAL_CHAR)
+ | (1l << IRI_CHAR) | (1l << UNWISE_CHAR) | (1l << WHITESPACE)
+ | (1l << NOT_XML_SCHEMA_WHITESPACE) | (1l << NON_XML_CHARACTER)
+ | (1l << DOUBLE_DASH_IN_REG_NAME);
+*/
+ @Override
+ public String toASCIIString() throws MalformedURLException {
+ if (hasExceptionMask(ToAsciiMask)) {
+ return createASCIIString();
+ }
+ return toString();
+ }
+
+ private String createASCIIString() throws MalformedURLException {
+ StringBuffer asciiString = new StringBuffer();
+
+ if (has(SCHEME)) {
+ toAscii(asciiString, getScheme(), errors(SCHEME));
+ asciiString.append(':');
+ }
+ if (has(AUTHORITY)) {
+ asciiString.append("//");
+ if (has(USER)) {
+ toAscii(asciiString, getRawUserinfo(), errors(USER));
+ asciiString.append('@');
+ }
+
+ String host = getRawHost();
+ regNameToAscii(asciiString,host);
+ if (has(PORT)) {
+ asciiString.append(':');
+ toAscii(asciiString, get(PORT), errors(USER));
+ }
+ }
+ toAscii(asciiString, getRawPath(), errors(PATH));
+ if (has(QUERY)) {
+ asciiString.append('?');
+ toAscii(asciiString, getRawQuery(), errors(QUERY));
+ }
+ if (has(FRAGMENT)) {
+ asciiString.append('#');
+ toAscii(asciiString, getRawFragment(), errors(FRAGMENT));
+ }
+ return asciiString.toString();
+ }
+
+ private void regNameToAscii(StringBuffer asciiString, String host)
+ throws MalformedURLException {
+ if ((errors(HOST) & ToAsciiMask) == 0) {
+ asciiString.append(host);
+ return;
+ }
+
+ asciiString.append(domainToAscii(host));
+
+ }
+
+ static CharSequence domainToAscii(String host) throws MalformedIDNException {
+
+ try {
+ return IDNP.toASCII(host, IDN.USE_STD3_ASCII_RULES|IDN.ALLOW_UNASSIGNED);
+ } catch (Exception e) {
+ throw new MalformedIDNException(e);
+ }
+ /*
+ int u[] = new int[host.length()];
+ for (int i = 0; i < host.length(); i++)
+ u[i] = host.charAt(i);
+
+ try {
+ return idna.domainToAscii(u);
+ } catch (XcodeException e) {
+ throw new MalformedIDNException(e);
+ }
+ */
+ }
+
+ private void toAscii(StringBuffer asciiString, String field, long errs) {
+ if ((errs & ToAsciiMask) == 0) {
+ asciiString.append(field);
+ return;
+ }
+ // 3.1 RFC 3987
+ // Step 1c
+
+ // nothing
+
+ // Step 2a
+ /*
+ * Step 2. For each character in 'ucschar' or 'iprivate', apply steps
+ * 2.1 through 2.3 below.
+ *
+ * We interpret this as any charcater above 127, below 32 and the unwise
+ * chars
+ *
+ * Systems accepting IRIs MAY also deal with the printable characters in
+ * US-ASCII that are not allowed in URIs, namely "<", ">", '"', space,
+ * "{", "}", "|", "\", "^", and "`", in step 2 above.
+ */
+ for (int i = 0; i < field.length(); i++) {
+ // TODO Java 1.4/1.5 issue
+ int ch = field.charAt(i);
+ if (ch > 127 || "<>\" {}|\\^`".indexOf(ch) != -1 || ch < 32) {
+ // 2.1
+ byte b[];
+ try {
+ b = field.substring(i, i + 1).getBytes("utf-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException("Impossible - utf-8 unsupported");
+ }
+ // 2.2, 2.3
+ for ( byte aB : b )
+ {
+ char buf[] = { '%', hex[( aB & ( 255 & ~15 ) ) >> 4], hex[aB & 15] };
+
+ asciiString.append( buf );
+ }
+ } else {
+ asciiString.append(new char[] { (char) ch });
+ }
+ }
+ }
+
+/*
+ * Subroutine for relativize.
+ *
+ * Relativizing path components is somewhat tricky.
+ * The code is in the method PathRelative.check
+ * which is invoked from relativizePaths
+ *
+ * There are only three static stateless objects of this class,
+ * each of which checks for a particular rule.
+ *
+ * The child object behaves slightly differently,
+ * with a helper method overridden, and one line of
+ * code specific to that object only.
+ *
+ */
+
+ static private final PathRelativize
+ child = new PathRelativize(CHILD, CHILD | PARENT | GRANDPARENT,
+ "."){
+ @Override
+ String descendentMatch(String descendent) {
+ return maybeDotSlash( descendent);
+ }
+ },
+ parent = new PathRelativize(PARENT, PARENT | GRANDPARENT,
+ ".."),
+ grandparent = new PathRelativize(GRANDPARENT, GRANDPARENT,
+ "../..");
+
+ /**
+ *
+ * @param in The path from this IRI
+ * @param out If successful, out[0] contains the answer
+ * @param flags Currently applicable rules
+ * @param rel The path to make relative
+ * @return True if the paths were relativized.
+ */
+ private boolean relativizePaths(String in, String[] out, int flags, String rel) {
+ if (child.check(in, out, flags, rel))
+ return true;
+ if (parent.check(out[0], out, flags, rel))
+ return true;
+ return grandparent.check(out[0], out, flags, rel);
+ }
+
+ static class PathRelativize {
+ final private int flag;
+ final private int allFlags;
+ final private String replacement;
+ /**
+ *
+ * @param flag If this flag is not present then this rule does not apply.
+ * @param allFlags If none of these flags are present then this rule and subsequence rules do not apply.
+ * @param replacement If there is a match, then use this as the relative path
+ */
+ PathRelativize(int flag, int allFlags, String replacement) {
+ this.flag = flag;
+ this.replacement = replacement;
+ this.allFlags = allFlags;
+ }
+ /**
+ * Return true if the rule applied.
+ * The result of the rule is returned in out[0]
+ * Return false if the rule did not apply.
+ * The input for the next rule is in out[0]
+ * @param in Absolute path to use in match
+ * @param out Result, as above.
+ * @param flags controlling rule applicability
+ * @param rel Relative path to use in match
+ * @return
+ */
+ boolean check(String in, String out[], int flags, String rel) {
+ out[0] = null;
+ if (in==null)
+ return false;
+ if ((flags & allFlags) == 0)
+ return false;
+ int ix = in.lastIndexOf('/');
+ if (ix==-1)
+ return false;
+ if (ix==0 && (flags & ABSOLUTE)!=0 && flag != CHILD)
+ return false;
+ in = in.substring(0,ix+1);
+ out[0] = in.substring(0,ix);
+ if ((flags & flag) == 0)
+ return false;
+ if (!rel.startsWith(in))
+ return false;
+ if (rel.length() == ix+1) {
+ out[0] = replacement;
+ return true;
+ }
+ out[0] = descendentMatch(rel.substring(ix+1));
+ return true;
+ }
+
+ String descendentMatch(String descendent) {
+ return replacement + "/" + descendent;
+ }
+
+ }
+
+
+ @Override
+ public IRI relativize(String abs, int flags) {
+ return relativize(new IRIImpl(getFactory(), abs), flags);
+ }
+
+ @Override
+ public IRI relativize(String abs) {
+ return relativize(abs, defaultRelative);
+ }
+
+ @Override
+ public IRI relativize(IRI abs) {
+ return relativize(abs, defaultRelative);
+ }
+ /*
+ * public String relativize(String abs, int flags) { return
+ * relativize(factory.create(abs),abs,flags); }
+ */
+ @Override
+ public IRI relativize(IRI abs, int flags) {
+ String rslt = relativize(abs, null, flags);
+ return rslt == null ? abs : getFactory().create(rslt);
+ }
+ /**
+ *
+ * @param r
+ * @param def
+ * Default result if can't make this relative.
+ * @param flags
+ */
+ private String relativize(IRI r, String def, int flags) {
+ if (!has(AUTHORITY)) // we could use the new rules for relative URIs for rootless, but I don't like them
+ return def;
+ if (!((AbsIRIImpl)r).has(AUTHORITY))
+ return def;
+ // logger.info("<"+Util.substituteStandardEntities(abs)+">");
+ // logger.info("<"+Util.substituteStandardEntities(r.m_path)+">");
+ boolean net = equal(r.getScheme(), getScheme());
+ boolean absl = net && equal(r.getRawHost(), getRawHost())
+ && equal(getRawUserinfo(), r.getRawUserinfo())
+ && equal(getPort(), r.getPort());
+ boolean same = absl && equal(getRawPath(), r.getRawPath())
+ && equal(getRawQuery(), r.getRawQuery());
+
+ String rslt = r.getRawFragment() == null ? "" : ("#" + r
+ .getRawFragment());
+
+ if (same && (flags & SAMEDOCUMENT) != 0)
+ return rslt;
+
+ String thisPath = getRawPath();
+ String pathToRel = r.getRawPath();
+ if (r.getRawQuery() != null) {
+ rslt = "?" + r.getRawQuery() + rslt;
+ if (equal(thisPath,pathToRel)
+ && (flags & CHILD)!=0 ) {
+ return rslt;
+ }
+ }
+ if (absl) {
+ if (pathToRel.length()>0) {
+ if (thisPath.length()>0) {
+ String out[] = new String[]{null};
+ if (relativizePaths(thisPath, out, flags, pathToRel)) {
+ return out[0]+rslt;
+ }
+ }
+ rslt = r.getRawPath() + rslt;
+ if (absl && (flags & ABSOLUTE) != 0) {
+ return rslt;
+ }
+ }
+ } else
+ rslt = r.getRawPath() + rslt;
+ if (net && (flags & NETWORK) != 0) {
+ return "//"
+ + (r.getRawUserinfo() == null ? ""
+ : (r.getRawUserinfo() + "@")) + r.getRawHost()
+ + (r.getPort() == IRI.NO_PORT ? "" : (":" + ((AbsIRIImpl)r).get(PORT))) + rslt;
+
+ }
+ return def;
+ }
+
+
+ static private String maybeDotSlash(String path) {
+ int colon = path.indexOf(':');
+ if (colon == -1)
+ return path;
+ int slash = path.indexOf('/');
+ if (slash==-1 || slash>colon)
+ return "./"+path;
+ return path;
+ }
+
+ static private String getLastSlash(String s) {
+ int ix = s.lastIndexOf('/', s.length() - 2);
+ return s.substring(0, ix + 1);
+ }
+
+ private boolean equal(String s1, String s2) {
+ return s1 == null ? s2 == null : s1.equals(s2);
+ }
+
+ private boolean equal(int s1, int s2) {
+ return s1 == s2;
+ }
+
+ public Iterator<Violation> allViolations() {
+ return exceptionsMask(~0l);
+ }
+
+ @Override
+ public String getRawUserinfo() {
+ return get(USER);
+ }
+
+ @Override
+ public int getPort() {
+ String port = get(PORT);
+ if (port == null)
+ return IRI.NO_PORT;
+ try {
+ int v = Integer.parseInt(port);
+ if (v<0)
+ return IRI.ILLFORMED_PORT;
+ return v;
+ } catch (Exception e) {
+ return IRI.ILLFORMED_PORT;
+ }
+ }
+
+ @Override
+ public String getRawQuery() {
+ return get(QUERY);
+ }
+
+ @Override
+ public String getRawFragment() {
+ return get(FRAGMENT);
+ }
+
+ @Override
+ public String getRawHost() {
+ return get(HOST);
+ }
+
+ @Override
+ public String getScheme() {
+ return get(SCHEME);
+ }
+
+ abstract String get(int comp);
+
+ @Override
+ public String getRawPath() {
+ return path;
+ }
+
+ @Override
+ public boolean isRootless() {
+ if (!has(SCHEME))
+ return false;
+ if (has(AUTHORITY))
+ return false;
+ if (path.equals(""))
+ return false;
+ if (path.charAt(0) == '/')
+ return false;
+ return true;
+ }
+
+ abstract String pathRemoveDots();
+
+ abstract boolean dotsOK();
+
+ @Override
+ public String getRawAuthority() {
+ return get(AUTHORITY);
+ }
+
+ @Override
+ public IRI create(IRI i) {
+ return new ResolvedRelativeIRI(this, (AbsIRIImpl) getFactory()
+ .create(i));
+ }
+
+ @Override
+ public IRI create(String s) {
+ return create(new IRIImpl(getFactory(), s) );
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null)
+ return false;
+ if (!(o instanceof IRI))
+ return false;
+ return toString().equals(o.toString());
+ }
+
+ @Override
+ public int hashCode() {
+ return toString().hashCode();
+ }
+
+ @Override
+ public String getAuthority() {
+ return getCooked(AUTHORITY);
+ }
+
+ @Override
+ public String getFragment() {
+ return getCooked(FRAGMENT);
+ }
+
+ @Override
+ public String getHost() {
+ return getCooked(HOST);
+ }
+
+ @Override
+ public String getPath() {
+ return getCooked(PATH);
+ }
+
+ @Override
+ public String getQuery() {
+ return getCooked(QUERY);
+ }
+
+ @Override
+ public String getUserinfo() {
+ return getCooked(USER);
+ }
+
+ private String getCooked(int component) {
+ // TODO getCooked
+ throw new UnsupportedOperationException("not yet implemented");
+ }
+
+ @Override
+ public IRI normalize(boolean useDns) {
+ // TODO normalize
+ throw new UnsupportedOperationException("not yet implemented");
+ }
+
+ /*
+ * Bidirectional IRIs MUST be rendered in the same way as they would be if
+ * they were in a left-to-right embedding; i.e., as if they were preceded by
+ * U+202A, LEFT-TO-RIGHT EMBEDDING (LRE), and followed by U+202C, POP
+ * DIRECTIONAL FORMATTING (PDF).
+ *
+ */
+ @Override
+ public String toDisplayString() {
+ return "\u202A" + toString() + "\u202C";
+ }
+
+ // TODO http://example.com/𐌀𐌁𐌂 =>
+ // http://example.com/%F0%90%8C%80%F0%90%8C%81%F0%90%8C%82
+
+ @Override
+ public String getASCIIHost() throws MalformedURLException {
+ StringBuffer asciiString = new StringBuffer();
+
+ String host = getRawHost();
+ if (host==null)
+ return null;
+ regNameToAscii(asciiString,host);
+ return asciiString.toString();
+ }
+
+ @Override
+ public boolean ladderEquals(IRI iri, int other) {
+ // TODO ladderEquals
+ throw new UnsupportedOperationException("not yet implemented");
+ }
+
+ @Override
+ public int ladderEquals(IRI iri) {
+ // TODO ladderEquals
+ throw new UnsupportedOperationException("not yet implemented");
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/AbsLexer.java
----------------------------------------------------------------------
diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/AbsLexer.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/AbsLexer.java
new file mode 100644
index 0000000..ae08392
--- /dev/null
+++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/AbsLexer.java
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.iri.impl;
+
+import java.text.Normalizer ;
+import java.lang.Character.UnicodeBlock ;
+
+import org.apache.jena.iri.ViolationCodes ;
+
+abstract class AbsLexer implements ViolationCodes {
+
+ /* user code: */
+ protected Parser parser;
+ protected int range;
+
+ /*
+ yyreset(null);
+ this.zzAtEOF = true;
+ int length = parser.end(range)-parser.start(range);
+ zzEndRead = length;
+ while (length > zzBuffer.length)
+ zzBuffer = new char[zzBuffer.length*2];
+
+ */
+ synchronized public void analyse(Parser p,int r) {
+ parser = p;
+ range = r;
+ if (!parser.has(range))
+ return;
+ parser.uri.getChars(
+ parser.start(range),
+ parser.end(range),
+ zzBuffer(),
+ 0);
+ try {
+ yylex();
+ }
+ catch (java.io.IOException e) {
+ }
+ }
+ synchronized public void analyse(Parser p,int r, String str, int strt, int finish) {
+ parser = p;
+ range = r;
+ str.getChars(
+ strt,
+ finish,
+ zzBuffer(),
+ 0);
+ try {
+ yylex();
+ }
+ catch (java.io.IOException e) {
+ }
+ }
+
+
+ abstract int yylex() throws java.io.IOException;
+ abstract char[] zzBuffer();
+
+ protected void error(int e) {
+ parser.recordError(range,e);
+ }
+
+ final protected void rule(int rule) {
+ parser.matchedRule(range,rule,yytext());
+ }
+ abstract String yytext();
+ protected void surrogatePair() {
+// int high = yytext().charAt(0);
+// int low = yytext().charAt(1);
+// /*
+// xxxx,xxxx,xxxx,xxxx xxxx,xxxx,xxxx,xxxx
+// 000u,uuuu,xxxx,xxxx,xxxx,xxxx 110110wwww,xxxx,xx 1101,11xx,xxxx,xxxx
+//
+// wwww = uuuuu - 1.
+// */
+// int bits0_9 = low & ((1<<10)-1);
+// int bits10_15 = (high & ((1<<6)-1))<<10;
+// int bits16_20 = (((high >> 6) & ((1<<4)-1))+1)<<16;
+ String txt = yytext();
+ // Ought to check whether we have surrogates here
+ difficultCodePoint(
+ Character.toCodePoint(txt.charAt(0), txt.charAt(1)),
+ txt);
+ }
+
+ private void difficultCodePoint(int codePoint, String txt) {
+ /* Legal XML
+ #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
+ */
+ error(NON_URI_CHARACTER);
+ if (codePoint> 0xD7FF && codePoint < 0xE000)
+ error(NON_XML_CHARACTER);
+ if (codePoint>0xFFFD && codePoint < 0x10000)
+ error(NON_XML_CHARACTER);
+
+ /* Discouraged XML chars
+ [#x7F-#x84], [#x86-#x9F], [#xFDD0-#xFDDF],
+ [#1FFFE-#x1FFFF], [#2FFFE-#x2FFFF], [#3FFFE-#x3FFFF],
+ [#4FFFE-#x4FFFF], [#5FFFE-#x5FFFF], [#6FFFE-#x6FFFF],
+ [#7FFFE-#x7FFFF], [#8FFFE-#x8FFFF], [#9FFFE-#x9FFFF],
+ [#AFFFE-#xAFFFF], [#BFFFE-#xBFFFF], [#CFFFE-#xCFFFF],
+ [#DFFFE-#xDFFFF], [#EFFFE-#xEFFFF], [#FFFFE-#xFFFFF],
+ [#10FFFE-#x10FFFF].
+ */
+
+ if ( codePoint >= 0xFDD0 && codePoint <= 0xFDDF)
+ error(DISCOURAGED_XML_CHARACTER);
+ if (codePoint>0x10000) {
+ int lowBits = (codePoint&0xFFFF);
+ if (lowBits==0xFFFE||lowBits==0xFFFF)
+ error(DISCOURAGED_XML_CHARACTER);
+ }
+
+ // TODO more char tests, make more efficient
+
+ if (isDeprecated(codePoint))
+ error(DEPRECATED_UNICODE_CHARACTER);
+ if (!Character.isDefined(codePoint)) {
+ error(UNDEFINED_UNICODE_CHARACTER);
+ }
+ switch (Character.getType(codePoint)) {
+ case Character.PRIVATE_USE:
+ error(PRIVATE_USE_CHARACTER);
+ break;
+ case Character.CONTROL:
+ error(UNICODE_CONTROL_CHARACTER);
+ break;
+ case Character.UNASSIGNED:
+ error(UNASSIGNED_UNICODE_CHARACTER);
+ break;
+ }
+
+ if (!Normalizer.isNormalized(txt, Normalizer.Form.NFC)) {
+ error(NOT_NFC);
+ }
+
+ if (!Normalizer.isNormalized(txt, Normalizer.Form.NFKC)) {
+ error(NOT_NFKC);
+ }
+
+ if (Character.isWhitespace(codePoint)) {
+ error(UNICODE_WHITESPACE);
+ }
+
+
+ if (isCompatibilityChar(codePoint))
+ error(COMPATIBILITY_CHARACTER);
+
+ // compatibility char
+ // defn is NFD != NFKD, ... hmmm
+
+ }
+
+ private boolean isCompatibilityChar(int codePoint) {
+
+ // Slight optimistation inherited from ICU4J version
+ // Not sure it's worth it since we can't do some of the ICU4J checks
+ UnicodeBlock block = UnicodeBlock.of(codePoint);
+
+ if (block == UnicodeBlock.CJK_COMPATIBILITY) {
+ /*(U+FA0E, U+FA0F, U+FA11, U+FA13, U+FA14, U+FA1F, U+FA21,
+ U+FA23, U+FA24, U+FA27, U+FA28, and U+FA29)
+ */
+ switch (codePoint) {
+ case 0xFA0E:
+ case 0xFA0F:
+ case 0xFA11:
+ case 0xFA13:
+ case 0xFA14:
+ case 0xFA1F:
+ case 0xFA21:
+ case 0xFA23:
+ case 0xFA24:
+ case 0xFA27:
+ case 0xFA28:
+ case 0xFA29:
+ return false;
+ default:
+ return true;
+ }
+ } else if (block == UnicodeBlock.CJK_COMPATIBILITY_FORMS
+ || block == UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT
+ || block == UnicodeBlock.CJK_RADICALS_SUPPLEMENT
+ || block == UnicodeBlock.KANGXI_RADICALS
+ || block == UnicodeBlock.HANGUL_COMPATIBILITY_JAMO) {
+ return true;
+ }
+
+ // codepoint -> charsequence ought to be easy
+ String cp = new String(new int[]{codePoint}, 0, 1);
+
+ // Compatibility char is where NFD differs from NFKD
+ return
+ !Normalizer.normalize(cp,Normalizer.Form.NFD).equals(
+ Normalizer.normalize(cp,Normalizer.Form.NFKD)
+ );
+
+ }
+
+ protected void difficultChar() {
+ difficultCodePoint(yytext().charAt(0),yytext());
+ }
+
+ /**
+ * Unicode deprecated characters. Not available from standard java libs.
+ * Taken from {@link "http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B:deprecated:%5D"}
+ * @param codePoint
+ * @return
+ */
+ private static boolean isDeprecated(int codePoint) {
+
+ // Common case
+ if (codePoint < 0x0149) return false;
+
+ if (codePoint >= 0xE0020 && codePoint <= 0xE007F) return true;
+
+ switch (codePoint) {
+ case 0x0149:
+ case 0x0673:
+ case 0x0F77:
+ case 0x0F79:
+ case 0x17A3:
+ case 0x17A4:
+ case 0x206A:
+ case 0x206B:
+ case 0x206C:
+ case 0x206D:
+ case 0x206E:
+ case 0x206F:
+ case 0x2329:
+ case 0x232A:
+ case 0xE0001:
+ return true;
+ default:
+ return false;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/BuildViolationCodes.java
----------------------------------------------------------------------
diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/BuildViolationCodes.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/BuildViolationCodes.java
new file mode 100644
index 0000000..27999bf
--- /dev/null
+++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/BuildViolationCodes.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.iri.impl;
+
+import java.io.File;
+
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+public class BuildViolationCodes {
+ public static void main(String[] args) throws TransformerException, TransformerFactoryConfigurationError {
+ Transformer xsl =
+ TransformerFactory.newInstance().newTransformer(
+ new StreamSource(new File("src/main/xml/org/apache/jena/iri/impl/viol2java.xsl"))
+ );
+ xsl.transform(
+ new StreamSource(new File("src/main/xml/org/apache/jena/iri/impl/violations.xml")),
+ new StreamResult(new File("src/main/java/org/apache/jena/iri/ViolationCodes.java"))
+
+ );
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/ComponentPattern.java
----------------------------------------------------------------------
diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/ComponentPattern.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/ComponentPattern.java
new file mode 100644
index 0000000..fad1559
--- /dev/null
+++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/ComponentPattern.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.iri.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.jena.iri.ViolationCodes ;
+
+
+public class ComponentPattern implements ViolationCodes {
+ final Pattern pattern;
+
+ final GroupAction actions[];
+
+ static final List<Pattern> allPatterns = new ArrayList<>();
+
+ ComponentPattern(String p) {
+ ComponentPatternParser parser = new ComponentPatternParser(p);
+ pattern = parser.get();
+ actions = parser.actions();
+// System.err.println(allPatterns.size() + ": " + p + " ==> "
+// + pattern.toString());
+ allPatterns.add(pattern);
+ }
+
+
+
+ public void analyse(Parser parser, int range) {
+ Matcher m = pattern.matcher(parser.get(range));
+ if (!m.matches()) {
+ parser.recordError(range, SCHEME_PATTERN_MATCH_FAILED);
+ return;
+ }
+ for (int g = 1; g <= m.groupCount(); g++)
+ if (m.start(g) != -1)
+ actions[g].check(m, parser, range);
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/ComponentPatternParser.java
----------------------------------------------------------------------
diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/ComponentPatternParser.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/ComponentPatternParser.java
new file mode 100644
index 0000000..b510893
--- /dev/null
+++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/ComponentPatternParser.java
@@ -0,0 +1,323 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.iri.impl;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.jena.iri.ViolationCodes ;
+
+
+public class ComponentPatternParser implements ViolationCodes {
+ static String separators = "([(](?![?]))|([(][?])|([)])|(\\[)|(\\])|([@][{])|([}]|[a-z]-[a-z])";
+
+ static final int OPEN_PAREN = 1;
+
+ static final int OPEN_NON_CAPTURING_PAREN = 2;
+
+ static final int CLOSE_PAREN = 3;
+
+ static final int OPEN_SQ = 4;
+
+ static final int CLOSE_SQ = 5;
+
+ static final int OPEN_VAR = 6;
+
+ static final int CLOSE_BRACE = 7;
+
+ static final int LOWER_CASE_RANGE = 8;
+
+ static final int OTHER = -1;
+
+ static final Pattern keyword = Pattern.compile(separators);
+
+ /* .NET port does not like this. Reworked.
+ *
+ static final Pattern splitter = Pattern.compile("(?=" + separators
+ + ")|(?<=" + separators + ")");
+
+
+ public ComponentPatternParser(String p) {
+ split = splitter.split(p);
+ field = 0;
+ classify = new int[split.length];
+ for (int i = 0; i < split.length; i++)
+ classify[i] = classify(split[i]);
+ while (field < split.length)
+ next();
+// System.err.println(p + " ==> "+ rslt.toString());
+ pattern = Pattern.compile(rslt.toString());
+ }
+*/
+ // working data
+ final String split[];
+
+ final int classify[];
+
+ int field;
+
+ int groupCount;
+
+ // result data
+ final StringBuffer rslt = new StringBuffer();
+
+ int shouldLowerCase;
+
+ int mustLowerCase;
+
+ int hostNames;
+
+ final Pattern pattern;
+
+ static final String emptyStringArray[] = new String[0];
+
+ static private String[] mySplit(String p) {
+ //return splitter.split(p);
+
+ Matcher m = keyword.matcher(p);
+ List<String> rslt = new ArrayList<>();
+ int pos = 0;
+// rslt.add("");
+ while (m.find()) {
+ if (m.start()>pos || pos==0) {
+ rslt.add(p.substring(pos,m.start()));
+ }
+ rslt.add(p.substring(m.start(),m.end()));
+ pos = m.end();
+ }
+ if (pos < p.length())
+ rslt.add(p.substring(pos));
+
+// m.
+// String preSplit[] = keyword.split(p);
+// String rslt[] = new String[preSplit.length*2];
+
+ return rslt.toArray(emptyStringArray);
+
+ }
+
+// static private String[] mySplitx(String p) {
+// String r[] = mySplit(p);
+// String s[] = splitter.split(p);
+// if (r.length!=s.length) {
+// System.err.println("Bad lengths: "+p+","+r.length+","+s.length);
+// }
+// for (int i=0;i<r.length && i <s.length;i++)
+// if (!r[i].equals(s[i]))
+// System.err.println("Bad component: "+p+","+r[i]+","+s[i]);
+// return r;
+//
+//
+// }
+ // end result data
+ public ComponentPatternParser(String p) {
+ split = mySplit(p);
+ field = 0;
+ classify = new int[split.length];
+ for (int i = 0; i < split.length; i++)
+ classify[i] = classify(split[i]);
+ while (field < split.length)
+ next();
+// System.err.println(p + " ==> "+ rslt.toString());
+ pattern = Pattern.compile(rslt.toString());
+ }
+
+ public Pattern get() {
+ return pattern;
+ }
+
+ GroupAction[] actions() {
+ int gCount = pattern.matcher("").groupCount()+1;
+ GroupAction result[] = new GroupAction[gCount];
+ for (int i=1;i<gCount;i++) {
+ int g = 1<<i;
+ if ((mustLowerCase & g)!=0)
+ result[i] = new ErrorAction(SCHEME_REQUIRES_LOWERCASE);
+ else if ((shouldLowerCase & g)!=0)
+ result[i] = new ErrorAction(SCHEME_PREFERS_LOWERCASE);
+ else if ((hostNames & g)!=0)
+ result[i] = new HostAction(i);
+ else
+ result[i] = GroupAction.NoAction;
+ }
+ return result;
+ }
+
+ private int classify(String string) {
+ Matcher m = keyword.matcher(string);
+ if (!m.matches())
+ return OTHER;
+ for (int i = 1; i <= m.groupCount(); i++)
+ if (m.start(i) != -1)
+ return i;
+ throw new IllegalStateException(
+ "IRI code internal error: no group matched.");
+ }
+
+ private void untilCloseSq() {
+ while (classify[field - 1] != CLOSE_SQ) {
+ if (field >= split.length)
+ throw new IllegalArgumentException(
+ "Internal IRI code error. Did not find CLOSE_SQ in until().");
+ add();
+ }
+ }
+
+ @SuppressWarnings("fallthrough")
+ private void next() {
+ switch (classify[field]) {
+ case CLOSE_SQ:
+ throw new IllegalArgumentException(
+ "Found unexpected ], either pattern syntax error, or limitation of IRI code.");
+ case OPEN_SQ:
+ add();
+ untilCloseSq();
+ break;
+ case OPEN_VAR:
+ field++;
+ rslt.append("(");
+ groupCount++;
+ if (split[field].equals("host")) {
+ addHost();
+ } else {
+ if (split[field].equals("shouldLowerCase")) {
+
+ shouldLowerCase |= (1 << groupCount);
+ } else if (split[field].equals("mustLowerCase")) {
+
+ mustLowerCase |= (1 << groupCount);
+ } else {
+ throw new IllegalArgumentException("No macro: "
+ + split[field]);
+ }
+ addLowerCase();
+ }
+ break;
+
+ case OPEN_PAREN:
+ groupCount++;
+ // fall through
+ case OPEN_NON_CAPTURING_PAREN:
+ case CLOSE_PAREN:
+ case CLOSE_BRACE:
+ case LOWER_CASE_RANGE:
+ case OTHER:
+ add();
+ return;
+ default:
+ throw new IllegalStateException("IRI code internal error.");
+ }
+ }
+
+ @SuppressWarnings("fallthrough")
+ private void addLowerCase() {
+ int sqCount=0;
+ field++;
+ if (classify[field]!=OPEN_PAREN)
+ throw new IllegalArgumentException(split[field-1]+" macro syntax error");
+ field++;
+ rslt.append("?:(?:"); // make group non-capturing.
+ StringBuffer caseInsensitiveEx = new StringBuffer();
+ while (classify[field-1]!=CLOSE_PAREN || sqCount>0 ) {
+ if (field >= split.length)
+ throw new IllegalArgumentException(
+ "Internal IRI code error. Did not find CLOSE_PAREN in addLowerCase().");
+
+ switch (classify[field]) {
+ case OPEN_SQ:
+ sqCount++;
+ caseInsensitiveEx.append('[');
+ break;
+ case CLOSE_SQ:
+ sqCount--;
+ caseInsensitiveEx.append(']');
+ break;
+ case LOWER_CASE_RANGE:
+ if (sqCount==0)
+ makeCaseInsensitive(caseInsensitiveEx);
+ else {
+ caseInsensitiveEx.append(split[field]);
+ caseInsensitiveEx.append((char)(split[field].charAt(0)-'a'+'A'));
+ caseInsensitiveEx.append('-');
+ caseInsensitiveEx.append((char)(split[field].charAt(2)-'a'+'A'));
+ }
+ break;
+ case OPEN_PAREN:
+ if (sqCount==0)
+ throw new IllegalStateException("IRI code internal error: capturing group not supported inside lowercase.");
+ // fall through
+ case OPEN_NON_CAPTURING_PAREN:
+ case CLOSE_PAREN: // here
+ case CLOSE_BRACE:
+ caseInsensitiveEx.append(split[field]);
+ break;
+ case OTHER:
+ makeCaseInsensitive(caseInsensitiveEx);
+ break;
+ default:
+ throw new IllegalStateException("IRI code internal error.");
+ }
+ add();
+ }
+ if (classify[field]!=CLOSE_BRACE)
+ throw new IllegalArgumentException("case macro syntax error");
+ field++;
+ rslt.append("|("); // start capturing group
+ rslt.append(caseInsensitiveEx);
+ rslt.append(")");
+ }
+
+ private void makeCaseInsensitive(StringBuffer caseInsensitiveEx) {
+ for (int i=0;i<split[field].length();i++) {
+ char c = split[field].charAt(i);
+ if (c>='a' && c<='z') {
+ caseInsensitiveEx.append('[');
+ caseInsensitiveEx.append(c);
+ caseInsensitiveEx.append((char)(c-'a'+'A'));
+ caseInsensitiveEx.append(']');
+ }
+ }
+ }
+
+ private void addHost() {
+ hostNames |= (1 << groupCount);
+ field++;
+ if (classify[field]!=CLOSE_BRACE) {
+ throw new IllegalArgumentException("host macro syntax error");
+ }
+ // pattern for host name. A sequence of chars that are not reserved.
+ // or an IP v6 or future address which starts and ends with [ ] and may
+ // include :.
+ rslt.append("[^\\[\\]:/?#@!$&'()*+,;=]*|\\[[^\\[\\]/?#@!$&'()*+,;=]*\\])");
+ field++;
+ }
+
+ private void add() {
+ rslt.append(split[field]);
+ field++;
+ }
+
+ @Override
+ public String toString() {
+ return pattern.pattern();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/ErrorAction.java
----------------------------------------------------------------------
diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/ErrorAction.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/ErrorAction.java
new file mode 100644
index 0000000..19df2dd
--- /dev/null
+++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/ErrorAction.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.iri.impl;
+
+import java.util.regex.Matcher;
+
+public class ErrorAction extends GroupAction {
+ final private int eCode;
+ ErrorAction(int code){
+ this.eCode = code;
+ }
+ @Override
+ public void check(Matcher m, Parser parser, int range) {
+ parser.recordError(range,eCode);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/Force.java
----------------------------------------------------------------------
diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/Force.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/Force.java
new file mode 100644
index 0000000..0a56142
--- /dev/null
+++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/Force.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.iri.impl;
+
+public interface Force {
+ static final int SHOULD = 0;
+ static final int DNS = 1;
+ static final int MINTING = 2;
+ static final int SECURITY = 3;
+// static final int SCHEME_SPECIFIC = 4;
+ static final int MUST = 4;
+ static final int SIZE = 5;
+ static final int minting = 1 << MINTING;
+ static final int must = 1 << MUST;
+ static final int should = 1 << SHOULD;
+ static final int dns = 1 << DNS;
+ static final int security = 1 << SECURITY;
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/GroupAction.java
----------------------------------------------------------------------
diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/GroupAction.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/GroupAction.java
new file mode 100644
index 0000000..b1c03eb
--- /dev/null
+++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/GroupAction.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.iri.impl;
+
+import java.util.regex.Matcher;
+
+public abstract class GroupAction {
+
+ public static final GroupAction NoAction = new GroupAction() {
+ @Override
+ public void check(Matcher m, Parser parser, int range) {
+ }
+ };
+
+ abstract public void check(Matcher m, Parser parser, int range);
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/HostAction.java
----------------------------------------------------------------------
diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/HostAction.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/HostAction.java
new file mode 100644
index 0000000..40cc55c
--- /dev/null
+++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/HostAction.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.iri.impl;
+
+import java.util.regex.Matcher;
+
+public class HostAction extends GroupAction {
+ final private int group;
+ HostAction(int group) {
+ this.group = group;
+ }
+ @Override
+ public void check(Matcher m, Parser parser, int range) {
+ Parser.hostLexer().analyse(parser,range,m.group(group));
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/IDNP.java
----------------------------------------------------------------------
diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/IDNP.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/IDNP.java
new file mode 100644
index 0000000..fdf1c46
--- /dev/null
+++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/IDNP.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2012 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jena.iri.impl;
+
+import java.net.IDN;
+
+/**
+ * IDNP: IDN Patched
+ *
+ * A wrapper around java.net.IDN to avoid a bug when checking result.
+ * It looks like the IDN is apply checks before fully converting, so this defers
+ * a similar check until the end.
+ */
+public class IDNP {
+
+ public static String toASCII(String host, int flags) {
+ if ((flags & IDN.USE_STD3_ASCII_RULES) != 0) {
+ return check(IDN.toASCII(host, flags ^ IDN.USE_STD3_ASCII_RULES));
+ } else {
+ return IDN.toASCII(host, flags);
+ }
+ }
+
+ // Step through each part of the host and ensure that they conform
+ private static String check(final String asciiHost) {
+ String[] parts = asciiHost.split("\\.");
+ for (String part: parts) checkPart(part);
+ return asciiHost;
+ }
+
+ // Part check: no leading or trailing hyphens, hyphens and alphanumerics.
+ // We try to follow java.net.IDN behaviour in our exceptions, in anticipation
+ // of dumping this class.
+ private static void checkPart(String part) {
+ if (part.charAt(0) == '-' ||
+ part.charAt(part.length() - 1) == '-') {
+ throw new IllegalArgumentException("Has leading or trailing hyphen");
+ }
+ for (int i = 0; i < part.length(); i++) {
+ char c = part.charAt(i);
+ // Host is limited to hyphens and alpha numerics
+ if (c != '-' &&
+ !(c >= '0' && c <= '9') &&
+ !(c >= 'a' && c <= 'z') &&
+ !(c >= 'A' && c <= 'Z')) {
+ throw new IllegalArgumentException("Contains non-LDH characters");
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIExamples.java
----------------------------------------------------------------------
diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIExamples.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIExamples.java
new file mode 100644
index 0000000..442b6dd
--- /dev/null
+++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIExamples.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.iri.impl;
+
+public class IRIExamples {
+
+ protected final String badExamples[];
+ protected final String goodExamples[];
+
+ public IRIExamples(String[] badExamples, String[] goodExamples) {
+
+ this.badExamples = badExamples;
+ this.goodExamples = goodExamples;
+ }
+
+ public String[] getBadExamples() {
+ return badExamples;
+ }
+
+ public String[] getGoodExamples() {
+ return goodExamples;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIFactoryImpl.java
----------------------------------------------------------------------
diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIFactoryImpl.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIFactoryImpl.java
new file mode 100644
index 0000000..ad45840
--- /dev/null
+++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIFactoryImpl.java
@@ -0,0 +1,498 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.iri.impl;
+
+import java.io.UnsupportedEncodingException;
+import java.util.AbstractSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import org.apache.jena.iri.IRI ;
+import org.apache.jena.iri.IRIComponents ;
+import org.apache.jena.iri.ViolationCodes ;
+
+
+public class IRIFactoryImpl
+ extends AbsIRIFactoryImpl
+ implements ViolationCodes, Force, IRIComponents {
+
+public static final int UNKNOWN_SYNTAX = -4;
+ // boolean throwUncheckedExceptions = false;
+ /*
+ static final long conformanceMasks[] = {
+ // RFC3986
+ (1l<<ILLEGAL_CHAR)
+ |(1l<<ILLEGAL_PERCENT_ENCODING)
+ |(1l<<EMPTY_SCHEME)
+ |(1l<<IP_V4_HAS_FOUR_COMPONENTS)
+ |(1l<<IP_V4_OCTET_RANGE)
+ |(1l<<IP_V6_OR_FUTURE_ADDRESS_SYNTAX)
+ |(1l<<IRI_CHAR)
+ |(1l<<LTR_CHAR)
+ |(1l<<NOT_XML_SCHEMA_WHITESPACE)
+ |(1l<<SCHEME_MUST_START_WITH_LETTER)
+ |(1l<<UNWISE_CHAR)
+ |(1l<<WHITESPACE)
+ |(1l<<ARBITRARY_CHAR)
+ ,
+ // RFC3987
+ (1l<<ILLEGAL_CHAR)
+ |(1l<<ILLEGAL_PERCENT_ENCODING)
+ |(1l<<EMPTY_SCHEME)
+ |(1l<<IP_V4_HAS_FOUR_COMPONENTS)
+ |(1l<<IP_V4_OCTET_RANGE)
+ |(1l<<IP_V6_OR_FUTURE_ADDRESS_SYNTAX)
+ |(1l<<LTR_CHAR)
+ |(1l<<NOT_XML_SCHEMA_WHITESPACE)
+ |(1l<<SCHEME_MUST_START_WITH_LETTER)
+ |(1l<<UNWISE_CHAR)
+ |(1l<<WHITESPACE)
+ |(1l<<ARBITRARY_CHAR)
+ ,
+ // RDF
+ (1l<<ILLEGAL_CHAR)
+ |(1l<<ILLEGAL_PERCENT_ENCODING)
+ |(1l<<EMPTY_SCHEME)
+ |(1l<<IP_V4_HAS_FOUR_COMPONENTS)
+ |(1l<<IP_V4_OCTET_RANGE)
+ |(1l<<IP_V6_OR_FUTURE_ADDRESS_SYNTAX)
+ |(1l<<SCHEME_MUST_START_WITH_LETTER)
+ |(1l<<RELATIVE_URI)
+ ,
+ // XLink
+ (1l<<ILLEGAL_CHAR)
+ |(1l<<ILLEGAL_PERCENT_ENCODING)
+ |(1l<<EMPTY_SCHEME)
+ |(1l<<IP_V4_HAS_FOUR_COMPONENTS)
+ |(1l<<IP_V4_OCTET_RANGE)
+ |(1l<<IP_V6_OR_FUTURE_ADDRESS_SYNTAX)
+ |(1l<<SCHEME_MUST_START_WITH_LETTER)
+ |(1l<<NON_XML_CHARACTER)
+ ,
+ // XMLSchema
+ (1l<<ILLEGAL_CHAR)
+ |(1l<<ILLEGAL_PERCENT_ENCODING)
+ |(1l<<EMPTY_SCHEME)
+ |(1l<<IP_V4_HAS_FOUR_COMPONENTS)
+ |(1l<<IP_V4_OCTET_RANGE)
+ |(1l<<IP_V6_OR_FUTURE_ADDRESS_SYNTAX)
+ |(1l<<SCHEME_MUST_START_WITH_LETTER)
+ |(1l<<NOT_XML_SCHEMA_WHITESPACE)
+ |(1l<<NON_XML_CHARACTER)
+ ,
+ // IDN
+// (1l<<ACE_PREFIX)
+ 0
+ ,
+ // Should
+ (1l<<LOWERCASE_PREFERRED)
+ |(1l<<PORT_SHOULD_NOT_BE_EMPTY)
+ |(1l<<PORT_SHOULD_NOT_START_IN_ZERO)
+ // |(1l<<SCHEME_NAMES_SHOULD_BE_LOWER_CASE)
+ |(1l<<PERCENT_ENCODING_SHOULD_BE_UPPERCASE)
+ |(1l<<IPv6ADDRESS_SHOULD_BE_LOWERCASE)
+ |(1l<<USE_PUNYCODE_NOT_PERCENTS)
+ ,
+ // Minting
+ /* consider HAS_PASSWORD vs LOWER_CASE_PREFERRED
+ * The former should be an error unless switched
+ * off (but it can be, unlike a MUST), whereas the
+ * latter should be a warning by default.
+ * /
+ (1l<<LOWERCASE_PREFERRED)
+ |(1l<<PORT_SHOULD_NOT_BE_EMPTY)
+ |(1l<<PORT_SHOULD_NOT_START_IN_ZERO)
+ // |(1l<<SCHEME_NAMES_SHOULD_BE_LOWER_CASE)
+ |(1l<<PERCENT_ENCODING_SHOULD_BE_UPPERCASE)
+ |(1l<<IPv6ADDRESS_SHOULD_BE_LOWERCASE)
+ |(1l<<USE_PUNYCODE_NOT_PERCENTS)
+ ,
+ // DNS
+ (1l<<NOT_DNS_NAME)
+ ,
+ };
+ */
+ protected long errors;
+ protected long warnings;
+
+ protected Set<Specification> specs = new HashSet<>();
+
+ public IRIFactoryImpl() {
+ }
+
+ public IRIFactoryImpl(IRIFactoryImpl template) {
+ if (backwardCompatibleRelativeRefs.size()==Integer.MAX_VALUE)
+ backwardCompatibleRelativeRefs = template.backwardCompatibleRelativeRefs;
+ else
+ backwardCompatibleRelativeRefs = new HashSet<>(backwardCompatibleRelativeRefs);
+ encoding = template.encoding;
+ errors = template.errors;
+ prohibited = template.prohibited;
+ required = template.required;
+ warnings = template.warnings;
+ System.arraycopy(template.asErrors,0,asErrors,0,asErrors.length);
+ System.arraycopy(template.asWarnings,0,asWarnings,0,asWarnings.length);
+ for ( Entry<String, SchemeSpecificPart> entry : template.schemes.entrySet() )
+ {
+ SchemeSpecificPart p = entry.getValue();
+ if ( p.withScheme() )
+ {
+ schemes.put( entry.getKey(), new WithScheme( (WithScheme) p ) );
+ }
+ else if ( p.port() != IRI.NO_PORT )
+ {
+ schemes.put( entry.getKey(), new NoScheme( p.port() ) );
+ }
+ }
+ }
+
+ /*
+ protected long recsToMask(int recs) {
+ long mask = 0;
+ for (int i=0; recs != 0 && i<conformanceMasks.length; i++) {
+ if ((recs & (1<<i)) != 0) {
+ mask |= conformanceMasks[i];
+ recs &= ~(1<<i);
+ }
+ }
+ return mask;
+ }
+*/
+ private final long getMask(boolean includeWarnings) {
+
+ return includeWarnings?(errors|warnings):errors;
+ }
+
+ @Override
+ protected IRIFactoryImpl getFactory() {
+ return this;
+ }
+
+ @Override
+ public IRI create(IRI i) {
+ if (i instanceof AbsIRIImpl &&
+ ((AbsIRIImpl)i).getFactory()==this)
+ return i;
+ return
+ create(i.toString());
+ }
+
+ boolean getSameSchemaRelativeReferences(String scheme) {
+ return backwardCompatibleRelativeRefs.contains(scheme.toLowerCase());
+ }
+
+ private String encoding = "utf-8";
+ String getEncoding() {
+ return encoding;
+ }
+ public void setEncoding(String enc) throws UnsupportedEncodingException {
+ // check enc is valid encoding.
+ "".getBytes(enc);
+ encoding = enc;
+ }
+
+
+ boolean asErrors[] = new boolean[]{
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+
+ };
+ boolean asWarnings[] = new boolean[]{
+ false,
+ false,
+ true,
+ false,
+ false,
+ false
+ };
+
+ protected void setViolation(int ix, boolean e, boolean w){
+ if (e && w)
+ throw new IllegalArgumentException("xxxViolation(true,true) is not permitted.");
+ initializing();
+ asErrors[ix]=e;
+ asWarnings[ix]=w;
+
+ }
+
+ protected boolean getAsWarnings(int ix) {
+ return asWarnings[ix];
+ }
+
+ protected boolean getAsErrors(int ix) {
+ return asErrors[ix];
+ }
+// boolean isException(int code) {
+// return (errors & (1l<<code))!=0;
+// }
+
+ private boolean initializing = true;
+private Set<String> backwardCompatibleRelativeRefs = new HashSet<>();
+ protected void initializing() {
+ if (!initializing)
+ throw new IllegalStateException("Cannot reinitialize IRIFactory after first use.");
+
+ }
+
+ @Override
+ public IRI create(String s) {
+ initializing = false;
+ return super.create(s);
+ }
+
+ public void setSameSchemeRelativeReferences(String scheme) {
+ if (scheme.equals("*"))
+ backwardCompatibleRelativeRefs = new AbstractSet<String>(){
+
+ @Override
+ public int size() {
+ return Integer.MAX_VALUE;
+ }
+
+ @Override
+ public Iterator<String> iterator() {
+ throw new UnsupportedOperationException();
+ }
+ @Override
+ public boolean add(String o) {
+ return false;
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return true;
+ }
+ };
+ else
+ backwardCompatibleRelativeRefs.add(scheme.toLowerCase());
+ }
+
+ protected void useSpec(String name, boolean asErr) {
+ initializing();
+ Specification spec = Specification.get(name);
+ specs.add(spec);
+ for (int i=0; i<Force.SIZE; i++) {
+ if (asErrors[i] || (asWarnings[i] && asErr)) {
+ errors |= spec.getErrors(i);
+ }
+ if (asWarnings[i] ) {
+ warnings |= spec.getErrors(i);
+ }
+ }
+ prohibited |= spec.getProhibited();
+ required |= spec.getRequired();
+ warnings &= ~errors;
+
+ }
+
+ public SchemeSpecificPart getScheme(String scheme, Parser parser) {
+
+ scheme = scheme.toLowerCase();
+ SchemeSpecificPart p = schemes.get(scheme);
+ if (p!=null) {
+ p.usedBy(parser);
+ return p;
+ }
+ int dash = scheme.indexOf('-');
+ if (dash != -1) {
+ if (scheme.startsWith("x-")) {
+ p = noScheme();
+ } else {
+ if (nonIETFScheme==null)
+ nonIETFScheme = new NoScheme() {
+ @Override void usedBy(Parser pp) {
+ pp.recordError(SCHEME,UNREGISTERED_NONIETF_SCHEME_TREE);
+ }
+ };
+ p = nonIETFScheme;
+ }
+ } else if (Specification.schemes.containsKey(scheme)) {
+ SchemeSpecification spec = (SchemeSpecification)Specification.schemes.get(scheme);
+ p = new NoScheme(spec.port);
+ } else{
+ if (unregisteredScheme==null){
+ unregisteredScheme = new NoScheme() {
+ @Override void usedBy(Parser pp) {
+ pp.recordError(SCHEME,UNREGISTERED_IANA_SCHEME);
+ }
+ };
+ }
+ p= unregisteredScheme;
+ }
+ p.usedBy(parser);
+// System.err.println("Scheme: "+scheme);
+ if (schemes.size() < 1000)
+ schemes.put(scheme,p);
+ return p;
+ }
+
+ private NoScheme unregisteredScheme=null;
+ private NoScheme nonIETFScheme=null;
+
+ public SchemeSpecificPart noScheme() {
+ return noScheme;
+ }
+ private class WithScheme extends SchemeSpecificPart
+ {
+ long zerrors;
+ long zwarnings;
+ int zrequired;
+ int zprohibited;
+ boolean inited = false;
+ final SchemeSpecification scheme;
+ private WithScheme(WithScheme ws) {
+ zerrors = ws.zerrors;
+ zwarnings = ws.zwarnings;
+ zprohibited = ws.zprohibited;
+ zrequired = ws.zrequired;
+ scheme = ws.scheme;
+ }
+ private WithScheme(SchemeSpecification spec, boolean asErr){
+ scheme = spec;
+ for (int i=0; i<Force.SIZE; i++) {
+ if (asErrors[i] || (asWarnings[i] && asErr)) {
+ zerrors |= spec.getErrors(i);
+ }
+ if (asWarnings[i] ) {
+ zwarnings |= spec.getErrors(i);
+ }
+ }
+
+ }
+ @Override void usedBy(Parser parser) {
+ if (!inited) {
+ inited = true;
+ zerrors |= errors;
+ zwarnings |= warnings;
+ zwarnings &= ~zerrors;
+ zrequired = scheme.getRequired() | required;
+ zprohibited = scheme.getProhibited() | prohibited;
+ }
+
+ }
+ @Override
+ public long getMask(boolean includeWarnings) {
+ return includeWarnings?(zerrors|zwarnings):zerrors;
+ }
+ @Override
+ public int getRequired() {
+ return zrequired;
+ }
+ @Override
+ public int getProhibited() {
+ return zprohibited;
+ }
+ @Override
+ public void analyse(Parser parser, int range) {
+ scheme.analyse(parser,range);
+ }
+ @Override
+ public int port() {
+ return scheme.port;
+ }
+ @Override
+ public boolean withScheme() {
+ return true;
+ }
+
+ }
+ private class NoScheme extends SchemeSpecificPart {
+
+ NoScheme() {
+ this(-1);
+ }
+ final private int port;
+ NoScheme(int i) {
+ port = i;
+ }
+ @Override
+ public long getMask(boolean includeWarnings) {
+ return IRIFactoryImpl.this.getMask(includeWarnings);
+ }
+ @Override
+ public int getRequired() {
+ return IRIFactoryImpl.this.getRequired();
+ }
+ @Override
+ public int getProhibited() {
+ return IRIFactoryImpl.this.getProhibited();
+ }
+ @Override
+ void usedBy(Parser parser) { /* nothing */ }
+ @Override
+ public void analyse(Parser parser, int range) {/* nothing */ }
+ @Override
+ public int port() {
+ return port;
+ }
+ @Override
+ public boolean withScheme() {
+ return false;
+ }
+
+ }
+
+ final private NoScheme noScheme = new NoScheme();
+ private int required = 0;
+ private int prohibited = 0;
+
+ public int getRequired() {
+ return required;
+ }
+
+ public int getProhibited() {
+ return prohibited ;
+ }
+
+ final private Map<String, SchemeSpecificPart> schemes = new HashMap<>();
+
+ public void useSchemeSpecificRules(String scheme, boolean asErr)
+ {
+ if (scheme.equals("*"))
+ {
+ for ( String s : Specification.schemes.keySet() )
+ {
+ scheme = s;
+ if ( !schemes.containsKey( scheme ) )
+ {
+ useSchemeSpecificRules( scheme, asErr );
+ }
+ }
+ return ;
+ }
+ scheme = scheme.toLowerCase() ;
+ SchemeSpecification spec = (SchemeSpecification) Specification.schemes.get(scheme) ;
+ if (spec == null)
+ {
+ schemes.put(scheme, noScheme) ;
+ } else
+ {
+ schemes.put(scheme, new WithScheme(spec, asErr)) ;
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIImpl.java
----------------------------------------------------------------------
diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIImpl.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIImpl.java
new file mode 100644
index 0000000..f2dc6bf
--- /dev/null
+++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIImpl.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.iri.impl;
+
+
+import org.apache.jena.iri.IRIComponents ;
+import org.apache.jena.iri.IRIFactory ;
+
+public class IRIImpl
+ extends AbsIRIImpl
+implements IRIComponents {
+
+ final IRIFactoryImpl factory;
+ final String original;
+ final Parser parser;
+ Exception idnaException;
+
+ SchemeSpecificPart scheme;
+
+ public IRIImpl(IRIFactory f) {
+ this(f,""
+// ,NO_EXCEPTIONS
+ );
+ }
+
+// IRIImpl(IRIFactoryImpl f, String s) {
+// this(f,s,ALL_EXCEPTIONS);
+//
+// }
+
+// private IRIImpl(IRIFactory f, IRIImpl b, IRI r) {
+// factory = f;
+//
+// // implement relative URI stuff ...
+//
+// if (b.original.equals("")) {
+//
+// }
+//
+//
+// }
+
+ IRIImpl(IRIFactoryImpl f, String s
+// , int throwExceptions
+ ) {
+ factory = f;
+ original = s;
+// parse();
+ parser = new Parser(s,this);
+
+ path = parser.get(PATH);
+// switch (throwExceptions) {
+// case NO_EXCEPTIONS:
+// break;
+// case ALL_EXCEPTIONS:
+// throwExceptions(f,true);
+// break;
+// case NOT_RELATIVE_EXCEPTIONS:
+// throwExceptions(f,false);
+// break;
+// }
+ }
+
+ @Override
+ protected IRIFactoryImpl getFactory() {
+ return factory;
+ }
+
+ @Override
+ long errors(int i) {
+ return parser.errors(i);
+ }
+
+ @Override
+ boolean has(int component) {
+ return parser.has(component);
+ }
+
+ @Override
+ String get(int comp) {
+ return parser.get(comp);
+ }
+
+ @Override
+ String pathRemoveDots() {
+ if (dotsOK())
+ return path;
+ return removeDotSegments(path);
+ }
+
+ @Override
+ boolean dotsOK() {
+ return (errors(PATH)&(1l<<NON_INITIAL_DOT_SEGMENT))==0;
+ }
+
+ @Override
+ public String toString() {
+ return original;
+ }
+
+ @Override
+ SchemeSpecificPart getSchemeSpec() {
+ return scheme;
+ }
+
+ @Override
+ Exception getIDNAException() {
+ return idnaException;
+ }
+
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIImplException.java
----------------------------------------------------------------------
diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIImplException.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIImplException.java
new file mode 100644
index 0000000..a0b9c40
--- /dev/null
+++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/IRIImplException.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.iri.impl;
+
+import org.apache.jena.iri.IRIException ;
+import org.apache.jena.iri.Violation ;
+
+public class IRIImplException extends IRIException {
+
+ private static final long serialVersionUID = 1072420548744246731L;
+ private final Violation violation;
+
+ @Override
+ public Violation getViolation() {
+ return violation;
+ }
+ public IRIImplException(Violation e) {
+ super();
+ violation = e;
+ }
+
+ @Override
+ public String getMessage() {
+ return getViolation().getShortMessage();
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/Lexer.java
----------------------------------------------------------------------
diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/Lexer.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/Lexer.java
new file mode 100644
index 0000000..db86a34
--- /dev/null
+++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/Lexer.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.iri.impl;
+
+interface Lexer {
+
+ void analyse(Parser parser, int i);
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-iri/src/main/java/org/apache/jena/iri/impl/LexerFragment.java
----------------------------------------------------------------------
diff --git a/jena-iri/src/main/java/org/apache/jena/iri/impl/LexerFragment.java b/jena-iri/src/main/java/org/apache/jena/iri/impl/LexerFragment.java
new file mode 100644
index 0000000..10124f9
--- /dev/null
+++ b/jena-iri/src/main/java/org/apache/jena/iri/impl/LexerFragment.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.iri.impl;
+
+import java.io.Reader;
+
+
+class LexerFragment extends LexerQuery {
+
+ LexerFragment(Reader reader) {
+ super(reader);
+ }
+
+}