/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ /* The following copyright is attached because marked parts of the following code are * copied and modified from Jena 2.4. */ /* * (c) Copyright 2001, 2002, 2003, 2004, 2005, 2006 Hewlett-Packard Development Company, LP * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Id: URIref.java,v 1.5 2006/03/22 13:52:49 andy_seaborne Exp AUTHOR: Jeremy J. Carroll */ package org.simantics.databoard.util; import java.util.Arrays; import java.util.List; /** * Contains utility methods for handling URI Strings in the context of ProCore * and the Simantics platform. This includes URI escaping and unescaping and * namespace/local name separation and joining. * *
* URI's in this context are assumed to be formed as follows: * *
* <namespace part>#<local name part> ** *
* The implementation of {@link #escape(String)} and {@link #unescape(String)} * is copied and modified from Jena's com.hp.hpl.jena.util.URIref. *
* * @see Percent-encoding * * @author Tuukka Lehtonen */ public final class URIStringUtils { /** * The character '/' is used as a path separator in URI namespace parts in ProCore. */ public static final char NAMESPACE_PATH_SEPARATOR = '/'; /** * The '#' character is used to separate the local name and namespace parts * of an URI, for examplehttp://www.example.org#localName
.
*/
public static final char NAMESPACE_LOCAL_SEPARATOR = '#';
/**
* Checks that only one separator character ({@link #NAMESPACE_LOCAL_SEPARATOR})
* between namespace and localname exists in the specified URI and returns
* its index.
*
* @param uri the URI to search from
* @return the character index of the separator ranging from 0 to uri.length()-1
* @throws IllegalArgumentException if no {@link #NAMESPACE_LOCAL_SEPARATOR}
* is found in the specified URI
*/
private static int assertSingleSeparatorPosition(String uri) {
int sharpIndex = uri.indexOf(NAMESPACE_LOCAL_SEPARATOR);
if (sharpIndex == -1) {
throw new IllegalArgumentException("URI '" + uri + "' does not contain any '" + NAMESPACE_LOCAL_SEPARATOR + "' separator characters");
}
int nextSharpIndex = uri.indexOf(NAMESPACE_LOCAL_SEPARATOR, sharpIndex + 1);
if (nextSharpIndex != -1) {
throw new IllegalArgumentException("URI '" + uri + "' contains multiple '" + NAMESPACE_LOCAL_SEPARATOR + "' separator characters");
}
return sharpIndex;
}
/**
* Checks that only one separator character (
* {@link #NAMESPACE_LOCAL_SEPARATOR}) between namespace and localname
* exists in the specified URI and returns its index. This version does not
* throw an exception when the separator is not found.
*
* @param uri the URI to search from
* @return the character index of the separator ranging from 0 to
* uri.length()-1 or -1 if no separator was found.
*/
private static int singleSeparatorPosition(String uri) {
int sharpIndex = uri.indexOf(NAMESPACE_LOCAL_SEPARATOR);
if (sharpIndex == -1) {
return -1;
}
int nextSharpIndex = uri.indexOf(NAMESPACE_LOCAL_SEPARATOR, sharpIndex + 1);
if (nextSharpIndex != -1) {
return -1;
}
return sharpIndex;
}
/**
* Splits the specified URI into a namespace and a local name and returns
* the namespace.
*
* * Assumes that namespaces are always separated by * {@link #NAMESPACE_LOCAL_SEPARATOR} characters. *
* * @param uri the URI to split, must be non-null * @return the namespace part of the specified URI * @throws IllegalArgumentException for URIs without a * {@link #NAMESPACE_LOCAL_SEPARATOR} * @throws NullPointerException fornull
URIs
*/
public static String getNamespace(String uri) {
if (uri == null)
throw new NullPointerException("null uri");
int separatorIndex = assertSingleSeparatorPosition(uri);
return uri.substring(0, separatorIndex);
}
public static String getRVIParent(String uri) {
int childSeparator = uri.lastIndexOf(URIStringUtils.NAMESPACE_PATH_SEPARATOR);
int propertySeparator = uri.lastIndexOf(URIStringUtils.NAMESPACE_LOCAL_SEPARATOR);
int separator = Math.max(childSeparator, propertySeparator);
return uri.substring(0, separator);
}
/**
* Splits the specified URI into a namespace and a local name and returns
* the local name.
*
* * Assumes that namespaces are always separated by * {@link #NAMESPACE_LOCAL_SEPARATOR} characters. *
* * @param uri the URI to split, must be non-null * @return the local name part of the specified URI * @throws IllegalArgumentException for URIs without a * {@link #NAMESPACE_LOCAL_SEPARATOR} * @throws NullPointerException fornull
URIs
*/
public static String getLocalName(String uri) {
if (uri == null)
throw new NullPointerException("null uri");
int separatorIndex = assertSingleSeparatorPosition(uri);
return uri.substring(separatorIndex + 1);
}
public static String escapeName(String name) {
char[] chars = name.toCharArray();
boolean modified = false;
for(int i=0;inull
if the URI
* cannot be split.
* @throws NullPointerException for null
URIs
*/
public static String[] trySplitNamespaceAndLocalName(String uri) {
if (uri == null)
throw new NullPointerException("null uri");
int separatorIndex = singleSeparatorPosition(uri);
return separatorIndex == -1 ?
null
: new String[] { uri.substring(0, separatorIndex), uri.substring(separatorIndex + 1) };
}
/**
* Splits the specified URI into a namespace and a local name and returns
* them both separately as an array.
*
* @param uri the URI to split, must be non-null
* @return [0] = namespace, [1] = local name
* @throws IllegalArgumentException for URIs without a
* {@link #NAMESPACE_LOCAL_SEPARATOR}
* @throws NullPointerException for null
URIs
*/
public static String[] splitNamespaceAndLocalName(String uri) {
if (uri == null)
throw new NullPointerException("null uri");
int separatorIndex = assertSingleSeparatorPosition(uri);
return new String[] { uri.substring(0, separatorIndex), uri.substring(separatorIndex + 1) };
}
/**
* Converts a unicode string into an RFC 2396 compliant URI, using %NN
* escapes where appropriate, including the
* {@link #NAMESPACE_PATH_SEPARATOR} character.
*
* @param localName the string to escape
* @return the escaped string
* @throws NullPointerException for null
URIs
*/
public static String escapeURI(String localName) {
if (localName == null)
throw new NullPointerException("null local name");
return encode(localName);
}
/**
* Add a suffix path to a namespace string, i.e. join the strings to
* together with the {@link #NAMESPACE_PATH_SEPARATOR} character in between.
*
* @param namespace the namespace to append to
* @param suffix the suffix to append
* @return the joined namespace
*/
public static String appendURINamespace(String namespace, String suffix) {
return new StringBuilder(namespace.length() + 1 + suffix.length())
.append(namespace)
.append(NAMESPACE_PATH_SEPARATOR)
.append(suffix)
.toString();
}
/**
* Join a namespace and a localname to form an URI with
* {@link #NAMESPACE_LOCAL_SEPARATOR}.
*
* @param namespace the namespace part to join
* @param localName the localname part to join
* @return the joined URI
*/
public static String makeURI(String namespace, String localName) {
String escapedLocalName = escapeURI(localName);
return new StringBuilder(namespace.length() + 1 + escapedLocalName.length())
.append(namespace)
.append(NAMESPACE_LOCAL_SEPARATOR)
.append(escapedLocalName)
.toString();
}
/**
* Convert a Unicode string, first to UTF-8 and then to an RFC 2396
* compliant URI with optional fragment identifier using %NN escape
* mechanism as appropriate. The '%' character is assumed to already
* indicated an escape byte. The '%' character must be followed by two
* hexadecimal digits.
*
*
* Meant to be used for encoding URI local name parts if it is desired to
* have '/' characters in the local name without creating a new namespace.
* For example these two URI's:
*
*
* http://foo.bar.com/foo/bar/org%2Fcom
*
* have the same namespace
* http://foo.bar.com/foo/bar/net%2Fcom
* http://foo.bar.com/foo/bar/
and
* different local names org%2Fcom
and net%2Fcom
* or org/com
and net/com
in unescaped form.
*