//UML Model Transformation Tool (UMT)
//Copyright (C) 2003, 2004, 2005 SINTEF
//Authors: jon.oldevik at sintef.no | roy.gronmo at sintef.no | tor.neple at sintef.no | fredrik.vraalsen at sintef.no
//Webpage: http://umt.sourceforge.net
//Deloped in the projects: ACEGIS (EU project - IST-2002-37724),
// CAFE (EUREKA/ITEA - ip00004), FAMILIES (ITEA project ip02009)
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU Lesser General Public License
//as published by the Free Software Foundation; either version 2.1
//of the License, or (at your option) any later version.
//
//This program 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
//Lesser General Public License for more details.
//
//You should have received a copy of the GNU Lesser General Public
//License along with this program; if not, write to the Free
//Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
//02111-1307 USA
package org.sintef.umt.systemfamily;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.*;
import javax.swing.border.TitledBorder;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
import org.sintef.umt.transformer.XMLUtility;
import org.sintef.umt.umtmain.UMTMain;
import org.w3c.dom.*;
/**
* @author jol
* VariabilityManager
* Created Aug 20, 2004
*/
import javax.swing.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.awt.event.*;
public class VariabilityManager extends JPanel implements ActionListener {
public static final String SYSTEM_FAMILY_VARIABILITY_FILE = "context.system_family_gen.html";
public static final String SYSTEM_FAMILY_INITIAL_STATE = "context.system_family.initial.html";
public final static Color bgColor = Color.white;
public final static Color altBackground = Color.lightGray;
public final static Color deactivatedBackground = Color.blue;
public final static Color fgColor = Color.black;
public final static Color varChecked = Color.green.brighter().brighter().brighter();
public final static Color varNotChecked = Color.pink;
public static Font defaultFont = null;
public static Font rendererFont1 = null;
public static Font rendererFont2 = null;
private int variationPointCounter = 0;
private static TitledBorder templateBorder;
private Element modelRoot = null;
public static final String VARIABILITY_INDICATOR = "vpvalue";
public static final String VARIABILITY_CLASS_ACTIVE = "variability_active";
private JComboBox exportSelectorBox = null;
private boolean viewDerivedModel = false;
private Hashtable idManager = new Hashtable ();
private Vector variabilityListeners = new Vector();
private Hashtable classPanels = new Hashtable ();
private VariabilityChecker variabilityChecker = null;
private VariabilityResolver variabilityResolver = null;
// private final static String VP_OPTIONAL = ""
// private Font h1,h2;
public VariabilityManager () {
templateBorder = new TitledBorder ("");
defaultFont = templateBorder.getTitleFont();
rendererFont1 = defaultFont.deriveFont(defaultFont.getStyle(), defaultFont.getSize() + 6);
rendererFont2 = defaultFont.deriveFont(defaultFont.getStyle(), defaultFont.getSize() + 4);
idManager.clear();
classPanels.clear();
}
public void addVariabilityEventListener (VariabilityEventListener listener) {
variabilityListeners.add(listener);
}
private void notifyVariabilityEventListeners (Object changedObject) {
for (Iterator it = variabilityListeners.iterator(); it.hasNext();) {
VariabilityEventListener listener = (VariabilityEventListener)it.next();
listener.variabilityModelChanged(changedObject);
}
}
public void variabilityPanel (Element rootelement) {
idManager.clear();
classPanels.clear();
modelRoot = rootelement;
setLayout(new BorderLayout ());
NodeList packages = rootelement.getElementsByTagName("package");
if (packages.getLength() > 0) {
JPanel pPanel = handlePackage((Element)packages.item(0), true);
TitledBorder border = new TitledBorder("ProductLine " + ((Element)packages.item(0)).getAttribute("name"));
Font f1 = defaultFont.deriveFont(defaultFont.getStyle(), defaultFont.getSize() + 10);
border.setTitleFont(f1);
pPanel.setBorder(border);
add(new JScrollPane(pPanel), BorderLayout.CENTER);
}
ImageIcon checkIcon = null;
ImageIcon resolveIcon = null;
ImageIcon storeConfigIcon = null;
ResourceBundle bundle = SystemFamilyTreeCellRenderer.getResourceBundle();
if (bundle != null) {
checkIcon = new ImageIcon (UMTMain.family_img_dir + bundle.getString("family.action.check"));
resolveIcon = new ImageIcon (UMTMain.family_img_dir + bundle.getString("family.action.resolve"));
storeConfigIcon = new ImageIcon (UMTMain.family_img_dir + bundle.getString("family.action.storeConfig"));
}
JButton check = new JButton ("Check");
JButton resolve = new JButton ("Resolve");
check.setContentAreaFilled(false);
resolve.setContentAreaFilled(false);
check.setIcon(checkIcon);
resolve.setIcon(resolveIcon);
check.setToolTipText("Check Product Line Model");
resolve.setToolTipText("Resolve Product Line Model - Generate System Model");
check.addActionListener(this);
resolve.addActionListener(this);
String[] data = {"UMT XMIL", "XMI1.0/UML 1.3","UML2"};
exportSelectorBox = new JComboBox (data);
exportSelectorBox.setFont(defaultFont);
JCheckBox viewDerivedChecker = new JCheckBox ("View result");
viewDerivedChecker.setSelected(false);
viewDerivedChecker.setToolTipText("Tick to view the resulting resolved model. ");
viewDerivedChecker.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.DESELECTED)
viewDerivedModel = false;
else if (e.getStateChange() == ItemEvent.SELECTED)
viewDerivedModel = true;
}
});
JButton saveConfig = new JButton ("");
saveConfig.setActionCommand("save_configuration");
saveConfig.setFont(defaultFont);
saveConfig.setIcon(storeConfigIcon);
saveConfig.setContentAreaFilled(false);
saveConfig.setToolTipText("Save Configuration as a new Family Model");
saveConfig.addActionListener(this);
JPanel actionPanel = new JPanel (new FlowLayout(FlowLayout.LEFT));
actionPanel.setBackground(bgColor);
actionPanel.add(check); actionPanel.add(resolve);
actionPanel.add(exportSelectorBox);
actionPanel.add(saveConfig);
actionPanel.add(viewDerivedChecker);
// actionPanel.add(exportBox); actionPanel.add(exportButton);
variabilityChecker = new VariabilityChecker ();
variabilityResolver = new VariabilityResolver ();
JPanel varPanel = new JPanel (new GridLayout(2,1));
varPanel.add(variabilityChecker);
varPanel.add(variabilityResolver);
actionPanel.add(varPanel);
add(actionPanel, BorderLayout.NORTH);
// setSize(300,200);
// setVisible(true);
repaint ();
}
private JPanel handlePackage (Element element, boolean isRoot) {
NodeList children = element.getChildNodes();
Element childelement = null;
JPanel pPanel = new JPanel (new BorderLayout());
pPanel.setBackground(bgColor);
// If there are sub packages, these should be placed in a new tab.
JTabbedPane containerTab = new JTabbedPane ();
containerTab.setFont(rendererFont1);
containerTab.setBackground(bgColor);
pPanel.add(containerTab);
if (isRoot) {
// add the category classes
NodeList classes = element.getElementsByTagName("class");
for (int i = 0; i < classes.getLength(); i++) {
Element e = (Element) classes.item(i);
String stereotype = e.getAttribute("stereoType");
String eid = e.getAttribute("id");
if (stereotype.equalsIgnoreCase("category")) {
idManager.put(eid, e);
JTabbedPane catTab = new JTabbedPane ();
//// FONT
catTab.setFont(rendererFont2);
containerTab.add(e.getAttribute("name"), catTab);
int index = containerTab.indexOfComponent(catTab);
containerTab.setIconAt(index, SystemFamilyTreeCellRenderer.categoryClass);
containerTab.setToolTipTextAt(index, "Category (group) '" + e.getAttribute("name") + "'");
JPanel cPanel= handleClass (e);
if (cPanel != null) {
catTab.addTab(e.getAttribute("name"), cPanel);
}
NodeList assocs = e.getElementsByTagName("association");
for (int j = 0; j < assocs.getLength(); j++) {
Element assoc = (Element) assocs.item(j);
String targetClass = assoc.getAttribute("targetClass");
// get the class
Object gotId = idManager.get(targetClass);
if (gotId == null) {
Element clazz = VariabilityManager.getClassElementWithID(assoc.getOwnerDocument().getDocumentElement(), targetClass);
if (clazz != null) {
cPanel= handleClass (clazz);
if (cPanel != null) {
catTab.addTab(clazz.getAttribute("name"), cPanel);
}
}
}
}
} else if (stereotype.equalsIgnoreCase("ProductLine")) {
idManager.put(eid, e);
JPanel cPanel = handleClass(e);
if (cPanel != null) {
containerTab.add(cPanel, "Attributes");
int index = containerTab.indexOfComponent(cPanel);
containerTab.setToolTipTextAt(index, "Attribute properties for the product line '" + e.getAttribute("name") + "'");
}
}
}
}
boolean hasPackages = false;
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeName().equalsIgnoreCase("package")) {
hasPackages = true;
break;
}
}
if (hasPackages) {
JTabbedPane packageTab = new JTabbedPane ();
containerTab.add("Packages", packageTab);
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeName().equalsIgnoreCase("package")){
JPanel childPanel = handlePackage ((Element) child, false);
// pPanel.setFont(h2);
// Font f1 = defaultFont.deriveFont(defaultFont.getStyle(), defaultFont.getSize() + 6);
// currentPackageTab.setFont(f1);
packageTab.addTab("Package " + ((Element)child).getAttribute("name"), childPanel);
}
}
}
return pPanel;
}
private JPanel handleClass (Element element) {
variationPointCounter = 0;
boolean has_variability = checkClassVariability (element);
JPanel cPanel = null;
idManager.put(element.getAttribute("id"), element);
if (has_variability) {
// cPanel = new JPanel (new FlowLayout(FlowLayout.LEFT));
cPanel = new JPanel (new BorderLayout());
cPanel.setBackground(bgColor);
// cPanel.setBackground(bgColor);
// TitledBorder border = new TitledBorder("Class " + element.getAttribute("name"));
// border.setTitleFont(defaultFont.deriveFont(defaultFont.getStyle(), defaultFont.getSize() + 2));
// cPanel.setBorder (border);
variationPointCounter++;
ClassPropertyTableModel tablemodel = new ClassPropertyTableModel (element);
JTable table = new JTable (tablemodel) {
public TableCellRenderer getCellRenderer(int row, int column) {
return new VariabilityCellRenderer ();
}
};
table.setBackground(bgColor);
TableColumn vpColumn = table.getColumnModel().getColumn(2);
vpColumn.setCellEditor(new VariabilityCellEditor());
JScrollPane scroll = new JScrollPane (table);
scroll.setBackground(bgColor);
cPanel.add(scroll);
if (cPanel != null)
classPanels.put(element.getAttribute("id"), cPanel);
} else {
}
return cPanel;
}
private int handleAttributes (NodeList attributes, JPanel vPanel) {
int count = 0;
for (int i = 0; i< attributes.getLength();i++)
count += handleAttribute ((Element)attributes.item(i), vPanel);
return count;
}
private void handleAssociations (NodeList associations, JPanel vPanel) {
for (int i = 0; i< associations.getLength();i++)
handleAssociation ((Element)associations.item(i), vPanel);
}
private void handleOperations (NodeList operations, JPanel vPanel) {
for (int i = 0; i< operations.getLength();i++)
handleOperation ((Element)operations.item(i), vPanel);
}
private int handleAttribute (Element element, JPanel vPanel) {
String stereotype = element.getAttribute("stereoType");
String name = element.getAttribute("name");
String type_id = element.getAttribute("type");
boolean is_vp = checkVariationPoint (stereotype);
if (is_vp) {
addCheckBox (vPanel, name, "Attribute <i>" + name + "</i>");
return 1;
}
return 0;
}
private void handleAssociation(Element element, JPanel vPanel) {
String stereotype = element.getAttribute("stereoType");
String name = element.getAttribute("name");
String otherEnd = element.getAttribute("otherEnd");
boolean is_vp = checkVariationPoint (stereotype);
if (is_vp) {
addCheckBox (vPanel, name, "Association <i>" + name + "</i>");
} else if (stereotype.equalsIgnoreCase("conflicts")) {
// body (pw, "Association <i>" + name + "</i> in conflict");
} else if (stereotype.equalsIgnoreCase("requires")) {
// body (pw, "Association <i>" + name + "</i> requires");
}
}
private void handleOperation(Element element, JPanel vPanel) {
String stereotype = element.getAttribute("stereoType");
String name = element.getAttribute("name");
boolean is_vp = checkVariationPoint (stereotype);
if (is_vp) {
addCheckBox (vPanel, name, "Operation " + name);
}
}
private void addCheckBox (JPanel vPanel, String name, String value) {
JCheckBox check = new JCheckBox ();
check.setBackground(bgColor);
check.setText(name);
check.setSelected(true);
check.setToolTipText("Optional variation point " + name);
vPanel.add(check);
}
/**
*
* @param element
* @return
*/
protected boolean checkClassVariability (Element element) {
boolean has_variability = false;
// has_variability = VariabilityManager.checkVariationPoint(element.getAttribute("stereoType"));
// if (has_variability) return true;
NodeList list = element.getElementsByTagName("attribute");
has_variability = checkVariationPointForList(list);
if (has_variability)
return true;
list = element.getElementsByTagName("operation");
has_variability = checkVariationPointForList(list);
if (has_variability) return true;
list = element.getElementsByTagName("association");
has_variability = checkVariationPointForList(list);
if (has_variability)
return true;
// check extra for association going to 'alternative classes'
for (int i = 0; i < list.getLength(); i++) {
Element assoc = (Element) list.item(i);
Element targetClazz = VariabilityManager.getClassElementWithID(
assoc.getOwnerDocument().getDocumentElement(), assoc.getAttribute("targetClass"));
has_variability = VariabilityManager.checkVariationPoint(targetClazz.getAttribute("stereoType"));
}
return has_variability;
}
//
// Utils
//
protected boolean checkVariationPointForList (NodeList list) {
boolean has_variability = false;
for (int i = 0; i< list.getLength();i++) {
String st = ((Element)list.item(i)).getAttribute("stereoType");
has_variability = checkVariationPoint(st);
if (has_variability)
return true;
}
return has_variability;
}
public static Vector getVariationPoints (NodeList list) {
Vector v = new Vector ();
boolean has_variability = false;
for (int i = 0; i< list.getLength();i++) {
String st = ((Element)list.item(i)).getAttribute("stereoType");
has_variability = checkVariationPoint(st);
if (has_variability)
v.add(list.item(i));
}
return v;
}
/**
* Static method that decides if a stereotype actually represents a variability
* @param stereotype
* @return
*/
public static boolean checkVariationPoint (String stereotype) {
if (stereotype == null)
return false;
else if (stereotype.equalsIgnoreCase("vp") || stereotype.equalsIgnoreCase("optional") || stereotype.equalsIgnoreCase("variationpoint"))
return true;
else if (stereotype.equalsIgnoreCase("range") || stereotype.equalsIgnoreCase("property"))
return true;
else if (stereotype.equalsIgnoreCase("conflicts") || stereotype.equalsIgnoreCase("requires"))
return true;
else if (stereotype.equalsIgnoreCase("alternative"))
return true;
return false;
}
//
// ActionListener
//
public void actionPerformed (java.awt.event.ActionEvent ae) {
Object source = ae.getSource();
String action = ae.getActionCommand();
if (action.equalsIgnoreCase("resolve")) {
resolveSystemFamily ();
} else if (action.equalsIgnoreCase("check")) {
checkSystemFamily ();
} else if (action.equalsIgnoreCase("save_configuration")) {
saveSystemFamilyConfiguration ();
}
}
private void checkSystemFamily () {
// System.out.println ("Check System Family ");
variabilityChecker.setModel(modelRoot);
variabilityChecker.startCheck();
}
private void resolveSystemFamily () {
// System.out.println ("Resolve System Family ");
variabilityResolver.setModel (modelRoot);
String selected = (String) exportSelectorBox.getSelectedItem();
variabilityResolver.startResolving(selected, true, viewDerivedModel);
}
/**
* Stores the current variability specification
* as a "new" System Family Model
*/
private void saveSystemFamilyConfiguration() {
System.out.println ("saveSystemFamilyConfiguration");
// Store the current model with variability settings
System.out.println ("DefaultVariabilityResolveEngineImpl::resolveModel");
DocumentBuilderFactory docfac = DocumentBuilderFactory.newInstance();
DocumentBuilder docbuild = null;
Document doc = null;
try {
docbuild = docfac.newDocumentBuilder();
doc = docbuild.newDocument();
} catch (ParserConfigurationException pcerr) {
System.out.println ("Could not create document :" + pcerr);
// Have to exit ---
}
Element newModelRoot = doc.createElement("model");
Element importModel = (Element) doc.importNode(modelRoot, true);
newModelRoot.appendChild(importModel);
storeModel(newModelRoot, "UMT");
}
private class VariabilityCellRenderer extends DefaultTableCellRenderer {
public VariabilityCellRenderer (){
super ();
}
public Component getTableCellRendererComponent(JTable table,
Object obj,
boolean isSelected,
boolean hasFocus,
int row,
int column)
{
// System.out.println ("RenderObject:" + obj.getClass().getName());
JComponent renderer = null;
String toolTipText = "";
if (obj instanceof Element) {
Element element = (Element)obj;
String stereotype = element.getAttribute("stereoType");
String vpvalue = element.getAttribute(VARIABILITY_INDICATOR);
boolean is_variation_point = checkVariationPoint(stereotype);
if (stereotype.equalsIgnoreCase("vp") || stereotype.equalsIgnoreCase("optional")) {
JCheckBox checker = new JCheckBox ();
toolTipText = "OPTIONAL variation point.";
checker.setSelected(vpvalue.equalsIgnoreCase("false")?false:true);
renderer = checker;
} else if (stereotype.equalsIgnoreCase("range")) {
// range variation points only for attributes
// Get range values
String[] ranges = VariabilityManager.getRangeValues(element);
JTextField tf = new JTextField (vpvalue);
tf.setEditable(false);
// MyLabel l = new MyLabel (vpvalue);
toolTipText = "RANGE variation point (Valid range: " + ranges[0] + " - " + ranges[1] + ")";
renderer = tf;
} else if (stereotype.equalsIgnoreCase("property")) {
// Property variation points only for attributes
JTextField tf = new JTextField (vpvalue);
tf.setEditable(false);
renderer = tf;
toolTipText = "PROPERTY variation point. " + vpvalue;
if (element.getNodeName().equalsIgnoreCase("attribute")) {
String typeid = element.getAttribute("type");
// Need to find type of this attribute
}
} else if (stereotype.equalsIgnoreCase("alternative")) {
JComboBox combo = null;
if (element.getNodeName().equalsIgnoreCase("attribute")) {
String data[] = {vpvalue};
combo = new JComboBox (data);
toolTipText = "Alternative variation point: " + vpvalue;
} else {
String sourceAssociation = element.getAttribute("sourceAssociation");
String id = element.getAttribute("id");
String key = getTypeAlternativeKey(id, sourceAssociation);
String vpvalueAssoc = ((Element)idManager.get(id)).getAttribute(key);
String data[] = {vpvalueAssoc};
combo = new JComboBox (data);
toolTipText = "Type Alternative variation point: " + vpvalueAssoc;
vpvalue = vpvalueAssoc;
}
/*
JTextField tf = null;
if (vpvalue != null)
tf = new JTextField (vpvalue);
else
tf = new JTextField ("alternative...");
*/
renderer = combo;
combo.setEditable(false);
} else {
JTextField tf = new JTextField (vpvalue);
tf.setEditable(false);
renderer = tf;
toolTipText = "Unhandled variation point type: " + stereotype;
}
if (is_variation_point && vpvalue.equals("")) {
renderer.setBackground(varNotChecked);
toolTipText = renderer.getToolTipText() + " # Not checked by user #";
} else if (is_variation_point) {
renderer.setBackground(varChecked);
// send update event to tree viewer
} else {
// renderer.setBackground(bgColor);
renderer.setBackground(Color.yellow);
}
/*
if (renderer instanceof JComboBox)
renderer.setFont(defaultFont);
else
renderer.setFont(rendererFont1);
*/
renderer.setToolTipText(toolTipText);
renderer.setFont(defaultFont);
return renderer;
} else {
JLabel label = new JLabel ((String)obj);
renderer = label;
renderer.setBackground(bgColor);
}
renderer.setFont(defaultFont);
return renderer;
}
}
private class VariabilityCellEditor extends AbstractCellEditor implements TableCellEditor,
ChangeListener {
Object editorvalue = null;
public Object getCellEditorValue() {
return editorvalue;
}
public Component getTableCellEditorComponent(JTable table,
Object value,
boolean isSelected,
int row,
int column) {
JComponent editor = null;
editorvalue = value;
// System.out.println ("getTableCellEditorComponent: " + value);
boolean is_variation_point = false;
String vpvalue = "";
if (value instanceof Element) {
Element element = (Element)value;
vpvalue = element.getAttribute(VARIABILITY_INDICATOR);
String stereotype = element.getAttribute("stereoType");
is_variation_point = checkVariationPoint(stereotype);
if (stereotype.equalsIgnoreCase("vp") || stereotype.equalsIgnoreCase("optional")) {
JCheckBox check = new JCheckBox ();
check.addChangeListener(this);
editor = check;
} else if (stereotype.equalsIgnoreCase("range")) {
NumberRangeVariabilityCellEditor rangeeditor = new NumberRangeVariabilityCellEditor (element);
rangeeditor.addChangeListener(this);
editor = rangeeditor;
} else if (stereotype.equalsIgnoreCase("property")) {
// the editor handles the actions
PropertyVariabilityCellEditor propertycelleditor = new PropertyVariabilityCellEditor (element);
editor = propertycelleditor;
} else if (stereotype.equalsIgnoreCase("alternative")) {
// The editor handles the actions
AlternativeVariabilityCellEditor altEditor = new AlternativeVariabilityCellEditor (element);
editor = altEditor;
}
else {
editor = new JTextField ((String) value);
}
} else {
JLabel label = new JLabel ((String)value);
editor = label;
}
if (is_variation_point){
editor.setBackground(varChecked);
}
if (editor instanceof JComboBox)
editor.setFont(rendererFont2);
else
editor.setFont(rendererFont1);
return editor;
}
public void stateChanged (ChangeEvent ce) {
Object source = ce.getSource();
Element element = null;
if (ce.getSource() instanceof JCheckBox) {
JCheckBox box = (JCheckBox)ce.getSource();
element = (Element)editorvalue;
String vpvalue = element.getAttribute(VARIABILITY_INDICATOR);
vpvalue = box.isSelected()?"true":"false";
element.setAttribute(VARIABILITY_INDICATOR, vpvalue);
checkOptionalVariabilityChange(element);
} else if (source instanceof NumberRangeVariabilityCellEditor) {
NumberRangeVariabilityCellEditor editor = (NumberRangeVariabilityCellEditor) source;
Object val = editor.getValue();
String strVal = val.toString();
element = (Element)editorvalue;
String vpvalue = element.getAttribute(VARIABILITY_INDICATOR);
vpvalue.toString();
element.setAttribute(VARIABILITY_INDICATOR, strVal);
}
notifyVariabilityEventListeners(editorvalue);
}
}
/**
* check OptionalVariabilityChange
* @param element
*/
protected void checkOptionalVariabilityChange (Element element) {
String varIndicator = element.getAttribute(VARIABILITY_INDICATOR);
if (element.getNodeName().equalsIgnoreCase("association")) {
String targetClassId = element.getAttribute("targetClass");
Collection assocs = getAssociationsToClass(this.modelRoot, targetClassId);
Element assoc = null;
boolean someIsTrue = false;
for (Iterator it = assocs.iterator(); it.hasNext();) {
assoc = (Element) it.next();
varIndicator = assoc.getAttribute(VARIABILITY_INDICATOR);
if (varIndicator.equals("false")) {
} else if (varIndicator.equals("true")){
someIsTrue = true;
break;
}
}
if (someIsTrue) {
// activate the pane containing this class.
variabilityActivation(targetClassId, true);
} else {
// deactivate the pane containing this class.
variabilityActivation(targetClassId, false);
}
}
}
protected void variabilityActivation (String classId, boolean activate) {
JPanel clazzPanel = (JPanel) classPanels.get(classId);
Container c = null;
Element clazzElement = null;
int index = 0;
if (clazzPanel != null){
c = clazzPanel.getParent();
if (c instanceof JTabbedPane) {
index = ((JTabbedPane)c).indexOfComponent(clazzPanel);
// ((JTabbedPane)c).setIconAt()
((JTabbedPane)c).setEnabledAt(index, activate);
//set activation property for the class element
clazzElement = getClassElementWithID(modelRoot, classId);
if (clazzElement != null) {
// set the VARIABILITY_CLASS_ACTIVE property
clazzElement.setAttribute(VARIABILITY_CLASS_ACTIVE, "" + activate);
}
}
}
}
/**
* Fetches the range values from a model element (attribute)
* For now, uses the initialValue property on the form value: int = 4{3-10},
* where 4 is the default, 3, is the lower and 10 the upper range value
*
* For now: Only returns low and high range values, not default value
*/
public static String[] getRangeValues (Element element) {
String[] ranges = new String [2];
ranges[0] = "2"; ranges[1] = "16";
String initialValue = element.getAttribute ("initialValue");
String[] valueSplit = initialValue.split(", ");
int beginindex = initialValue.indexOf('{');
int nextindex = initialValue.indexOf('-', beginindex);
int endindex = initialValue.indexOf('}', nextindex);
try {
ranges[0] = initialValue.substring(beginindex+1, nextindex).trim();
ranges[1] = initialValue.substring(nextindex+1, endindex).trim();
} catch (Exception ex) {
}
return ranges;
}
/**
* Fetches the alternative values from a model element (attribute)
* For now, uses the initialValue property on the form: {3,100, 2000, 200}
* @param element
* @return
*/
public static Object [] getAlternativeValuesForAttribute (Element element) {
Vector alts = new Vector ();
String initialValue = element.getAttribute ("initialValue");
String[] valueSplit = initialValue.split("[,\\{\\}]");
for (int i = 0; i < valueSplit.length; i++) {
if (!valueSplit[i].trim().equals(""))
alts.add(valueSplit[i].trim());
}
return alts.toArray();
}
/**
* Fetches the type alternatives for a class - determined by its subclasses
* @param element
* @return
*/
public static Object [] getAlternativeValuesForClass (Element element) {
Vector alts = new Vector ();
Vector subs = VariabilityManager.getSubclasses(element.getOwnerDocument().getDocumentElement(), element.getAttribute("id"));
for (Iterator it = subs.iterator(); it.hasNext();) {
Element sub = (Element) it.next();
alts.add(sub.getAttribute("name"));
}
return alts.toArray();
}
private class NumberRangeVariabilityCellEditor extends JSpinner implements ChangeListener, KeyListener {
private Element editorvalue = null;
public NumberRangeVariabilityCellEditor (Element element) {
// Get the range values
addKeyListener(this);
editorvalue = element;
String vpvalue = element.getAttribute(VARIABILITY_INDICATOR);
String[] ranges = VariabilityManager.getRangeValues(element);
String minval = ranges[0], maxval = ranges[1];
setToolTipText("Legal range values: {" + minval + " - " + maxval + "}");
// Must fetch type
// element.getAttribute("type");
String type = "int";
if (minval.indexOf('.') > -1 || maxval.indexOf('.') > -1)
type = "double";
if (type.equalsIgnoreCase("int") || type.equalsIgnoreCase("integer") || type.equalsIgnoreCase("short") || type.equalsIgnoreCase("long")){
int val = 4, min = 4, max = 20, step = 1;
min = Integer.parseInt(minval); max = Integer.parseInt(maxval);
val = min;
if (vpvalue != null && !vpvalue.equals("")) {
val = Integer.parseInt(vpvalue);
}
SpinnerNumberModel model = new SpinnerNumberModel (val, min, max, step);
setModel(model);
} else if (type.equalsIgnoreCase("float") || type.equalsIgnoreCase("double")) {
// values currently defined by substring of initialValue property e.g. {2-15}
double val = 2.0, min = 2.0, max = 14.4, step = 0.1;
min = Double.parseDouble(minval); max = Double.parseDouble(maxval);
val = min;
if (vpvalue != null && !vpvalue.equals("")) {
val = Double.parseDouble(vpvalue);
}
SpinnerNumberModel model = new SpinnerNumberModel (val, min, max, step);
setModel(model);
} else {
// TODO: What to do here?
// Type could also be an enumeration
//
SpinnerListModel model = new SpinnerListModel ();
setModel (model);
}
this.setBackground(varNotChecked);
addChangeListener(this);
}
public void stateChanged (ChangeEvent ce) {
System.out.println ("NumberRangeCellEditor::stateChanged");
JSpinner spin = (JSpinner) ce.getSource();
Object value = spin.getValue();
editorvalue.setAttribute(VARIABILITY_INDICATOR, value.toString());
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER || e.getKeyCode() == KeyEvent.VK_TAB) {
System.out.println ("Enter | tab");
}
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
}
private class PropertyVariabilityCellEditor extends JTextField implements ActionListener, KeyListener {
private Element editorvalue = null;
public PropertyVariabilityCellEditor (Element element) {
editorvalue = element;
String type = element.getAttribute("type");
String vpvalue = element.getAttribute(VARIABILITY_INDICATOR);
setToolTipText("Select value for property: (Type...)");
setText (editorvalue.getAttribute(VARIABILITY_INDICATOR));
// addCaretListener(this);
addActionListener(this);
addKeyListener(this);
}
public void actionPerformed (ActionEvent ae) {
// System.out.println ("PropertyCellEditor::actionPerformed: " + ae.getActionCommand());
editorvalue.setAttribute(VARIABILITY_INDICATOR, ae.getActionCommand());
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER || e.getKeyCode() == KeyEvent.VK_TAB) {
editorvalue.setAttribute(VARIABILITY_INDICATOR, getText());
}
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
}
private class AlternativeVariabilityCellEditor extends JComboBox implements ActionListener {
private Element editorvalue = null;
public AlternativeVariabilityCellEditor (Element element) {
editorvalue = element;
Object[] alternativeValues = null;
if (element.getNodeName().equalsIgnoreCase("attribute")) {
alternativeValues = VariabilityManager.getAlternativeValuesForAttribute(editorvalue);
setToolTipText("Select value for Alternative vp.");
}
else if (element.getNodeName().equalsIgnoreCase("class")) {
alternativeValues = VariabilityManager.getAlternativeValuesForClass(editorvalue);
setToolTipText("Select type alternative for " + element.getAttribute("name"));
}
String vpvalue = element.getAttribute(VARIABILITY_INDICATOR);
if (alternativeValues == null || alternativeValues.length == 0) {
alternativeValues = new String[1];
alternativeValues[0] = "No alternatives";
}
setModel(new DefaultComboBoxModel(alternativeValues));
addActionListener(this);
}
public void actionPerformed (ActionEvent ae) {
// System.out.println ("PropertyCellEditor::actionPerformed: " + ae.getActionCommand());
String action = ae.getActionCommand();
String selected = (String) getSelectedItem();
if (editorvalue.getNodeName().equalsIgnoreCase("attribute")) {
editorvalue.setAttribute(VARIABILITY_INDICATOR, selected);
} else if (editorvalue.getNodeName().equalsIgnoreCase("class")) {
String sourceAssociation = editorvalue.getAttribute("sourceAssociation");
String id = editorvalue.getAttribute("id");
String key = getTypeAlternativeKey(id, sourceAssociation);
Element orgClazz = (Element)idManager.get(id);
orgClazz.setAttribute(key, selected);
editorvalue.setAttribute(key, selected);
}
notifyVariabilityEventListeners(editorvalue);
}
}
public static void storeModel (Element model, String exportType) {
Writer writer = null;
if (exportType.startsWith("UMT")) {
writer = getStoreWriter(model, exportType, "xml");
if (writer != null) {
XMLUtility.streamToXML(model, writer);
try {
writer.close();
} catch (IOException ioex) {
}
}
}
}
public static void storeTextModel (Element orgModel, StringBuffer model, String exportType) {
Writer writer = null;
String ext = exportType.startsWith("UML2")? "uml2": "xmi";
writer = getStoreWriter(orgModel, exportType, ext);
if (writer != null) {
PrintWriter printer = new PrintWriter(writer);
printer.print(model.toString());
printer.close();
}
}
protected static Writer getStoreWriter (Element orgModel, String modelType, String extension) {
JFileChooser savedialog = new JFileChooser ("Save product model(" + modelType + ")");
savedialog.setCurrentDirectory (new java.io.File (org.sintef.umt.umtmain.UMTMain.getCurrentStoreDir()));
String name = orgModel.getAttribute("name");
if (name == null) name = "DerivedModel";
savedialog.setSelectedFile(new File (name + "." + extension));
int ret = savedialog.showSaveDialog(null);
if(ret == JFileChooser.APPROVE_OPTION) {
File f = savedialog.getSelectedFile();
java.io.FileWriter writer = null;
try {
writer = new java.io.FileWriter (f);
return writer;
} catch (java.io.IOException ex) {
System.out.println ("VariabilityResolver::getStoreWriter- " + ex);
}
}
return null;
}
/**
*
* @param rootDoc
* @param id
* @return
*/
public static Element getClassElementWithID (Element rootDoc, String id) {
NodeList classes = rootDoc.getElementsByTagName("class");
for (int i = 0; i < classes.getLength(); i++) {
Element clazz = (Element)classes.item(i);
if (clazz.getAttribute("id").equalsIgnoreCase(id))
return clazz;
}
return null;
}
/**
*
* @param rootDoc
* @param superClassID
* @return
*/
public static Vector getSubclasses (Element rootDoc, String superClassID) {
Vector subClasses = new Vector ();
String scID = null;
NodeList classes = rootDoc.getElementsByTagName("class");
for (int i = 0; i < classes.getLength(); i++) {
Element clazz = (Element)classes.item(i);
scID = clazz.getAttribute("superClass");
if (scID.equalsIgnoreCase(superClassID))
subClasses.add(clazz);
}
return subClasses;
}
public static Collection getAssociationsToClass (Element rootDoc, String classId) {
ArrayList assocsForClass = new ArrayList();
NodeList assocs = rootDoc.getElementsByTagName ("association");
String targetClass = null;
for (int i = 0; i < assocs.getLength(); i++) {
Element assoc = (Element) assocs.item(i);
targetClass = assoc.getAttribute("targetClass");
if (targetClass.equals(classId))
assocsForClass.add(assoc);
}
return assocsForClass;
}
public static Element getAssociationFromID (Element rootDoc, String id) {
NodeList assocs = rootDoc.getElementsByTagName("association");
for (int i = 0; i < assocs.getLength(); i++) {
Element assoc = (Element) assocs.item(i);
if (assoc.getAttribute("id").equals(id))
return assoc;
}
return null;
}
public static String getTypeAlternativeKey (String classId, String assocId) {
return "CLASS-" + classId + "ASSOC-" + assocId;
}
}