/* * Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * 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. * * * Neither the name of Business Objects nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. */ /* * ResourcePath.java * Creation date: Sep 13, 2004. * By: Edward Lam */ package org.openquark.cal.services; import java.util.Arrays; import java.util.List; /** * A ResourcePath represents a componentized path relative to the classloader root. * * This class is necessary because in our development environment, an abstract relative path such as "/CAL/" * can refer to more than one absolute path on the file system. * * @author Edward Lam */ public abstract class ResourcePath { public static final ResourcePath.Folder EMPTY_PATH = new ResourcePath.Folder(new String[0]); /** The path elements of which this path is comprised. */ private final String[] pathElements; /** * A ResourcePath which represents a Folder. * @author Edward Lam */ public static class Folder extends ResourcePath { /** * Constructor for a Folder. * @param pathElements the elements of which this path is comprised. */ public Folder(String[] pathElements) { super(pathElements); } /** * {@inheritDoc} */ @Override public ResourcePath.Folder getFolder() { return this; } /** * Get a resource path folder which represents this resource path, extended by one element. * @param newPathElement a new path element. * @return a new resource path, which represents this path extended by the given path element. */ public ResourcePath.FilePath extendFile(String newPathElement) { return (ResourcePath.FilePath)extend(newPathElement, false); } /** * Get a resource path folder which represents this resource path, extended by one element. * @param newPathElement a new path element. * @return a new resource path, which represents this path extended by the given path element. * If the new path element is empty, this folder is returned. */ public ResourcePath.Folder extendFolder(String newPathElement) { newPathElement = newPathElement.trim(); if (newPathElement.length() == 0) { return this; } return (ResourcePath.Folder)extend(newPathElement, true); } /** * Get a resource path folder which represents this resource path, extended by a number of elements. * @param newPathElements the new path elements. * @return a new resource path, which represents this path extended by the given path elements. */ public ResourcePath.Folder extendFolders(String[] newPathElements) { ResourcePath.Folder extendedFolder = this; for (final String element : newPathElements) { extendedFolder = extendedFolder.extendFolder(element); } return extendedFolder; } /** * Get a resource path which represents this resource path, extended by one element. * @param newPathElement a new path element. * @param folder if true, extend with a folder. Otherwise extend with a file. * @return a new resource path, which represents this path extended by the given path element. */ private ResourcePath extend(String newPathElement, boolean folder) { String[] pathElements = getPathElements(); String[] newPathElements = new String[pathElements.length + 1]; System.arraycopy(pathElements, 0, newPathElements, 0, pathElements.length); newPathElements[pathElements.length] = newPathElement; if (folder) { return new ResourcePath.Folder(newPathElements); } else { return new ResourcePath.FilePath(newPathElements); } } /** * Constructs a folder resource path from a path string without a leading slash. * <p> * Warning: This should not be exposed as part of the public API! * (path string without leading slashes is a package-private concept) * * @param pathStringMinusSlash a path string without a leading slash. * @return the corresponding folder resource path. */ static ResourcePath.Folder makeFromPathStringMinusSlash(String pathStringMinusSlash) { String[] elements = pathStringMinusSlash.split("/"); return new ResourcePath.Folder(elements); } } /** * A ResourcePath which represents a resource/file. * @author Edward Lam */ public static class FilePath extends ResourcePath { /** * Constructor for a FilePath. * @param pathElements the elements of which this path is comprised. */ public FilePath(String[] pathElements) { super(pathElements); } /** * {@inheritDoc} */ @Override public Folder getFolder() { String[] pathElements = getPathElements(); int nFolderElements = pathElements.length - 1; List<String> pathElementList = Arrays.asList(pathElements); List<String> pathElementSubList = pathElementList.subList(0, nFolderElements); String[] folderElements = new String[nFolderElements]; return new ResourcePath.Folder(pathElementSubList.toArray(folderElements)); } /** * @return the file component of the path. */ public String getFileName() { String[] pathElements = getPathElements(); return pathElements[pathElements.length - 1]; } } /** * Constructor for a ResourcePath. * @param pathElements the elements of which this path is comprised. */ private ResourcePath(String[] pathElements) { this.pathElements = pathElements.clone(); } /** * @return the path elements of which this path is comprised. */ public String[] getPathElements() { return pathElements; } /** * @return the last path element, or null if there aren't any. */ public String getName() { if (pathElements.length == 0) { return null; } return pathElements[pathElements.length - 1]; } /** * {@inheritDoc} */ @Override public String toString() { StringBuilder sb = new StringBuilder("ResourcePath: ["); for (int i = 0; i < pathElements.length; i++) { if (i > 0) { sb.append(", "); } sb.append(pathElements[i]); } sb.append("]"); return sb.toString(); } /** * Get the path in string form. * @return the path in string form. * ie. /pathElem1/pathElem2/.../pathElemn */ public String getPathString() { if (pathElements.length == 0) { return "/"; } StringBuilder sb = new StringBuilder(); for (final String element : pathElements) { sb.append("/" + element); } return sb.toString(); } /** * Get the path in string form, without the leading slash * @return the path in string form. * ie. pathElem1/pathElem2/.../pathElemn */ String getPathStringMinusSlash() { return getPathString().substring(1); } /** * @return the subpath of this path which corresponds to the path to the directory. */ public abstract Folder getFolder(); /** * {@inheritDoc} */ @Override public boolean equals(Object obj) { if (obj.getClass() != getClass()) { return false; } return Arrays.equals(getPathElements(), ((ResourcePath)obj).getPathElements()); } /** * {@inheritDoc} */ @Override public int hashCode() { int hash = (this instanceof Folder) ? 17 : 37; for (final String element : pathElements) { hash *= 37; hash += (17 * element.hashCode()); } return hash; } }