package de.FeatureModellingTool.ModelChecker;
import java.awt.event.ActionEvent;
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import javax.swing.*;
import applet.WebConstantDefinition;
import de.FeatureModellingTool.FeatureModel.ConstraintModel;
import de.FeatureModellingTool.FeatureModel.Feature;
import de.FeatureModellingTool.FeatureModel.FeatureModel;
import de.FeatureModellingTool.FeatureModel.FeatureRelation;
import de.FeatureModellingTool.FeatureModel.Variability;
import de.reuse.Context;
import de.reuse.ContextImplementation;
/**
* Created by IntelliJ IDEA.
* User: saturn
* Date: 2003-9-17
* Time: 14:01:48
* To change this template use Options | File Templates.
*/
class ModelCheckerImplementation extends JPanel implements ModelChecker, ModelCheckerUI, ConstantDefinition {
protected JList infoDisplayer = null;
protected JToolBar toolBar = null;
protected FeatureModel featureModel = null;
protected ConstraintModel constraintModel = null;
protected FeatureCheckInfoModel fchkInfoModel = new FeatureCheckInfoModel();
protected HashSet conflictRelations = new HashSet();
private boolean isAtomicSetBuilt = false;
protected final ContextImplementation context = new ContextImplementation();
protected final EntryAction entryAction = new EntryAction();
protected final DefaultListModel listModel = new DefaultListModel();
public ModelCheckerImplementation() {
infoDisplayer = new JList();
infoDisplayer.setModel(listModel);
toolBar = new JToolBar();
toolBar.setFloatable(false);
toolBar.setOrientation(JToolBar.VERTICAL);
//toolBar.setBorderPainted(false);
toolBar.setRollover(true);
toolBar.setBorder(BorderFactory.createEmptyBorder());
ImageIcon actionIcon = null;
try{
actionIcon = new ImageIcon(new URL(WebConstantDefinition.RES_HOST+"begin.png"));
}catch(Exception e){
e.printStackTrace();
}
JButton actionButton = new JButton(actionIcon);
//actionButton.setBorderPainted(false);
actionButton.addActionListener(this.entryAction);
actionButton.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, this.getBackground()), BorderFactory.createEtchedBorder()));
toolBar.add(actionButton);
context.addContextChangeListener(new ContextChangeListener());
this.setLayout(new BorderLayout());
infoDisplayer.setBorder(BorderFactory.createEmptyBorder());
JScrollPane scrollPane = new JScrollPane(infoDisplayer);
scrollPane.setBorder(BorderFactory.createEmptyBorder());
this.add(scrollPane, BorderLayout.CENTER);
this.add(toolBar, BorderLayout.WEST);
}
public Context getContext() {
return context;
}
protected class ContextChangeListener implements PropertyChangeListener {
public void propertyChange(PropertyChangeEvent e) {
contextChange(e);
}
}
protected void contextChange(PropertyChangeEvent e) {
String propertyName = e.getPropertyName();
if (FEATURE_MODEL.equals(propertyName)) {
boolean oldV = entryAction.isEnabled();
featureModel = (FeatureModel) e.getNewValue();
boolean newV = entryAction.isEnabled();
if (oldV != newV) {
entryAction.firePropertyChange("enabled", Boolean.valueOf(oldV), Boolean.valueOf(newV));
}
} else if (CONSTRAINT_MODEL.equals(propertyName)) {
constraintModel = (ConstraintModel) e.getNewValue();
}
}
public JComponent getCheckerComponent() {
return this;
}
public Action getEntryAction() {
return entryAction;
}
protected class EntryAction extends AbstractAction {
public EntryAction() {
this.putValue(Action.NAME, "ģ�ͼ��");
}
public boolean isEnabled() {
if (!super.isEnabled()) return false;
if (featureModel == null) return false;
return true;
}
public void actionPerformed(ActionEvent e) {
if (!isEnabled()) return;
checkModel();
}
public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
super.firePropertyChange(propertyName, oldValue, newValue);
}
}
protected void checkModel() {
try {
listModel.removeAllElements();
conflictRelations.clear();
isAtomicSetBuilt = false;
fchkInfoModel = new FeatureCheckInfoModel();
//System.out.println("Begin check: ");
genAtomicSet();
printAtomicSet();
genDependentSet();
printDependentSet();
boolean hasConflict = false;
Iterator iter = fchkInfoModel.getSeedFeatures().iterator();
while(iter.hasNext()) {
Feature f = (Feature)iter.next();
FeatureCheckInfo fchkInfo = fchkInfoModel.getFeatureCheckInfo(f);
if(isConflictInDependentSet(fchkInfo.getDependentSet()))
hasConflict = true;
}
if(hasConflict) {
listModel.addElement("**has Conflict!**");
//System.out.println("**has Conflict!**");
Iterator iter2 = conflictRelations.iterator();
while(iter2.hasNext()) {
FeatureRelation fr = (FeatureRelation)iter2.next();
listModel.addElement(fr.getName() + ", start feature: " + fr.getStartFeature().getName() + ", end feature: "+ fr.getEndFeature().getName());
//System.out.println(fr.getName() + ", start feature: " + fr.getStartFeature().getName() + ", end feature: "+ fr.getEndFeature().getName());
}
} else {
listModel.addElement("No Conflict!");
//System.out.println("**no conflict!**");
}
} catch(ModelInvalidateException e) {
}
}
protected void getSeedFeatures() throws ModelInvalidateException {
Iterator iter = featureModel.getAllFeature().values().iterator();
while(iter.hasNext()) {
Feature f = (Feature)iter.next();
if(f.getVariability()==Variability.Null) {
throw new ModelInvalidateException(ModelInvalidateException.FeatureInfoNotEnough);
}
if(f.getVariability()==Variability.Optional
|| f.getVariability()==Variability.Alternative) {
fchkInfoModel.addSeedFeature(f);
}
Feature rf = fchkInfoModel.getRootOfFeature(f);
fchkInfoModel.addSeedFeature(rf);
}
}
protected void genAtomicSet() throws ModelInvalidateException {
//find out all seed features
getSeedFeatures();
//calculate their atomic set
Iterator iter = fchkInfoModel.getSeedFeatures().iterator();
while(iter.hasNext()) {
Feature f = (Feature)iter.next();
if(fchkInfoModel.isFeatureNotInAnyAtmoicSet(f)) {
//create a atmoic set that contains "f"
AtomicFeatureSet as = new AtomicFeatureSet();
as.setSeed(f);
fchkInfoModel.addFeatureToAtomicSet(f, as);
}
}
isAtomicSetBuilt = true;
}
protected void printAtomicSet() {
//System.out.println("Begin print Atomic Set: ");
Iterator iter = fchkInfoModel.getSeedFeatures().iterator();
while(iter.hasNext()) {
Feature f = (Feature)iter.next();
//System.out.println("Seed Feature: " + f.getName() + ", its Atomic Set contains:");
FeatureCheckInfo fchkInfo = fchkInfoModel.getFeatureCheckInfo(f);
HashSet fs = fchkInfo.getAtomicSet().getFeatures();
Iterator iter2 = fs.iterator();
while(iter2.hasNext()) {
Feature af = (Feature)iter2.next();
//System.out.print(af.getName() + "/");
}
//System.out.println(";");
}
}
protected void genDependentSet() throws ModelInvalidateException {
//pleased call genAtomicSet first
if(!isAtomicSetBuilt)
genAtomicSet();
//conclude the "require" relation between atomic set
HashSet implictRelations = fchkInfoModel.getImplictRelations();
Map relations = featureModel.getAllFeatureRelation(FeatureRelation.REQUIRE);
if(relations!=null) {
implictRelations.addAll(relations.values());
}
if(implictRelations.size() > 0) {
Iterator relationIter = implictRelations.iterator();
while(relationIter.hasNext()) {
FeatureRelation fr = (FeatureRelation)relationIter.next();
fchkInfoModel.addRequireRelationBetweenAtomicSet(fr);
}
//calculate the closed dependent set of each seed feature
HashMap reqRelations = fchkInfoModel.getReqRelations();
boolean stop = true;
do {
stop = true;
Iterator entryIter = reqRelations.entrySet().iterator();
while(entryIter.hasNext()) {
Map.Entry entry = ((Map.Entry)entryIter.next());
AtomicFeatureSet startAS = (AtomicFeatureSet)entry.getKey();
HashSet reqSet = (HashSet)entry.getValue();
HashSet reqSet2 = (HashSet) reqSet.clone();
Iterator endASIter = reqSet2.iterator();
while(endASIter.hasNext()) {
AtomicFeatureSet endAS = (AtomicFeatureSet)endASIter.next();
HashSet set = (HashSet)reqRelations.get(endAS);
if(set!=null && !reqSet.containsAll(set)) {
stop = false;
reqSet.addAll(set);
}
}
}
} while(!stop);
//generate dependent set
Iterator seedIter = fchkInfoModel.getSeedFeatures().iterator();
while(seedIter.hasNext()) {
Feature sf = (Feature)seedIter.next();
fchkInfoModel.genDependentSetOfFeature(sf);
}
} else {
Iterator seedIter = fchkInfoModel.getSeedFeatures().iterator();
while(seedIter.hasNext()) {
Feature sf = (Feature)seedIter.next();
FeatureCheckInfo fchkInfo = fchkInfoModel.getFeatureCheckInfo(sf);
DependentFeatureSet ds = new DependentFeatureSet();
ds.setSource(sf);
ds.setFeatures(fchkInfo.getAtomicSet().getFeatures());
fchkInfo.setDependentSet(ds);
}
}
}
protected void printDependentSet() {
//System.out.println("Begin print Dependent Set: ");
Iterator iter = fchkInfoModel.getSeedFeatures().iterator();
while(iter.hasNext()) {
Feature f = (Feature)iter.next();
//System.out.println("Seed Feature: " + f.getName() + ", its Dependent Set contains:");
FeatureCheckInfo fchkInfo = fchkInfoModel.getFeatureCheckInfo(f);
HashSet fs = fchkInfo.getDependentSet().getFeatures();
Iterator iter2 = fs.iterator();
while(iter2.hasNext()) {
Feature af = (Feature)iter2.next();
//System.out.print(af.getName() + "/");
}
//System.out.println(";");
}
}
protected boolean isConflictInDependentSet(DependentFeatureSet ds) {
boolean hasConflict = false;
HashSet features = ds.getFeatures();
Map relations = featureModel.getAllFeatureRelation(FeatureRelation.EXCLUDE);
if(relations!=null && relations.size()>0) {
Iterator iter = relations.values().iterator();
while(iter.hasNext()) {
FeatureRelation relation = (FeatureRelation)iter.next();
Feature start = relation.getStartFeature();
Feature end = relation.getEndFeature();
if(features.contains(start) && features.contains(end)) {
conflictRelations.add(relation);
hasConflict = true;
}
}
}
return hasConflict;
}
}