package org.bundlemaker.core.internal.analysis;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.bundlemaker.core.analysis.IAnalysisModelConfiguration;
import org.bundlemaker.core.analysis.IAnalysisModelModifiedListener;
import org.bundlemaker.core.analysis.IAnalysisModelVisitor;
import org.bundlemaker.core.analysis.IBundleMakerArtifact;
import org.bundlemaker.core.analysis.IDependency;
import org.bundlemaker.core.analysis.IGroupAndModuleContainer;
import org.bundlemaker.core.analysis.IGroupArtifact;
import org.bundlemaker.core.analysis.IModuleArtifact;
import org.bundlemaker.core.analysis.IResourceArtifact;
import org.bundlemaker.core.analysis.IRootArtifact;
import org.bundlemaker.core.internal.analysis.cache.ArtifactCache;
import org.bundlemaker.core.internal.analysis.cache.ModuleKey;
import org.bundlemaker.core.internal.analysis.cache.impl.ModuleSubCache;
import org.bundlemaker.core.internal.api.resource.IModifiableModularizedSystem;
import org.bundlemaker.core.internal.modelext.ModelExtFactory;
import org.bundlemaker.core.internal.modules.ChangeAction;
import org.bundlemaker.core.internal.modules.Group;
import org.bundlemaker.core.internal.modules.Module;
import org.bundlemaker.core.internal.modules.event.ClassificationChangedEvent;
import org.bundlemaker.core.internal.modules.event.GroupChangedEvent;
import org.bundlemaker.core.internal.modules.event.IModularizedSystemChangedListener;
import org.bundlemaker.core.internal.modules.event.ModuleClassificationChangedEvent;
import org.bundlemaker.core.internal.modules.event.ModuleIdentifierChangedEvent;
import org.bundlemaker.core.internal.modules.event.ModuleMovedEvent;
import org.bundlemaker.core.internal.modules.event.MovableUnitMovedEvent;
import org.bundlemaker.core.project.IProjectContentResource;
import org.bundlemaker.core.resource.IModule;
import org.bundlemaker.core.resource.IModuleAwareMovableUnit;
import org.bundlemaker.core.resource.IModuleResource;
import org.bundlemaker.core.spi.analysis.AbstractArtifact;
import org.bundlemaker.core.spi.analysis.AbstractArtifactContainer;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Features;
import com.tinkerpop.blueprints.Graph;
import com.tinkerpop.blueprints.Vertex;
/**
* <p>
* </p>
*
* @author Gerd Wütherich (gerd@gerd-wuetherich.de)
*/
public class AdapterRoot2IArtifact extends AbstractArtifactContainer implements IRootArtifact,
IModularizedSystemChangedListener {
/** - */
private IModifiableModularizedSystem _modularizedSystem;
/** - */
private ArtifactCache _artifactCache;
/** - */
private final GroupAndModuleContainerDelegate _groupAndModuleContainerDelegate;
/** - */
private final IAnalysisModelConfiguration _artifactModelConfiguration;
/** - */
private final CopyOnWriteArrayList<IAnalysisModelModifiedListener> _artifactModelChangedListeners;
/** - */
private boolean _cachesInitialized;
private boolean _isInInvalidationCaches;
/**
* <p>
* Creates a new instance of type {@link AdapterModule2IArtifact}.
* </p>
*
* @param modularizedSystem
* @param artifactCache
*/
public AdapterRoot2IArtifact(IModifiableModularizedSystem modularizedSystem,
IAnalysisModelConfiguration modelConfiguration, ArtifactCache artifactCache) {
super(name(modularizedSystem));
//
Assert.isNotNull(modelConfiguration);
// set the resource module
_modularizedSystem = modularizedSystem;
_modularizedSystem.getListenerList().addModularizedSystemChangedListener(this);
//
_artifactCache = artifactCache;
//
_artifactModelConfiguration = modelConfiguration;
//
_groupAndModuleContainerDelegate = new GroupAndModuleContainerDelegate(this);
//
_artifactModelChangedListeners = new CopyOnWriteArrayList<IAnalysisModelModifiedListener>();
}
@Override
public void resetTransformations() {
getModularizedSystem().undoTransformations(null);
}
@Override
public final void disableModelModifiedNotification(boolean isDisabled) {
getModularizedSystem().getListenerList().disableModelModifiedNotification(isDisabled);
}
/**
* {@inheritDoc}
*/
@Override
public final void modelModifiedNotificationDisabled(boolean isDisabled) {
//
if (!isDisabled) {
for (IAnalysisModelModifiedListener artifactModelChangedListener : _artifactModelChangedListeners) {
artifactModelChangedListener.analysisModelModified();
}
}
}
/**
* {@inheritDoc}
*/
@Override
public final boolean isModelModifiedNotificationDisabled() {
return getModularizedSystem().getListenerList().isModelModifiedNotificationDisabled();
}
@Override
public final boolean areCachesInitialized() {
return _cachesInitialized;
}
/**
* {@inheritDoc}
*/
@Override
public final void initializeCaches(IProgressMonitor progressMonitor) {
//
this.accept(new IAnalysisModelVisitor.Adapter() {
@Override
public boolean onVisit(IBundleMakerArtifact artifact) {
((AbstractArtifact) artifact).initializeCaches();
return true;
}
});
//
_cachesInitialized = true;
}
/**
* {@inheritDoc}
*/
@Override
public IModuleArtifact getModuleArtifact(IModule module) {
Assert.isNotNull(module);
return _artifactCache.getModuleCache().get(new ModuleKey(module));
}
@Override
public IGroupArtifact getGroupArtifact(Group group) {
Assert.isNotNull(group);
return (IGroupArtifact) _artifactCache.getGroupCache().get(group);
}
/**
* {@inheritDoc}
*/
@Override
public IResourceArtifact getResourceArtifact(IModuleResource resource) {
return _artifactCache.getResourceCache().get(resource);
}
/**
* <p>
* </p>
*
* @return
*/
public ArtifactCache getArtifactCache() {
return _artifactCache;
}
/**
* {@inheritDoc}
*/
@Override
public IAnalysisModelConfiguration getConfiguration() {
return _artifactModelConfiguration;
}
/**
* {@inheritDoc}
*/
public IModuleArtifact getOrCreateModule(String qualifiedModuleName, String moduleVersion) {
return _groupAndModuleContainerDelegate.getOrCreateModule(qualifiedModuleName, moduleVersion);
}
/**
* {@inheritDoc}
*/
public IGroupArtifact getOrCreateGroup(IPath path) {
return _groupAndModuleContainerDelegate.getOrCreateGroup(path);
}
/**
* {@inheritDoc}
*/
public IGroupArtifact getOrCreateGroup(String path) {
return _groupAndModuleContainerDelegate.getOrCreateGroup(path);
}
@Override
public boolean isVirtual() {
return false;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isMovable() {
return false;
}
@Override
public final String getName() {
return _modularizedSystem.getName();
}
@Override
public final String getQualifiedName() {
return getName();
}
@Override
public IModifiableModularizedSystem getModularizedSystem() {
return _modularizedSystem;
}
@Override
public String handleCanAdd(IBundleMakerArtifact artifact) {
//
if (!(artifact.isInstanceOf(IGroupArtifact.class) || artifact instanceof AdapterModule2IArtifact)) {
return "Only groups and modules are addable to root";
}
// prevent entries with duplicate names entries
if (getChild(artifact.getName()) != null) {
return String.format("The group '%s' already contains a child with the name '%s'.", this.getQualifiedName(),
artifact.getName());
}
//
return null;
}
@Override
public IRootArtifact getRoot() {
return this;
}
@Override
public IPath getFullPath() {
return new Path(".");
}
@Override
protected void onRemoveArtifact(IBundleMakerArtifact artifact) {
// CHANGE THE UNDERLYING MODEL
if (!AdapterUtils.removeResourceModuleFromModularizedSystem(artifact)) {
internalRemoveArtifact(artifact);
}
}
/**
* {@inheritDoc}
*/
@Override
public void accept(IAnalysisModelVisitor visitor) {
//
if (visitor.visit(this)) {
//
for (IBundleMakerArtifact artifact : getChildren()) {
((IBundleMakerArtifact) artifact).accept(visitor);
}
}
}
/**
* {@inheritDoc}
*/
@Override
public void movableUnitChanged(MovableUnitMovedEvent event, ChangeAction action) {
switch (action) {
case ADDED: {
// get the movable unit
IModuleAwareMovableUnit movableUnit = event.getMovableUnit();
IAnalysisModelConfiguration configuration = getConfiguration();
// Step 1: Handle resources
// Step 1a: Handle BinaryContent
if (configuration.isBinaryContent() && movableUnit.hasAssociatedBinaryResources()) {
// iterate over the associated binary resources
for (IProjectContentResource resource : movableUnit.getAssociatedBinaryResources()) {
_addResource(resource.adaptAs(IModuleResource.class));
}
}
// Step 1b: Handle SourceContent
else if (configuration.isSourceContent() && movableUnit.hasAssociatedSourceResource()) {
// iterate over the associated binary resources
_addResource(movableUnit.getAssociatedSourceResource().adaptAs(IModuleResource.class));
}
// TODO: BUGFIX!!
else if (configuration.isSourceContent() && movableUnit.hasAssociatedBinaryResources()) {
// iterate over the associated binary resources
for (IProjectContentResource resource : movableUnit.getAssociatedBinaryResources()) {
_addResource(resource.adaptAs(IModuleResource.class));
}
}
break;
}
case REMOVED: {
//
IModuleAwareMovableUnit movableUnit = event.getMovableUnit();
IAnalysisModelConfiguration configuration = getConfiguration();
if (configuration.isBinaryContent() && movableUnit.hasAssociatedBinaryResources()
/* && ( configuration.containsAllResources() || !movableUnit.hasAssociatedTypes()) */) {
for (IProjectContentResource resource : movableUnit.getAssociatedBinaryResources()) {
IBundleMakerArtifact artifact = _artifactCache.getResourceCache().get(resource);
if (artifact != null && artifact.getParent() != null) {
((AdapterPackage2IArtifact) artifact.getParent()).internalRemoveArtifact(artifact);
}
}
} else if (configuration.isSourceContent() && movableUnit.hasAssociatedSourceResource()
/* && ( configuration.containsAllResources() || !movableUnit.hasAssociatedTypes()) */) {
IProjectContentResource resource = movableUnit.getAssociatedSourceResource();
IBundleMakerArtifact artifact = _artifactCache.getResourceCache().get(resource);
if (artifact != null && artifact.getParent() != null) {
((AdapterPackage2IArtifact) artifact.getParent()).internalRemoveArtifact(artifact);
}
}
break;
}
}
//
handleModelModification();
}
private void _addResource(IModuleResource resource) {
//
if (!ModelExtFactory.getModelExtensionFactory().shouldAddResourceArtifact(resource)) {
return;
}
// add the resource
IBundleMakerArtifact artifact = _artifactCache.getResourceCache().getOrCreate(resource);
AbstractArtifactContainer parentArtifact = _artifactCache.getResourceCache().getOrCreateParent(resource);
parentArtifact.internalAddArtifact(artifact);
}
@Override
public void moduleIdentifierChanged(ModuleIdentifierChangedEvent event) {
//
ModuleSubCache moduleCache = _artifactCache.getModuleCache();
//
AdapterModule2IArtifact moduleArtifact = (AdapterModule2IArtifact) moduleCache.getOrCreate(new ModuleKey(event
.getModule()));
moduleArtifact.setName(event.getModule().getModuleIdentifier().toString());
//
handleModelModification();
}
/**
* {@inheritDoc}
*/
@Override
public void moduleChanged(ModuleMovedEvent event, ChangeAction changeAction) {
switch (changeAction) {
case ADDED: {
//
ModuleSubCache moduleCache = _artifactCache.getModuleCache();
//
AdapterModule2IArtifact moduleArtifact = (AdapterModule2IArtifact) moduleCache.getOrCreate(new ModuleKey(event
.getModule()));
//
if (moduleArtifact.getParent() == null) {
IGroupAndModuleContainer parent = moduleCache.getModuleParent(event.getModule());
((AbstractArtifactContainer) parent).internalAddArtifact(moduleArtifact);
}
break;
}
case REMOVED: {
AdapterModule2IArtifact moduleArtifact = (AdapterModule2IArtifact) _artifactCache.getModuleCache().get(
new ModuleKey(event.getModule()));
if (moduleArtifact != null) {
((AbstractArtifactContainer) moduleArtifact.getParent()).internalRemoveArtifact(moduleArtifact);
}
break;
}
}
//
handleModelModification();
}
/**
* {@inheritDoc}
*/
@Override
public void moduleClassificationChanged(ModuleClassificationChangedEvent event) {
//
IModule module = event.getModule();
//
IBundleMakerArtifact moduleArtifact = _artifactCache.getModuleCache().getOrCreate(
new ModuleKey(
module));
//
Group classification = ((Module) module).getClassificationGroup();
if (classification != null) {
IGroupAndModuleContainer groupArtifact = _artifactCache.getGroupCache().getOrCreate(classification);
((AbstractArtifactContainer) groupArtifact).internalAddArtifact(moduleArtifact);
} else {
internalAddArtifact(moduleArtifact);
}
//
handleModelModification();
}
/**
* {@inheritDoc}
*/
@Override
public void classificationChanged(ClassificationChangedEvent event) {
//
if (event.isMovedGroup()) {
//
IBundleMakerArtifact movedGroupArtifact = _artifactCache.getGroupCache().getOrCreate(
event.getMovedGroup());
//
if (((Group) event.getMovedGroup()).getParentGroup() == null) {
//
if (((Group) event.getMovedGroup()).hasRootParent()) {
this.internalAddArtifact(movedGroupArtifact);
}
//
else {
AbstractArtifactContainer currentParent = (AbstractArtifactContainer) movedGroupArtifact
.getParent();
currentParent.internalRemoveArtifact(movedGroupArtifact);
}
}
//
else {
IBundleMakerArtifact parentArtifact = _artifactCache.getGroupCache()
.getOrCreate(
event.getNewParentGroup());
((AbstractArtifactContainer) parentArtifact).internalAddArtifact(movedGroupArtifact);
}
}
//
else if (event.isGroupRenamed()) {
// nothing to do here...
}
//
handleModelModification();
}
/**
* {@inheritDoc}
*/
@Override
public void groupChanged(GroupChangedEvent event, ChangeAction changeAction) {
switch (changeAction) {
case ADDED: {
getArtifactCache().getGroupCache().getOrCreate((Group) event.getGroup());
break;
}
case REMOVED: {
IGroupArtifact groupArtifact = getRoot().getGroupArtifact(event.getGroup());
AbstractArtifactContainer parent = (AbstractArtifactContainer) groupArtifact.getParent();
parent.internalRemoveArtifact(groupArtifact);
break;
}
}
//
handleModelModification();
}
/**
* <p>
* </p>
*
* @param modularizedSystem
* @return
*/
private static String name(IModifiableModularizedSystem modularizedSystem) {
Assert.isNotNull(modularizedSystem);
return modularizedSystem.getName();
}
/**
* <p>
* </p>
*
* @param listener
*/
public void addAnalysisModelModifiedListener(IAnalysisModelModifiedListener listener) {
Assert.isNotNull(listener);
_artifactModelChangedListeners.addIfAbsent(listener);
}
/**
* <p>
* </p>
*
* @param listener
*/
public void removeAnalysisModelModifiedListener(IAnalysisModelModifiedListener listener) {
Assert.isNotNull(listener);
_artifactModelChangedListeners.remove(listener);
}
/**
* <p>
* </p>
*
*/
public void handleModelModification() {
//
if (!getModularizedSystem().getListenerList().isHandleModelModification()) {
return;
}
//
_cachesInitialized = false;
//
_isInInvalidationCaches = true;
this.accept(new IAnalysisModelVisitor.Adapter() {
@Override
public boolean onVisit(IBundleMakerArtifact artifact) {
((AbstractArtifact) artifact).invalidateCaches();
return true;
}
});
_isInInvalidationCaches = false;
//
if (!getModularizedSystem().getListenerList().isModelModifiedNotificationDisabled()) {
for (IAnalysisModelModifiedListener artifactModelChangedListener : _artifactModelChangedListeners) {
artifactModelChangedListener.analysisModelModified();
}
}
}
/**
* <p>
* </p>
*
* @return
*/
public boolean isInInvalidationCaches() {
return _isInInvalidationCaches;
}
// --- Blueprint API -------------------
private final Function<IDependency, Edge> _dependencyToEdgeConverterFunction = new Function<IDependency, Edge>() {
@Override
public Edge apply(
IDependency dependency) {
return dependency;
}
};
/*
* (non-Javadoc)
*
* @see com.tinkerpop.blueprints.Graph#getFeatures()
*/
@Override
public Features getFeatures() {
throw new UnsupportedOperationException();
}
/*
* (non-Javadoc)
*
* @see com.tinkerpop.blueprints.Graph#addVertex(java.lang.Object)
*/
@Override
public Vertex addVertex(Object id) {
throw new UnsupportedOperationException("addVertex");
}
/*
* (non-Javadoc)
*
* @see com.tinkerpop.blueprints.Graph#getVertex(java.lang.Object)
*/
@Override
public Vertex getVertex(Object id) {
throw new UnsupportedOperationException("getVertex");
}
/*
* (non-Javadoc)
*
* @see com.tinkerpop.blueprints.Graph#removeVertex(com.tinkerpop.blueprints.Vertex)
*/
@Override
public void removeVertex(Vertex vertex) {
throw new UnsupportedOperationException("removeVertex");
}
/*
* (non-Javadoc)
*
* @see com.tinkerpop.blueprints.Graph#getVertices()
*/
@Override
public Iterable<Vertex> getVertices() {
final List<Vertex> result = new LinkedList<Vertex>();
accept(new IAnalysisModelVisitor.Adapter() {
/*
* (non-Javadoc)
*
* @see org.bundlemaker.core.analysis.IAnalysisModelVisitor.Adapter#onVisit(org.bundlemaker.core.analysis.
* IBundleMakerArtifact)
*/
@Override
public boolean onVisit(IBundleMakerArtifact artifact) {
result.add(artifact);
return true;
}
});
return result;
}
/*
* (non-Javadoc)
*
* @see com.tinkerpop.blueprints.Graph#getVertices(java.lang.String, java.lang.Object)
*/
@Override
public Iterable<Vertex> getVertices(String key, Object value) {
throw new UnsupportedOperationException();
}
/*
* (non-Javadoc)
*
* @see com.tinkerpop.blueprints.Graph#addEdge(java.lang.Object, com.tinkerpop.blueprints.Vertex,
* com.tinkerpop.blueprints.Vertex, java.lang.String)
*/
@Override
public Edge addEdge(Object id, Vertex outVertex, Vertex inVertex, String label) {
throw new UnsupportedOperationException("addEdge");
}
/*
* (non-Javadoc)
*
* @see com.tinkerpop.blueprints.Graph#getEdge(java.lang.Object)
*/
@Override
public Edge getEdge(Object id) {
throw new UnsupportedOperationException();
}
/*
* (non-Javadoc)
*
* @see com.tinkerpop.blueprints.Graph#removeEdge(com.tinkerpop.blueprints.Edge)
*/
@Override
public void removeEdge(Edge edge) {
throw new UnsupportedOperationException("removeEdge");
}
/*
* (non-Javadoc)
*
* @see com.tinkerpop.blueprints.Graph#getEdges()
*/
@Override
public Iterable<Edge> getEdges() {
return toEdgeIterable(getDependenciesTo());
}
private Iterable<Edge> toEdgeIterable(Iterable<IDependency> iterable) {
return Iterables.transform(iterable, _dependencyToEdgeConverterFunction);
}
/*
* (non-Javadoc)
*
* @see com.tinkerpop.blueprints.Graph#getEdges(java.lang.String, java.lang.Object)
*/
@Override
public Iterable<Edge> getEdges(String key, Object value) {
throw new UnsupportedOperationException();
}
/*
* (non-Javadoc)
*
* @see com.tinkerpop.blueprints.Graph#shutdown()
*/
@Override
public void shutdown() {
}
/*
* (non-Javadoc)
*
* @see org.bundlemaker.core.analysis.IRootArtifact#getBlueprintGraph()
*/
@Override
public Graph getBlueprintGraph() {
return this;
}
/*
* (non-Javadoc)
*
* @see org.bundlemaker.core.analysis.spi.AbstractArtifact#getArtifactType()
*/
@Override
protected String getArtifactType() {
return "root";
}
}