/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.webservice;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.teiid.core.designer.HashCodeUtil;
/**
* @since 8.0
*/
public abstract class AbstractWebServiceResource implements IWebServiceResource {
private final String fullPath;
private final String namespace;
private final Set referencingResources;
private final Set referencedResources;
private final Set resolvedByThis;
private IWebServiceResource resolvedResource;
/**
*
* @since 4.2
*/
protected AbstractWebServiceResource( final String namespace, final String fullPath ) {
super();
this.referencedResources = new HashSet();
this.referencingResources = new HashSet();
this.resolvedByThis = new HashSet();
this.fullPath = fullPath != null && fullPath.trim().length() != 0 ? fullPath : null;
this.namespace = namespace;
}
protected abstract boolean exists();
protected abstract File doGetFile();
protected abstract InputStream doGetRawInputStream() throws Exception;
/**
* @see org.teiid.designer.webservice.IWebServiceResource#getFullPath()
* @since 4.2
*/
@Override
public String getFullPath() {
if ( this.fullPath != null && isResolvedToSelf() ) {
return this.fullPath;
}
if ( this.getResolvedResource() != null ) {
return this.getResolvedResource().getFullPath();
}
return null;
}
/**
* @see org.teiid.designer.webservice.IWebServiceResource#getFile()
* @since 4.2
*/
@Override
public File getFile() {
if ( this.resolvedResource != null ) {
return this.getResolvedResource().getFile();
}
return doGetFile();
}
/**
* @see org.teiid.designer.webservice.IWebServiceResource#getNamespace()
* @since 4.2
*/
@Override
public String getNamespace() {
return namespace;
}
/**
* @see org.teiid.designer.webservice.IWebServiceResource#isWsdl()
* @since 4.2
*/
@Override
public boolean isWsdl() {
final String path = this.getFullPath();
if ( path != null && path.length() > EXTENSION_WSDL.length() ) {
if ( path.toLowerCase().endsWith("." + EXTENSION_WSDL) ) { //$NON-NLS-1$
return true;
}
}
return false;
}
/**
* @see org.teiid.designer.webservice.IWebServiceResource#getInputStream()
* @since 4.2
*/
@Override
public InputStream getInputStream() throws Exception {
if ( this.isResolvedToSelf() ) {
if ( this.exists() ) {
final InputStream rawStream = doGetRawInputStream();
return new BufferedInputStream(rawStream);
}
return null;
}
if ( this.resolvedResource != null ) {
return this.resolvedResource.getInputStream();
}
return null;
}
/**
* @see org.teiid.designer.webservice.IWebServiceResource#isXsd()
* @since 4.2
*/
@Override
public boolean isXsd() {
final String path = this.getFullPath();
if ( path != null && path.length() > EXTENSION_XSD.length() ) {
if ( path.toLowerCase().endsWith("." + EXTENSION_XSD) ) { //$NON-NLS-1$
return true;
}
}
return false;
}
/**
* @see org.teiid.designer.webservice.IWebServiceResource#getReferencingResources()
* @since 4.2
*/
@Override
public Collection getReferencingResources() {
return this.referencingResources;
}
/**
* @see org.teiid.designer.webservice.IWebServiceResource#getReferencedResources()
* @since 4.2
*/
@Override
public Collection getReferencedResources() {
return this.referencedResources;
}
public synchronized void removeFromAllReferencers() {
final Iterator iter = getReferencingResources().iterator();
while (iter.hasNext()) {
final AbstractWebServiceResource referencing = (AbstractWebServiceResource)iter.next();
referencing.removeReferencedResource(this);
}
}
public synchronized boolean removeReferencedResource( final IWebServiceResource referenced ) {
if ( referenced == null ) {
return false;
}
if ( referenced == this ) {
return false;
}
final boolean removedReferenced = this.referencedResources.remove(referenced);
if ( removedReferenced && referenced instanceof AbstractWebServiceResource ) {
((AbstractWebServiceResource)referenced).referencingResources.remove(this);
}
return removedReferenced;
}
public synchronized boolean addReferencedResource( final IWebServiceResource referenced ) {
if ( referenced == null ) {
return false;
}
if ( referenced == this ) {
return false;
}
// Make sure there is no cirularity ...
final boolean directOrIndirect = this.isReferencedDirectlyOrIndirectly(referenced);
if ( directOrIndirect ) {
return false;
}
this.referencedResources.add(referenced);
if ( referenced instanceof AbstractWebServiceResource ) {
((AbstractWebServiceResource)referenced).referencingResources.add(this);
}
return true;
}
protected boolean isReferencedDirectlyOrIndirectly( final IWebServiceResource referenced ) {
final Iterator iter = this.referencedResources.iterator();
while (iter.hasNext()) {
final AbstractWebServiceResource directRef = (AbstractWebServiceResource)iter.next();
if ( directRef.equals(referenced) ) {
return true;
}
// See if the direct references the supplied
final boolean indirect = directRef.isReferencedDirectlyOrIndirectly(referenced);
if ( indirect ) {
return true;
}
}
return false;
}
/**
* @see org.teiid.designer.webservice.IWebServiceResource#getStatus()
* @since 4.2
*/
@Override
public IStatus getStatus() {
// Check that this is resolved ...
if ( this.isResolvedToSelf() ) {
final Object[] params = new Object[] {this.getNamespace(),this.getFullPath()};
final String msg = WebServicePlugin.Util.getString("AbstractWebServiceResource.NamespaceIsResolvedToSelf",params); //$NON-NLS-1$
return new Status(IStatus.OK,WebServicePlugin.PLUGIN_ID,STATUS_RESOLVED_TO_SELF,msg,null);
}
if ( this.isResolved() ) {
final Object[] params = new Object[] {this.getNamespace(),this.getFullPath()};
final String msg = WebServicePlugin.Util.getString("AbstractWebServiceResource.NamespaceIsResolved",params); //$NON-NLS-1$
return new Status(IStatus.OK,WebServicePlugin.PLUGIN_ID,STATUS_RESOLVED,msg,null);
}
// It's not resolved at all, but maybe there is a path that is invalid ...
if ( this.getFullPath() != null ) {
final Object[] params = new Object[] {this.getNamespace(),this.getFullPath()};
final String msg = WebServicePlugin.Util.getString("AbstractWebServiceResource.NamespaceIsResolvedToNonExistantFile",params); //$NON-NLS-1$
return new Status(IStatus.ERROR,WebServicePlugin.PLUGIN_ID,STATUS_RESOLVED_PATH_DOESNT_EXIST,msg,null);
}
// There is no path at all
final Object[] params = new Object[] {this.getNamespace()};
final String msg = WebServicePlugin.Util.getString("AbstractWebServiceResource.NamespaceIsUnresolved",params); //$NON-NLS-1$
return new Status(IStatus.ERROR,WebServicePlugin.PLUGIN_ID,STATUS_UNRESOLVED,msg,null);
}
/**
* @see org.teiid.designer.webservice.IWebServiceResource#isResolved()
* @since 4.2
*/
@Override
public boolean isResolved() {
if ( isResolvedToSelf() ) {
return true;
}
if ( this.resolvedResource == null ) {
// If this is not resolved by another resource, then this resource must exist to be resolved
return this.exists();
}
// This is resolved by another resource, so simply delegate ...
return this.resolvedResource.isResolved();
}
/**
* @see org.teiid.designer.webservice.IWebServiceResource#isResolvedToSelf()
* @since 4.2
*/
@Override
public boolean isResolvedToSelf() {
return resolvedResource == null && this.exists();
}
/**
* @see org.teiid.designer.webservice.IWebServiceResource#getResolvedResource()
* @since 4.2
*/
@Override
public IWebServiceResource getResolvedResource() {
return exists() && resolvedResource == null ? this : resolvedResource;
}
/**
* @see org.teiid.designer.webservice.IWebServiceResource#getResourcesResolved()
* @since 4.2
*/
@Override
public Collection getResourcesResolved() {
return this.resolvedByThis;
}
@Override
public IWebServiceResource getLastResolvedResource() {
IWebServiceResource result = this;
while ( result != null ) {
final IWebServiceResource resolved = result.getResolvedResource();
if ( resolved == null || resolved == result) {
return resolved;
}
result = result.getResolvedResource();
}
return null;
}
/**
* @see org.teiid.designer.webservice.IWebServiceResource#setResolvedResource(org.teiid.designer.webservice.IWebServiceResource)
* @since 4.2
*/
@Override
public boolean setResolvedResource( final IWebServiceResource resource ) {
if ( resource == this.resolvedResource ) {
return true; // do nothing ...
}
// Remove from existing ...
if ( this.resolvedResource instanceof AbstractWebServiceResource) {
((AbstractWebServiceResource)this.resolvedResource).resolvedByThis.remove(this);
}
if ( resource == null ) {
this.resolvedResource = null;
return true;
}
if ( resource == this ) {
// If setting to itself, then it must exist ...
if ( this.exists() ) {
this.resolvedResource = this;
return true;
}
return false;
}
this.resolvedResource = resource;
if ( this.resolvedResource instanceof AbstractWebServiceResource) {
((AbstractWebServiceResource)this.resolvedResource).resolvedByThis.add(this);
}
return true;
}
/**
* @see java.lang.Object#equals(java.lang.Object)
* @since 4.2
*/
@Override
public boolean equals(Object obj) {
if ( obj == null ) {
return false;
}
if ( obj == this ) {
return true;
}
// Instances must be of the same class
if ( !obj.getClass().equals(this.getClass()) ) {
return false;
}
final AbstractWebServiceResource that = (AbstractWebServiceResource)obj;
// Check the namespaces ...
if ( !this.getNamespace().equals(that.getNamespace()) ) {
return false;
}
// Namespaces are the same; check whether they both exist
if ( this.exists() != that.exists() ) {
return false; // one exists, and one doesn't
}
// Namespaces are same and they both exist; check that the full paths are the same ...
final String thisPath = this.getFullPath();
final String thatPath = that.getFullPath();
if ( thisPath == null ) {
if ( thatPath != null ) {
return false;
}
// Otherwise, both are null
} else {
if ( thatPath == null ) {
return false;
}
// Otherwise, both are non-null
if ( !this.getFullPath().equals(that.getFullPath()) ) {
return false; // different locations
}
}
// Namespaces and full paths are identical, and both exist directly. Therefore,
// they are two objects that represent the exact same resource
return true;
}
/**
* @see java.lang.Object#hashCode()
* @since 4.2
*/
@Override
public int hashCode() {
int hc = 0; // or = super.hashCode();
hc = HashCodeUtil.hashCode(hc, this.namespace);
hc = HashCodeUtil.hashCode(hc, this.getFullPath());
return hc;
}
/**
* @see java.lang.Object#toString()
* @since 4.2
*/
@Override
public String toString() {
if ( this.isResolvedToSelf() ) {
return this.getNamespace() + "->self->" + this.getFullPath(); //$NON-NLS-1$
}
return this.getNamespace() + "->" + this.getFullPath(); //$NON-NLS-1$
}
}