package gov.nasa.jpl.mbee.mdk.docgen.table;
import com.nomagic.magicdraw.uml2.util.UML2ModelUtil;
import com.nomagic.uml2.ext.jmi.helpers.StereotypesHelper;
import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.*;
import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Class;
import com.nomagic.uml2.ext.magicdraw.mdprofiles.Stereotype;
import gov.nasa.jpl.mbee.mdk.util.Utils;
import javax.swing.tree.DefaultMutableTreeNode;
import java.util.*;
import java.util.Enumeration;
/**
* properties table for docgen 3 this has a lot of methods that can probably be
* optimized and make more efficient and less convoluted need to revisit once we
* have a more generic graph collection/filter capability
*
* @author dlam
*/
public class PropertiesTable {
private List<Stereotype> splitStereotype = null;
private List<Stereotype> systemIncludeStereotype = null;
private List<Stereotype> systemExcludeStereotype = null;
private List<String> systemIncludeTypeName = null;
private List<String> systemExcludeTypeName = null;
private List<String> systemIncludeName = null;
private List<String> systemExcludeName = null;
private Integer systemAssociationType = null;
private Boolean consolidateTypes = null;
private Boolean showMultiplicity = null;
private Integer floatingPrecision = null;
private Integer maxDepth = null;
private List<String> topIncludeTypeName = null;
private List<String> topExcludeTypeName = null;
private List<Stereotype> topIncludeStereotype = null;
private List<Stereotype> topExcludeStereotype = null;
private List<String> topIncludeName = null;
private List<String> topExcludeName = null;
private Integer topAssociationType = null;
private List<String> topOrder = null;
private Boolean includeInherited;
private List<Element> targets;
Map<Class, Map<Class, Map<Property, Class>>> filteredStructures;
private Map<Class, Map<Class, Map<Class, Integer>>> consolidated;
private int numPropertyHeaders;
private List<String> colspecs;
private List<List<Map<String, String>>> headers;
private EditableTable et;
public EditableTable getEt() {
return et;
}
public PropertiesTable(List<Stereotype> topIncludeStereotype, List<Stereotype> topExcludeStereotype,
List<String> topIncludeName, List<String> topExcludeName, List<String> topIncludeTypeName,
List<String> topExcludeTypeName, List<String> topOrder, List<Stereotype> systemIncludeStereotype,
List<Stereotype> systemExcludeStereotype, List<String> systemIncludeName,
List<String> systemExcludeName, List<String> systemIncludeTypeName,
List<String> systemExcludeTypeName, List<Stereotype> splitStereotype, int maxDepth,
int systemAssociationType, int topAssociationType, List<Element> targets, boolean includeInherited) {
this.splitStereotype = splitStereotype;
this.systemIncludeStereotype = systemIncludeStereotype;
this.systemExcludeStereotype = systemExcludeStereotype;
this.systemIncludeTypeName = systemIncludeTypeName;
this.systemExcludeTypeName = systemExcludeTypeName;
this.systemIncludeName = systemIncludeName;
this.systemExcludeName = systemExcludeName;
this.systemAssociationType = systemAssociationType;
this.consolidateTypes = true;
this.showMultiplicity = true;
this.floatingPrecision = -1;
this.maxDepth = maxDepth;
this.topIncludeTypeName = topIncludeTypeName;
this.topExcludeTypeName = topExcludeTypeName;
this.topIncludeStereotype = topIncludeStereotype;
this.topExcludeStereotype = topExcludeStereotype;
this.topIncludeName = topIncludeName;
this.topExcludeName = topExcludeName;
this.topAssociationType = topAssociationType;
this.topOrder = topOrder;
this.targets = targets;
this.includeInherited = includeInherited;
}
public void showTable() {
et.showTable();
}
/**
* makes all the necessary data structures and tables
*
* @return
*/
public void doMainThings() {
filteredStructures = new HashMap<Class, Map<Class, Map<Property, Class>>>();
List<Map<String, List<String>>> propertiesStructure = new ArrayList<Map<String, List<String>>>();
Map<String, String> types = new HashMap<String, String>();
List<Class> nptElements = new ArrayList<Class>();
for (Element e : targets) {
if (e instanceof Class) {
nptElements.add((Class) e);
}
}
int maxTreeDepth = 0;
for (Element e : nptElements) {
Map<Class, Map<Property, Class>> filteredStructure = new HashMap<Class, Map<Property, Class>>();
populateAttributesStructures((Class) e, filteredStructure, propertiesStructure, types);
int depth = getDepthOfCompositionalMap(filteredStructure, (Class) e);
if (depth > maxTreeDepth) {
maxTreeDepth = depth;
}
filteredStructures.put((Class) e, filteredStructure);
}
numPropertyHeaders = getNumPropertyHeaders(propertiesStructure);
DefaultMutableTreeNode tree = sortPropertiesStructure(propertiesStructure);
colspecs = new ArrayList<String>();
getColSpecsFromTree(tree, colspecs);
int columns = maxTreeDepth + numPropertyHeaders;
List<List<Object>> table = new ArrayList<List<Object>>();
List<List<PropertyEnum>> whatToShow = new ArrayList<List<PropertyEnum>>();
List<List<Boolean>> editable = new ArrayList<List<Boolean>>();
consolidated = new HashMap<Class, Map<Class, Map<Class, Integer>>>();
consolidateTypes(filteredStructures, consolidated);
if (this.consolidateTypes) {
populateTableModelConsolidate(table, whatToShow, editable, nptElements, consolidated, colspecs,
maxTreeDepth, columns);
}
else {
populateTableModel(table, whatToShow, editable, nptElements, filteredStructures, colspecs,
maxTreeDepth, columns);
}
headers = getHeadersFromTree(tree, types, propertiesStructure.size());
List<String> etheaders = new ArrayList<String>();
for (int i = 0; i < maxTreeDepth; i++) {
etheaders.add("");
}
if (this.showMultiplicity) {
etheaders.add("Multiplicity");
}
for (String colspec : colspecs) {
etheaders.add("<html>" + colspec.replaceAll(";", "<br/>") + "</html>");
}
et = new EditableTable("Properties Table", table, etheaders, editable, whatToShow, floatingPrecision);
et.prepareTable();
}
private void populateTableModel(List<List<Object>> tableModel, List<List<PropertyEnum>> whatToShow,
List<List<Boolean>> editable, List<Class> systemElements,
Map<Class, Map<Class, Map<Property, Class>>> systemStructure, List<String> colspecs,
int maxTreeDepth, int columns) {
Collections.sort(systemElements, new Comparator<Class>() {
@Override
public int compare(Class arg0, Class arg1) {
return arg0.getName().compareTo(arg1.getName());
}
});
for (Class systemElement : systemElements) {
populateTableModelRecursive(tableModel, whatToShow, editable, null, systemElement,
systemStructure.get(systemElement), colspecs, maxTreeDepth, columns, 1);
}
}
private void populateTableModelRecursive(List<List<Object>> tableModel,
List<List<PropertyEnum>> whatToShow, List<List<Boolean>> editable, Property systemProperty,
Class systemElement, Map<Class, Map<Property, Class>> systemStructure, List<String> colspecs,
int maxTreeDepth, int columns, int curDepth) {
List<Object> row = new ArrayList<Object>();
List<PropertyEnum> what = new ArrayList<PropertyEnum>();
List<Boolean> edits = new ArrayList<Boolean>();
if (curDepth == 1) {
row.add(systemElement);
edits.add(true);
for (int i = 1; i < maxTreeDepth; i++) {
row.add("");
edits.add(false);
}
}
else {
for (int i = 0; i < curDepth - 1; i++) {
row.add("");
edits.add(false);
}
row.add(systemProperty);
edits.add(true);
for (int i = curDepth; i < maxTreeDepth; i++) {
row.add("");
edits.add(false);
}
}
for (int i = 0; i < maxTreeDepth; i++) {
what.add(PropertyEnum.NAME);
}
if (this.showMultiplicity) {
if (curDepth > 1) {
row.add(Utils.getMultiplicity(systemProperty));
}
else {
row.add("");
}
what.add(PropertyEnum.NAME);
edits.add(false);
}
for (String colspec : colspecs) {
row.add(getPropertyElement(systemElement, Arrays.asList(colspec.split(";")), includeInherited));
what.add(PropertyEnum.VALUE);
edits.add(true);
}
tableModel.add(row);
whatToShow.add(what);
editable.add(edits);
Map<Property, Class> children = systemStructure.get(systemElement);
List<Property> sortedProperties = sortProperty(new ArrayList<Property>(children.keySet()));
for (Property p : sortedProperties) {
populateTableModelRecursive(tableModel, whatToShow, editable, p, children.get(p),
systemStructure, colspecs, maxTreeDepth, columns, curDepth + 1);
}
}
private void populateTableModelConsolidate(List<List<Object>> tableModel,
List<List<PropertyEnum>> whatToShow, List<List<Boolean>> editable, List<Class> systemElements,
Map<Class, Map<Class, Map<Class, Integer>>> consolidated, List<String> colspecs,
int maxTreeDepth, int columns) {
Collections.sort(systemElements, new Comparator<Class>() {
@Override
public int compare(Class arg0, Class arg1) {
return arg0.getName().compareTo(arg1.getName());
}
});
for (Class systemElement : systemElements) {
populateTableModelConsolidateRecursive(tableModel, whatToShow, editable, systemElement,
consolidated.get(systemElement), null, colspecs, maxTreeDepth, columns, 1);
}
}
private void populateTableModelConsolidateRecursive(List<List<Object>> tableModel,
List<List<PropertyEnum>> whatToShow, List<List<Boolean>> editable, Class systemElement,
Map<Class, Map<Class, Integer>> consolidate, Map<Class, Integer> units, List<String> colspecs,
int maxTreeDepth, int columns, int curDepth) {
List<Object> row = new ArrayList<Object>();
List<PropertyEnum> what = new ArrayList<PropertyEnum>();
List<Boolean> edits = new ArrayList<Boolean>();
for (int i = 0; i < curDepth - 1; i++) {
row.add("");
edits.add(false);
}
row.add(systemElement);
edits.add(true);
for (int i = curDepth; i < maxTreeDepth; i++) {
row.add("");
edits.add(false);
}
for (int i = 0; i < maxTreeDepth; i++) {
what.add(PropertyEnum.NAME);
}
if (this.showMultiplicity) {
if (curDepth > 1) {
row.add(units.get(systemElement));
}
else {
row.add("");
}
what.add(PropertyEnum.NAME);
edits.add(false);
}
for (String colspec : colspecs) {
row.add(getPropertyElement(systemElement, Arrays.asList(colspec.split(";")), includeInherited));
what.add(PropertyEnum.VALUE);
edits.add(true);
}
tableModel.add(row);
whatToShow.add(what);
editable.add(edits);
Map<Class, Integer> children = consolidate.get(systemElement);
List<Class> childrenTypes = new ArrayList<Class>(children.keySet());
Collections.sort(childrenTypes, new Comparator<Class>() {
@Override
public int compare(Class arg0, Class arg1) {
return arg0.getName().compareTo(arg1.getName());
}
});
for (Class p : childrenTypes) {
populateTableModelConsolidateRecursive(tableModel, whatToShow, editable, p, consolidate,
children, colspecs, maxTreeDepth, columns, curDepth + 1);
}
}
static class PropertyNameComparator implements Comparator<Property> {
@Override
public int compare(Property arg0, Property arg1) {
return arg0.getName().compareTo(arg1.getName());
}
}
public static List<Property> sortProperty(List<Property> props) {
Collections.sort(props, new PropertyNameComparator());
return props;
}
public static int getDepthOfCompositionalMap(Map<Class, Map<Property, Class>> map, Class c) {
return getDepthOfCompositionalMapRecursive(map, 1, c);
}
private static int getDepthOfCompositionalMapRecursive(Map<Class, Map<Property, Class>> map, int cur,
Class c) {
int max = cur;
Map<Property, Class> children = map.get(c);
for (Map.Entry<Property, Class> entry : children.entrySet()) {
int branch = getDepthOfCompositionalMapRecursive(map, cur + 1, entry.getValue());
if (branch > max) {
max = branch;
}
}
return max;
}
private void populateAttributesStructures(Class root, Map<Class, Map<Property, Class>> filteredStructure,
List<Map<String, List<String>>> propertiesStructure, Map<String, String> types) {
boolean getall = false;
boolean checkExclude = false;
if (systemIncludeStereotype.isEmpty() && systemIncludeName.isEmpty()
&& systemIncludeTypeName.isEmpty()) {
if (systemExcludeStereotype.isEmpty() && systemExcludeName.isEmpty()
&& systemExcludeTypeName.isEmpty()) {
getall = true;
}
else {
checkExclude = true;
}
}
populateAttributes(root, filteredStructure, propertiesStructure, types, getall, checkExclude, 1,
new HashSet<String>(), null);
}
private void populateAttributes(Class root, Map<Class, Map<Property, Class>> filteredStructure,
List<Map<String, List<String>>> propertiesStructure, Map<String, String> types, boolean getall,
boolean checkExclude, int curDepth, Set<String> propIgnore, Element from) {
if (maxDepth > 0 && curDepth > maxDepth) {
return;
}
// printToLog("populating " + root.getQualifiedName());
Map<Property, Class> children = new HashMap<Property, Class>();
List<Property> iterate = new ArrayList<Property>(root.getOwnedAttribute());
if (includeInherited) {
iterate.addAll(getInheritedProperties(root));
}
for (Property attr : iterate) {
Type attrType = attr.getType();
if (attrType != null && attrType == from) {
continue;
}
if (attrType != null && attrType instanceof Class) {
if (StereotypesHelper.hasStereotypeOrDerived(attrType, splitStereotype)
|| StereotypesHelper.hasStereotypeOrDerived(attr, splitStereotype)) {
if (topIncludeStereotype.isEmpty() && topIncludeName.isEmpty()
&& topIncludeTypeName.isEmpty()) {
if (topExcludeStereotype.isEmpty() && topExcludeName.isEmpty()
&& topExcludeTypeName.isEmpty()) {
populateTopStructure(attr, propertiesStructure, types, 0, "", true, false,
propIgnore, null);
}
else {
populateTopStructure(attr, propertiesStructure, types, 0, "", false, true,
propIgnore, null);
}
}
else {
populateTopStructure(attr, propertiesStructure, types, 0, "", false, false,
propIgnore, null);
}
continue;
}
if ((systemAssociationType == 1 && (attr.getAggregation() == AggregationKindEnum.SHARED || attr
.getAggregation() == AggregationKindEnum.NONE))
|| (systemAssociationType == 2 && (attr.getAggregation() == AggregationKindEnum.COMPOSITE || attr
.getAggregation() == AggregationKindEnum.NONE))) {
continue;
}
if (StereotypesHelper.hasStereotypeOrDerived(attr, systemExcludeStereotype)
|| StereotypesHelper.hasStereotypeOrDerived(attrType, systemExcludeStereotype)
|| systemExcludeName.contains(attr.getName())
|| systemExcludeTypeName.contains(attrType.getName())) {
continue;
}
if (getall || checkExclude
|| StereotypesHelper.hasStereotypeOrDerived(attr, systemIncludeStereotype)
|| StereotypesHelper.hasStereotypeOrDerived(attrType, systemIncludeStereotype)
|| systemIncludeName.contains(attr.getName())
|| systemIncludeTypeName.contains(attrType.getName())) {
children.put(attr, (Class) attrType);
populateAttributes((Class) attrType, filteredStructure, propertiesStructure, types,
getall, true, curDepth + 1, propIgnore, root);
continue;
}
if (includeAttribute((Class) attrType, root)) {
children.put(attr, (Class) attrType);
populateAttributes((Class) attrType, filteredStructure, propertiesStructure, types,
getall, checkExclude, curDepth + 1, propIgnore, root);
continue;
}
}
else {
if (topIncludeStereotype.isEmpty() && topIncludeName.isEmpty()
&& topIncludeTypeName.isEmpty()) {
if (topExcludeStereotype.isEmpty() && topExcludeName.isEmpty()
&& topExcludeTypeName.isEmpty()) {
populateTopStructure(attr, propertiesStructure, types, 0, "", true, false,
propIgnore, null);
}
else {
populateTopStructure(attr, propertiesStructure, types, 0, "", false, true,
propIgnore, null);
}
}
else {
populateTopStructure(attr, propertiesStructure, types, 0, "", false, false, propIgnore,
null);
}
}
}
if (maxDepth > 0 && curDepth + 1 > maxDepth) {
filteredStructure.put(root, new HashMap<Property, Class>());
}
else {
filteredStructure.put(root, children);
}
}
private boolean includeAttribute(Class system, Element from) {
List<Property> iterate = new ArrayList<Property>(system.getOwnedAttribute());
if (includeInherited) {
iterate.addAll(getInheritedProperties(system));
}
for (Property attr : iterate) {
Type attrType = attr.getType();
if (attrType != null && attrType == from) {
continue;
}
if (attrType != null && attrType instanceof Class) {
if (StereotypesHelper.hasStereotypeOrDerived(attrType, splitStereotype)
|| StereotypesHelper.hasStereotypeOrDerived(attr, splitStereotype)) {
continue;
}
if ((systemAssociationType == 1 && (attr.getAggregation() == AggregationKindEnum.SHARED || attr
.getAggregation() == AggregationKindEnum.NONE))
|| (systemAssociationType == 2 && (attr.getAggregation() == AggregationKindEnum.COMPOSITE || attr
.getAggregation() == AggregationKindEnum.NONE))) {
continue;
}
if (StereotypesHelper.hasStereotypeOrDerived(attr, systemExcludeStereotype)
|| StereotypesHelper.hasStereotypeOrDerived(attrType, systemExcludeStereotype)
|| systemExcludeName.contains(attr.getName())
|| systemExcludeTypeName.contains(attrType.getName())) {
continue;
}
if (StereotypesHelper.hasStereotypeOrDerived(attr, systemIncludeStereotype)
|| StereotypesHelper.hasStereotypeOrDerived(attrType, systemIncludeStereotype)
|| systemIncludeName.contains(attr.getName())
|| systemIncludeTypeName.contains(attrType.getName())) {
return true;
}
if (includeAttribute((Class) attrType, system)) {
return true;
}
}
}
return false;
}
/**
* [ {"prop1a":["prop2a", "prop2b", "c"], "prop1b":["d", "e"], "prop1c":[]},
* {"prop1a;prop2a":["f", "g"], "prop1a;prop2b":["m", "n"], "prop1a;c":[],
* "prop1b;d":[], "prop1b;e":[]}, {"prop1a;prop2a;f":[],
* "prop1a;prop2a;g":[], "prop1a;prop2b;m":[], "prop1a;prop2b;n":[]} ] use
* semicolon for delimiters
*/
private boolean populateTopStructure(Property systemProperty,
List<Map<String, List<String>>> propertiesStructure, Map<String, String> types, int curDepth,
String prefix, boolean getall, boolean checkExclude, Set<String> propIgnore, Element from) {
// if no filters are set, getall should be true
// if no includes are set, checkExclude should be true
String propName = systemProperty.getName();
if (curDepth > 0) {
propName = prefix + ";" + propName;
}
if (propIgnore.contains(propName)) {
return false;
}
// printToLog("populatePropertiesStructure " +
// systemProperty.getQualifiedName());
Type propType = systemProperty.getType();
if (propType != null && propType == from) {
return false;
}
Map<String, List<String>> propMap = null;
if (propertiesStructure.size() == curDepth) {
propMap = new HashMap<String, List<String>>();
propertiesStructure.add(propMap);
}
else {
propMap = propertiesStructure.get(curDepth);
}
List<String> children = propMap.get(propName);
boolean newProp = false;
if (children == null) {
children = new ArrayList<String>();
propMap.put(propName, children);
newProp = true;
}
// check association type
if ((topAssociationType == 1 && (systemProperty.getAggregation() == AggregationKindEnum.SHARED || systemProperty
.getAggregation() == AggregationKindEnum.NONE))
|| (topAssociationType == 2 && (systemProperty.getAggregation() == AggregationKindEnum.COMPOSITE || systemProperty
.getAggregation() == AggregationKindEnum.NONE))) {
if (newProp) {
propMap.remove(propName);
propIgnore.add(propName);
}
return false;
}
// get everything from here on
if (getall) {
types.put(propName, propType == null ? "" : propType.getName());
if (propType != null && propType instanceof Class) {
List<Property> iterate = new ArrayList<Property>(((Class) propType).getOwnedAttribute());
if (includeInherited) {
iterate.addAll(getInheritedProperties((Class) propType));
}
for (Property p : iterate) {
if (populateTopStructure(p, propertiesStructure, types, curDepth + 1, propName, getall,
checkExclude, propIgnore, systemProperty.getOwner())) {
if (!children.contains(p.getName())) {
children.add(p.getName());
}
}
}
}
return true;
}
// check excludes
if (StereotypesHelper.hasStereotypeOrDerived(systemProperty, topExcludeStereotype)
|| propType != null
&& StereotypesHelper.hasStereotypeOrDerived(propType, topExcludeStereotype)
|| topExcludeName.contains(systemProperty.getName()) || propType != null
&& topExcludeTypeName.contains(propType.getName())) {
if (newProp) {// in the chance that the model is messed up....some
// are included before and now it's exlcude becuase of
// missing stereotypes, etc
propMap.remove(propName);
propIgnore.add(propName);
}
return false;
}
// include until exclude
if (checkExclude) {
types.put(propName, propType == null ? "" : propType.getName());
if (propType != null && propType instanceof Class) {
List<Property> iterate = new ArrayList<Property>(((Class) propType).getOwnedAttribute());
if (includeInherited) {
iterate.addAll(getInheritedProperties((Class) propType));
}
for (Property p : iterate) {
if (populateTopStructure(p, propertiesStructure, types, curDepth + 1, propName, getall,
checkExclude, propIgnore, systemProperty.getOwner())) {
if (!children.contains(p.getName())) {
children.add(p.getName());
}
}
}
}
return true;
}
// check include
if (StereotypesHelper.hasStereotypeOrDerived(systemProperty, topIncludeStereotype)
|| propType != null
&& StereotypesHelper.hasStereotypeOrDerived(propType, topIncludeStereotype)
|| topIncludeName.contains(systemProperty.getName()) || propType != null
&& topIncludeTypeName.contains(propType.getName())) {
types.put(propName, propType == null ? "" : propType.getName());
if (topExcludeName.isEmpty() && topExcludeTypeName.isEmpty() && topExcludeStereotype.isEmpty()) {
// no exclude filters, include everything
if (propType != null && propType instanceof Class) {
List<Property> iterate = new ArrayList<Property>(((Class) propType).getOwnedAttribute());
if (includeInherited) {
iterate.addAll(getInheritedProperties((Class) propType));
}
for (Property p : iterate) {
if (populateTopStructure(p, propertiesStructure, types, curDepth + 1, propName, true,
false, propIgnore, systemProperty.getOwner())) {
if (!children.contains(p.getName())) {
children.add(p.getName());
}
}
}
}
}
else {
// need to check for excludes for children, but will include
// stuff if exclude doesn't match
if (propType != null && propType instanceof Class) {
List<Property> iterate = new ArrayList<Property>(((Class) propType).getOwnedAttribute());
if (includeInherited) {
iterate.addAll(getInheritedProperties((Class) propType));
}
for (Property p : iterate) {
if (populateTopStructure(p, propertiesStructure, types, curDepth + 1, propName,
false, true, propIgnore, systemProperty.getOwner())) {
if (!children.contains(p.getName())) {
children.add(p.getName());
}
}
}
}
}
return true;
}
// check if this is part of a branch that should be included
if (includeTop(systemProperty, from)) {
types.put(propName, propType == null ? "" : propType.getName());
if (propType != null && propType instanceof Class) {
List<Property> iterate = new ArrayList<Property>(((Class) propType).getOwnedAttribute());
if (includeInherited) {
iterate.addAll(getInheritedProperties((Class) propType));
}
for (Property p : iterate) {
if (populateTopStructure(p, propertiesStructure, types, curDepth + 1, propName, getall,
checkExclude, propIgnore, systemProperty.getOwner())) {
if (!children.contains(p.getName())) {
children.add(p.getName());
}
}
}
}
return true;
}
if (newProp) {
propMap.remove(propName);
propIgnore.add(propName);
}
return false;
}
private boolean includeTop(Property systemProperty, Element from) {
// systemProperty has already been checked by populateTopStructure and
// it's unclear, need to check its children
if ((topAssociationType == 1 && (systemProperty.getAggregation() == AggregationKindEnum.SHARED || systemProperty
.getAggregation() == AggregationKindEnum.NONE))
|| (topAssociationType == 2 && (systemProperty.getAggregation() == AggregationKindEnum.COMPOSITE || systemProperty
.getAggregation() == AggregationKindEnum.NONE))) {
return false;
}
Type propType = systemProperty.getType();
if (propType != null && propType == from) {
return false;
}
// check for exclude, then include, then recurse
if (StereotypesHelper.hasStereotypeOrDerived(systemProperty, topExcludeStereotype)
|| propType != null
&& StereotypesHelper.hasStereotypeOrDerived(propType, topExcludeStereotype)
|| topExcludeName.contains(systemProperty.getName()) || propType != null
&& topExcludeTypeName.contains(propType.getName())) {
return false;
}
if (StereotypesHelper.hasStereotypeOrDerived(systemProperty, topIncludeStereotype)
|| propType != null
&& StereotypesHelper.hasStereotypeOrDerived(propType, topIncludeStereotype)
|| topIncludeName.contains(systemProperty.getName()) || propType != null
&& topIncludeTypeName.contains(propType.getName())) {
return true;
}
if (propType != null && propType instanceof Class) {
List<Property> iterate = new ArrayList<Property>(((Class) propType).getOwnedAttribute());
if (includeInherited) {
iterate.addAll(getInheritedProperties((Class) propType));
}
for (Property p : iterate) {
if (includeTop(p, systemProperty.getOwner())) {
return true;
}
}
}
return false;
}
public static String getPropertyValue(Class e, List<String> propSpec, boolean includeInherited) {
Property p = getPropertyElement(e, propSpec, includeInherited);
if (p == null) {
return "n/a";
}
return UML2ModelUtil.getDefault(p);
}
public static Property getPropertyElement(Class e, List<String> propSpec, boolean includeInherited) {
List<Property> iterate = new ArrayList<Property>(e.getOwnedAttribute());
if (includeInherited) {
iterate.addAll(getInheritedProperties(e));
}
if (propSpec.size() < 2) {
for (Property p : iterate) {
if (p.getName().equals(propSpec.get(0))) {
return p;
}
}
return null;
}
for (Property p : iterate) {
if (p.getName().equals(propSpec.get(0)) && p.getType() != null && p.getType() instanceof Class) {
return getPropertyElement((Class) p.getType(), propSpec.subList(1, propSpec.size()),
includeInherited);
}
}
return null;
}
private int getNumPropertyHeaders(List<Map<String, List<String>>> struct) {
int res = 0;
for (Map<String, List<String>> level : struct) {
for (Map.Entry<String, List<String>> entry : level.entrySet()) {
if (entry.getValue().isEmpty()) {
res++;
}
}
}
return res;
}
private DefaultMutableTreeNode sortPropertiesStructure(List<Map<String, List<String>>> propertiesStructure) {
DefaultMutableTreeNode res = new DefaultMutableTreeNode();
if (propertiesStructure.isEmpty()) {
return res;
}
Map<String, List<String>> row = propertiesStructure.get(0);
sortPropertiesStructureRecursive(res, propertiesStructure, 0, row.keySet(), "");
return res;
}
private void sortPropertiesStructureRecursive(DefaultMutableTreeNode parentNode,
List<Map<String, List<String>>> propertiesStructure, int curDepth, Set<String> props,
String prefix) {
Map<String, List<String>> row = propertiesStructure.get(curDepth);
List<String> emptyProp = new ArrayList<String>();
List<String> drillProp = new ArrayList<String>();
for (String key : props) {
String mapKey = key;
if (!prefix.isEmpty()) {
mapKey = prefix + ";" + key;
}
if (row.get(mapKey).isEmpty()) {
emptyProp.add(key);
}
else {
drillProp.add(key);
}
}
List<String> emptyUserAlphaSorted = sortUserInput(emptyProp);
List<String> drillUserAlphaSorted = sortUserInput(drillProp);
for (String s : emptyUserAlphaSorted) {
String mapKey = s;
if (!prefix.isEmpty()) {
mapKey = prefix + ";" + s;
}
DefaultMutableTreeNode child = new DefaultMutableTreeNode();
child.setUserObject(mapKey);
parentNode.add(child);
}
for (String s : drillUserAlphaSorted) {
String mapKey = s;
if (!prefix.isEmpty()) {
mapKey = prefix + ";" + s;
}
DefaultMutableTreeNode child = new DefaultMutableTreeNode();
child.setUserObject(mapKey);
parentNode.add(child);
sortPropertiesStructureRecursive(child, propertiesStructure, curDepth + 1, new HashSet<String>(
row.get(mapKey)), mapKey);
}
}
private List<String> sortUserInput(Collection<String> strings) {
List<String> res = new ArrayList<String>();
for (String user : topOrder) {
if (strings.contains(user)) {
res.add(user);
}
}
List<String> alpha = new ArrayList<String>();
for (String prop : strings) {
if (!res.contains(prop)) {
alpha.add(prop);
}
}
Collections.sort(alpha);
res.addAll(alpha);
return res;
}
private List<List<Map<String, String>>> getHeadersFromTree(DefaultMutableTreeNode tree,
Map<String, String> types, int headerDepth) {
List<List<Map<String, String>>> res = new ArrayList<List<Map<String, String>>>();
getHeadersFromTreeRecursive(tree, types, res, 1, headerDepth);
return res;
}
@SuppressWarnings("rawtypes")
private void getHeadersFromTreeRecursive(DefaultMutableTreeNode tree, Map<String, String> types,
List<List<Map<String, String>>> res, int curDepth, int headerDepth) {
Enumeration children = tree.children();
if (!children.hasMoreElements()) {
return;
}
List<Map<String, String>> props = null;
if (res.size() < curDepth) {
props = new ArrayList<Map<String, String>>();
res.add(props);
}
else {
props = res.get(curDepth - 1);
}
while (children.hasMoreElements()) {
DefaultMutableTreeNode child = (DefaultMutableTreeNode) children.nextElement();
Map<String, String> propDetail = new HashMap<String, String>();
String propQName = (String) child.getUserObject();
String[] blah = propQName.split(";");
String propName = blah[blah.length - 1];
propDetail.put("name", propName);
if (!child.children().hasMoreElements() && curDepth < headerDepth) {
propDetail.put("morerows", Integer.toString(headerDepth - curDepth));
}
if (child.children().hasMoreElements()) {
String namest = findSpanStartTree(child);
String nameend = findSpanEndTree(child);
if (!namest.equals(nameend)) {
propDetail.put("namest", namest);
propDetail.put("nameend", nameend);
}
}
propDetail.put("type", types.get(propQName));
props.add(propDetail);
getHeadersFromTreeRecursive(child, types, res, curDepth + 1, headerDepth);
}
}
private String findSpanStartTree(DefaultMutableTreeNode tree) {
if (tree.getChildCount() > 0) {
return findSpanStartTree((DefaultMutableTreeNode) tree.getFirstChild());
}
return (String) tree.getUserObject();
}
private String findSpanEndTree(DefaultMutableTreeNode tree) {
if (tree.getChildCount() > 0) {
return findSpanEndTree((DefaultMutableTreeNode) tree.getLastChild());
}
return (String) tree.getUserObject();
}
@SuppressWarnings("rawtypes")
private void getColSpecsFromTree(DefaultMutableTreeNode tree, List<String> res) {
Enumeration children = tree.children();
if (!children.hasMoreElements() && tree.getUserObject() != null) {
res.add((String) tree.getUserObject());
}
while (children.hasMoreElements()) {
getColSpecsFromTree((DefaultMutableTreeNode) children.nextElement(), res);
}
}
public static void consolidateTypes(Map<Class, Map<Class, Map<Property, Class>>> structures,
Map<Class, Map<Class, Map<Class, Integer>>> typeUnits) {
for (Class top : structures.keySet()) {
Map<Class, Map<Property, Class>> structure = structures.get(top);
if (!typeUnits.containsKey(top)) {
typeUnits.put(top, new HashMap<Class, Map<Class, Integer>>());
}
Map<Class, Map<Class, Integer>> typeunit = typeUnits.get(top);
for (Class c : structure.keySet()) {
if (!typeunit.containsKey(c)) {
typeunit.put(c, new HashMap<Class, Integer>());
}
Map<Class, Integer> units = typeunit.get(c);
Map<Property, Class> props = structure.get(c);
for (Property p : props.keySet()) {
Class type = props.get(p);
if (!units.containsKey(type)) {
units.put(type, getMultiplicity(p));
}
else {
units.put(type, units.get(type) + getMultiplicity(p));
}
}
}
}
}
public static int getMultiplicity(Property p) {
int lower = p.getLower();
int upper = p.getUpper();
if (lower == upper) {
return lower;
}
if (upper == -1 && lower > 0) {
return lower;
}
return 1;
}
public static List<Property> getInheritedProperties(Class c) {
List<Property> owned = new ArrayList<Property>(c.getOwnedAttribute());
Collection<NamedElement> inherited = new ArrayList<NamedElement>(c.getInheritedMember());
List<NamedElement> inheritedCopy = new ArrayList<NamedElement>(inherited);
List<Property> res = new ArrayList<Property>();
for (NamedElement ne : inherited) {
if (ne instanceof Property) {
for (Property redef : ((Property) ne).getRedefinedProperty()) {
inheritedCopy.remove(redef);
}
}
else {
inheritedCopy.remove(ne);
}
}
for (Property p : owned) {
for (Property redef : p.getRedefinedProperty()) {
inheritedCopy.remove(redef);
}
}
for (NamedElement e : inheritedCopy) {
res.add((Property) e);
}
return res;
}
public Map<Class, Map<Class, Map<Property, Class>>> getFilteredStructures() {
return filteredStructures;
}
public Map<Class, Map<Class, Map<Class, Integer>>> getConsolidated() {
return consolidated;
}
public int getNumPropertyHeaders() {
return numPropertyHeaders;
}
public List<String> getColspecs() {
return colspecs;
}
public List<List<Map<String, String>>> getHeaders() {
return headers;
}
}