/*******************************************************************************
* This file is protected by Copyright.
* Please refer to the COPYRIGHT file distributed with this source distribution.
*
* This file is part of REDHAWK IDE.
*
* 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
*******************************************************************************/
package gov.redhawk.ide.sad.internal.ui.properties.model;
import java.util.Collection;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.UnexecutableCommand;
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.impl.AdapterImpl;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.edit.command.AddCommand;
import org.eclipse.emf.edit.command.RemoveCommand;
import org.eclipse.emf.edit.command.SetCommand;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.provider.IDisposable;
import org.eclipse.emf.edit.provider.ItemProvider;
import org.eclipse.emf.edit.provider.ViewerNotification;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.swt.widgets.Composite;
import gov.redhawk.ide.sad.internal.ui.editor.XViewerCellEditor;
import mil.jpeojtrs.sca.prf.AbstractProperty;
import mil.jpeojtrs.sca.prf.AbstractPropertyRef;
import mil.jpeojtrs.sca.sad.ExternalProperties;
import mil.jpeojtrs.sca.sad.ExternalProperty;
import mil.jpeojtrs.sca.sad.SadComponentInstantiation;
import mil.jpeojtrs.sca.sad.SadFactory;
import mil.jpeojtrs.sca.sad.SadPackage;
import mil.jpeojtrs.sca.sad.SoftwareAssembly;
/**
*
*/
public abstract class SadPropertyImpl< T extends AbstractProperty > extends ItemProvider implements SadProperty {
protected final T def;
protected AbstractPropertyRef< ? > ref;
protected ExternalProperty externalProperty;
private Adapter adapter = null;
private ILabelProvider labelProvider = null;
/**
*
*/
public SadPropertyImpl(AdapterFactory adapterFactory, T def, Object parent) {
super(adapterFactory);
this.def = def;
this.parent = parent;
}
@Override
public void dispose() {
if (ref != null) {
ref.eAdapters().remove(adapter);
}
setExternalProperty(null);
// Dispose of nested children (e.g., in structs and struct sequences)
for (Object child : children) {
((IDisposable) child).dispose();
}
children.clear();
}
@Override
public Object getParent() {
return parent;
}
@Override
public Object getParent(Object object) {
// Workaround for reverse tree traversal via an AdapterFactoryContentProvider, which will always call the
// 1-argument getParent. If we return the ViewerComponent object, getParent(Object) on it will fail because
// it's not the EObject, so this unwraps it. Property-specific code that needs to refer to the parent should
// use the no argument version.
if (parent instanceof SadPropertiesComponent) {
return ((SadPropertiesComponent) parent).getComponentInstantiation();
}
return parent;
}
@Override
public boolean canSetExternalId() {
return (parent instanceof SadPropertiesComponent);
}
protected AbstractPropertyRef< ? > getValueRef() {
return ref;
}
@Override
public T getDefinition() {
return this.def;
}
public XViewerCellEditor createCellEditor(Composite parent) {
return null;
}
public SadPropertiesComponent getComponent() {
if (parent instanceof SadPropertiesComponent) {
return (SadPropertiesComponent) parent;
} else {
return ((SadPropertyImpl< ? >) parent).getComponent();
}
}
@Override
public SadComponentInstantiation getComponentInstantiation() {
return getComponent().getComponentInstantiation();
}
@Override
public String getExternalID() {
if (externalProperty != null) {
return externalProperty.getExternalPropID();
}
return null;
}
@Override
public String getID() {
return def.getId();
}
@Override
public boolean isAssemblyControllerProperty() {
return getComponent().isAssemblyController();
}
protected void setFeatureValue(EStructuralFeature feature, Object value) {
EditingDomain editingDomain = getEditingDomain();
Class< ? > commandClass;
if (value == null) {
commandClass = RemoveCommand.class;
} else {
commandClass = SetCommand.class;
}
Command command = createCommand(editingDomain, commandClass, feature, value);
if (command != null && command.canExecute()) {
editingDomain.getCommandStack().execute(command);
}
}
protected abstract boolean isEmpty(Object value);
@Override
public ILabelProvider getLabelProvider() {
if (labelProvider == null) {
labelProvider = createLabelProvider();
}
return labelProvider;
}
protected abstract ILabelProvider createLabelProvider();
@Override
public void setSadValue(Object value) {
if (value != null && isEmpty(value)) {
value = null;
}
setFeatureValue(SadPropertiesPackage.Literals.SAD_PROPERTY__VALUE, value);
}
@Override
public void setExternalID(String newExternalID) {
if (newExternalID != null) {
newExternalID = newExternalID.trim();
if (newExternalID.isEmpty()) {
newExternalID = null;
}
}
setFeatureValue(SadPropertiesPackage.Literals.SAD_PROPERTY__EXTERNAL_ID, newExternalID);
}
@Override
public Collection< ? > getKinds() {
if (getParent() instanceof SadProperty) {
return ((SadProperty) getParent()).getKinds();
}
return getKindTypes();
}
protected abstract Collection< ? > getKindTypes();
public EditingDomain getEditingDomain() {
return ((NestedItemProvider) getParent()).getEditingDomain();
}
protected Object getModelObject(EStructuralFeature feature) {
if (feature == SadPropertiesPackage.Literals.SAD_PROPERTY__VALUE) {
return ref;
} else if (feature == SadPropertiesPackage.Literals.SAD_PROPERTY__EXTERNAL_ID) {
return externalProperty;
}
return null;
}
protected Object createModelObject(EStructuralFeature feature, Object value) {
if (feature == SadPropertiesPackage.Literals.SAD_PROPERTY__EXTERNAL_ID) {
ExternalProperty property = SadFactory.eINSTANCE.createExternalProperty();
SadComponentInstantiation compInst = getComponentInstantiation();
property.setCompRefID(compInst.getId());
property.setPropID(getID());
property.setExternalPropID((String) value);
return property;
}
return null;
}
protected Command createCommand(EditingDomain domain, Class< ? > commandClass, EStructuralFeature feature, Object value) {
Object modelObject = getModelObject(feature);
if (modelObject == null && (commandClass == SetCommand.class)) {
return createParentCommand(domain, feature, createModelObject(feature, value));
}
if (commandClass == SetCommand.class) {
return createSetCommand(domain, modelObject, feature, value);
} else if (commandClass == RemoveCommand.class) {
return createRemoveCommand(domain, modelObject, feature);
}
return UnexecutableCommand.INSTANCE;
}
protected Command createParentCommand(EditingDomain domain, EStructuralFeature feature, Object value) {
if (feature == SadPropertiesPackage.Literals.SAD_PROPERTY__EXTERNAL_ID) {
SoftwareAssembly sad = getComponent().getSoftwareAssembly();
ExternalProperties properties = sad.getExternalProperties();
if (properties != null) {
return AddCommand.create(domain, properties, SadPackage.Literals.EXTERNAL_PROPERTIES__PROPERTIES, value);
} else {
properties = SadFactory.eINSTANCE.createExternalProperties();
properties.getProperties().add((ExternalProperty) value);
return SetCommand.create(domain, sad, SadPackage.Literals.SOFTWARE_ASSEMBLY__EXTERNAL_PROPERTIES, properties);
}
}
return ((NestedItemProvider) getParent()).createAddChildCommand(domain, value, feature);
}
protected Command createSetCommand(EditingDomain domain, Object owner, EStructuralFeature feature, Object value) {
if (feature == SadPropertiesPackage.Literals.SAD_PROPERTY__EXTERNAL_ID) {
return SetCommand.create(domain, owner, SadPackage.Literals.EXTERNAL_PROPERTY__EXTERNAL_PROP_ID, value);
}
return UnexecutableCommand.INSTANCE;
}
protected Command createRemoveCommand(EditingDomain domain, Object object, EStructuralFeature feature) {
if (feature == SadPropertiesPackage.Literals.SAD_PROPERTY__EXTERNAL_ID) {
ExternalProperties properties = (ExternalProperties) ((EObject) object).eContainer();
if (properties.getProperties().size() == 1) {
return RemoveCommand.create(domain, properties);
} else {
return RemoveCommand.create(domain, object);
}
} else if (feature == SadPropertiesPackage.Literals.SAD_PROPERTY__VALUE) {
NestedItemProvider parentProvider = (NestedItemProvider) getParent();
return parentProvider.createRemoveChildCommand(domain, object, feature);
}
return UnexecutableCommand.INSTANCE;
}
public void setReference(AbstractPropertyRef< ? > reference) {
if (ref == reference) {
return;
}
unregisterAdapter(ref);
registerAdapter(reference);
ref = reference;
}
public void setExternalProperty(ExternalProperty externalProperty) {
if (this.externalProperty == externalProperty) {
return;
}
unregisterAdapter(this.externalProperty);
registerAdapter(externalProperty);
this.externalProperty = externalProperty;
}
protected Adapter getAdapter() {
if (adapter == null) {
adapter = createAdapter();
}
return adapter;
}
protected Adapter createAdapter() {
return new AdapterImpl() {
@Override
public void notifyChanged(Notification msg) {
SadPropertyImpl.this.notifyChanged(msg);
}
};
}
protected void notifyChanged(Notification msg) {
if (msg.getFeature() == SadPackage.Literals.EXTERNAL_PROPERTY__EXTERNAL_PROP_ID) {
fireNotifyChanged(new ViewerNotification(msg, this, false, true));
}
}
private void registerAdapter(EObject eObject) {
if (eObject != null) {
eObject.eAdapters().add(getAdapter());
}
}
private void unregisterAdapter(EObject eObject) {
if (eObject != null) {
eObject.eAdapters().remove(getAdapter());
}
}
}