/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.foundation.viewpoint;
import java.lang.reflect.Type;
import java.util.Vector;
import java.util.logging.Logger;
import org.openflexo.antar.binding.BindingDefinition;
import org.openflexo.antar.binding.BindingDefinition.BindingDefinitionType;
import org.openflexo.foundation.FlexoModelObject;
import org.openflexo.foundation.Inspectors;
import org.openflexo.foundation.validation.FixProposal;
import org.openflexo.foundation.validation.ValidationError;
import org.openflexo.foundation.validation.ValidationIssue;
import org.openflexo.foundation.validation.ValidationRule;
import org.openflexo.foundation.view.ViewConnector;
import org.openflexo.foundation.view.ViewShape;
import org.openflexo.foundation.view.action.EditionSchemeAction;
import org.openflexo.foundation.view.action.LinkSchemeAction;
import org.openflexo.foundation.viewpoint.ViewPoint.ViewPointBuilder;
import org.openflexo.foundation.viewpoint.binding.ViewPointDataBinding;
/**
* This edition primitive addresses the creation of a new connector linking two shapes in a diagram
*
* @author sylvain
*
*/
public class AddConnector extends AddShemaElementAction {
private static final Logger logger = Logger.getLogger(LinkSchemeAction.class.getPackage().getName());
public AddConnector(ViewPointBuilder builder) {
super(builder);
}
@Override
public EditionActionType getEditionActionType() {
return EditionActionType.AddConnector;
}
/*@Override
public List<ConnectorPatternRole> getAvailablePatternRoles() {
if (getEditionPattern() != null) {
return getEditionPattern().getPatternRoles(ConnectorPatternRole.class);
}
return null;
}*/
@Override
public String getInspectorName() {
return Inspectors.VPM.ADD_CONNECTOR_INSPECTOR;
}
@Override
public ConnectorPatternRole getPatternRole() {
PatternRole superPatternRole = super.getPatternRole();
if (superPatternRole instanceof ConnectorPatternRole) {
return (ConnectorPatternRole) superPatternRole;
} else if (superPatternRole != null) {
// logger.warning("Unexpected pattern role of type " + superPatternRole.getClass().getSimpleName());
return null;
}
return null;
}
public ViewShape getFromShape(EditionSchemeAction action) {
if (getPatternRole() != null && !getPatternRole().getStartShapeAsDefinedInAction()) {
FlexoModelObject returned = action.getEditionPatternInstance().getPatternActor(getPatternRole().getStartShapePatternRole());
return (ViewShape) action.getEditionPatternInstance().getPatternActor(getPatternRole().getStartShapePatternRole());
} else {
return (ViewShape) getFromShape().getBindingValue(action);
}
}
public ViewShape getToShape(EditionSchemeAction action) {
if (getPatternRole() != null && !getPatternRole().getEndShapeAsDefinedInAction()) {
FlexoModelObject returned = action.getEditionPatternInstance().getPatternActor(getPatternRole().getEndShapePatternRole());
return (ViewShape) action.getEditionPatternInstance().getPatternActor(getPatternRole().getEndShapePatternRole());
} else {
return (ViewShape) getToShape().getBindingValue(action);
}
}
@Override
public String toString() {
return "AddConnector " + Integer.toHexString(hashCode()) + " patternRole=" + getPatternRole();
}
/*@Override
public ConnectorPatternRole getPatternRole() {
try {
return super.getPatternRole();
} catch (ClassCastException e) {
logger.warning("Unexpected pattern role type");
setPatternRole(null);
return null;
}
}*/
// FIXME: if we remove this useless code, some FIB won't work (see EditionPatternView.fib, inspect an AddIndividual)
// Need to be fixed in KeyValueProperty.java
/*@Override
public void setPatternRole(ConnectorPatternRole patternRole) {
super.setPatternRole(patternRole);
}*/
private ViewPointDataBinding fromShape;
private ViewPointDataBinding toShape;
private BindingDefinition FROM_SHAPE = new BindingDefinition("fromShape", ViewShape.class, BindingDefinitionType.GET, true);
public BindingDefinition getFromShapeBindingDefinition() {
return FROM_SHAPE;
}
public ViewPointDataBinding getFromShape() {
if (fromShape == null) {
fromShape = new ViewPointDataBinding(this, EditionActionBindingAttribute.fromShape, getFromShapeBindingDefinition());
}
return fromShape;
}
public void setFromShape(ViewPointDataBinding fromShape) {
if (fromShape != null) {
fromShape.setOwner(this);
fromShape.setBindingAttribute(EditionActionBindingAttribute.fromShape);
fromShape.setBindingDefinition(getFromShapeBindingDefinition());
}
this.fromShape = fromShape;
notifyBindingChanged(this.fromShape);
}
private BindingDefinition TO_SHAPE = new BindingDefinition("toShape", ViewShape.class, BindingDefinitionType.GET, true);
public BindingDefinition getToShapeBindingDefinition() {
return TO_SHAPE;
}
public ViewPointDataBinding getToShape() {
if (toShape == null) {
toShape = new ViewPointDataBinding(this, EditionActionBindingAttribute.toShape, getToShapeBindingDefinition());
}
return toShape;
}
public void setToShape(ViewPointDataBinding toShape) {
if (toShape != null) {
toShape.setOwner(this);
toShape.setBindingAttribute(EditionActionBindingAttribute.toShape);
toShape.setBindingDefinition(getToShapeBindingDefinition());
}
this.toShape = toShape;
notifyBindingChanged(this.toShape);
}
@Override
public Type getAssignableType() {
return ViewConnector.class;
}
@Override
public boolean isAssignationRequired() {
return true;
}
public static class AddConnectorActionMustAdressAValidConnectorPatternRole extends
ValidationRule<AddConnectorActionMustAdressAValidConnectorPatternRole, AddConnector> {
public AddConnectorActionMustAdressAValidConnectorPatternRole() {
super(AddConnector.class, "add_connector_action_must_address_a_valid_connector_pattern_role");
}
@Override
public ValidationIssue<AddConnectorActionMustAdressAValidConnectorPatternRole, AddConnector> applyValidation(AddConnector action) {
if (action.getPatternRole() == null) {
Vector<FixProposal<AddConnectorActionMustAdressAValidConnectorPatternRole, AddConnector>> v = new Vector<FixProposal<AddConnectorActionMustAdressAValidConnectorPatternRole, AddConnector>>();
for (ConnectorPatternRole pr : action.getEditionPattern().getConnectorPatternRoles()) {
v.add(new SetsPatternRole(pr));
}
return new ValidationError<AddConnectorActionMustAdressAValidConnectorPatternRole, AddConnector>(this, action,
"add_connector_action_does_not_address_a_valid_connector_pattern_role", v);
}
return null;
}
protected static class SetsPatternRole extends FixProposal<AddConnectorActionMustAdressAValidConnectorPatternRole, AddConnector> {
private ConnectorPatternRole patternRole;
public SetsPatternRole(ConnectorPatternRole patternRole) {
super("assign_action_to_pattern_role_($patternRole.patternRoleName)");
this.patternRole = patternRole;
}
public ConnectorPatternRole getPatternRole() {
return patternRole;
}
@Override
protected void fixAction() {
AddConnector action = getObject();
action.setAssignation(new ViewPointDataBinding(patternRole.getPatternRoleName()));
}
}
}
public static class AddConnectorActionMustHaveAValidStartingShape extends
ValidationRule<AddConnectorActionMustHaveAValidStartingShape, AddConnector> {
public AddConnectorActionMustHaveAValidStartingShape() {
super(AddConnector.class, "add_connector_action_must_have_a_valid_starting_shape");
}
@Override
public ValidationIssue<AddConnectorActionMustHaveAValidStartingShape, AddConnector> applyValidation(AddConnector action) {
if (action.getPatternRole() != null && action.getPatternRole().getStartShapeAsDefinedInAction()
&& !(action.getFromShape().isSet() && action.getFromShape().isValid())) {
Vector<FixProposal<AddConnectorActionMustHaveAValidStartingShape, AddConnector>> v = new Vector<FixProposal<AddConnectorActionMustHaveAValidStartingShape, AddConnector>>();
if (action.getEditionScheme() instanceof LinkScheme) {
EditionPattern targetEditionPattern = ((LinkScheme) action.getEditionScheme()).getFromTargetEditionPattern();
if (targetEditionPattern != null) {
for (ShapePatternRole pr : action.getEditionPattern().getShapePatternRoles()) {
v.add(new SetsStartingShapeToStartTargetShape(targetEditionPattern, pr));
}
}
}
for (ShapePatternRole pr : action.getEditionPattern().getShapePatternRoles()) {
v.add(new SetsStartingShapeToShape(pr));
}
return new ValidationError<AddConnectorActionMustHaveAValidStartingShape, AddConnector>(this, action,
"add_connector_action_does_not_have_a_valid_starting_shape", v);
}
return null;
}
protected static class SetsStartingShapeToShape extends FixProposal<AddConnectorActionMustHaveAValidStartingShape, AddConnector> {
private ShapePatternRole patternRole;
public SetsStartingShapeToShape(ShapePatternRole patternRole) {
super("sets_starting_shape_to_($patternRole.patternRoleName)");
this.patternRole = patternRole;
}
public ShapePatternRole getPatternRole() {
return patternRole;
}
@Override
protected void fixAction() {
AddConnector action = getObject();
action.setFromShape(new ViewPointDataBinding(patternRole.getPatternRoleName()));
}
}
protected static class SetsStartingShapeToStartTargetShape extends
FixProposal<AddConnectorActionMustHaveAValidStartingShape, AddConnector> {
private EditionPattern target;
private ShapePatternRole patternRole;
public SetsStartingShapeToStartTargetShape(EditionPattern target, ShapePatternRole patternRole) {
super("sets_starting_shape_to_fromTarget.($patternRole.patternRoleName)");
this.target = target;
this.patternRole = patternRole;
}
public ShapePatternRole getPatternRole() {
return patternRole;
}
public EditionPattern getTarget() {
return target;
}
@Override
protected void fixAction() {
AddConnector action = getObject();
action.setFromShape(new ViewPointDataBinding(EditionScheme.FROM_TARGET + "." + patternRole.getPatternRoleName()));
}
}
}
public static class AddConnectorActionMustHaveAValidEndingShape extends
ValidationRule<AddConnectorActionMustHaveAValidEndingShape, AddConnector> {
public AddConnectorActionMustHaveAValidEndingShape() {
super(AddConnector.class, "add_connector_action_must_have_a_valid_ending_shape");
}
@Override
public ValidationIssue<AddConnectorActionMustHaveAValidEndingShape, AddConnector> applyValidation(AddConnector action) {
if (action.getPatternRole() != null && action.getPatternRole().getEndShapeAsDefinedInAction()
&& !(action.getToShape().isSet() && action.getToShape().isValid())) {
Vector<FixProposal<AddConnectorActionMustHaveAValidEndingShape, AddConnector>> v = new Vector<FixProposal<AddConnectorActionMustHaveAValidEndingShape, AddConnector>>();
if (action.getEditionScheme() instanceof LinkScheme) {
EditionPattern targetEditionPattern = ((LinkScheme) action.getEditionScheme()).getToTargetEditionPattern();
if (targetEditionPattern != null) {
for (ShapePatternRole pr : action.getEditionPattern().getShapePatternRoles()) {
v.add(new SetsEndingShapeToToTargetShape(targetEditionPattern, pr));
}
}
}
for (ShapePatternRole pr : action.getEditionPattern().getShapePatternRoles()) {
v.add(new SetsEndingShapeToShape(pr));
}
return new ValidationError<AddConnectorActionMustHaveAValidEndingShape, AddConnector>(this, action,
"add_connector_action_does_not_have_a_valid_ending_shape", v);
}
return null;
}
protected static class SetsEndingShapeToShape extends FixProposal<AddConnectorActionMustHaveAValidEndingShape, AddConnector> {
private ShapePatternRole patternRole;
public SetsEndingShapeToShape(ShapePatternRole patternRole) {
super("sets_ending_shape_to_($patternRole.patternRoleName)");
this.patternRole = patternRole;
}
public ShapePatternRole getPatternRole() {
return patternRole;
}
@Override
protected void fixAction() {
AddConnector action = getObject();
action.setToShape(new ViewPointDataBinding(patternRole.getPatternRoleName()));
}
}
protected static class SetsEndingShapeToToTargetShape extends
FixProposal<AddConnectorActionMustHaveAValidEndingShape, AddConnector> {
private EditionPattern target;
private ShapePatternRole patternRole;
public SetsEndingShapeToToTargetShape(EditionPattern target, ShapePatternRole patternRole) {
super("sets_ending_shape_to_toTarget.($patternRole.patternRoleName)");
this.target = target;
this.patternRole = patternRole;
}
public ShapePatternRole getPatternRole() {
return patternRole;
}
public EditionPattern getTarget() {
return target;
}
@Override
protected void fixAction() {
AddConnector action = getObject();
action.setToShape(new ViewPointDataBinding(EditionScheme.TO_TARGET + "." + patternRole.getPatternRoleName()));
}
}
}
}