/******************************************************************************* * Copyright (c) 2010 Fraunhofer IWU and others. * 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: * Fraunhofer IWU - initial API and implementation *******************************************************************************/ package net.enilink.komma.core; import java.util.List; /** * Interface for a Uniform Resource Identifier (URI), as specified by <a * href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>, with certain * enhancements. A <code>URI</code> instance can be created by specifying values * for its components, or by providing a single URI string, which is parsed into * its components. Static factory methods whose names begin with "create" are * used for both forms of object creation. * * <p> * Like <code>String</code>, <code>URI</code> implementations are immutable; a * <code>URI</code> instance offers several by-value methods that return a new * <code>URI</code> object based on its current state. Most useful, a relative * <code>URI</code> can be {@link #resolve(URI) resolve}d against a base * absolute <code>URI</code> -- the latter typically identifies the document in * which the former appears. The inverse to this is {@link #deresolve(URI) * deresolve}, which answers the question, "what relative URI will resolve, * against the given base, to this absolute URI?" * * <p> * In the <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC</a>, much attention * is focused on a hierarchical naming system used widely to locate resources * via common protocols such as HTTP, FTP, and Gopher, and to identify files on * a local file system. Accordingly, implementations need functionality to * handle such URIs, which can be identified via {@link #isHierarchical * isHierarchical}. * */ public interface URI extends IReference { /** * When specified as the last argument to * {@link #createURI(String, boolean, int) createURI}, indicates that there * is no fragment, so any <code>#</code> characters should be encoded. * * @see #createURI(String, boolean, int) */ public static final int FRAGMENT_NONE = 0; /** * When specified as the last argument to * {@link #createURI(String, boolean, int) createURI}, indicates that the * first <code>#</code> character should be taken as the fragment separator, * and any others should be encoded. * * @see #createURI(String, boolean, int) */ public static final int FRAGMENT_FIRST_SEPARATOR = 1; /** * When specified as the last argument to * {@link #createURI(String, boolean, int) createURI}, indicates that the * last <code>#</code> character should be taken as the fragment separator, * and any others should be encoded. * * @see #createURI(String, boolean, int) */ public static final int FRAGMENT_LAST_SEPARATOR = 2; /** * Returns <code>true</code> if this is a relative URI, or * <code>false</code> if it is an absolute URI. */ boolean isRelative(); /** * Returns <code>true</code> if this a a hierarchical URI, or * <code>false</code> if it is of the generic form. */ boolean isHierarchical(); /** * Returns <code>true</code> if this is a hierarchical URI with an authority * component; <code>false</code> otherwise. */ boolean hasAuthority(); /** * Returns <code>true</code> if this is a non-hierarchical URI with an * opaque part component; <code>false</code> otherwise. */ boolean hasOpaquePart(); /** * Returns <code>true</code> if this is a hierarchical URI with a device * component; <code>false</code> otherwise. */ boolean hasDevice(); /** * Returns <code>true</code> if this is a hierarchical URI with an absolute * or relative path; <code>false</code> otherwise. */ boolean hasPath(); /** * Returns <code>true</code> if this is a hierarchical URI with an absolute * path, or <code>false</code> if it is non-hierarchical, has no path, or * has a relative path. */ boolean hasAbsolutePath(); /** * Returns <code>true</code> if this is a hierarchical URI with a relative * path, or <code>false</code> if it is non-hierarchical, has no path, or * has an absolute path. */ boolean hasRelativePath(); /** * Returns <code>true</code> if this is a hierarchical URI with an empty * relative path; <code>false</code> otherwise. * * <p> * Note that <code>!hasEmpty()</code> does <em>not</em> imply that this URI * has any path segments; however, <code>hasRelativePath && * !hasEmptyPath()</code> does. */ boolean hasEmptyPath(); /** * Returns <code>true</code> if this is a hierarchical URI with a query * component; <code>false</code> otherwise. */ boolean hasQuery(); /** * Returns <code>true</code> if this URI has a fragment component; * <code>false</code> otherwise. */ boolean hasFragment(); /** * Returns <code>true</code> if this is a current document reference; that * is, if it is a relative hierarchical URI with no authority, device or * query components, and no path segments; <code>false</code> is returned * otherwise. */ boolean isCurrentDocumentReference(); /** * Returns <code>true</code> if this is a * {@link #isCurrentDocumentReference() current document reference} with no * fragment component; <code>false</code> otherwise. * * @see #isCurrentDocumentReference() */ boolean isEmpty(); /** * Returns <code>true</code> if this is a hierarchical URI that may refer * directly to a locally accessible file. This is considered to be the case * for a file-scheme absolute URI, or for a relative URI with no query; * <code>false</code> is returned otherwise. */ boolean isFile(); /** * Returns <code>true</code> if this is a platform URI, that is, an * absolute, hierarchical URI, with "platform" scheme, no authority, and at * least two segments; <code>false</code> is returned otherwise. * * @since org.eclipse.emf.common 2.3 */ boolean isPlatform(); /** * Returns <code>true</code> if this is a platform resource URI, that is, a * {@link #isPlatform platform URI} whose first segment is "resource"; * <code>false</code> is returned otherwise. * * @see #isPlatform * @since org.eclipse.emf.common 2.3 */ boolean isPlatformResource(); /** * Returns <code>true</code> if this is a platform plug-in URI, that is, a * {@link #isPlatform platform URI} whose first segment is "plugin"; * <code>false</code> is returned otherwise. * * @see #isPlatform * @since org.eclipse.emf.common 2.3 */ boolean isPlatformPlugin(); /** * Returns <code>true</code> if this is an archive URI. If so, it is also * hierarchical, with an authority (consisting of an absolute URI followed * by "!"), no device, and an absolute path. */ boolean isArchive(); /** * Returns <code>true</code> if <code>object</code> is an instance of * <code>URI</code> equal to this one; <code>false</code> otherwise. * * <p> * Equality is determined strictly by comparing components, not by * attempting to interpret what resource is being identified. The comparison * of schemes is case-insensitive. */ boolean equals(Object object); /** * If this is an absolute URI, returns the scheme component; * <code>null</code> otherwise. */ String scheme(); /** * If this is a non-hierarchical URI, returns the opaque part component; * <code>null</code> otherwise. */ String opaquePart(); /** * If this is a hierarchical URI with an authority component, returns it; * <code>null</code> otherwise. */ String authority(); /** * If this is a hierarchical URI with an authority component that has a user * info portion, returns it; <code>null</code> otherwise. */ String userInfo(); /** * If this is a hierarchical URI with an authority component that has a host * portion, returns it; <code>null</code> otherwise. */ String host(); /** * If this is a hierarchical URI with an authority component that has a port * portion, returns it; <code>null</code> otherwise. */ String port(); /** * If this is a hierarchical URI with a device component, returns it; * <code>null</code> otherwise. */ String device(); /** * If this is a hierarchical URI with a path, returns an array containing * the segments of the path; an empty array otherwise. The leading separator * in an absolute path is not represented in this array, but a trailing * separator is represented by an empty-string segment as the final element. */ String[] segments(); /** * Returns an unmodifiable list containing the same segments as the array * returned by {@link #segments segments}. */ List<String> segmentsList(); /** * Returns the number of elements in the segment array that would be * returned by {@link #segments segments}. */ int segmentCount(); /** * Provides fast, indexed access to individual segments in the path segment * array. * * @exception java.lang.IndexOutOfBoundsException * if <code>i < 0</code> or <code>i >= segmentCount()</code>. */ String segment(int i); /** * Returns the last segment in the segment array, or <code>null</code>. */ String lastSegment(); /** * If this is a hierarchical URI with a path, returns a string * representation of the path; <code>null</code> otherwise. The path * consists of a leading segment separator character (a slash), if the path * is absolute, followed by the slash-separated path segments. If this URI * has a separate <a href="#device_explanation">device component</a>, it is * <em>not</em> included in the path. */ String path(); /** * If this is a hierarchical URI with a path, returns a string * representation of the path, including the authority and the <a * href="#device_explanation">device component</a>; <code>null</code> * otherwise. * * <p> * If there is no authority, the format of this string is: * * <pre> * device/pathSegment1/pathSegment2... * </pre> * * <p> * If there is an authority, it is: * * <pre> * // authority/device/pathSegment1/pathSegment2... * </pre> * * <p> * For an <a href="#archive_explanation">archive URI</a>, it's just: * * <pre> * authority/pathSegment1/pathSegment2... * </pre> */ String devicePath(); /** * If this is a hierarchical URI with a query component, returns it; * <code>null</code> otherwise. */ String query(); /** * Returns the URI formed from this URI and the given query. * * @exception java.lang.IllegalArgumentException * if <code>query</code> is not a valid query (portion) * according to {@link #validQuery validQuery}. */ URI appendQuery(String query); /** * If this URI has a non-null {@link #query query}, returns the URI formed * by removing it; this URI unchanged, otherwise. */ URI trimQuery(); /** * If this URI has a fragment component, returns it; <code>null</code> * otherwise. */ String fragment(); /** * Returns the URI formed from this URI and the given fragment. * * @exception java.lang.IllegalArgumentException * if <code>fragment</code> is not a valid fragment (portion) * according to {@link #validFragment validFragment}. */ URI appendFragment(String fragment); /** * If this URI has a non-null {@link #fragment fragment}, returns the URI * formed by removing it; this URI unchanged, otherwise. */ URI trimFragment(); /** * If this URI has a non-null {@link #fragment fragment}, returns the URI * formed by removing it while keeping the '#' symbol; If this URI has no * fragment {@link #fragment fragment}, returns the URI without its last * segment; this URI unchanged, otherwise. */ URI namespace(); /** * Returns the URI formed from this URI and the given local part. * * @exception java.lang.IllegalArgumentException * if <code>localPart</code> is not a valid segment according * to {@link #validSegment} or a valid fragment (portion) * according to {@link #validFragment}. */ URI appendLocalPart(String localPart); /** * Returns the local part of this URI. * * <ul> * <li>If the URI has a fragment component then return it, else * <li>If the URI has a path then return the last path segment, * <li>If this fails, split after the last occurrence of the ':' character. * </ul> */ String localPart(); /** * Resolves this URI reference against a <code>base</code> absolute * hierarchical URI, returning the resulting absolute URI. If already * absolute, the URI itself is returned. URI resolution is described in * detail in section 5.2 of <a * href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>, * "Resolving Relative References to Absolute Form." * * <p> * During resolution, empty segments, self references ("."), and parent * references ("..") are interpreted, so that they can be removed from the * path. Step 6(g) gives a choice of how to handle the case where parent * references point to a path above the root: the offending segments can be * preserved or discarded. This method preserves them. To have them * discarded, please use the two-parameter form of * {@link #resolve(URI, boolean) resolve}. * * @exception java.lang.IllegalArgumentException * if <code>base</code> is non-hierarchical or is relative. */ URI resolve(URI base); /** * Resolves this URI reference against a <code>base</code> absolute * hierarchical URI, returning the resulting absolute URI. If already * absolute, the URI itself is returned. URI resolution is described in * detail in section 5.2 of <a * href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>, * "Resolving Relative References to Absolute Form." * * <p> * During resolution, empty segments, self references ("."), and parent * references ("..") are interpreted, so that they can be removed from the * path. Step 6(g) gives a choice of how to handle the case where parent * references point to a path above the root: the offending segments can be * preserved or discarded. This method can do either. * * @param preserveRootParents * <code>true</code> if segments referring to the parent of the * root path are to be preserved; <code>false</code> if they are * to be discarded. * * @exception java.lang.IllegalArgumentException * if <code>base</code> is non-hierarchical or is relative. */ URI resolve(URI base, boolean preserveRootParents); /** * Finds the shortest relative or, if necessary, the absolute URI that, when * resolved against the given <code>base</code> absolute hierarchical URI * using {@link #resolve(URI) resolve}, will yield this absolute URI. * * @exception java.lang.IllegalArgumentException * if <code>base</code> is non-hierarchical or is relative. * @exception java.lang.IllegalStateException * if <code>this</code> is relative. */ URI deresolve(URI base); /** * Finds an absolute URI that, when resolved against the given * <code>base</code> absolute hierarchical URI using * {@link #resolve(URI, boolean) resolve}, will yield this absolute URI. * * @param preserveRootParents * the boolean argument to <code>resolve(URI, * boolean)</code> for which the returned URI should resolve to this URI. * @param anyRelPath * if <code>true</code>, the returned URI's path (if any) will be * relative, if possible. If <code>false</code>, the form of the * result's path will depend upon the next parameter. * @param shorterRelPath * if <code>anyRelPath</code> is <code>false</code> and this * parameter is <code>true</code>, the returned URI's path (if * any) will be relative, if one can be found that is no longer * (by number of segments) than the absolute path. If both * <code>anyRelPath</code> and this parameter are * <code>false</code>, it will be absolute. * * @exception java.lang.IllegalArgumentException * if <code>base</code> is non-hierarchical or is relative. * @exception java.lang.IllegalStateException * if <code>this</code> is relative. */ URI deresolve(URI base, boolean preserveRootParents, boolean anyRelPath, boolean shorterRelPath); /** * If this URI may refer directly to a locally accessible file, as * determined by {@link #isFile isFile}, {@link #decode decodes} and formats * the URI as a pathname to that file; returns null otherwise. * * <p> * If there is no authority, the format of this string is: * * <pre> * device/pathSegment1/pathSegment2... * </pre> * * <p> * If there is an authority, it is: * * <pre> * // authority/device/pathSegment1/pathSegment2... * </pre> * * <p> * However, the character used as a separator is system-dependent and * obtained from {@link java.io.File#separatorChar}. */ String toFileString(); /** * If this is a platform URI, as determined by {@link #isPlatform}, returns * the workspace-relative or plug-in-based path to the resource, optionally * {@link #decode decoding} the segments in the process. * * @see #createPlatformResourceURI(String, boolean) * @see #createPlatformPluginURI * @since org.eclipse.emf.common 2.3 */ String toPlatformString(boolean decode); /** * Returns the URI formed by appending the specified segment on to the end * of the path of this URI, if hierarchical; this URI unchanged, otherwise. * If this URI has an authority and/or device, but no path, the segment * becomes the first under the root in an absolute path. * * @exception java.lang.IllegalArgumentException * if <code>segment</code> is not a valid segment according * to {@link #validSegment}. */ URI appendSegment(String segment); /** * Returns the URI formed by appending the specified segments on to the end * of the path of this URI, if hierarchical; this URI unchanged, otherwise. * If this URI has an authority and/or device, but no path, the segments are * made to form an absolute path. * * @param segments * an array of non-null strings, each representing one segment of * the path. If desired, a trailing separator should be * represented by an empty-string segment as the last element of * the array. * * @exception java.lang.IllegalArgumentException * if <code>segments</code> is not a valid segment array * according to {@link #validSegments}. */ URI appendSegments(String[] segments); /** * Returns the URI formed by trimming the specified number of segments * (including empty segments, such as one representing a trailing separator) * from the end of the path of this URI, if hierarchical; otherwise, this * URI is returned unchanged. * * <p> * Note that if all segments are trimmed from an absolute path, the root * absolute path remains. * * @param i * the number of segments to be trimmed in the returned URI. If * less than 1, this URI is returned unchanged; if equal to or * greater than the number of segments in this URI's path, all * segments are trimmed. */ URI trimSegments(int i); /** * Returns <code>true</code> if this is a hierarchical URI that has a path * that ends with a trailing separator; <code>false</code> otherwise. * * <p> * A trailing separator is represented as an empty segment as the last * segment in the path; note that this definition does <em>not</em> include * the lone separator in the root absolute path. */ boolean hasTrailingPathSeparator(); /** * If this is a hierarchical URI whose path includes a file extension, that * file extension is returned; null otherwise. We define a file extension as * any string following the last period (".") in the final path segment. If * there is no path, the path ends in a trailing separator, or the final * segment contains no period, then we consider there to be no file * extension. If the final segment ends in a period, then the file extension * is an empty string. */ String fileExtension(); /** * Returns the URI formed by appending a period (".") followed by the * specified file extension to the last path segment of this URI, if it is * hierarchical with a non-empty path ending in a non-empty segment; * otherwise, this URI is returned unchanged. * * <p> * The extension is appended regardless of whether the segment already * contains an extension. * * @exception java.lang.IllegalArgumentException * if <code>fileExtension</code> is not a valid segment * (portion) according to {@link #validSegment}. */ URI appendFileExtension(String fileExtension); /** * If this URI has a non-null {@link #fileExtension fileExtension}, returns * the URI formed by removing it; this URI unchanged, otherwise. */ URI trimFileExtension(); /** * Returns <code>true</code> if this is a hierarchical URI that ends in a * slash; that is, it has a trailing path separator or is the root absolute * path, and has no query and no fragment; <code>false</code> is returned * otherwise. */ boolean isPrefix(); /** * If this is a hierarchical URI reference and <code>oldPrefix</code> is a * prefix of it, this returns the URI formed by replacing it by * <code>newPrefix</code>; <code>null</code> otherwise. * * <p> * In order to be a prefix, the <code>oldPrefix</code>'s {@link #isPrefix * isPrefix} must return <code>true</code>, and it must match this URI's * scheme, authority, and device. Also, the paths must match, up to prefix's * end. * * @exception java.lang.IllegalArgumentException * if either <code>oldPrefix</code> or <code>newPrefix</code> * is not a prefix URI according to {@link #isPrefix}. */ URI replacePrefix(URI oldPrefix, URI newPrefix); }