svn commit: r16658 - trunk/src/argouml-app/src/org/argouml/notation/providers/uml/AbstractMessageNotationUml.java
Michiel van der Wulp <[email protected]>
| Newsgroups | gmane.comp.lang.uml.argouml.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: mvw
Date: 2009-01-19 08:04:54-0800
New Revision: 16658
Modified:
trunk/src/argouml-app/src/org/argouml/notation/providers/uml/AbstractMessageNotationUml.java
Log:
More commenting and refactoring as preparation for issue 5150.
Modified: trunk/src/argouml-app/src/org/argouml/notation/providers/uml/AbstractMessageNotationUml.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/argouml-app/src/org/argouml/notation/providers/uml/AbstractMessageNotationUml.java?view=diff&pathrev=16658&r1=16657&r2=16658
==============================================================================
--- trunk/src/argouml-app/src/org/argouml/notation/providers/uml/AbstractMessageNotationUml.java (original)
+++ trunk/src/argouml-app/src/org/argouml/notation/providers/uml/AbstractMessageNotationUml.java 2009-01-19 08:04:54-0800
@@ -98,8 +98,16 @@
* Parsing a text that is generated by one of the backup scenarios,
* causes it to be written back in the script of the Action.
* Hence, editing the text on the diagram only once
- * causes the Action Script to be used from then on.
- *
+ * causes the Action Script to be used from then on. <p>
+ *
+ * Supported operations for the parser: <p>
+ * <ul>
+ * <li>Locating an Operation by name and the number of arguments -
+ * the operation is hooked to the CallAction of the Message.
+ * <li>Create an Operation with given name (no arguments).
+ * <li>etc.
+ * </ul>
+ *
* @see MessageNotationUml
* @see SDMessageNotationUml
* @since 0.28.alpha1
@@ -428,14 +436,15 @@
protected void parseMessage(Object umlMessage, String s)
throws ParseException {
String fname = null;
- StringBuilder guard = null; // the condition or iteration expression (recurrence)
+ // the condition or iteration expression (recurrence):
+ StringBuilder guard = null;
String paramExpr = null;
String token;
StringBuilder varname = null;
List<List> predecessors = new ArrayList<List>();
List<Integer> seqno = null;
List<Integer> currentseq = new ArrayList<Integer>();
- List<String> args = null;
+// List<String> args = null;
boolean mustBePre = false;
boolean mustBeSeq = false;
boolean parallell = false;
@@ -443,7 +452,6 @@
boolean mayDeleteExpr = false;
boolean refindOperation = false;
boolean hasPredecessors = false;
- int i;
currentseq.add(null);
currentseq.add(null);
@@ -713,43 +721,13 @@
throw pre;
}
- if (paramExpr != null) {
- MyTokenizer st = new MyTokenizer(paramExpr, "\\,",
- parameterCustomSep);
- args = new ArrayList<String>();
- while (st.hasMoreTokens()) {
- token = st.nextToken();
-
- if (",".equals(token)) {
- if (args.size() == 0) {
- args.add(null);
- }
- args.add(null);
- } else {
- if (args.size() == 0) {
- if (token.trim().length() == 0) {
- continue;
- }
- args.add(null);
- }
- String arg = args.get(args.size() - 1);
- if (arg != null) {
- arg = arg + token;
- } else {
- arg = token;
- }
- args.set(args.size() - 1, arg);
- }
- }
- } else if (mayDeleteExpr) {
- args = new ArrayList<String>();
- }
+ List<String> args = parseArguments(paramExpr, mayDeleteExpr);
if (LOG.isDebugEnabled()) {
StringBuffer buf = new StringBuffer();
buf.append("ParseMessage: " + s + "\n");
buf.append("Message: ");
- for (i = 0; seqno != null && i + 1 < seqno.size(); i += 2) {
+ for (int i = 0; seqno != null && i + 1 < seqno.size(); i += 2) {
if (i > 0) {
buf.append(", ");
}
@@ -757,7 +735,7 @@
}
buf.append("\n");
buf.append("predecessors: " + predecessors.size() + "\n");
- for (i = 0; i < predecessors.size(); i++) {
+ for (int i = 0; i < predecessors.size(); i++) {
int j;
List v = predecessors.get(i);
buf.append(" Predecessor: ");
@@ -799,22 +777,66 @@
}
/**
- * @param umlMessage
- * @param predecessors
- * @param hasPredecessors
- * @throws ParseException
+ * @param paramExpr
+ * @param mayDeleteExpr
+ * @return
+ */
+ protected List<String> parseArguments(String paramExpr,
+ boolean mayDeleteExpr) {
+ String token;
+ List<String> args = null;
+ if (paramExpr != null) {
+ MyTokenizer st = new MyTokenizer(paramExpr, "\\,",
+ parameterCustomSep);
+ args = new ArrayList<String>();
+ while (st.hasMoreTokens()) {
+ token = st.nextToken();
+
+ if (",".equals(token)) {
+ if (args.size() == 0) {
+ args.add(null);
+ }
+ args.add(null);
+ } else {
+ if (args.size() == 0) {
+ if (token.trim().length() == 0) {
+ continue;
+ }
+ args.add(null);
+ }
+ String arg = args.get(args.size() - 1);
+ if (arg != null) {
+ arg = arg + token;
+ } else {
+ arg = token;
+ }
+ args.set(args.size() - 1, arg);
+ }
+ }
+ } else if (mayDeleteExpr) {
+ args = new ArrayList<String>();
+ }
+ return args;
+ }
+
+ /**
+ * Set the predecessors of the given Message.
+ *
+ * @param umlMessage the given UML Message object to be adapted
+ * @param predecessors the given predecessors as parsed
+ * @param hasPredecessors true if there are some, if false we do nothing
+ * @throws ParseException if something is wrong with the predecessor text
*/
protected void handlePredecessors(Object umlMessage,
List<List> predecessors, boolean hasPredecessors)
throws ParseException {
- int i;
- // TODO: Predecessors is not implemented, because it
- // causes some problems that I've not found an easy way to handle yet,
+
+ // Predecessors used to be not implemented, because it
+ // caused some problems that I've not found an easy way to handle yet,
// d00mst. The specific problem is that the notation currently is
// ambiguous on second message after a thread split.
-
// Why not implement it anyway? d00mst
-
+ // TODO: Document this ambiguity and the choice made.
if (hasPredecessors) {
Collection roots =
findCandidateRoots(
@@ -823,13 +845,12 @@
null,
null);
List<Object> pre = new ArrayList<Object>();
- Iterator it;
+
predfor:
- for (i = 0; i < predecessors.size(); i++) {
- it = roots.iterator();
- while (it.hasNext()) {
+ for (int i = 0; i < predecessors.size(); i++) {
+ for (Object root : roots) {
Object msg =
- walkTree(it.next(), predecessors.get(i));
+ walkTree(root, predecessors.get(i));
if (msg != null && msg != umlMessage) {
if (isBadPreMsg(umlMessage, msg)) {
String parseMsg = "parsing.error.message.one-pred";
@@ -853,31 +874,40 @@
}
/**
- * @param umlMessage
- * @param fname
- * @param refindOperation
+ * Update the model with the operation name. <p>
+ *
+ * The given operation name is located on the receiver of the given message.
+ * If an operation with the given name
+ * and a matching number of arguments is located,
+ * then the CallAction of the message is adapted accordingly.
+ *
+ * @param umlMessage the message of which the CallAction is to be adapted
+ * @param fname the name of the operation to be used
+ * @param refindOperation true if we have to set the operation
+ * of the CallAction
+ * @throws ParseException if the operation syntax can not be parsed
*/
protected void handleOperation(Object umlMessage, String fname,
- boolean refindOperation) {
+ boolean refindOperation) throws ParseException {
if (fname != null && refindOperation) {
Object role = Model.getFacade().getReceiver(umlMessage);
List ops =
getOperation(
- Model.getFacade().getBases(role),
- fname.trim(),
- Model.getFacade().getActualArguments(
- Model.getFacade().getAction(umlMessage)).size());
-
- // TODO: Should someone choose one, if there are more
- // than one?
- if (Model.getFacade().isACallAction(
- Model.getFacade().getAction(umlMessage))) {
- Object a = /* (MCallAction) */Model.getFacade().getAction(umlMessage);
+ Model.getFacade().getBases(role),
+ fname.trim(),
+ Model.getFacade().getActualArguments(
+ Model.getFacade().getAction(umlMessage)).size());
+
+ Object callAction = Model.getFacade().getAction(umlMessage);
+ if (Model.getFacade().isACallAction(callAction)) {
if (ops.size() > 0) {
- Model.getCommonBehaviorHelper().setOperation(a,
- /* (MOperation) */ops.get(0));
+ // If there are more than one suitable operation,
+ // then we pick the first one.
+ Model.getCommonBehaviorHelper().setOperation(callAction,
+ ops.get(0));
} else {
- Model.getCommonBehaviorHelper().setOperation(a, null);
+ Model.getCommonBehaviorHelper().setOperation(
+ callAction, null);
}
}
}
@@ -1099,11 +1129,18 @@
}
/**
- * @param umlMessage
- * @param fname
- * @param varname
- * @param refindOperation
- * @return
+ * Store the given function name and return variable name
+ * in the script of the action of the given message. <p>
+ *
+ * Constraint: the given Message shall have an Action.
+ *
+ * @param umlMessage the given UML Message object to adapt
+ * @param fname the name of the function
+ * @param varname the return variable name
+ * @param refindOperation if false, then we may return true or false.
+ * If true, we return true.
+ * @return true if we stored the fname and varname
+ * in the Action of the Message
*/
protected boolean handleFunctionName(Object umlMessage, String fname,
StringBuilder varname, boolean refindOperation) {
@@ -1113,18 +1150,18 @@
expr = varname.toString().trim() + " := " + expr;
}
- if (Model.getFacade().getScript(
- Model.getFacade().getAction(umlMessage)) == null
- || !expr.equals(Model.getFacade().getBody(
- Model.getFacade().getScript(
- Model.getFacade().getAction(umlMessage))))) {
- Object e =
+ Object action = Model.getFacade().getAction(umlMessage);
+ assert action != null;
+ Object script = Model.getFacade().getScript(action);
+ if (script == null
+ || !expr.equals(Model.getFacade().getBody(script))) {
+ Object newActionExpression =
Model.getDataTypesFactory()
.createActionExpression(
getExpressionLanguage(),
expr.trim());
Model.getCommonBehaviorHelper().setScript(
- Model.getFacade().getAction(umlMessage), e);
+ action, newActionExpression);
refindOperation = true;
}
}
@@ -1132,23 +1169,25 @@
}
/**
- * @param umlMessage
- * @param varname
- * @param mayDeleteExpr
- * @return
+ * Fill in the variable name if it is blank. <p>
+ * The variable name is the part in front of the assignment operator.
+ *
+ * @param umlMessage the given message to fill the variable name for
+ * @param varname if null, then we get the variable name from the model.
+ * @param mayDeleteExpr if true, then we may delete the variable,
+ * and hence we return an empty string
+ * @return the original variable name, or if it was null,
+ * a variable name generated from the model
*/
protected StringBuilder fillBlankVariableName(Object umlMessage,
StringBuilder varname, boolean mayDeleteExpr) {
/* If no variable name was given, then retain the one in the model. */
if (varname == null) {
- if (!mayDeleteExpr
- && Model.getFacade().getScript(
- Model.getFacade().getAction(umlMessage))
- != null) {
+ Object script = Model.getFacade().getScript(
+ Model.getFacade().getAction(umlMessage));
+ if (!mayDeleteExpr && script != null) {
String body =
- (String) Model.getFacade().getBody(
- Model.getFacade().getScript(
- Model.getFacade().getAction(umlMessage)));
+ (String) Model.getFacade().getBody(script);
int idx = body.indexOf(":=");
if (idx < 0) {
idx = body.indexOf("=");
@@ -1167,23 +1206,26 @@
}
/**
- * @param umlMessage
- * @param fname
- * @param mayDeleteExpr
- * @return
+ * Fill in the function name if it is blank. <p>
+ *
+ * The fname is the part of the script after the assignment operator.
+ *
+ * @param umlMessage the given message to fill the fname for
+ * @param fname if null, then we get the fname from the model.
+ * @param mayDeleteExpr if true, then we may delete the function,
+ * and hence we return an empty string
+ * @return the original fname, or if it was null,
+ * a fname generated from the model
*/
protected String fillBlankFunctionName(Object umlMessage, String fname,
boolean mayDeleteExpr) {
/* If no function-name was given, then retain the one in the model. */
if (fname == null) {
- if (!mayDeleteExpr
- && Model.getFacade().getScript(
- Model.getFacade().getAction(umlMessage))
- != null) {
+ Object script = Model.getFacade().getScript(
+ Model.getFacade().getAction(umlMessage));
+ if (!mayDeleteExpr && script != null) {
String body =
- (String) Model.getFacade().getBody(
- Model.getFacade().getScript(
- Model.getFacade().getAction(umlMessage)));
+ (String) Model.getFacade().getBody(script);
int idx = body.indexOf(":=");
if (idx >= 0) {
@@ -1210,7 +1252,8 @@
* @param umlMessage the UML Message object
* @param guard the guard expression string
* @param parallell true if parallel execution was indicated
- * @param iterative true if this is an iterative expression, as opposed to a condition
+ * @param iterative true if this is an iterative expression,
+ * as opposed to a condition
*/
protected void handleGuard(Object umlMessage, StringBuilder guard,
boolean parallell, boolean iterative) {
@@ -1234,9 +1277,10 @@
}
/**
- * Build an Action for the given UML Message if it did not have one yet.
+ * Build a CallAction for the given UML Message
+ * if it did not have an Action yet.
*
- * @param umlMessage
+ * @param umlMessage the UML Message object to create an Action for
*/
protected void buildAction(Object umlMessage) {
if (Model.getFacade().getAction(umlMessage) == null) {
@@ -1250,7 +1294,14 @@
}
/**
- * TODO: This name of the expression language should be configurable by the user.
+ * TODO: This name of the expression language should be
+ * configurable by the user. <p>
+ *
+ * According to the UML standard,
+ * the expression language should be the same
+ * for all elements in one diagram. <p>
+ *
+ * UML is not a sensible default - usually this is some pseudo-language.
*
* @return the name of the expression language
*/
@@ -1259,7 +1310,8 @@
}
/**
- * Walks a call tree from a root node following the directions given in path
+ * Walks a call tree from a <code>root</code> node
+ * following the directions given in <code>path</code>
* to a destination node. If the destination node cannot be reached, then
* null is returned.
*
@@ -1597,50 +1649,47 @@
}
/**
- * Finds the operations in Collection c with the given name
+ * Finds all operations in a given collection of classifiers
+ * with the given name
* and the given number of parameters.
- * If no operation is found, one is created. The applicable
- * operations are returned.
+ * If no operation is found, one is created in the first given Classifier.
+ * The applicable operations are returned.
*
- * @param c the collection of operations to be searched
+ * @param classifiers the collection of classifiers to search for operations
* @param name the name of the operation to be found
* @param params the number of parameters of the operation to be found
* @return a list of the sought operations
+ * @throws ParseException if the operation syntax can not be parsed
*/
- private List getOperation(Collection c, String name, int params) {
- List<Object> ops = new ArrayList<Object>();
- Iterator it;
+ private List getOperation(Collection classifiers, String name, int params)
+ throws ParseException {
+ List<Object> operations = new ArrayList<Object>();
if (name == null || name.length() == 0) {
- return ops;
+ return operations;
}
- it = c.iterator();
- while (it.hasNext()) {
- Object clf = /* (MClassifier) */it.next();
+ for (Object clf : classifiers) {
Collection oe = Model.getFacade().getFeatures(clf);
- Iterator it2 = oe.iterator();
- while (it2.hasNext()) {
- Object me = /* (MModelElement) */it2.next();
- if (!(Model.getFacade().isAOperation(me))) {
+ for (Object operation : oe) {
+ if (!(Model.getFacade().isAOperation(operation))) {
continue;
}
-
- Object op = /* (MOperation) */me;
- if (!name.equals(Model.getFacade().getName(op))) {
+
+ if (!name.equals(Model.getFacade().getName(operation))) {
continue;
}
- if (params != countParameters(op)) {
+ if (params != countParameters(operation)) {
continue;
}
- ops.add(op);
+ operations.add(operation);
}
}
- if (ops.size() > 0) {
- return ops;
+ if (operations.size() > 0) {
+ return operations;
}
- it = c.iterator();
+ Iterator it = classifiers.iterator();
if (it.hasNext()) {
StringBuilder expr = new StringBuilder(name + "(");
int i;
@@ -1660,17 +1709,11 @@
.getCurrentProject().getDefaultReturnType();
Object op = Model.getCoreFactory().buildOperation(cls, returnType);
- try {
- (new OperationNotationUml(op)).parseOperation(
+ new OperationNotationUml(op).parseOperation(
expr.toString(), op);
- } catch (ParseException pe) {
- LOG.error("Unexpected ParseException in getOperation: " + pe,
- pe);
-
- }
- ops.add(op);
+ operations.add(op);
}
- return ops;
+ return operations;
}
/**
@@ -1706,7 +1749,8 @@
}
activator = Model.getFacade().getActivator(umlMessage);
- for (Object predecessor : Model.getFacade().getPredecessors(umlMessage)) {
+ for (Object predecessor
+ : Model.getFacade().getPredecessors(umlMessage)) {
if (Model.getFacade().getActivator(predecessor)
!= activator) {
continue;
------------------------------------------------------
http://argouml.tigris.org/ds/viewMessage.do?dsForumId=5905&dsMessageId=1034925
To unsubscribe from this discussion, e-mail: [[email protected]].