package gov.nasa.jpl.mbee.mdk.model;
import com.nomagic.magicdraw.core.Application;
import com.nomagic.uml2.ext.jmi.helpers.ModelHelper;
import com.nomagic.uml2.ext.jmi.helpers.StereotypesHelper;
import com.nomagic.uml2.ext.magicdraw.activities.mdbasicactivities.InitialNode;
import com.nomagic.uml2.ext.magicdraw.activities.mdfundamentalactivities.ActivityNode;
import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.*;
import com.nomagic.uml2.ext.magicdraw.mdprofiles.Stereotype;
import gov.nasa.jpl.mbee.mdk.docgen.DocGenProfile;
import gov.nasa.jpl.mbee.mdk.docgen.docbook.DBParagraph;
import gov.nasa.jpl.mbee.mdk.docgen.docbook.DocumentElement;
import gov.nasa.jpl.mbee.mdk.docgen.docbook.From;
import gov.nasa.jpl.mbee.mdk.generator.DocumentValidator;
import gov.nasa.jpl.mbee.mdk.generator.GenerationContext;
import gov.nasa.jpl.mbee.mdk.util.*;
import gov.nasa.jpl.mbee.mdk.util.Utils.AvailableAttribute;
import java.util.*;
public class Paragraph extends Query {
private String text;
private List<Property> stereotypeProperties;
private From fromProperty;
private DocumentValidator validator = null;
private boolean tryOcl = false;
private boolean iterate = true;
private AvailableAttribute attribute = null; // this is redundant with fromProperty
public InitialNode bnode;
public ActivityNode activityNode;
public GenerationContext context = null;
public GenerationContext makeContext() {
ActivityNode n = null;
if (bnode != null && bnode.getOutgoing().iterator().hasNext()) { // should
// check
// next
// node
// is
// collect/filter
// node
n = bnode.getOutgoing().iterator().next().getTarget();
}
Stack<List<Object>> in = new Stack<List<Object>>();
// in.add( targets );
context = new GenerationContext(in, n, getValidator(), Application.getInstance().getGUILog());
return context;
}
public Paragraph(String t) {
text = t;
}
public Paragraph() {
}
public Paragraph(DocumentValidator dv) {
this.validator = dv;
}
public void setText(String t) {
text = t;
}
public String getText() {
return text;
}
public void setStereotypeProperties(List<Property> p) {
stereotypeProperties = p;
}
public List<Property> getStereotypeProperties() {
return stereotypeProperties;
}
public void setFrom(From f) {
fromProperty = f;
}
public From getFrom() {
return fromProperty;
}
public DocumentValidator getValidator() {
return validator;
}
// /* (non-Javadoc)
// * @see gov.nasa.jpl.mbee.mdk.model.Query#parse()
// */
// @Override
// public void parse() {
// super.parse();
// }
protected void addOclParagraph(List<DocumentElement> res,
Object oclExpression, Object context) {
addOclParagraph(res, oclExpression, context, new HashSet<Object>());
}
protected void addOclParagraph(List<DocumentElement> res,
Object oclExpression, Object context,
HashSet<Object> seen) {
// check for infinite recursion
if (seen.contains(oclExpression)) {
return;
}
seen.add(oclExpression);
if (oclExpression instanceof Collection) {
Collection<?> oclColl = (Collection<?>) oclExpression;
for (Object ocl : oclColl) {
addOclParagraph(res, ocl, context, seen);
}
return;
}
Debug.outln("addOclParagraph(" + res + ", \"" + oclExpression
+ "\", " + context + ")" + " class(" + context.getClass() + ")");
Object result =
DocumentValidator.evaluate(oclExpression, context,
getValidator(), true);
Debug.outln("ocl result = " + result);
// if ( result instanceof Collection && ((Collection<?>)result).size() == 1 ) {
// result = ( (Collection< ? >)result ).iterator().next();
// }
addAttributeParagraphs(res, result);
}
public void addAttributeParagraphs(List<DocumentElement> res, Object result) {
if (result instanceof Element && getFrom() != null) {
Element e = (Element) result;
Object v = Utils.getElementAttribute(e, attribute);
if (!Utils2.isNullOrEmpty(v)) {
Object o;
DBParagraph dbParagraph = new DBParagraph(v, e, getFrom());
if (getDgElement() != null && (o = StereotypesHelper.getStereotypePropertyFirst(getDgElement(), DocGenProfile.editableChoosable, "editable")) instanceof Boolean) {
dbParagraph.setEditable((Boolean) o);
}
res.add(dbParagraph);
}
}
else if (!Utils2.isNullOrEmpty(result)) {
if (result instanceof Collection) {
// Get the attribute for each element in the result list and
// create a paragraph for each.
// TODO -- REVIEW -- Do we want to make this a DBList so that we
// can distinguish nested collections as subparagraphs?
for (Object o : (Collection<?>) result) {
addAttributeParagraphs(res, o);
}
}
else {
if (!Utils2.isNullOrEmpty(result)) {
Object o;
DBParagraph dbParagraph = new DBParagraph(result);
if (getDgElement() != null && (o = StereotypesHelper.getStereotypePropertyFirst(getDgElement(), DocGenProfile.editableChoosable, "editable")) instanceof Boolean) {
dbParagraph.setEditable((Boolean) o);
}
res.add(dbParagraph);
}
}
}
}
/**
* Create DocBook paragraph(s) for this Paragraph.
*
* @param forViewEditor
* @param outputDir
* @return Return one or more DBParagraphs for docgen or the view editor
* based on properties of the Paragraph UML stereotype.
* <p>
* <code>
* O=tryOcl && T=gotText && R=gotTargets && S=gotStereotypeProperties && D=don't care <br><br>
* <p>
* 1 D && !T && !R && D: return nothing <br>
* 2 !O && !T && R && !S: return a paragraph of documentation for each target <br>
* 3 !O && !T && R && S: return a paragraph for each target-property pair <br>
* 4 !O && T && D && D: return a paragraph of the text, tied to the "body" slot of dgElement <br>
* <br>
* 5 O && !T && R && !S: return a paragraph of the evaluation of the documentation of each target as OCL on dgElement <br>
* 6 O && !T && R && S: return a paragraph of the evaluation of each target-property as OCL on dgElement <br>
* 7 O && T && !R && D: return a paragraph of the evaluation of the text as OCL on dgElement <br>
* 8 O && T && R && !S: return a paragraph of the evaluation of the text as OCL on each target <br>
* 9 O && T && R && S: return a paragraph of the evaluation of the text as OCL on each target-property pair <br>
* </code>
* <p>
* @see gov.nasa.jpl.mbee.mdk.model.Query#visit(boolean, java.lang.String)
*/
@Override
public List<DocumentElement> visit(boolean forViewEditor, String outputDir) {
Debug.outln("visit(" + forViewEditor + ", " + outputDir + ")");
List<DocumentElement> res = new ArrayList<DocumentElement>();
List<Reference> refs = new ArrayList<Reference>();
if (getIgnore()) {
return res;
}
boolean gotText = getText() != null;// && !getText().isEmpty();
boolean gotTargets = getTargets() != null && !getTargets().isEmpty();
boolean gotStereotypeProperties =
!Utils2.isNullOrEmpty(getStereotypeProperties());
boolean allTargetsAreProperties = false;
Debug.outln("gotText = " + gotText + ", " + getText());
Debug.outln("gotTargets = " + gotTargets + ", " + MoreToString.Helper.toLongString(getTargets()));
Debug.outln("gotStereotypeProperties = " + gotStereotypeProperties + ", " + getStereotypeProperties());
Debug.outln("desiredAttribute = " + attribute);
if (gotText && !tryOcl) { // ignoring targets -- should be none -- REVIEW
Debug.outln("case 4");
// case 4: return a paragraph of the text, tied to the "body" slot
// of dgElement or the documentation of the dgElement if dgElement
// is something other than a Paragraph
if (forViewEditor || !getText().trim().isEmpty()) {
//GeneratorUtils.getObjectProperty( getDgElement(), DocGenProfile.paragraphStereotype, "body", null );
// TODO @donbot find a way to remove this getProject() call
Stereotype paragraphStereotype = Utils.getStereotype(Application.getInstance().getProject(), DocGenProfile.paragraphStereotype);
Slot s = Utils.getSlot(getDgElement(), Utils.getStereotypePropertyByName(paragraphStereotype, "body"));
//StereotypesHelper.getSlot( getDgElement(), , arg2, arg3 )
DBParagraph dbParagraph;
if (s != null) {
dbParagraph = new DBParagraph(getText(), s, From.DVALUE);
}
else { // dgElement is not a Paragraph
if (getDgElement() != null && getFrom() != null) {
dbParagraph = new DBParagraph(getText(), getDgElement(), getFrom());
}
else if (getDgElement() != null) { // getFrom() must be null
dbParagraph = new DBParagraph(getText(), getDgElement(), From.DOCUMENTATION);
}
else {
dbParagraph = new DBParagraph(getText());
}
}
Object o;
if (getDgElement() != null && (o = StereotypesHelper.getStereotypePropertyFirst(getDgElement(), DocGenProfile.editableChoosable, "editable")) instanceof Boolean) {
dbParagraph.setEditable((Boolean) o);
}
res.add(dbParagraph);
} //else {
//res.add(new DBParagraph(getText()));
//}
}
else if (gotText && !gotTargets) { // tryOcl must be true
Debug.outln("case 7");
// case 7: return a paragraph of the evaluation of the text as OCL on dgElement
addOclParagraph(res, getText(), new ArrayList<Object>());
}
else if (gotTargets) {
// In case 5, we get the OCL from the targets; if the targets are
// Properties, then we look for the OCL in their values; otherwise,
// we use the documentation as OCL.
allTargetsAreProperties = true;
for (Object o : targets) {
if (o != null && !(o instanceof Property) && !(o instanceof Slot) && !(o instanceof Constraint)) {
allTargetsAreProperties = false;
break;
}
}
// Build up a list of References before generating DBParagraphs.
for (Object o : targets) {
Element e = null;
if (o instanceof Element) {
e = (Element) o;
}
else if (!tryOcl) {
continue;
}
Reference ref = null;
if (gotStereotypeProperties) {
// for cases 3, 6, and 9
Debug.outln("case 3, 6, or 9, target=" + o);
for (Property p : getStereotypeProperties()) {
ref = Reference.getPropertyReference(e, p);
refs.add(ref);
}
}
else {
if (tryOcl && gotText) {
Debug.outln("case 8, target=" + Utils.getName(o));
// for case 8
ref = new Reference(o);
}
else {
Debug.outln("case 2 or 5");
// for cases 2 and 5
//Object ocl = allTargetsAreProperties ? : ModelHelper.getComment( e );
if (allTargetsAreProperties && tryOcl) {
Object v = Utils.getElementAttribute(e, AvailableAttribute.Value);
ref = new Reference(e, From.DVALUE, v);
}
else {
if (attribute != null) {
ref = new Reference(e, fromProperty, Utils.getElementAttribute(e, attribute));
}
else {
ref = new Reference(e, From.DOCUMENTATION, ModelHelper.getComment(e));
}
}
}
refs.add(ref);
}
}
if (tryOcl && !iterate && gotText) {
Debug.outln("case 8 or 9 a");
// for cases 8 & 9 when !iterate
// apply text as OCL to the collection as a whole
ArrayList<Object> results = new ArrayList<Object>();
for (Reference r : refs) {
results.add(r.getResult());
}
addOclParagraph(res, getText(), results);
}
else {
if (!iterate) {
Debug.error(false, "The iterate property should be true when not using OCL or when the OCL is in the targets instead of the body: " + dgElement);
// REVIEW -- create a validation violation instead?
// getValidator().addViolationIfUnique( rule, element, comment, reported ); // no public rule to reference!
}
// creating paragraph for each reference
for (Reference r : refs) {
if (!tryOcl) { // gotText is false
Debug.outln("case 2 or 3, ref=" + r);
// cases 2 & 3: return a paragraph for each
// target-property pair (3) or for each target's
// documentation (2)
res.addAll(Common.getReferenceAsDocumentElements(r, this));
// res.add( new DBParagraph( r.getLegacyResult(),
// r.getElement(), r.getFrom() ) );
}
else {
if (gotText) {
Debug.outln("case 8 or 9, ref=" + r);
// cases 8 & 9: return a paragraph of the evaluation
// of the text as OCL on each target-property pair (9)
// or on each target (8)
addOclParagraph(res, getText(), r.getResult());
}
else {
Debug.outln("case 5 or 6, ref=" + r);
// cases 5 & 6: add a paragraph of the evaluation of
// the value of each target-property (6) or of each target's
// documentation (5) as OCL on dgElement
addOclParagraph(res, r.getResult(), new ArrayList<Object>());
}
}
}
}
} // else case 1: gotText and gotTarget are both false, so return nothing
Debug.outln("visit(" + forViewEditor + ", \"" + outputDir + ") returning " + res);
return res;
}
@SuppressWarnings("unchecked")
@Override
public void initialize() {
String body = (String) GeneratorUtils.getObjectProperty(dgElement, DocGenProfile.paragraphStereotype,
"body", null);
setText(body);
Object doOcl = GeneratorUtils.getObjectProperty(dgElement, DocGenProfile.paragraphStereotype,
"evaluateOcl", null);
if (doOcl != null) {
tryOcl = Utils.isTrue(doOcl, true);
}
Object iter = GeneratorUtils.getObjectProperty(dgElement, DocGenProfile.paragraphStereotype,
"iterate", null);
if (iter != null) {
iterate = Utils.isTrue(iter, false); // TODO -- use this!
}
Object attr = GeneratorUtils.getObjectProperty(dgElement,
DocGenProfile.attributeChoosable, "desiredAttribute", null);
if (attr instanceof EnumerationLiteral) {
attribute = Utils.AvailableAttribute.valueOf(((EnumerationLiteral) attr).getName());
if (attribute != null) {
setFrom(Utils.getFromAttribute(attribute));
}
}
setStereotypeProperties((List<Property>) GeneratorUtils
.getListProperty(dgElement, DocGenProfile.stereotypePropertyChoosable,
"stereotypeProperties", new ArrayList<Property>()));
}
}