package com.xrosstools.xunit.editor.model;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.gef.EditPart;
import org.eclipse.ui.views.properties.ComboBoxPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertySource;
import org.eclipse.ui.views.properties.PropertyDescriptor;
import org.eclipse.ui.views.properties.TextPropertyDescriptor;
import com.xrosstools.xunit.BehaviorType;
/**
* TODO 1. if using reference, type should be set to referenced unit
* @author jiehe
*
*/
public abstract class UnitNode implements UnitConstants, IPropertySource {
private String name;
private String description;
private BehaviorType type = BehaviorType.processor;
private String className = MSG_DEFAULT;
private String referenceName;
private List<UnitNodeConnection> inputs = new ArrayList<UnitNodeConnection>();
private List<UnitNodeConnection> outputs = new ArrayList<UnitNodeConnection>();
private UnitNodeProperties properties = new UnitNodeProperties();
protected UnitNodeHelper helper;
protected EditPart part;
private PropertyChangeSupport listeners = new PropertyChangeSupport(this);
public UnitNode(String name){
this.name = name;
}
public abstract String getDefaultImplName();
public String getImplClassName(){
if(className == null || !MSG_DEFAULT.equalsIgnoreCase(className))
return className;
return getDefaultImplName();
}
public UnitNodeProperties getProperties() {
return properties;
}
/**
* DecoratorNode class will override this method to getType from
* decoratee
*/
public BehaviorType getType() {
return type;
}
/**
* DecoratorNode class will override this method to disable setType
*/
public void setType(BehaviorType type) {
this.type = type;
firePropertyChange(PROP_NODE);
}
protected final IPropertyDescriptor getDescriptor(String propName){
PropertyDescriptor descriptor = new TextPropertyDescriptor(propName, propName);
descriptor.setCategory(getCategory(propName));
return descriptor;
}
protected final IPropertyDescriptor getDescriptor(String propName, String[] values){
PropertyDescriptor descriptor = new ComboBoxPropertyDescriptor(propName, propName, values);
descriptor.setCategory(getCategory(propName));
return descriptor;
}
public IPropertyDescriptor[] getBasicPropertyDescriptors(){
IPropertyDescriptor[] descriptors = new IPropertyDescriptor[]{
getDescriptor(PROP_NAME),
getDescriptor(PROP_DESCRIPTION),
getDescriptor(PROP_CLASS),
getDescriptor(PROP_REFERENCE, getReferenceValues()),
};
return combine(descriptors, properties.getPropertyDescriptors());
}
public IPropertyDescriptor[] getAdditionalPropertyDescriptors(){
return new IPropertyDescriptor[0];
}
protected abstract String getCategory(String id);
public abstract String[] getReferenceValues();
public IPropertyDescriptor[] getPropertyDescriptors() {
IPropertyDescriptor[] p1 = getBasicPropertyDescriptors();
IPropertyDescriptor[] p2 = getAdditionalPropertyDescriptors();
return combine(p1, p2);
}
private IPropertyDescriptor[] combine(IPropertyDescriptor[] p1, IPropertyDescriptor[] p2) {
IPropertyDescriptor[] descriptors = new IPropertyDescriptor[p1.length + p2.length];
System.arraycopy(p1, 0, descriptors, 0, p1.length);
System.arraycopy(p2, 0, descriptors, p1.length, p2.length);
return descriptors;
}
public Object getPropertyValue(Object propName) {
if (PROP_NAME.equals(propName))
return helper.getValue(name);
if (PROP_DESCRIPTION.equals(propName))
return helper.getValue(description);
if (PROP_CLASS.equals(propName))
return helper.getValue(className);
if (PROP_BEHAVIOR_TYPE.equals(propName))
return type.ordinal();
if (PROP_REFERENCE.equals(propName))
return helper.getIndex(getReferenceValues(), referenceName);
return properties.getPropertyValue(propName);
}
public void setPropertyValue(Object propName, Object value){
if (PROP_NAME.equals(propName))
setName((String)value);
if (PROP_DESCRIPTION.equals(propName))
setDescription((String)value);
if (PROP_CLASS.equals(propName))
setClassName((String)value);
if (PROP_BEHAVIOR_TYPE.equals(propName))
setType(BehaviorType.getType((Integer)value));
if (PROP_REFERENCE.equals(propName))
setReferenceName(getReferenceValues()[(Integer)value]);
properties.setPropertyValue(propName, value);
}
public Object getEditableValue(){
return this;
}
public boolean isPropertySet(Object propName){
return true;
}
public void resetPropertyValue(Object propName){
}
public void setHelper(UnitNodeHelper helper){
this.helper = helper;
}
public void setPart(EditPart part){
this.part = part;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
firePropertyChange(PROP_NODE);
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
firePropertyChange(PROP_NODE);
}
public String getClassName() {
return className;
}
public boolean isValid(String value){
if(value == null)
return false;
return value.trim().length() > 0;
}
public void setClassName(String className) {
// To make sure there is no ambiguous value
if(isValid(className)){
referenceName = null;
className = className.trim();
if(getDefaultImplName().equalsIgnoreCase(className))
className = MSG_DEFAULT;
this.className = className;
}
firePropertyChange(PROP_NODE);
}
public String getReferenceName() {
return referenceName;
}
public void setReferenceName(String referenceName) {
this.referenceName = referenceName;
// To make sure there is no ambiguous value
if(isValid(referenceName))
className = null;
firePropertyChange(PROP_NODE);
}
public List<UnitNodeConnection> getInputs() {
return inputs;
}
public UnitNodeConnection getInput() {
return inputs.size() > 0 ? inputs.get(0) : null;
}
public String getInputLabel(){
UnitNodeConnection input = getInput();
return input == null? null : input.getLabel();
}
public void setInputLabel(String label){
UnitNodeConnection input = getInput();
if(input != null)
input.setLabel(label);
}
public List<UnitNodeConnection> getOutputs() {
return outputs;
}
public UnitNodeConnection getOutput() {
return outputs.size() > 0 ? outputs.get(0) : null;
}
public void removeOutput(UnitNodeConnection output){
if(!outputs.contains(output))
return;
outputs.remove(output);
output.getTarget().removeInput(output);
firePropertyChange(PROP_OUTPUTS);
}
public void removeAllOutputs(){
List<UnitNodeConnection> tempOutputs = new ArrayList<UnitNodeConnection>(outputs);
for(UnitNodeConnection output:tempOutputs)
removeOutput(output);
firePropertyChange(PROP_OUTPUTS);
}
public void removeInput(UnitNodeConnection input){
if(!inputs.contains(input))
return;
inputs.remove(input);
input.getSource().removeOutput(input);
firePropertyChange(PROP_INPUTS);
}
public void removeAllInputs(){
List<UnitNodeConnection> tempInputs = new ArrayList<UnitNodeConnection>(inputs);
for(UnitNodeConnection input:tempInputs)
removeInput(input);
firePropertyChange(PROP_INPUTS);
}
public void removeAllConnections(){
removeAllInputs();
removeAllOutputs();
}
public void addOutput(UnitNodeConnection output){
outputs.add(output);
firePropertyChange(PROP_OUTPUTS);
}
public void addInput(UnitNodeConnection input){
inputs.add(input);
firePropertyChange(PROP_INPUTS);
}
/**
* Helper method for remove links from a node
*/
public static void removeAllConnections(UnitNode unit){
if(unit != null)
unit.removeAllConnections();
}
public static void removeAllInputs(UnitNode unit){
if(unit != null)
unit.removeAllInputs();
}
public static void removeAllOutputs(UnitNode unit){
if(unit != null)
unit.removeAllOutputs();
}
public void addPropertyChangeListener(PropertyChangeListener lilistener) {
listeners.addPropertyChangeListener(lilistener);
}
public void removePropertyChangeListener(PropertyChangeListener lilistener) {
listeners.removePropertyChangeListener(lilistener);
}
protected void firePropertyChange(String propertyName, Object oldValue, Object newValue){
listeners.firePropertyChange(propertyName, oldValue, newValue);
}
protected void firePropertyChange(String propertyName){
firePropertyChange(propertyName, null, null);
}
}