blob: 77cb36b9872228bd6678fc60d190c850ffb07dd0 [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2007 The University of Manchester
*
* Modifications to the initial code base are copyright of their
* respective authors, or their employers as appropriate.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
******************************************************************************/
package net.sf.taverna.t2.reference.impl;
import java.io.Serializable;
import java.net.URI;
import java.net.URISyntaxException;
import net.sf.taverna.t2.reference.T2Reference;
import net.sf.taverna.t2.reference.T2ReferenceType;
import net.sf.taverna.t2.reference.h3.HibernateComponentClass;
/**
* An implementation of T2Reference specific to the ReferenceSetImpl. This is
* needed because ReferenceSetImpl uses a component based primary key driven
* from the namespace and local parts of T2Reference. This in turn means we can
* query hibernate directly with a T2Reference instance in the data access
* object. Because this is only used as a component (i.e. a value type) we don't
* need to define a hibernate mapping file for it.
*
* @author Tom Oinn
*
*/
public class T2ReferenceImpl implements T2Reference, Serializable,
HibernateComponentClass {
private static final long serialVersionUID = 8363330461158750319L;
private URI cachedUri = null;
private String localPart;
private String namespacePart;
private boolean containsErrors = false;
private T2ReferenceType referenceType = T2ReferenceType.ReferenceSet;
private int depth = 0;
public T2ReferenceImpl() {
// Default constructor for Hibernate et al
}
/**
* Construct a deep copy of the given T2Reference
*
* @param source
* T2Reference to copy
*/
private T2ReferenceImpl(T2Reference source) {
super();
setNamespacePart(source.getNamespacePart());
setLocalPart(source.getLocalPart());
setContainsErrors(source.containsErrors());
setReferenceType(source.getReferenceType());
setDepth(source.getDepth());
}
public static T2ReferenceImpl getAsImpl(T2Reference source) {
if (source instanceof T2ReferenceImpl) {
return (T2ReferenceImpl) source;
} else {
return new T2ReferenceImpl(source);
}
}
/**
* Return whether the identified entity either is or contains errors
*/
public boolean containsErrors() {
return this.containsErrors;
}
/**
* Property accessor for Hibernate, complies with java bean spec
*/
public boolean getContainsErrors() {
return this.containsErrors;
}
/**
* Get the depth of the entity referred to by this reference
*/
public int getDepth() {
return this.depth;
}
/**
* Get the local part of the URI for this reference
*/
public String getLocalPart() {
return this.localPart;
}
/**
* Get the namespace part of the URI for this reference
*/
public String getNamespacePart() {
return namespacePart;
}
/**
* Get the type of the entity to which this reference refers
*/
public T2ReferenceType getReferenceType() {
return this.referenceType;
}
/**
* This method is only ever called from within Hibernate when
* re-constructing the identifier component to set the namespace part of the
* identifier.
*/
public synchronized void setNamespacePart(String namespacePart) {
this.namespacePart = namespacePart;
this.hashCode = -1;
cachedUri = null;
}
/**
* This method is only ever called from within Hibernate when
* re-constructing the identifier component to set the local part of the
* identifier.
*/
public synchronized void setLocalPart(String localPart) {
this.localPart = localPart;
this.hashCode = -1;
cachedUri = null;
}
/**
* This method is only ever called from within Hibernate when
* re-constructing the identifier component to set the depth of the
* identifier.
*/
public synchronized void setDepth(int depth) {
this.depth = depth;
this.hashCode = -1;
cachedUri = null;
}
/**
* This method is only ever called from within Hibernate when
* re-constructing the identifier component to set the error property of the
* identifier.
*/
public synchronized void setContainsErrors(boolean containsErrors) {
this.containsErrors = containsErrors;
cachedUri = null;
}
/**
* This method is only ever called from within Hibernate when
* re-constructing the identifier component to set the reference type
* property of the identifier.
*/
public synchronized void setReferenceType(T2ReferenceType type) {
this.referenceType = type;
cachedUri = null;
}
/**
* By default when printing an identifier we use {@link #toUri()}.{@link java.net.URI#toASCIIString() toASCIIString()}
*/
@Override
public String toString() {
return toUri().toASCIIString();
}
/**
* Drill inside an error document reference to get the error one deeper than
* this as long as it is at least depth 1.
*/
T2ReferenceImpl getDeeperErrorReference() {
if (getReferenceType().equals(T2ReferenceType.ErrorDocument)) {
if (getDepth() == 0) {
throw new AssertionError(
"Error identifier already has depth 0, cannot decrease");
}
T2ReferenceImpl result = new T2ReferenceImpl();
result.setContainsErrors(true);
result.setDepth(getDepth() - 1);
result.setLocalPart(getLocalPart());
result.setNamespacePart(getNamespacePart());
result.setReferenceType(T2ReferenceType.ErrorDocument);
return result;
}
throw new AssertionError(
"Attempt to get a deeper reference on something that isn't an error ref");
}
/**
* Returns the identifier expressed as a {@link java.net.URI URI},
* constructed based on the reference type. For references to ReferenceSet
* this is
* <code>new URI("t2:ref//" + namespacePart + "?" + localPart)</code>
* leading to URIs of the form <code>t2:ref//namespace?local</code>
*/
public synchronized URI toUri() {
if (cachedUri != null) {
return cachedUri;
} else if (referenceType.equals(T2ReferenceType.ReferenceSet)) {
try {
URI result = new URI("t2:ref//" + namespacePart + "?"
+ localPart);
cachedUri = result;
return result;
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
} else if (referenceType.equals(T2ReferenceType.IdentifiedList)) {
try {
URI result = new URI("t2:list//" + namespacePart + "?"
+ localPart + "/" + containsErrors + "/" + depth);
cachedUri = result;
return result;
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
} else if (referenceType.equals(T2ReferenceType.ErrorDocument)) {
try {
URI result = new URI("t2:error//" + namespacePart + "?"
+ localPart + "/" + depth);
cachedUri = result;
return result;
} catch (URISyntaxException e) {
e.printStackTrace();
return null;
}
} else {
return null;
}
}
/**
* Use the equality operator over the URI representation of this bean.
*/
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}
if (other instanceof T2ReferenceImpl) {
T2ReferenceImpl otherRef = (T2ReferenceImpl) other;
if (localPart.equals(otherRef.localPart)
&& namespacePart.equals(otherRef.namespacePart)
&& depth == otherRef.depth) {
return true;
} else {
return false;
}
} else {
return false;
}
}
private int hashCode = -1;
/**
* Use hashcode method from the string representation of namespace, local
* and depth parts
*/
@Override
public synchronized int hashCode() {
if (this.hashCode == -1) {
this.hashCode = getCompactForm().hashCode();
}
return this.hashCode;
}
private String compactForm = null;
public synchronized String getCompactForm() {
if (this.compactForm == null) {
this.compactForm = getNamespacePart() + ":" + getLocalPart() + ":"
+ getDepth();
}
return this.compactForm;
}
}