package gov.nasa.jpl.mbee.mdk.generator;
import com.nomagic.magicdraw.core.Application;
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.model.Container;
import gov.nasa.jpl.mbee.mdk.model.DocGenElement;
import gov.nasa.jpl.mbee.mdk.model.Document;
import gov.nasa.jpl.mbee.mdk.model.Section;
import gov.nasa.jpl.mbee.mdk.util.Pair;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* This parses a view structure and Product spec that uses associations for
* specifying children views and their order to form a view hierarchy
*
* @author dlam
*/
public class ProductViewParser {
private Class start;
private DocumentGenerator dg;
private Document doc;
private boolean recurse;
private boolean singleView;
private Set<Element> noSections;
private Set<Element> excludeViews;
private Stereotype productS;
private boolean product;
private List<Class> visitedViews;
@SuppressWarnings("unchecked")
public ProductViewParser(DocumentGenerator dg, boolean singleView, boolean recurse, Document doc,
Element start) {
this.visitedViews = new ArrayList<Class>();
this.dg = dg;
this.singleView = singleView;
this.recurse = recurse;
this.doc = doc;
if (start instanceof Class) {
this.start = (Class) start;
}
this.productS = dg.getProductStereotype();
if (productS != null && StereotypesHelper.hasStereotypeOrDerived(start, productS)) {
product = true;
doc.setProduct(true);
doc.setDgElement(start);
List<Element> noSections = StereotypesHelper.getStereotypePropertyValue(start,
productS, "noSections");
List<Element> excludeViews = StereotypesHelper.getStereotypePropertyValue(start,
productS, "excludeViews");
this.noSections = new HashSet<Element>(noSections);
this.excludeViews = new HashSet<Element>(excludeViews);
}
else {
noSections = new HashSet<Element>();
excludeViews = new HashSet<Element>();
}
}
public void parse() {
if (start == null) {
return;
}
Container top = doc;
if (!product) {
Section chapter1 = dg.parseView(start);
top = chapter1;
doc.addElement(chapter1);
}
else {
Section s = dg.parseView(start);
for (DocGenElement e : s.getChildren()) {
top.addElement(e);
}
}
if (!singleView || recurse) {
handleViewChildren(start, top);
}
}
/**
* @param view
* @param parent parent view the current view should go under
* @param nosection whether current view is a nosection
*/
private void parseView(Class view, Container parent, boolean nosection, boolean recurse) {
if (visitedViews.contains(view)) {
Application.getInstance().getGUILog().log("[WARNING] View " + view.getName() + " has already been visited. Skipping view.");
}
else {
visitedViews.add(view);
String viewname = view.getName();
Section viewSection = dg.parseView(view);
viewSection.setNoSection(nosection);
parent.addElement(viewSection);
if (recurse) {
handleViewChildren(view, viewSection);
}
visitedViews.remove(view);
}
}
private void handleViewChildren(Class view, Container viewSection) {
List<Pair<Class, AggregationKind>> childSections = new ArrayList<>(),
childNoSections = new ArrayList<>();
for (Property prop : view.getOwnedAttribute()) {
if (!(prop.getType() instanceof Class)) {
continue;
}
Class type = (Class) prop.getType();
if (type == null || !StereotypesHelper.hasStereotypeOrDerived(type, dg.getView())
|| excludeViews.contains(prop) || excludeViews.contains(type)) {
continue;
}
if (noSections.contains(prop) || noSections.contains(type)) {
childNoSections.add(new Pair<>(type, prop.getAggregation()));
}
else {
childSections.add(new Pair<>(type, prop.getAggregation()));
}
}
for (Pair<Class, AggregationKind> pair : childNoSections) {
parseView(pair.getKey(), viewSection, true, !AggregationKindEnum.NONE.equals(pair.getValue()));
}
for (Pair<Class, AggregationKind> pair : childSections) {
parseView(pair.getKey(), viewSection, false, !AggregationKindEnum.NONE.equals(pair.getValue()));
}
}
}