/**
* Copyright (c) 2002-2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
*/
package org.eclipse.emf.mapping.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.notify.impl.AdapterFactoryImpl;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.common.notify.impl.NotificationImpl;
import org.eclipse.emf.common.notify.impl.NotifyingListImpl;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.edit.provider.ChangeNotifier;
import org.eclipse.emf.edit.provider.Disposable;
import org.eclipse.emf.edit.provider.IDisposable;
import org.eclipse.emf.edit.provider.INotifyChangedListener;
import org.eclipse.emf.mapping.MappedObjectState;
import org.eclipse.emf.mapping.Mapping;
import org.eclipse.emf.mapping.MappingFactory;
import org.eclipse.emf.mapping.MappingPackage;
import org.eclipse.emf.mapping.MappingRoot;
import org.eclipse.emf.mapping.domain.MappingDomain;
/**
* <!-- begin-user-doc -->
* An implementation of the model object '<em><b>Root</b></em>'.
* <!-- end-user-doc -->
* <p>
* The following features are implemented:
* </p>
* <ul>
* <li>{@link org.eclipse.emf.mapping.impl.MappingRootImpl#isOutputReadOnly <em>Output Read Only</em>}</li>
* <li>{@link org.eclipse.emf.mapping.impl.MappingRootImpl#isTopToBottom <em>Top To Bottom</em>}</li>
* <li>{@link org.eclipse.emf.mapping.impl.MappingRootImpl#getCommandStack <em>Command Stack</em>}</li>
* </ul>
*
* @generated
*/
public class MappingRootImpl extends MappingImpl implements MappingRoot
{
/**
* The default value of the '{@link #isOutputReadOnly() <em>Output Read Only</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #isOutputReadOnly()
* @generated
* @ordered
*/
protected static final boolean OUTPUT_READ_ONLY_EDEFAULT = false;
/**
* The cached value of the '{@link #isOutputReadOnly() <em>Output Read Only</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #isOutputReadOnly()
* @generated
* @ordered
*/
protected boolean outputReadOnly = OUTPUT_READ_ONLY_EDEFAULT;
/**
* The default value of the '{@link #isTopToBottom() <em>Top To Bottom</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #isTopToBottom()
* @generated
* @ordered
*/
protected static final boolean TOP_TO_BOTTOM_EDEFAULT = false;
/**
* The cached value of the '{@link #isTopToBottom() <em>Top To Bottom</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #isTopToBottom()
* @generated
* @ordered
*/
protected boolean topToBottom = TOP_TO_BOTTOM_EDEFAULT;
/**
* The default value of the '{@link #getCommandStack() <em>Command Stack</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getCommandStack()
* @generated
* @ordered
*/
protected static final String COMMAND_STACK_EDEFAULT = null;
/**
* The cached value of the '{@link #getCommandStack() <em>Command Stack</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getCommandStack()
* @generated
* @ordered
*/
protected String commandStack = COMMAND_STACK_EDEFAULT;
/**
* This keeps track of the mapping domain that uses this mapping root.
*/
protected MappingDomain domain;
/**
* This keeps track of whether the output has been modified.
*/
protected boolean outputDirty = false;
/**
* This allows this listen for changes to inputs or outputs.
*/
protected AdapterImpl mappedObjectListener;
/**
* This keeps track of the factory for creating the {@link org.eclipse.emf.mapping.MappedObjectState}.
*/
protected AdapterFactory mappedObjectStateAdapterFactory;
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
*/
protected MappingRootImpl()
{
super();
this.mappedObjectStateAdapterFactory = createMappedObjectStateAdapterFactory();
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
protected EClass eStaticClass()
{
return MappingPackage.Literals.MAPPING_ROOT;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public boolean isOutputReadOnly()
{
return outputReadOnly;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setOutputReadOnly(boolean newOutputReadOnly)
{
boolean oldOutputReadOnly = outputReadOnly;
outputReadOnly = newOutputReadOnly;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, MappingPackage.MAPPING_ROOT__OUTPUT_READ_ONLY, oldOutputReadOnly, outputReadOnly));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public boolean isTopToBottom()
{
return topToBottom;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setTopToBottom(boolean newTopToBottom)
{
boolean oldTopToBottom = topToBottom;
topToBottom = newTopToBottom;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, MappingPackage.MAPPING_ROOT__TOP_TO_BOTTOM, oldTopToBottom, topToBottom));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public String getCommandStack()
{
return commandStack;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setCommandStack(String newCommandStack)
{
String oldCommandStack = commandStack;
commandStack = newCommandStack;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, MappingPackage.MAPPING_ROOT__COMMAND_STACK, oldCommandStack, commandStack));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public Object eGet(int featureID, boolean resolve, boolean coreType)
{
switch (featureID)
{
case MappingPackage.MAPPING_ROOT__OUTPUT_READ_ONLY:
return isOutputReadOnly();
case MappingPackage.MAPPING_ROOT__TOP_TO_BOTTOM:
return isTopToBottom();
case MappingPackage.MAPPING_ROOT__COMMAND_STACK:
return getCommandStack();
}
return super.eGet(featureID, resolve, coreType);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void eSet(int featureID, Object newValue)
{
switch (featureID)
{
case MappingPackage.MAPPING_ROOT__OUTPUT_READ_ONLY:
setOutputReadOnly((Boolean)newValue);
return;
case MappingPackage.MAPPING_ROOT__TOP_TO_BOTTOM:
setTopToBottom((Boolean)newValue);
return;
case MappingPackage.MAPPING_ROOT__COMMAND_STACK:
setCommandStack((String)newValue);
return;
}
super.eSet(featureID, newValue);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void eUnset(int featureID)
{
switch (featureID)
{
case MappingPackage.MAPPING_ROOT__OUTPUT_READ_ONLY:
setOutputReadOnly(OUTPUT_READ_ONLY_EDEFAULT);
return;
case MappingPackage.MAPPING_ROOT__TOP_TO_BOTTOM:
setTopToBottom(TOP_TO_BOTTOM_EDEFAULT);
return;
case MappingPackage.MAPPING_ROOT__COMMAND_STACK:
setCommandStack(COMMAND_STACK_EDEFAULT);
return;
}
super.eUnset(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public boolean eIsSet(int featureID)
{
switch (featureID)
{
case MappingPackage.MAPPING_ROOT__OUTPUT_READ_ONLY:
return outputReadOnly != OUTPUT_READ_ONLY_EDEFAULT;
case MappingPackage.MAPPING_ROOT__TOP_TO_BOTTOM:
return topToBottom != TOP_TO_BOTTOM_EDEFAULT;
case MappingPackage.MAPPING_ROOT__COMMAND_STACK:
return COMMAND_STACK_EDEFAULT == null ? commandStack != null : !COMMAND_STACK_EDEFAULT.equals(commandStack);
}
return super.eIsSet(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public String toString()
{
if (eIsProxy()) return super.toString();
StringBuffer result = new StringBuffer(super.toString());
result.append(" (outputReadOnly: ");
result.append(outputReadOnly);
result.append(", topToBottom: ");
result.append(topToBottom);
result.append(", commandStack: ");
result.append(commandStack);
result.append(')');
return result.toString();
}
public MappingDomain getDomain()
{
return domain;
}
public void setDomain(MappingDomain domain)
{
if (this.domain != domain)
{
if (this.domain != null)
{
eAdapters.remove(mappedObjectListener);
}
this.domain = domain;
domain.setMappingRoot(this);
mappedObjectListener =
new AdapterImpl()
{
@Override
public void notifyChanged(Notification notification)
{
Object feature = notification.getFeature();
if (feature == MappingPackage.eINSTANCE.getMapping_Inputs() || feature == MappingPackage.eINSTANCE.getMapping_Outputs())
{
initializeMappedObjectStates();
}
}
};
eAdapters().add(mappedObjectListener);
initializeMappedObjectStates();
}
}
public void refreshMappedObjectStates(Mapping subtree)
{
for (Object input : subtree.getInputs())
{
for (Iterator<?> objects = domain.treeIterator(input); objects.hasNext(); )
{
Object object = objects.next();
MappedObjectState mappedObjectState = getMappedObjectState(object);
if (mappedObjectState != null)
{
mappedObjectState.setInput();
}
}
}
for (Object output : subtree.getOutputs())
{
for (Iterator<?> objects = domain.treeIterator(output); objects.hasNext(); )
{
MappedObjectState mappedObjectState = getMappedObjectState(objects.next());
if (mappedObjectState != null)
{
mappedObjectState.setOutput();
}
}
}
for (Iterator<Mapping> mappings = subtree.treeIterator(); mappings.hasNext(); )
{
Mapping mapping = mappings.next();
for (Object input : mapping.getInputs())
{
MappedObjectState mappedObjectState = getMappedObjectState(input);
if (mappedObjectState != null)
{
mappedObjectState.getMappings().add(mapping);
}
}
for (Object output : mapping.getOutputs())
{
MappedObjectState mappedObjectState = getMappedObjectState(output);
if (mappedObjectState != null)
{
mappedObjectState.getMappings().add(mapping);
}
}
}
}
protected void initializeMappedObjectStates()
{
refreshMappedObjectStates(this);
if (getTypeMapping() instanceof MappingRootImpl)
{
((MappingRootImpl)getTypeMapping()).initializeMappedObjectStates();
}
}
public Mapping getParentMapping(Collection<?> collection)
{
// Barring a better result, this will be the result.
//
Mapping result = this;
// Cache the tree path for each object.
//
final Collection<List<?>> allTreePaths = new ArrayList<List<?>>();
for (Object object : collection)
{
allTreePaths.add(domain.getTreePath(object));
}
// Iterate over the mappings in the tree.
//
OuterLoop: for (TreeIterator<Mapping> mappings = treeIterator(); mappings.hasNext(); )
{
Mapping mapping = mappings.next();
// Check to make sure that every object in the collection has an ancestor that is contained in this mapping.
//
for (Iterator<List<?>> treePaths = allTreePaths.iterator(); treePaths.hasNext(); )
{
List<?> treePath = treePaths.next();
Collection<?> mappedObjects = mapping.getMappedObjects();
mappedObjects.retainAll(treePath);
// If the intersection is empty, i.e., no ancestor is in the mapping...
//
if (mappedObjects.isEmpty())
{
// If this mapping isn't a parent, it's children definitely won't be either.
//
mappings.prune();
continue OuterLoop;
}
}
// Make sure the collections aren't identical...
//
Collection<?> mappedObjects = mapping.getMappedObjects();
if (!collection.containsAll(mappedObjects) || !mappedObjects.containsAll(collection))
{
result = mapping;
}
}
return result;
}
public boolean isDirty()
{
/**
if (getRuleList() != null)
{
return getRuleList().isDirty();
}
**/
return false;
}
public boolean isOutputDirty()
{
return outputDirty;
}
public void register(Mapping mapping)
{
for (Object input : mapping.getInputs())
{
MappedObjectState mappedObjectState = getMappedObjectState(input);
if (mappedObjectState != null)
{
mappedObjectState.getMappings().add(mapping);
}
}
for (Object output : mapping.getOutputs())
{
MappedObjectState mappedObjectState = getMappedObjectState(output);
if (mappedObjectState != null)
{
mappedObjectState.getMappings().add(mapping);
}
}
}
public void deregister(Mapping mapping)
{
for (Object input : mapping.getInputs())
{
MappedObjectState mappedObjectState = getMappedObjectState(input);
if (mappedObjectState != null)
{
mappedObjectState.getMappings().remove(mapping);
}
}
for (Object output : mapping.getOutputs())
{
MappedObjectState mappedObjectState = getMappedObjectState(output);
if (mappedObjectState != null)
{
mappedObjectState.getMappings().remove(mapping);
}
}
}
public boolean canCreateMapping(Collection<?> inputs, Collection<?> outputs, Mapping mapping)
{
if (domain == null)
{
return false;
}
int enablementFlags = domain.getMappingEnablementFlags();
if ((enablementFlags & MappingDomain.ENABLE_EMPTY_INPUTS) == 0 && inputs.size() == 0 ||
(enablementFlags & MappingDomain.ENABLE_EMPTY_OUTPUTS) == 0 && outputs.size() == 0 ||
inputs.size() == 0 && outputs.size() == 0 ||
(enablementFlags & MappingDomain.ENABLE_MULTIPLE_INPUTS) == 0 && inputs.size() > 1 ||
(enablementFlags & MappingDomain.ENABLE_MULTIPLE_OUTPUTS) == 0 && outputs.size() > 1 ||
(enablementFlags & MappingDomain.ENABLE_MULTIPLE_INPUT_MAPPINGS) == 0 && isMapped(inputs, mapping) ||
(enablementFlags & MappingDomain.ENABLE_MULTIPLE_OUTPUT_MAPPINGS) == 0 && isMapped(outputs, mapping) ||
(enablementFlags & MappingDomain.ENABLE_UNMAPPED_PARENTS) == 0 && !hasMappedParents(inputs, outputs) ||
(enablementFlags & MappingDomain.ENABLE_INCOMPATIBLE_METAOBJECTS) == 0 && !hasCompatibleMetaObjects(inputs, outputs) ||
(enablementFlags & MappingDomain.ENABLE_INCOMPATIBLE_TYPE_CLASSIFIERS) == 0 && !hasCompatibleTypes(inputs, outputs))
{
return false;
}
for (Object input : inputs)
{
if (!isAttachedObject(input))
{
return false;
}
}
for (Object output : outputs)
{
if (!isAttachedObject(output))
{
return false;
}
}
return true;
}
public boolean canRemoveMapping(Mapping mapping)
{
int enablementFlags = domain.getMappingEnablementFlags();
if (mapping.getNestedIn() == null ||
(enablementFlags & MappingDomain.ENABLE_UNMAPPED_PARENTS) == 0 && hasMappedChildren(mapping))
{
return false;
}
return true;
}
protected boolean hasMappedChildren(Mapping mapping)
{
return !mapping.getNested().isEmpty();
}
protected boolean hasMappedParents(Collection<?> inputs, Collection<?> outputs)
{
Collection<Object> parents = new HashSet<Object>();
for (Object input : inputs)
{
parents.add(domain.getParent(input));
}
for (Object output : outputs)
{
parents.add(domain.getParent(output));
}
return !getAllMappings(parents).isEmpty();
}
protected boolean isMapped(Collection<?> collection, Mapping mapping)
{
for (Object object : collection)
{
Collection<? extends Mapping> mappings = getMappings(object);
if (!mappings.isEmpty())
{
if (mapping == null || mappings.size() > 1 || !mappings.contains(mapping))
{
return true;
}
}
}
return false;
}
protected boolean hasCompatibleMetaObjects(Collection<?> inputs, Collection<?> outputs)
{
for (Object input : inputs)
{
EObject inputType = ((EObject)input).eClass();
EObject convertedInputType = domain.getOutputMetaObject(inputType);
for (Object output : outputs)
{
EObject outputType = ((EObject)output).eClass();
if (convertedInputType != outputType)
{
return false;
}
}
}
return true;
}
protected boolean hasCompatibleTypes(Collection<?> inputs, Collection<?> outputs)
{
MappingRoot typeMappingRoot = getTypeMappingRoot();
if (typeMappingRoot != null)
{
Collection<Object> inputTypes = getTypeClassifiers(inputs);
Collection<Object> outputTypes = getTypeClassifiers(outputs);
if (inputTypes.equals(outputTypes))
return true;
if (inputTypes.size() != inputs.size() || outputTypes.size() != outputs.size())
return false;
if (getTypeMappings(inputTypes, outputTypes).isEmpty() &&
hasTypeMappings(inputTypes) && hasTypeMappings(outputTypes))
{
return false;
}
}
return true;
}
protected Collection<?> getTypeMappings(Collection<?> inputTypes, Collection<?> outputTypes)
{
Collection<?> typeMappings;
if (outputTypes.isEmpty())
{
typeMappings = getTypeMappingRoot().getAllMappings(inputTypes);
}
else
{
Collection<Object> allTypes = new ArrayList<Object>(inputTypes);
allTypes.addAll(outputTypes);
typeMappings = getTypeMappingRoot().getExactMappings(allTypes);
}
return typeMappings;
}
protected boolean hasTypeMappings(Collection<?> types)
{
return !getTypeMappingRoot().getAllMappings(types).isEmpty();
}
protected Collection<Object> getTypeClassifiers(Collection<?> collection)
{
Collection<Object> types = new ArrayList<Object>();
for (Object object : collection)
{
Object type = domain.getTypeClassifier(object);
if (type != null)
{
types.add(type);
}
}
return types;
}
public Mapping createMapping(Collection<?> inputs, Collection<?> outputs)
{
Mapping newMapping = createMapping();
initializeNewMapping(newMapping, inputs, outputs);
return newMapping;
}
protected Mapping createMapping()
{
return MappingFactory.eINSTANCE.createMapping();
}
protected void initializeNewMapping(Mapping newMapping, Collection<?> inputs, Collection<?> outputs)
{
@SuppressWarnings("unchecked")
Collection<EObject> eObjectInputs = (Collection<EObject>)inputs;
@SuppressWarnings("unchecked")
Collection<EObject> eObjectOutputs = (Collection<EObject>)outputs;
newMapping.getInputs().addAll(eObjectInputs);
newMapping.getOutputs().addAll(eObjectOutputs);
if (getTypeMappingRoot() != null)
{
Collection<?> inputTypes = getTypeClassifiers(inputs);
if (!inputTypes.isEmpty())
{
Collection<?> outputTypes = getTypeClassifiers(outputs);
Collection<?> typeMappings = getTypeMappings(inputTypes, outputTypes);
if (!typeMappings.isEmpty())
{
newMapping.setTypeMapping((Mapping)typeMappings.iterator().next());
}
}
}
}
public void resetDirty()
{
this.setOutputDirty(false);
}
public void setOutputDirty(boolean dirty)
{
outputDirty = dirty;
}
public boolean isInputObject(Object object)
{
MappedObjectState mappedObjectState = (MappedObjectState)mappedObjectStateAdapterFactory.adapt(object, MappedObjectState.class);
return
mappedObjectState != null && mappedObjectState.isInput();
}
public boolean isOutputObject(Object object)
{
MappedObjectState mappedObjectState = (MappedObjectState)mappedObjectStateAdapterFactory.adapt(object, MappedObjectState.class);
return
mappedObjectState != null && mappedObjectState.isOutput();
}
public boolean isTopObject(Object object)
{
MappedObjectState mappedObjectState = (MappedObjectState)mappedObjectStateAdapterFactory.adapt(object, MappedObjectState.class);
if (mappedObjectState != null)
return isTopToBottom() ? mappedObjectState.isInput() : mappedObjectState.isOutput();
return false;
}
public boolean isBottomObject(Object object)
{
MappedObjectState mappedObjectState = (MappedObjectState)mappedObjectStateAdapterFactory.adapt(object, MappedObjectState.class);
if (mappedObjectState != null)
return !isTopToBottom() ? mappedObjectState.isInput() : mappedObjectState.isOutput();
return false;
}
public boolean isAttachedObject(Object object)
{
Object root = object;
//FB used to check for parent != null.
// Need to find the top most model object not including the resource.
// parent instanceof Eobject only checks for trees in model object space.
for (Object parent = domain.getParent(object); parent instanceof EObject; parent = domain.getParent(parent))
{
root = parent;
}
return getInputs().contains(root) || getOutputs().contains(root);
}
public Collection<? extends Mapping> getMappings(Object object)
{
MappedObjectState mappedObjectState = getMappedObjectState(object);
if (mappedObjectState == null)
{
return Collections.emptySet();
}
else
{
return mappedObjectState.getMappings();
}
}
public Collection<? extends Mapping> getAllMappings(Collection<?> collection)
{
Iterator<?> objects = collection.iterator();
if (objects.hasNext())
{
Collection<Mapping> result = new ArrayList<Mapping>(getMappings(objects.next()));
while (objects.hasNext() && !result.isEmpty())
{
result.retainAll(getMappings(objects.next()));
}
return result;
}
else
{
return Collections.emptySet();
}
}
public Collection<? extends Mapping> getExactMappings(Collection<?> collection)
{
Collection<Mapping> result = new ArrayList<Mapping>();
for (Mapping mapping : getAllMappings(collection))
{
if (collection.containsAll(mapping.getMappedObjects()))
{
result.add(mapping);
}
}
return result;
}
/**
* This is a simple implementation of the basic information that needs to be maintained for any mapped object.
*/
protected class MappedObjectStateAdapter extends AdapterImpl implements MappedObjectState, IDisposable
{
/**
* This indicates whether the mapped object is an input.
*/
protected boolean isInput;
/**
* This indicates whether the object is an output.
*/
protected boolean isOutput;
/**
* This keeps track of the originating input of the mapped object, if any.
*/
protected Object originatingInput;
/**
* This keeps track of all the mappings that involve the mapped object.
*/
protected Collection<Mapping> mappings =
new NotifyingListImpl<Mapping>()
{
private static final long serialVersionUID = 1L;
@Override
public Object getNotifier()
{
return getTarget();
}
@Override
protected boolean isNotificationRequired()
{
return true;
}
@Override
protected NotificationImpl createNotification(int eventType, Object oldObject, Object newObject, int index, boolean wasSet)
{
Object object = oldObject == null ? newObject : oldObject;
// Ensure that this is a touch notification so to resource aren't marked as dirty.
//
ENotificationImpl notification =
new ENotificationImpl
((InternalEObject)getTarget(),
Notification.SET,
Notification.NO_FEATURE_ID - 1,
object,
object,
Notification.NO_INDEX,
wasSet);
MappedObjectStateAdapter.this.fireNotifyChanged(notification);
return notification;
}
@Override
protected boolean isUnique()
{
return true;
}
};
/**
* This is where {@link org.eclipse.emf.edit.provider.IChangeNotifier} is delegated.
*/
protected ChangeNotifier changeNotifier = new ChangeNotifier();
/**
* This returns when type is the {@link #mappedObjectStateAdapterFactory}.
*/
@Override
public boolean isAdapterForType(Object type)
{
return type == mappedObjectStateAdapterFactory;
}
public boolean isInput()
{
return isInput;
}
public void setInput()
{
isInput = true;
}
public boolean isOutput()
{
return isOutput;
}
public void setOutput()
{
isOutput = true;
ENotificationImpl note =
new ENotificationImpl
((InternalEObject)getTarget(),
Notification.SET,
Notification.NO_FEATURE_ID - 2,
Boolean.TRUE,
Boolean.TRUE,
Notification.NO_INDEX);
changeNotifier.fireNotifyChanged(note);
}
public Object getOriginatingInput()
{
return originatingInput;
}
public void setOriginatingInput(Object originatingInput)
{
setOutput();
this.originatingInput = originatingInput;
}
public Collection<Mapping> getMappings()
{
return mappings;
}
public void addListener(INotifyChangedListener notifyChangedListener)
{
changeNotifier.addListener(notifyChangedListener);
}
public void removeListener(INotifyChangedListener notifyChangedListener)
{
changeNotifier.removeListener(notifyChangedListener);
}
public void fireNotifyChanged(Notification notification)
{
changeNotifier.fireNotifyChanged(notification);
}
public void dispose()
{
if (target != null)
{
target.eAdapters().remove(this);
}
}
}
/**
* This uses the {@link #mappedObjectStateAdapterFactory} to get an adapter that implements this interface.
*/
public MappedObjectState getMappedObjectState(Object object)
{
return (MappedObjectState)mappedObjectStateAdapterFactory.adapt(object, MappedObjectState.class);
}
public MappingRoot getTypeMappingRoot()
{
return (MappingRoot)getTypeMapping();
}
/**
* By default, this creates an adapter factory that delegates {@link AdapterFactoryImpl#createAdapter(Notifier) createAdapter}
* to {@link #createMappedObjectStateAdapter createMappedObjectStateAdapter}.
*/
protected AdapterFactory createMappedObjectStateAdapterFactory()
{
return new MappedObjectStateAdapterFactory();
}
/**
* This is the factory that creates adapters for the objects being mapped.
* It must be disposed if the lifetime of the mapped objects is longer than the lifetime of the mapping root.
*/
protected class MappedObjectStateAdapterFactory extends AdapterFactoryImpl implements IDisposable
{
protected Disposable disposable = new Disposable();
public MappedObjectStateAdapterFactory()
{
super();
}
@Override
public Adapter createAdapter(Notifier target)
{
return createMappedObjectStateAdapter(target);
}
@Override
public boolean isFactoryForType(Object type)
{
return super.isFactoryForType(type) || type == MappedObjectState.class;
}
@Override
public Adapter adapt(Notifier notifier, Object type)
{
return super.adapt(notifier, this);
}
@Override
public Object adapt(Object object, Object type)
{
Object result = super.adapt(object, type);
return
result instanceof MappedObjectState ? result : null;
}
@Override
public Adapter adaptNew(Notifier object, Object type)
{
Adapter result = super.adaptNew(object, type);
disposable.add(result);
return result;
}
public void dispose()
{
disposable.dispose();
}
}
/**
* By default, this creates a new instance of {@link MappedObjectStateAdapter}.
*/
protected Adapter createMappedObjectStateAdapter(Notifier target)
{
return new MappedObjectStateAdapter();
}
public void dispose()
{
if (mappedObjectStateAdapterFactory instanceof IDisposable)
{
((IDisposable)mappedObjectStateAdapterFactory).dispose();
}
MappingRoot typeMappingRoot = getTypeMappingRoot();
if (typeMappingRoot != null)
{
typeMappingRoot.dispose();
}
// printAdapters();
}
protected void printAdapters()
{
walk(this);
for (TreeIterator<Mapping> mappings = treeIterator(); mappings.hasNext(); )
{
for (EObject eObject : mappings.next().getMappedObjects())
{
walk(eObject);
}
}
}
protected void walk(EObject object)
{
for (EObject child : object.eContents())
{
Collection<Adapter> adapters = child.eAdapters();
if (adapters != null)
{
boolean once = false;
for (Object adapter : adapters)
{
if (adapter != null)
{
if (!once)
{
System.out.println("*** " + child);
once = true;
}
System.out.println(" * " + adapter);
}
}
}
walk(child);
}
}
} //MappingRootImpl