/**
* @file: ModelValidation.java
* @author: tlc
* @date: 2006-11-17
* @version: 1.0.0
*/
package de.FeatureModellingTool.GraphicalEditor;
import java.util.Iterator;
import java.util.Set;
import de.FeatureModellingTool.FeatureModel.ConstraintModel;
import de.FeatureModellingTool.FeatureModel.Feature;
import de.FeatureModellingTool.FeatureModel.FeatureModel;
import de.FeatureModellingTool.FeatureModel.FeatureRelation;
import de.FeatureModellingTool.FeatureModel.FeatureRelationProperties;
import de.FeatureModellingTool.FeatureModel.VPConstraint;
import de.reuse.Context;
/**
* 1���½����� input: parent, child
* 1��������������
* 2�������������棨�Լ��ĸ���
* 2�������� input: oldParent, oldChild, newNode, isChangeParent
* 1����child��ͬ�½�
* 2����parent�������������棨�Լ���offspring��
*
* todo: ��changeһ��plconnection��startʱ�������ӿ��ܿ�������sink�ˣ�����������source�ˣ���ʱӦ��ֻ��������sink��
* ���ڵ�����ʱֻ�е�source��sink����������ʱ����������
*
* @author tlc
*/
public class ModelValidation {
private Context context;
//--ModelValidation share parent component's context
public ModelValidation(Context context) {
this.context = context;
}
private FeatureModel getFeatureModel() {
return (FeatureModel)context.getValue(GraphicalEditor.FEATURE_MODEL);
}
private ConstraintModel getConstraintModel() {
return (ConstraintModel)context.getValue(GraphicalEditor.CONSTRAINT_MODEL);
}
public boolean canConnect(String startFeatureId, String endFeatureId, String relationName) {
if ((startFeatureId == null) || (endFeatureId == null) || (relationName == null))
return false;
//--not refinement relation: no validation
if (!relationName.equals(FeatureRelationProperties.DECOMPOSE) &&
!relationName.equals(FeatureRelationProperties.DECOMPOSE))
return true;
//--end feature has parent already?
Feature endParent = getParent(endFeatureId);
if (endParent != null)
return false;
//--end is root of start?
Feature startRoot = getRoot(startFeatureId);
if (startRoot != null) {
if (endFeatureId.equals(startRoot.getID()))
return false;
}
return true;
}
public boolean canConnect(String featureId, String constraintId, boolean isSource) {
if ((featureId == null) || (constraintId == null))
return false;
//--not vp constraint: no validation
VPConstraint vpConstraint = getConstraintModel().getVPConstraint(constraintId);
if (vpConstraint == null)
return true;
//--connect to vp constraint source: feature as parent of other features
if (isSource) {
int sourceCount = vpConstraint.getSourceFeatureSet().size();
if (sourceCount > 1)
throw new RuntimeException("model error founded: mutiple sources in a vp constraint");
else if (sourceCount == 1)
return false;
//--if the root of feature is a node of vp constraint sinks
Feature root = getRoot(featureId);
Iterator<Feature> itF = vpConstraint.getSinkFeatureSet().iterator();
while (itF.hasNext()) {
Feature sink = itF.next();
Feature sinkParent = getParent(sink.getID());
if (sinkParent != null)
return false;
if (root.getID().equals(sink.getID()))
return false;
}
return true;
}
//--connect to vp constaint sink:
Feature parent = getParent(featureId);
if (parent != null)
return false;
//--if the root of vp constraint source is the feature
Set<Feature> setF = vpConstraint.getSourceFeatureSet();
if (setF.size() > 1)
throw new RuntimeException("model error founded: mutiple sources in a vp constraint");
else if (setF.size() == 0)
return true;
Feature source = setF.iterator().next();
Feature sourceRoot = getRoot(source.getID());
if (featureId.equals(sourceRoot.getID()))
return false;
return true;
}
public boolean canChangeConnection(String oldStartFeatureId, String oldEndFeatureId, String newFeatureId,
boolean bChangeStart, String relationName) {
if (oldStartFeatureId == null || oldEndFeatureId == null || newFeatureId == null || relationName == null)
return false;
//--not refinement relation: no validation
if (!relationName.equals(FeatureRelationProperties.DECOMPOSE) &&
!relationName.equals(FeatureRelationProperties.DECOMPOSE))
return true;
if (!bChangeStart) { //--change child
if (newFeatureId.equals(oldEndFeatureId))
return true;
return canConnect(oldStartFeatureId, newFeatureId, relationName);
}
//--change parent
Feature ancestorOfNewNode = getParent(newFeatureId);
while (ancestorOfNewNode != null) {
String tempId = ancestorOfNewNode.getID();
if (oldEndFeatureId.equals(tempId))
return false;
ancestorOfNewNode = getParent(tempId);
}
return true;
}
public boolean canChangeConnection(String featureId, String constraintId, boolean isSource,
String newEntityId, boolean bChangeConstraint) {
if (featureId == null || constraintId == null || newEntityId == null)
return false;
if (newEntityId.equals(featureId) || newEntityId.equals(constraintId))
return true;
if (isSource && !bChangeConstraint) { //---change parent feature
VPConstraint vpConstraint = getConstraintModel().getVPConstraint(constraintId);
Set<Feature> setSinkFeature = vpConstraint.getSinkFeatureSet();
Iterator<Feature> itSinkFeature = setSinkFeature.iterator();
while (itSinkFeature.hasNext()) {
String sinkFeatureId = itSinkFeature.next().getID();
if (sinkFeatureId.equals(newEntityId))
return false;
}
Feature ancestorOfNewFeature = getParent(newEntityId);
while (ancestorOfNewFeature != null) {
String tempId = ancestorOfNewFeature.getID();
itSinkFeature = setSinkFeature.iterator();
while (itSinkFeature.hasNext()) {
String sinkFeatureId = itSinkFeature.next().getID();
if (sinkFeatureId.equals(tempId))
return false;
}
ancestorOfNewFeature = getParent(tempId);
}
return true;
}
if (bChangeConstraint)
return canConnect(featureId, newEntityId, isSource);
return canConnect(newEntityId, constraintId, isSource);
}
private Feature getParent(String featureId) {
Feature parent = getFeatureModel().getParentFeature(featureId);
if (parent == null)
parent = getConstraintModel().getParentFeature(featureId);
return parent;
}
private Feature getRoot(String featureId) {
if (featureId == null)
return null;
String rootId = featureId;
String tempId = featureId;
while (tempId != null) {
rootId = tempId;
Feature parent = getParent(tempId);
if (parent != null)
tempId = parent.getID();
else
tempId = null;
}
return getFeatureModel().getFeature(rootId);
}
}