/*
* $Header: /home/cvs/jakarta-slide/src/share/org/apache/slide/store/ResourceId.java,v 1.2.2.1 2004/02/05 16:05:12 mholz Exp $
* $Revision: 1.2.2.1 $
* $Date: 2004/02/05 16:05:12 $
*
* ====================================================================
*
* Copyright 1999-2002 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.slide.store;
import java.util.Enumeration;
import org.apache.slide.common.Namespace;
import org.apache.slide.common.Scope;
import org.apache.slide.common.ScopeTokenizer;
import org.apache.slide.common.ServiceAccessException;
import org.apache.slide.common.ServiceConnectionFailedException;
import org.apache.slide.common.ServiceMissingOnRootNodeException;
import org.apache.slide.common.SlideToken;
import org.apache.slide.common.Uri;
import org.apache.slide.common.UriPath;
import org.apache.slide.content.NodeProperty;
import org.apache.slide.store.Store;
import org.apache.slide.util.Configuration;
import org.apache.slide.util.XMLValue;
import org.jdom.Element;
/**
* Uniquely identifies a resource. The main operation with ResourceIds is equals. Immutable.
*
* Technically, ResourceId extends Uri, but the only reason to do so is compatibility with
* existing store interfaces. Logically, a ResourceId is *not* an Uri: Uris have a structure,
* resourceId have not. Consequently, almost all Uri methods in this class throw
* UnsupportedOperation exceptions.
*
* @author michael.hartmeier@softwareag.com
* @author peter.nevermann@softwareag.com
* @version $Revision: 1.2.2.1 $
*/
public final class ResourceId extends Uri {
public static String RESOURCE_ID_SCHEMA = "urn:uuid:";
/**
** There are probably no two jvm's working on the same database that initialitzing this
** class at the same mill second
**/
private static final String TIMESTAMP = String.valueOf(System.currentTimeMillis());
/**
** Number of uuri created in this JVM session
**/
private static int counter = 0;
/**
* @pre uriStr has to contain store prefix, i.e. extractStoreUri has to succeed
*/
public static ResourceId createNew(Uri uri) {
String newUuri;
boolean useBinding = Configuration.useBinding(uri.getStore());
if (useBinding) {
String scopeSlash = uri.getScope().toString();
if (!"/".equals(scopeSlash)) {
scopeSlash += "/";
}
synchronized (ResourceId.class) {
newUuri = uri.isStoreRoot()
? scopeSlash
: scopeSlash+TIMESTAMP+"."+counter++;
}
} else {
newUuri = uri.toString();
}
return new ResourceId(uri, newUuri);
}
public static ResourceId create(Uri uri, String uuri) {
return new ResourceId(uri, uuri);
}
private static String resourceIdSchema(Store store) {
if (Configuration.useBinding(store)) {
return RESOURCE_ID_SCHEMA;
}
else {
return "";
}
}
private final String uuri;
/**
* Constructor
*
* @param uri an Uri
* @param id /scope/identifier
*
*/
private ResourceId(Uri uri, String uuri) {
super(uri.getToken(), uri.getNamespace(), uri.toString());
this.uuri = uuri;
parseUuri(uuri);
}
/**
* Tests equivalence of two ResourceIds.
*
* @param obj Object to test
* @return boolean
*/
public boolean equals(Object obj) {
ResourceId resourceId;
if (obj instanceof ResourceId) {
resourceId = (ResourceId) obj;
return getNamespace() == resourceId.getNamespace() &&
getStore() == resourceId.getStore() && uuri.equals(resourceId.uuri);
} else {
return false;
}
}
public String toString() {
return uuri;
}
/**
* Intentionally does not return anything like the origianl uri.
*
* @return String
*/
public String getUuri() {
return uuri;
}
/**
* Hash code.
*
* @return int hash code
*/
public int hashCode() {
return super.hashCode();
}
public Scope getScope() {
return super.getScope();
}
public Store getStore() {
return super.getStore();
}
public SlideToken getToken() {
return super.getToken();
}
public Namespace getNamespace() {
return super.getNamespace();
}
public boolean isStoreRoot() {
UriPath thisPath = new UriPath(uuri);
UriPath scopePath = new UriPath(scope.toString());
return thisPath.equals(scopePath);
}
// -------------------------------------------------------------
public void setUri(String uri) {
throw new UnsupportedOperationException();
}
public Enumeration getScopes() {
throw new UnsupportedOperationException();
}
public void setToken(SlideToken token) {
throw new UnsupportedOperationException();
}
public Uri getParentUri() {
throw new UnsupportedOperationException();
}
public void invalidateServices() {
throw new UnsupportedOperationException();
}
public void reconnectServices() {
throw new UnsupportedOperationException();
}
public String getRelative() {
throw new UnsupportedOperationException();
}
/**
* Do not clone ResourceId's, use aliasing.
*/
public Uri cloneObject() {
throw new UnsupportedOperationException();
}
public boolean isParent(Uri uri) {
throw new UnsupportedOperationException();
}
public String asXml() {
XMLValue r = new XMLValue();
Element hrefElm = new Element("href", NodeProperty.NamespaceCache.DEFAULT_NAMESPACE);
hrefElm.setText(resourceIdSchema(getStore())+getUuri());
r.add(hrefElm);
return r.toString();
}
/**
* This function is called by the constructor and when uri is changed.
*
* @param uri Uri to parse
*/
private void parseUuri(String uuri) {
// We first try to tokenize the uri string.
scopes = new ScopeTokenizer(token, namespace, uuri);
// Find the qualifiying stuff from the registry.
// Then we contentStore the scope of the found Data Source
// within scope.
store = null;
while ((store == null) && (scopes.hasMoreElements())) {
Scope courScope = scopes.nextScope();
try {
if (token == null) {
store = namespace.retrieveStore(courScope, null);
} else {
store = namespace.retrieveStore(courScope, token.getCredentialsToken());
}
if (store != null) {
scope = courScope;
}
}
catch (ServiceConnectionFailedException e) {
// Problem ...
// FIXME : Throw a RuntimeException ??
}
catch (ServiceAccessException e) {
// Problem ...
// FIXME : Throw a RuntimeException ??
}
}
// If descriptorsStore or contentStore is still null, then no valid
// scope is defined in the namespace ...
if (store == null) {
throw new ServiceMissingOnRootNodeException();
}
}
}