package org.bundlemaker.core.spi.analysis;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import org.bundlemaker.core.analysis.IAnalysisModelConfiguration;
import org.bundlemaker.core.analysis.IArtifactSelector;
import org.bundlemaker.core.analysis.IBundleMakerArtifact;
import org.bundlemaker.core.analysis.IDependency;
import org.bundlemaker.core.analysis.IRootArtifact;
import org.bundlemaker.core.internal.analysis.AdapterRoot2IArtifact;
import org.bundlemaker.core.resource.IModularizedSystem;
import org.eclipse.core.runtime.Assert;
import com.google.common.base.Joiner;
import com.google.common.collect.Iterables;
import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Query;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.blueprints.util.DefaultQuery;
/**
* <p>
* Abstract base class for all artifacts.
* </p>
*
* @author Kai Lehmann
* @author Gerd Wütherich (gerd@gerd-wuetherich.de)
*/
public abstract class AbstractArtifact implements IBundleMakerArtifact {
private final static AtomicLong ID_GENERATOR = new AtomicLong();
private final Long _id;
/** the name of this artifact */
private String _name;
/** the direct parent */
private IBundleMakerArtifact _parent;
/** the root artifact */
private AdapterRoot2IArtifact _root;
/** the properties */
private Map<String, Object> _properties;
/** CACHE */
private Set<IBundleMakerArtifact> _cachedParents;
/**
* <p>
* Creates a new instance of type {@link AbstractArtifact}.
* </p>
*
* @param name
* the name of this artifact, must not be {@code null}.
*/
public AbstractArtifact(String name) {
Assert.isNotNull(name);
this._id = ID_GENERATOR.getAndIncrement();
// set the name
this._name = name;
}
/**
* {@inheritDoc}
*/
@Override
public String getName() {
return _name;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isInstanceOf(Class<? extends IBundleMakerArtifact> clazz) {
// return false if clazz is null
if (clazz == null) {
return false;
}
// return result
return clazz.isAssignableFrom(this.getClass());
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
public <T extends IBundleMakerArtifact> T castTo(Class<T> clazz) {
//
Assert.isNotNull(clazz);
Assert.isTrue(isInstanceOf(clazz), String.format("Can not cast '%s' to '%s'.", this.getClass(), clazz));
// cast
return (T) this;
}
/**
* {@inheritDoc}
*/
@Override
public IModularizedSystem getModularizedSystem() {
return getRoot().getModularizedSystem();
}
/**
* {@inheritDoc}
*/
@Override
public IAnalysisModelConfiguration getConfiguration() {
return getRoot().getConfiguration();
}
/**
* {@inheritDoc}
*/
@Override
public IBundleMakerArtifact getParent() {
return _parent;
}
@Override
public Collection<? extends IBundleMakerArtifact> getAncestors() {
return Collections.unmodifiableCollection(getCachedParents());
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
public <T extends IBundleMakerArtifact> T getParent(Class<T> type) {
// return null if no parent exist
if (_parent == null || _parent == this) {
return null;
}
//
if (type.isAssignableFrom(_parent.getClass())) {
return (T) _parent;
}
//
return _parent.getParent(type);
}
@Override
public boolean isAncestorOf(IBundleMakerArtifact artifact) {
//
if (artifact == null) {
return false;
}
//
return ((AbstractArtifact) artifact).getCachedParents().contains(this);
}
/**
* {@inheritDoc}
*/
@Override
public IRootArtifact getRoot() {
//
if (_root == null) {
_root = (AdapterRoot2IArtifact) getParent(IRootArtifact.class);
}
//
return _root;
}
/**
* {@inheritDoc}
*/
@Override
public void setProperty(String key, Object value) {
Assert.isNotNull(key);
properties().put(key, value);
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
public <T> T getProperty(Object key, Class<T> t) {
T property = (T) properties().get(key);
if (property != null) {
return property;
} else if (this.getParent() != null) {
return this.getParent().getProperty(key, t);
} else {
return null;
}
}
public Set<String> getPropertyKeys() {
return properties().keySet();
}
/**
* {@inheritDoc}
*/
@Override
public Object getProperty(String key) {
return getProperty(key, Object.class);
}
/**
* {@inheritDoc}
*/
@Override
public void addArtifact(IBundleMakerArtifact artifact) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
@Override
public void addArtifacts(List<? extends IBundleMakerArtifact> artifact) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
@Override
public void addArtifacts(IArtifactSelector artifactSelector) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
@Override
public boolean removeArtifact(IBundleMakerArtifact artifact) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
@Override
public void removeArtifacts(List<? extends IBundleMakerArtifact> artifact) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
@Override
public void removeArtifacts(IArtifactSelector artifactSelector) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
@Override
public List<IReferencingArtifact> getContainedReferencingArtifacts() {
return Collections.emptyList();
}
/**
* {@inheritDoc}
*/
@Override
public List<IReferencedArtifact> getContainedReferencedArtifacts() {
return Collections.emptyList();
}
@Override
public Collection<IDependency> getDependenciesFrom() {
return Collections.emptyList();
}
@Override
public IDependency getDependencyFrom(IBundleMakerArtifact artifact) {
return null;
}
@Override
public Collection<IDependency> getDependenciesFrom(Collection<? extends IBundleMakerArtifact> artifacts) {
return Collections.emptyList();
}
@Override
public Collection<IDependency> getDependenciesFrom(IBundleMakerArtifact... artifacts) {
return Collections.emptyList();
}
@Override
public Collection<IDependency> getDependenciesTo() {
return Collections.emptyList();
}
@Override
public IDependency getDependencyTo(IBundleMakerArtifact artifact) {
return null;
}
@Override
public Collection<IDependency> getDependenciesTo(Collection<? extends IBundleMakerArtifact> artifacts) {
return Collections.emptyList();
}
@Override
public Collection<IDependency> getDependenciesTo(IBundleMakerArtifact... artifacts) {
return Collections.emptyList();
}
@Override
public Collection<IBundleMakerArtifact> getChildren() {
return Collections.emptySet();
}
@Override
public <T extends IBundleMakerArtifact> Collection<T> getChildren(Class<T> clazz) {
return Collections.emptySet();
}
/**
* <p>
* </p>
*
*/
public void invalidateCaches() {
_cachedParents = null;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return _name;
}
/**
* {@inheritDoc}
*/
@Override
public int compareTo(IBundleMakerArtifact o) {
//
if (o == null) {
return Integer.MIN_VALUE;
}
// compare the qualified name
return this.getQualifiedName().compareTo(o.getQualifiedName());
}
public void initializeCaches() {
getCachedParents();
}
/**
* <p>
* Sets the given parent
* </p>
*
* @param parent
* may be {@code null}.
*/
protected void setParent(IBundleMakerArtifact parent) {
this._parent = parent;
}
/**
* <p>
* Sets the name of this {@link IBundleMakerArtifact}.
* </p>
*
* @param name
* must not be {@code null}.
*/
protected void setName(String name) {
Assert.isNotNull(name);
this._name = name;
}
/**
* <p>
* Internal method that lazily initializes the properties map.
* </p>
*
* @return
*/
private Map<String, Object> properties() {
// lazy initialize the map
if (_properties == null) {
HashMap<String, Object> properties = new HashMap<String, Object>();
addDefaultProperties(properties);
_properties = properties;
}
// return the result
return _properties;
}
/**
* @param properties
*/
protected void addDefaultProperties(HashMap<String, Object> properties) {
properties.put("qname", getQualifiedName());
properties.put("name", getName());
// TODO
properties.put("artifacttype", getArtifactType());
}
/**
* Return the type of this artifact as a String. The return value will be put as 'artifacttype' in this artifact's
* {@link #getPropertyKeys() properties}
*
* @return
*/
protected abstract String getArtifactType();
/**
* <p>
* </p>
*
* @return
*/
private Set<IBundleMakerArtifact> getCachedParents() {
//
if (_cachedParents == null) {
//
_cachedParents = new HashSet<IBundleMakerArtifact>();
//
if (hasParent()) {
_cachedParents.add(getParent());
_cachedParents.addAll(((AbstractArtifact) getParent()).getCachedParents());
}
}
//
return _cachedParents;
}
// ---- Blueprint -----------------
/*
* (non-Javadoc)
*
* @see com.tinkerpop.blueprints.Vertex#getEdges(com.tinkerpop.blueprints.Direction, java.lang.String[])
*/
@Override
public Iterable<Edge> getEdges(Direction direction, String... labels) {
Iterable<? extends Edge> iterable = null;
switch (direction) {
case IN:
iterable = getDependenciesFrom();
break;
case OUT:
iterable = getDependenciesTo();
break;
case BOTH:
iterable = Iterables.concat(getDependenciesFrom(), getDependenciesTo());
break;
}
// TODO: Add parents and childs
if (labels == null || labels.length == 0) {
return (Iterable<Edge>) iterable;
}
throw new UnsupportedOperationException("getEdges with labels (" + Joiner.on(",").join(labels).toString()
+ ") not supported");
}
/*
* (non-Javadoc)
*
* @see com.tinkerpop.blueprints.Vertex#getVertices(com.tinkerpop.blueprints.Direction, java.lang.String[])
*/
@Override
public Iterable<Vertex> getVertices(Direction direction, String... labels) {
// TODO Auto-generated method stub
return null;
}
/*
* (non-Javadoc)
*
* @see com.tinkerpop.blueprints.Vertex#query()
*/
@Override
public Query query() {
return new DefaultQuery(this);
}
/*
* (non-Javadoc)
*
* @see com.tinkerpop.blueprints.Element#removeProperty(java.lang.String)
*/
@Override
public Object removeProperty(String key) {
throw new UnsupportedOperationException();
}
/*
* (non-Javadoc)
*
* @see com.tinkerpop.blueprints.Element#getId()
*/
@Override
public Object getId() {
return this._id;
}
}