29
// in src/org/argouml/notation/providers/uml/AssociationEndNameNotationUml.java
protected void parseAssociationEnd(Object role, String text)
throws ParseException {
MyTokenizer st;
String name = null;
StringBuilder stereotype = null;
String token;
boolean derived = false;
text = text.trim();
/* Handle Derived: */
if (text.length() > 0 && "/".indexOf(text.charAt(0)) >= 0) {
derived = true;
text = text.substring(1);
text = text.trim();
}
try {
st = new MyTokenizer(text, "<<,\u00AB,\u00BB,>>");
while (st.hasMoreTokens()) {
token = st.nextToken();
if ("<<".equals(token) || "\u00AB".equals(token)) {
if (stereotype != null) {
String msg =
"parsing.error.association-name.twin-stereotypes";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
stereotype = new StringBuilder();
while (true) {
token = st.nextToken();
if (">>".equals(token) || "\u00BB".equals(token)) {
break;
}
stereotype.append(token);
}
} else {
if (name != null) {
String msg =
"parsing.error.association-name.twin-names";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
name = token;
}
}
} catch (NoSuchElementException nsee) {
String ms = "parsing.error.association-name.unexpected-end-element";
throw new ParseException(Translator.localize(ms),
text.length());
} catch (ParseException pre) {
throw pre;
}
dealWithDerived(role, derived);
if (name != null) {
name = name.trim();
}
if (name != null && name.startsWith("+")) {
name = name.substring(1).trim();
Model.getCoreHelper().setVisibility(role,
Model.getVisibilityKind().getPublic());
}
if (name != null && name.startsWith("-")) {
name = name.substring(1).trim();
Model.getCoreHelper().setVisibility(role,
Model.getVisibilityKind().getPrivate());
}
if (name != null && name.startsWith("#")) {
name = name.substring(1).trim();
Model.getCoreHelper().setVisibility(role,
Model.getVisibilityKind().getProtected());
}
if (name != null && name.startsWith("~")) {
name = name.substring(1).trim();
Model.getCoreHelper().setVisibility(role,
Model.getVisibilityKind().getPackage());
}
if (name != null) {
Model.getCoreHelper().setName(role, name);
}
StereotypeUtility.dealWithStereotypes(role, stereotype, true);
}
// in src/org/argouml/notation/providers/uml/ObjectFlowStateTypeNotationUml.java
protected Object parseObjectFlowState1(Object objectFlowState, String s)
throws ParseException {
Object c =
Model.getActivityGraphsHelper()
.findClassifierByName(objectFlowState, s);
if (c != null) {
/* Great! The class already existed - just use it. */
Model.getCoreHelper().setType(objectFlowState, c);
return objectFlowState;
}
/* Let's create a class with the given name, otherwise
* the user will not understand why we refuse his input! */
if (s != null && s.length() > 0) {
Object topState = Model.getFacade().getContainer(objectFlowState);
if (topState != null) {
Object machine = Model.getFacade().getStateMachine(topState);
if (machine != null) {
Object ns = Model.getFacade().getNamespace(machine);
if (ns != null) {
Object clazz = Model.getCoreFactory().buildClass(s, ns);
Model.getCoreHelper().setType(objectFlowState, clazz);
return objectFlowState;
}
}
}
}
String msg = "parsing.error.object-flow-type.classifier-not-found";
Object[] args = {s};
throw new ParseException(Translator.localize(msg, args), 0);
}
// in src/org/argouml/notation/providers/uml/TransitionNotationUml.java
protected Object parseTransition(Object trans, String s)
throws ParseException {
s = s.trim();
int a = s.indexOf("[");
int b = s.indexOf("]");
int c = s.indexOf("/");
if (((a < 0) && (b >= 0)) || ((b < 0) && (a >= 0)) || (b < a)) {
String msg = "parsing.error.transition.no-matching-square-brackets";
throw new ParseException(Translator.localize(msg), 0);
}
if ((c >= 0) && (c < b) && (c > a) && (a > 0)) {
String msg = "parsing.error.transition.found-bracket-instead-slash";
throw new ParseException(Translator.localize(msg), 0);
}
String[] s1 = s.trim().split("/", 2);
String eg = s1[0].trim();
String[] s2 = eg.split("\\[", 2);
if (s2[0].trim().length() > 0) {
parseTrigger(trans, s2[0].trim());
}
if (s2.length > 1) {
if (s2[1].trim().endsWith("]")) {
String g = s2[1].trim();
g = g.substring(0, g.length() - 1).trim();
if (g.length() > 0) {
parseGuard(trans, g);
}
}
}
if (s1.length > 1) {
if (s1[1].trim().length() > 0) {
parseEffect(trans, s1[1].trim());
}
}
return trans;
}
// in src/org/argouml/notation/providers/uml/TransitionNotationUml.java
private void parseTrigger(Object trans, String trigger)
throws ParseException {
// let's look for a TimeEvent, ChangeEvent, CallEvent or SignalEvent
String s = "";
boolean timeEvent = false;
boolean changeEvent = false;
boolean callEvent = false;
boolean signalEvent = false;
trigger = trigger.trim();
StringTokenizer tokenizer = new StringTokenizer(trigger, "()");
String name = tokenizer.nextToken().trim();
if (name.equalsIgnoreCase("after")) {
timeEvent = true;
} else if (name.equalsIgnoreCase("when")) {
changeEvent = true;
} else {
// the part after the || is for when there's nothing between the ()
if (tokenizer.hasMoreTokens()
|| (trigger.indexOf("(") > 0)
|| (trigger.indexOf(")") > 1)) {
callEvent = true;
if (!trigger.endsWith(")") || !(trigger.indexOf("(") > 0)) {
String msg =
"parsing.error.transition.no-matching-brackets";
throw new ParseException(
Translator.localize(msg), 0);
}
} else {
signalEvent = true;
}
}
if (timeEvent || changeEvent || callEvent) {
if (tokenizer.hasMoreTokens()) {
s = tokenizer.nextToken().trim();
} // else the empty s will do
}
/*
* We can distinguish between 4 cases:
* 1. A trigger is given. None exists yet.
* 2. The trigger was present, and it is the same type,
* or a different type, and its text is changed, or the same.
* 3. A trigger is not given. None exists yet.
* 4. The name of the trigger was present, but is removed.
* The reaction in these cases should be:
* 1. Find the referred trigger (issue 5988) or create a new one, and hook it to the transition.
* 2. Rename the trigger.
* 3. Nop.
* 4. Unhook and erase the existing trigger.
*/
Object evt = Model.getFacade().getTrigger(trans);
/* It is safe to give a null to the next function,
* since a statemachine is always composed by a model anyhow. */
Object ns =
Model.getStateMachinesHelper()
.findNamespaceForEvent(trans, null);
StateMachinesFactory sMFactory =
Model.getStateMachinesFactory();
boolean weHaveAnEvent = false;
if (trigger.length() > 0) {
// case 1 and 2
if (evt == null) {
// case 1
if (timeEvent) { // after(...)
evt = findOrBuildTimeEvent(s, ns);
/* Do not set the name. */
}
if (changeEvent) { // when(...)
evt = findOrBuildChangeEvent(s, ns);
/* Do not set the name. */
}
if (callEvent) { // operation(paramlist)
String triggerName =
trigger.indexOf("(") > 0
? trigger.substring(0, trigger.indexOf("(")).trim()
: trigger;
/* This case is a bit different, because of the parameters.
* If the event already exists, the parameters are ignored. */
evt = findCallEvent(triggerName, ns);
if (evt == null) {
evt = sMFactory.buildCallEvent(trans, triggerName, ns);
// and parse the parameter list
NotationUtilityUml.parseParamList(evt, s, 0);
}
}
if (signalEvent) { // signalname
evt = findOrBuildSignalEvent(trigger, ns);
}
weHaveAnEvent = true;
} else {
// case 2
if (timeEvent) {
if (Model.getFacade().isATimeEvent(evt)) {
/* Just change the time expression */
Object timeExpr = Model.getFacade().getWhen(evt);
if (timeExpr == null) {
// we have an event without expression
timeExpr = Model.getDataTypesFactory().createTimeExpression("", s);
Model.getStateMachinesHelper().setWhen(evt, timeExpr);
} else {
Model.getDataTypesHelper().setBody(timeExpr, s);
}
} else {
/* It's a time-event now,
* but was of another type before! */
delete(evt); /* TODO: What if used elsewhere? */
evt = sMFactory.buildTimeEvent(s, ns);
weHaveAnEvent = true;
}
}
if (changeEvent) {
if (Model.getFacade().isAChangeEvent(evt)) {
/* Just change the ChangeExpression */
Object changeExpr =
Model.getFacade().getChangeExpression(evt);
if (changeExpr == null) {
/* Create a new expression: */
changeExpr = Model.getDataTypesFactory()
.createBooleanExpression("", s);
Model.getStateMachinesHelper().setExpression(evt,
changeExpr);
} else {
Model.getDataTypesHelper().setBody(changeExpr, s);
}
} else {
/* The parsed text describes a change-event,
* but the model contains another type! */
delete(evt); /* TODO: What if used elsewhere? */
evt = sMFactory.buildChangeEvent(s, ns);
weHaveAnEvent = true;
}
}
if (callEvent) {
if (Model.getFacade().isACallEvent(evt)) {
/* Just change the Name and linked operation */
String triggerName =
trigger.indexOf("(") > 0
? trigger.substring(0, trigger.indexOf("(")).trim()
: trigger;
if (!Model.getFacade().getName(evt)
.equals(triggerName)) {
Model.getCoreHelper().setName(evt, triggerName);
}
/* TODO: Change the linked operation. */
} else {
delete(evt); /* TODO: What if used elsewhere? */
evt = sMFactory.buildCallEvent(trans, trigger, ns);
// and parse the parameter list
NotationUtilityUml.parseParamList(evt, s, 0);
weHaveAnEvent = true;
}
}
if (signalEvent) {
if (Model.getFacade().isASignalEvent(evt)) {
/* Just change the Name and linked signal */
if (!Model.getFacade().getName(evt).equals(trigger)) {
Model.getCoreHelper().setName(evt, trigger);
}
/* TODO: link to the Signal. */
} else {
delete(evt); /* TODO: What if used elsewhere? */
evt = sMFactory.buildSignalEvent(trigger, ns);
weHaveAnEvent = true;
}
}
}
if (weHaveAnEvent && (evt != null)) {
Model.getStateMachinesHelper().setEventAsTrigger(trans, evt);
}
} else {
// case 3 and 4
if (evt == null) {
/* case 3 */
} else {
// case 4
delete(evt); // erase it
}
}
}
// in src/org/argouml/notation/providers/uml/AssociationRoleNotationUml.java
protected void parseRole(Object role, String text)
throws ParseException {
String token;
boolean hasColon = false;
boolean hasSlash = false;
String rolestr = null;
String basestr = null;
MyTokenizer st = new MyTokenizer(text, " ,\t,/,:");
while (st.hasMoreTokens()) {
token = st.nextToken();
if (" ".equals(token) || "\t".equals(token)) {
/* Do nothing. */
} else if ("/".equals(token)) {
hasSlash = true;
hasColon = false;
} else if (":".equals(token)) {
hasColon = true;
hasSlash = false;
} else if (hasColon) {
if (basestr != null) {
String msg =
"parsing.error.association-role.association-extra-text";
throw new ParseException(Translator.localize(msg), st
.getTokenIndex());
}
basestr = token;
} else if (hasSlash) {
if (rolestr != null) {
String msg =
"parsing.error.association-role.association-extra-text";
throw new ParseException(Translator.localize(msg), st
.getTokenIndex());
}
rolestr = token;
} else {
String msg =
"parsing.error.association-role.association-extra-text";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
}
if (basestr == null) {
/* If no base was typed, then only set the name: */
if (rolestr != null) {
Model.getCoreHelper().setName(role, rolestr.trim());
}
return;
}
/* If the base was not changed, then only set the name: */
Object currentBase = Model.getFacade().getBase(role);
if (currentBase != null) {
String currentBaseStr = Model.getFacade().getName(currentBase);
if (currentBaseStr == null) {
/* TODO: Is this needed? */
currentBaseStr = "";
}
if (currentBaseStr.equals(basestr)) {
if (rolestr != null) {
Model.getCoreHelper().setName(role, rolestr.trim());
}
return;
}
}
Collection c =
Model.getCollaborationsHelper().getAllPossibleBases(role);
Iterator i = c.iterator();
while (i.hasNext()) {
Object candidate = i.next();
if (basestr.equals(Model.getFacade().getName(candidate))) {
if (Model.getFacade().getBase(role) != candidate) {
/* If the base is already set to this assoc,
* then do not set it again.
* This check is needed, otherwise the setbase()
* below gives an exception.*/
Model.getCollaborationsHelper().setBase(role, candidate);
}
/* Only set the name if the base was found: */
if (rolestr != null) {
Model.getCoreHelper().setName(role, rolestr.trim());
}
return;
}
}
String msg = "parsing.error.association-role.base-not-found";
throw new ParseException(Translator.localize(msg), 0);
}
// in src/org/argouml/notation/providers/uml/MultiplicityNotationUml.java
Deprecated
protected Object parseMultiplicity(final Object multiplicityOwner,
final String s1) throws ParseException {
String s = s1.trim();
Object multi = null;
try {
multi = Model.getDataTypesFactory().createMultiplicity(s);
} catch (IllegalArgumentException iae) {
throw new ParseException(iae.getLocalizedMessage(), 0);
}
setMultiplicity(multiplicityOwner, s1);
return multi;
}
// in src/org/argouml/notation/providers/uml/MultiplicityNotationUml.java
protected void setMultiplicity(final Object multiplicityOwner,
final String arg) throws ParseException {
try {
Model.getCoreHelper().setMultiplicity(multiplicityOwner, arg);
} catch (IllegalArgumentException iae) {
throw new ParseException(iae.getLocalizedMessage(), 0);
}
}
// in src/org/argouml/notation/providers/uml/AssociationNameNotationUml.java
protected void parseAssociationName(Object modelElement, String text)
throws ParseException {
boolean derived = false;
text = text.trim();
/* Handle Derived: */
if (text.length() > 0 && "/".indexOf(text.charAt(0)) >= 0) {
derived = true;
text = text.substring(1);
text = text.trim();
}
NotationUtilityUml.setDerived(modelElement, derived);
NotationUtilityUml.parseModelElement(modelElement, text);
}
// in src/org/argouml/notation/providers/uml/NotationUtilityUml.java
protected static void parseModelElement(Object me, String text)
throws ParseException {
MyTokenizer st;
List<String> path = null;
String name = null;
StringBuilder stereotype = null;
String token;
try {
st = new MyTokenizer(text, "<<,\u00AB,\u00BB,>>,::");
while (st.hasMoreTokens()) {
token = st.nextToken();
if ("<<".equals(token) || "\u00AB".equals(token)) {
if (stereotype != null) {
String msg =
"parsing.error.model-element-name.twin-stereotypes";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
stereotype = new StringBuilder();
while (true) {
token = st.nextToken();
if (">>".equals(token) || "\u00BB".equals(token)) {
break;
}
stereotype.append(token);
}
} else if ("::".equals(token)) {
if (name != null) {
name = name.trim();
}
if (path != null && (name == null || "".equals(name))) {
String msg =
"parsing.error.model-element-name.anon-qualifiers";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
if (path == null) {
path = new ArrayList<String>();
}
if (name != null) {
path.add(name);
}
name = null;
} else {
if (name != null) {
String msg =
"parsing.error.model-element-name.twin-names";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
name = token;
}
}
} catch (NoSuchElementException nsee) {
String msg =
"parsing.error.model-element-name.unexpected-name-element";
throw new ParseException(Translator.localize(msg),
text.length());
} catch (ParseException pre) {
throw pre;
}
if (name != null) {
name = name.trim();
}
if (path != null && (name == null || "".equals(name))) {
String msg = "parsing.error.model-element-name.must-end-with-name";
throw new ParseException(Translator.localize(msg), 0);
}
if (name != null && name.startsWith("+")) {
name = name.substring(1).trim();
Model.getCoreHelper().setVisibility(me,
Model.getVisibilityKind().getPublic());
}
if (name != null && name.startsWith("-")) {
name = name.substring(1).trim();
Model.getCoreHelper().setVisibility(me,
Model.getVisibilityKind().getPrivate());
}
if (name != null && name.startsWith("#")) {
name = name.substring(1).trim();
Model.getCoreHelper().setVisibility(me,
Model.getVisibilityKind().getProtected());
}
if (name != null && name.startsWith("~")) {
name = name.substring(1).trim();
Model.getCoreHelper().setVisibility(me,
Model.getVisibilityKind().getPackage());
}
if (name != null) {
Model.getCoreHelper().setName(me, name);
}
StereotypeUtility.dealWithStereotypes(me, stereotype, false);
if (path != null) {
Object nspe =
Model.getModelManagementHelper().getElement(
path,
Model.getFacade().getRoot(me));
if (nspe == null || !(Model.getFacade().isANamespace(nspe))) {
String msg =
"parsing.error.model-element-name.namespace-unresolved";
throw new ParseException(Translator.localize(msg),
0);
}
if (!Model.getCoreHelper().isValidNamespace(me, nspe)) {
String msg =
"parsing.error.model-element-name.namespace-invalid";
throw new ParseException(Translator.localize(msg),
0);
}
Model.getCoreHelper().addOwnedElement(nspe, me);
}
}
// in src/org/argouml/notation/providers/uml/NotationUtilityUml.java
static void parseParamList(Object op, String param, int paramOffset)
throws ParseException {
MyTokenizer st =
new MyTokenizer(param, " ,\t,:,=,\\,", parameterCustomSep);
// Copy returned parameters because it will be a live collection for MDR
Collection origParam =
new ArrayList(Model.getFacade().getParameters(op));
Object ns = Model.getFacade().getRoot(op);
if (Model.getFacade().isAOperation(op)) {
Object ow = Model.getFacade().getOwner(op);
if (ow != null && Model.getFacade().getNamespace(ow) != null) {
ns = Model.getFacade().getNamespace(ow);
}
}
Iterator it = origParam.iterator();
while (st.hasMoreTokens()) {
String kind = null;
String name = null;
String tok;
String type = null;
StringBuilder value = null;
Object p = null;
boolean hasColon = false;
boolean hasEq = false;
while (it.hasNext() && p == null) {
p = it.next();
if (Model.getFacade().isReturn(p)) {
p = null;
}
}
while (st.hasMoreTokens()) {
tok = st.nextToken();
if (",".equals(tok)) {
break;
} else if (" ".equals(tok) || "\t".equals(tok)) {
if (hasEq) {
value.append(tok);
}
} else if (":".equals(tok)) {
hasColon = true;
hasEq = false;
} else if ("=".equals(tok)) {
if (value != null) {
String msg =
"parsing.error.notation-utility.two-default-values";
throw new ParseException(Translator.localize(msg),
paramOffset + st.getTokenIndex());
}
hasEq = true;
hasColon = false;
value = new StringBuilder();
} else if (hasColon) {
if (type != null) {
String msg = "parsing.error.notation-utility.two-types";
throw new ParseException(Translator.localize(msg),
paramOffset + st.getTokenIndex());
}
if (tok.charAt(0) == '\'' || tok.charAt(0) == '\"') {
String msg =
"parsing.error.notation-utility.type-quoted";
throw new ParseException(Translator.localize(msg),
paramOffset + st.getTokenIndex());
}
if (tok.charAt(0) == '(') {
String msg =
"parsing.error.notation-utility.type-expr";
throw new ParseException(Translator.localize(msg),
paramOffset + st.getTokenIndex());
}
type = tok;
} else if (hasEq) {
value.append(tok);
} else {
if (name != null && kind != null) {
String msg =
"parsing.error.notation-utility.extra-text";
throw new ParseException(Translator.localize(msg),
paramOffset + st.getTokenIndex());
}
if (tok.charAt(0) == '\'' || tok.charAt(0) == '\"') {
String msg =
"parsing.error.notation-utility.name-kind-quoted";
throw new ParseException(
Translator.localize(msg),
paramOffset + st.getTokenIndex());
}
if (tok.charAt(0) == '(') {
String msg =
"parsing.error.notation-utility.name-kind-expr";
throw new ParseException(
Translator.localize(msg),
paramOffset + st.getTokenIndex());
}
kind = name;
name = tok;
}
}
if (p == null) {
/* Leave the type undefined (see issue 6145): */
p = Model.getCoreFactory().buildParameter(op, null);
}
if (name != null) {
Model.getCoreHelper().setName(p, name.trim());
}
if (kind != null) {
setParamKind(p, kind.trim());
}
if (type != null) {
Model.getCoreHelper().setType(p, getType(type.trim(), ns));
}
if (value != null) {
// TODO: Find a better default language
// TODO: We should know the notation language, since it is us
Project project =
ProjectManager.getManager().getCurrentProject();
ProjectSettings ps = project.getProjectSettings();
String notationLanguage = ps.getNotationLanguage();
Object initExpr =
Model.getDataTypesFactory()
.createExpression(
notationLanguage,
value.toString().trim());
Model.getCoreHelper().setDefaultValue(p, initExpr);
}
}
while (it.hasNext()) {
Object p = it.next();
if (!Model.getFacade().isReturn(p)) {
Model.getCoreHelper().removeParameter(op, p);
Model.getUmlFactory().delete(p);
}
}
}
// in src/org/argouml/notation/providers/uml/StateBodyNotationUml.java
protected void parseStateBody(Object st, String s) throws ParseException {
boolean foundEntry = false;
boolean foundExit = false;
boolean foundDo = false;
/* Generate all the existing internal transitions,
* so that we can compare them as text with the newly entered ones.
*/
ModelElementInfoList internalsInfo =
new ModelElementInfoList(
Model.getFacade().getInternalTransitions(st));
StringTokenizer lines = new StringTokenizer(s, "\n\r");
while (lines.hasMoreTokens()) {
String line = lines.nextToken().trim();
/* Now let's check if the new line is already present in
* the old list of internal transitions; if it is, then
* mark the old one to be retained (i.e. do not create a new one),
* if it isn't, continue with parsing:
*/
if (!internalsInfo.checkRetain(line)) {
if (line.toLowerCase().startsWith("entry")
&& line.substring(5).trim().startsWith("/")) {
parseStateEntryAction(st, line);
foundEntry = true;
} else if (line.toLowerCase().startsWith("exit")
&& line.substring(4).trim().startsWith("/")) {
parseStateExitAction(st, line);
foundExit = true;
} else if (line.toLowerCase().startsWith("do")
&& line.substring(2).trim().startsWith("/")) {
parseStateDoAction(st, line);
foundDo = true;
} else {
Object t =
Model.getStateMachinesFactory()
.buildInternalTransition(st);
if (t == null) {
continue;
}
/* TODO: If the next line trows an exception, then what
* do we do with the remainder of the
* parsed/to be parsed lines?
*/
/* TODO: Is this a good way of handling nested notation?
* The following fails the tests:
* new TransitionNotationUml(t).parse(line);
*/
new TransitionNotationUml(t).parseTransition(t, line);
/* Add this new one, and mark it to be retained: */
internalsInfo.add(t, true);
}
}
}
if (!foundEntry) {
delete(Model.getFacade().getEntry(st));
}
if (!foundExit) {
delete(Model.getFacade().getExit(st));
}
if (!foundDo) {
delete(Model.getFacade().getDoActivity(st));
}
/* Process the final list of internal transitions,
* and hook it to the state:
*/
Model.getStateMachinesHelper().setInternalTransitions(st,
internalsInfo.finalisedList());
}
// in src/org/argouml/notation/providers/uml/EnumerationLiteralNotationUml.java
protected void parseEnumerationLiteralFig(
Object enumeration, Object literal, String text)
throws ParseException {
if (enumeration == null || literal == null) {
return;
}
Project project = ProjectManager.getManager().getCurrentProject();
ParseException pex = null;
int start = 0;
int end = NotationUtilityUml.indexOfNextCheckedSemicolon(text, start);
if (end == -1) {
/* No text. We may remove the literal. */
project.moveToTrash(literal);
return;
}
String s = text.substring(start, end).trim();
if (s.length() == 0) {
/* No non-white chars in text? remove literal! */
project.moveToTrash(literal);
return;
}
parseEnumerationLiteral(s, literal);
int i = Model.getFacade().getEnumerationLiterals(enumeration)
.indexOf(literal);
// check for more literals (';' separated):
start = end + 1;
end = NotationUtilityUml.indexOfNextCheckedSemicolon(text, start);
while (end > start && end <= text.length()) {
s = text.substring(start, end).trim();
if (s.length() > 0) {
// yes, there are more:
Object newLiteral =
Model.getCoreFactory().createEnumerationLiteral();
if (newLiteral != null) {
try {
if (i != -1) {
Model.getCoreHelper().addLiteral(
enumeration, ++i, newLiteral);
} else {
Model.getCoreHelper().addLiteral(
enumeration, 0, newLiteral);
}
parseEnumerationLiteral(s, newLiteral);
} catch (ParseException ex) {
if (pex == null) {
pex = ex;
}
}
}
}
start = end + 1;
end = NotationUtilityUml.indexOfNextCheckedSemicolon(text, start);
}
if (pex != null) {
throw pex;
}
}
// in src/org/argouml/notation/providers/uml/EnumerationLiteralNotationUml.java
protected void parseEnumerationLiteral(String text, Object literal)
throws ParseException {
text = text.trim();
if (text.length() == 0) {
return;
}
// strip any trailing semi-colons
if (text.charAt(text.length() - 1) == ';') {
text = text.substring(0, text.length() - 2);
}
MyTokenizer st;
String name = null;
StringBuilder stereotype = null;
String token;
try {
st = new MyTokenizer(text, "<<,\u00AB,\u00BB,>>");
while (st.hasMoreTokens()) {
token = st.nextToken();
if ("<<".equals(token) || "\u00AB".equals(token)) {
if (stereotype != null) {
String msg =
"parsing.error.model-element-name.twin-stereotypes";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
stereotype = new StringBuilder();
while (true) {
token = st.nextToken();
if (">>".equals(token) || "\u00BB".equals(token)) {
break;
}
stereotype.append(token);
}
} else {
if (name != null) {
String msg =
"parsing.error.model-element-name.twin-names";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
name = token;
}
}
} catch (NoSuchElementException nsee) {
String msg =
"parsing.error.model-element-name.unexpected-name-element";
throw new ParseException(Translator.localize(msg),
text.length());
} catch (ParseException pre) {
throw pre;
}
if (name != null) {
name = name.trim();
}
if (name != null) {
Model.getCoreHelper().setName(literal, name);
}
StereotypeUtility.dealWithStereotypes(literal, stereotype, false);
return;
}
// in src/org/argouml/notation/providers/uml/OperationNotationUml.java
public void parseOperationFig(
Object classifier,
Object operation,
String text) throws ParseException {
if (classifier == null || operation == null) {
return;
}
ParseException pex = null;
int start = 0;
int end = NotationUtilityUml.indexOfNextCheckedSemicolon(text, start);
Project currentProject =
ProjectManager.getManager().getCurrentProject();
if (end == -1) {
//no text? remove op!
currentProject.moveToTrash(operation);
return;
}
String s = text.substring(start, end).trim();
if (s.length() == 0) {
//no non-whitechars in text? remove op!
currentProject.moveToTrash(operation);
return;
}
parseOperation(s, operation);
int i = Model.getFacade().getFeatures(classifier).indexOf(operation);
// check for more operations (';' separated):
start = end + 1;
end = NotationUtilityUml.indexOfNextCheckedSemicolon(text, start);
while (end > start && end <= text.length()) {
s = text.substring(start, end).trim();
if (s.length() > 0) {
// yes, there are more:
Object returnType = currentProject.getDefaultReturnType();
Object newOp =
Model.getCoreFactory()
.buildOperation(classifier, returnType);
if (newOp != null) {
try {
parseOperation(s, newOp);
//newOp.setOwnerScope(op.getOwnerScope()); //
//not needed in case of operation
if (i != -1) {
Model.getCoreHelper().addFeature(
classifier, ++i, newOp);
} else {
Model.getCoreHelper().addFeature(
classifier, newOp);
}
} catch (ParseException ex) {
if (pex == null) {
pex = ex;
}
}
}
}
start = end + 1;
end = NotationUtilityUml.indexOfNextCheckedSemicolon(text, start);
}
if (pex != null) {
throw pex;
}
}
// in src/org/argouml/notation/providers/uml/OperationNotationUml.java
public void parseOperation(String s, Object op) throws ParseException {
MyTokenizer st;
boolean hasColon = false;
String name = null;
String parameterlist = null;
StringBuilder stereotype = null;
String token;
String type = null;
String visibility = null;
List<String> properties = null;
int paramOffset = 0;
s = s.trim();
if (s.length() > 0
&& NotationUtilityUml.VISIBILITYCHARS.indexOf(s.charAt(0))
>= 0) {
visibility = s.substring(0, 1);
s = s.substring(1);
}
try {
st = new MyTokenizer(s, " ,\t,<<,\u00AB,\u00BB,>>,:,=,{,},\\,",
NotationUtilityUml.operationCustomSep);
while (st.hasMoreTokens()) {
token = st.nextToken();
if (" ".equals(token) || "\t".equals(token)
|| ",".equals(token)) {
continue; // Do nothing
} else if ("<<".equals(token) || "\u00AB".equals(token)) {
if (stereotype != null) {
parseError("operation.stereotypes",
st.getTokenIndex());
}
stereotype = new StringBuilder();
while (true) {
token = st.nextToken();
if (">>".equals(token) || "\u00BB".equals(token)) {
break;
}
stereotype.append(token);
}
} else if ("{".equals(token)) {
properties = tokenOpenBrace(st, properties);
} else if (":".equals(token)) {
hasColon = true;
} else if ("=".equals(token)) {
parseError("operation.default-values", st.getTokenIndex());
} else if (token.charAt(0) == '(' && !hasColon) {
if (parameterlist != null) {
parseError("operation.two-parameter-lists",
st.getTokenIndex());
}
parameterlist = token;
} else {
if (hasColon) {
if (type != null) {
parseError("operation.two-types",
st.getTokenIndex());
}
if (token.length() > 0
&& (token.charAt(0) == '\"'
|| token.charAt(0) == '\'')) {
parseError("operation.type-quoted",
st.getTokenIndex());
}
if (token.length() > 0 && token.charAt(0) == '(') {
parseError("operation.type-expr",
st.getTokenIndex());
}
type = token;
} else {
if (name != null && visibility != null) {
parseError("operation.extra-text",
st.getTokenIndex());
}
if (token.length() > 0
&& (token.charAt(0) == '\"'
|| token.charAt(0) == '\'')) {
parseError("operation.name-quoted",
st.getTokenIndex());
}
if (token.length() > 0 && token.charAt(0) == '(') {
parseError("operation.name-expr",
st.getTokenIndex());
}
if (name == null
&& visibility == null
&& token.length() > 1
&& NotationUtilityUml.VISIBILITYCHARS.indexOf(
token.charAt(0))
>= 0) {
visibility = token.substring(0, 1);
token = token.substring(1);
}
if (name != null) {
visibility = name;
name = token;
} else {
name = token;
}
}
}
} // end while loop
} catch (NoSuchElementException nsee) {
parseError("operation.unexpected-end-operation",
s.length());
} catch (ParseException pre) {
throw pre;
}
if (parameterlist != null) {
// parameterlist is guaranteed to contain at least "("
if (parameterlist.charAt(parameterlist.length() - 1) != ')') {
parseError("operation.parameter-list-incomplete",
paramOffset + parameterlist.length() - 1);
}
paramOffset++;
parameterlist = parameterlist.substring(1,
parameterlist.length() - 1);
NotationUtilityUml.parseParamList(op, parameterlist, paramOffset);
}
if (visibility != null) {
Model.getCoreHelper().setVisibility(op,
NotationUtilityUml.getVisibility(visibility.trim()));
}
if (name != null) {
Model.getCoreHelper().setName(op, name.trim());
} else if (Model.getFacade().getName(op) == null
|| "".equals(Model.getFacade().getName(op))) {
Model.getCoreHelper().setName(op, "anonymous");
}
if (type != null) {
Object ow = Model.getFacade().getOwner(op);
Object ns = null;
if (ow != null && Model.getFacade().getNamespace(ow) != null) {
ns = Model.getFacade().getNamespace(ow);
} else {
ns = Model.getFacade().getRoot(op);
}
Object mtype = NotationUtilityUml.getType(type.trim(), ns);
setReturnParameter(op, mtype);
}
if (properties != null) {
NotationUtilityUml.setProperties(op, properties,
NotationUtilityUml.operationSpecialStrings);
}
// Don't create a stereotype for <<signal>> on a Reception
// but create any other parsed stereotypes as needed
if (!Model.getFacade().isAReception(op)
|| !RECEPTION_KEYWORD.equals(stereotype.toString())) {
StereotypeUtility.dealWithStereotypes(op, stereotype, true);
}
}
// in src/org/argouml/notation/providers/uml/OperationNotationUml.java
private void parseError(String message, int offset)
throws ParseException {
throw new ParseException(
Translator.localize("parsing.error." + message),
offset);
}
// in src/org/argouml/notation/providers/uml/OperationNotationUml.java
private List<String> tokenOpenBrace(MyTokenizer st, List<String> properties)
throws ParseException {
String token;
StringBuilder propname = new StringBuilder();
String propvalue = null;
if (properties == null) {
properties = new ArrayList<String>();
}
while (true) {
token = st.nextToken();
if (",".equals(token) || "}".equals(token)) {
if (propname.length() > 0) {
properties.add(propname.toString());
properties.add(propvalue);
}
propname = new StringBuilder();
propvalue = null;
if ("}".equals(token)) {
break;
}
} else if ("=".equals(token)) {
if (propvalue != null) {
String msg =
"parsing.error.operation.prop-stereotypes";
Object[] args = {propname};
throw new ParseException(
Translator.localize(msg,
args),
st.getTokenIndex());
}
propvalue = "";
} else if (propvalue == null) {
propname.append(token);
} else {
propvalue += token;
}
}
if (propname.length() > 0) {
properties.add(propname.toString());
properties.add(propvalue);
}
return properties;
}
// in src/org/argouml/notation/providers/uml/AbstractMessageNotationUml.java
protected void parseMessage(Object umlMessage, String s)
throws ParseException {
String fname = null;
// 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;
boolean mustBePre = false;
boolean mustBeSeq = false;
boolean parallell = false;
boolean iterative = false;
boolean mayDeleteExpr = false;
boolean refindOperation = false;
boolean hasPredecessors = false;
currentseq.add(null);
currentseq.add(null);
try {
MyTokenizer st = new MyTokenizer(s, " ,\t,*,[,],.,:,=,/,\\,",
MyTokenizer.PAREN_EXPR_STRING_SEPARATOR);
while (st.hasMoreTokens()) {
token = st.nextToken();
if (" ".equals(token) || "\t".equals(token)) {
if (currentseq == null) {
if (varname != null && fname == null) {
varname.append(token);
}
}
} else if ("[".equals(token)) {
if (mustBePre) {
String msg = "parsing.error.message.pred-unqualified";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
mustBeSeq = true;
if (guard != null) {
String msg = "parsing.error.message.several-specs";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
guard = new StringBuilder();
while (true) {
token = st.nextToken();
if ("]".equals(token)) {
break;
}
guard.append(token);
}
} else if ("*".equals(token)) {
if (mustBePre) {
String msg = "parsing.error.message.pred-unqualified";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
mustBeSeq = true;
if (currentseq != null) {
iterative = true;
}
} else if (".".equals(token)) {
if (currentseq == null) {
String msg = "parsing.error.message.unexpected-dot";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
if (currentseq.get(currentseq.size() - 2) != null
|| currentseq.get(currentseq.size() - 1) != null) {
currentseq.add(null);
currentseq.add(null);
}
} else if (":".equals(token)) {
if (st.hasMoreTokens()) {
String t = st.nextToken();
if ("=".equals(t)) {
st.putToken(":=");
continue;
}
st.putToken(t);
}
if (mustBePre) {
String msg = "parsing.error.message.pred-colon";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
if (currentseq != null) {
if (currentseq.size() > 2
&& currentseq.get(currentseq.size() - 2) == null
&& currentseq.get(currentseq.size() - 1) == null) {
currentseq.remove(currentseq.size() - 1);
currentseq.remove(currentseq.size() - 1);
}
seqno = currentseq;
currentseq = null;
mayDeleteExpr = true;
}
} else if ("/".equals(token)) {
if (st.hasMoreTokens()) {
String t = st.nextToken();
if ("/".equals(t)) {
st.putToken("//");
continue;
}
st.putToken(t);
}
if (mustBeSeq) {
String msg = "parsing.error.message.sequence-slash";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
mustBePre = false;
mustBeSeq = true;
if (currentseq.size() > 2
&& currentseq.get(currentseq.size() - 2) == null
&& currentseq.get(currentseq.size() - 1) == null) {
currentseq.remove(currentseq.size() - 1);
currentseq.remove(currentseq.size() - 1);
}
if (currentseq.get(currentseq.size() - 2) != null
|| currentseq.get(currentseq.size() - 1) != null) {
predecessors.add(currentseq);
currentseq = new ArrayList<Integer>();
currentseq.add(null);
currentseq.add(null);
}
hasPredecessors = true;
} else if ("//".equals(token)) {
if (mustBePre) {
String msg = "parsing.error.message.pred-parallelized";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
mustBeSeq = true;
if (currentseq != null) {
parallell = true;
}
} else if (",".equals(token)) {
if (currentseq != null) {
if (mustBeSeq) {
String msg = "parsing.error.message.many-numbers";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
mustBePre = true;
if (currentseq.size() > 2
&& currentseq.get(currentseq.size() - 2) == null
&& currentseq.get(currentseq.size() - 1) == null) {
currentseq.remove(currentseq.size() - 1);
currentseq.remove(currentseq.size() - 1);
}
if (currentseq.get(currentseq.size() - 2) != null
|| currentseq.get(currentseq.size() - 1) != null) {
predecessors.add(currentseq);
currentseq = new ArrayList<Integer>();
currentseq.add(null);
currentseq.add(null);
}
hasPredecessors = true;
} else {
if (varname == null && fname != null) {
varname = new StringBuilder(fname + token);
fname = null;
} else if (varname != null && fname == null) {
varname.append(token);
} else {
String msg = "parsing.error.message.found-comma";
throw new ParseException(
Translator.localize(msg),
st.getTokenIndex());
}
}
} else if ("=".equals(token) || ":=".equals(token)) {
if (currentseq == null) {
if (varname == null) {
varname = new StringBuilder(fname);
fname = "";
} else {
fname = "";
}
}
} else if (currentseq == null) {
if (paramExpr == null && token.charAt(0) == '(') {
if (token.charAt(token.length() - 1) != ')') {
String msg =
"parsing.error.message.malformed-parameters";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
if (fname == null || "".equals(fname)) {
String msg =
"parsing.error.message.function-not-found";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
if (varname == null) {
varname = new StringBuilder();
}
paramExpr = token.substring(1, token.length() - 1);
} else if (varname != null && fname == null) {
varname.append(token);
} else if (fname == null || fname.length() == 0) {
fname = token;
} else {
String msg = "parsing.error.message.unexpected-token";
Object[] parseExcArgs = {token};
throw new ParseException(
Translator.localize(msg, parseExcArgs),
st.getTokenIndex());
}
} else {
boolean hasVal =
currentseq.get(currentseq.size() - 2) != null;
boolean hasOrd =
currentseq.get(currentseq.size() - 1) != null;
boolean assigned = false;
int bp = findMsgOrderBreak(token);
if (!hasVal && !assigned && bp == token.length()) {
try {
currentseq.set(
currentseq.size() - 2, Integer.valueOf(
token));
assigned = true;
} catch (NumberFormatException nfe) { }
}
if (!hasOrd && !assigned && bp == 0) {
try {
currentseq.set(
currentseq.size() - 1, Integer.valueOf(
parseMsgOrder(token)));
assigned = true;
} catch (NumberFormatException nfe) { }
}
if (!hasVal && !hasOrd && !assigned && bp > 0
&& bp < token.length()) {
Integer nbr, ord;
try {
nbr = Integer.valueOf(token.substring(0, bp));
ord = Integer.valueOf(
parseMsgOrder(token.substring(bp)));
currentseq.set(currentseq.size() - 2, nbr);
currentseq.set(currentseq.size() - 1, ord);
assigned = true;
} catch (NumberFormatException nfe) { }
}
if (!assigned) {
String msg = "parsing.error.message.unexpected-token";
Object[] parseExcArgs = {token};
throw new ParseException(
Translator.localize(msg, parseExcArgs),
st.getTokenIndex());
}
}
}
} catch (NoSuchElementException nsee) {
String msg = "parsing.error.message.unexpected-end-message";
throw new ParseException(Translator.localize(msg), s.length());
} catch (ParseException pre) {
throw pre;
}
List<String> args = parseArguments(paramExpr, mayDeleteExpr);
printDebugInfo(s, fname, guard, paramExpr, varname, predecessors,
seqno, parallell, iterative);
/* Now apply the changes to the model: */
buildAction(umlMessage);
handleGuard(umlMessage, guard, parallell, iterative);
fname = fillBlankFunctionName(umlMessage, fname, mayDeleteExpr);
varname = fillBlankVariableName(umlMessage, varname, mayDeleteExpr);
refindOperation = handleFunctionName(umlMessage, fname, varname,
refindOperation);
refindOperation = handleArguments(umlMessage, args, refindOperation);
refindOperation = handleSequenceNumber(umlMessage, seqno,
refindOperation);
handleOperation(umlMessage, fname, refindOperation);
handlePredecessors(umlMessage, predecessors, hasPredecessors);
}
// in src/org/argouml/notation/providers/uml/AbstractMessageNotationUml.java
protected void handlePredecessors(Object umlMessage,
List<List> predecessors, boolean hasPredecessors)
throws ParseException {
// 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(
Model.getFacade().getMessages(
Model.getFacade().getInteraction(umlMessage)),
null,
null);
List<Object> pre = new ArrayList<Object>();
predfor:
for (int i = 0; i < predecessors.size(); i++) {
for (Object root : roots) {
Object msg =
walkTree(root, predecessors.get(i));
if (msg != null && msg != umlMessage) {
if (isBadPreMsg(umlMessage, msg)) {
String parseMsg = "parsing.error.message.one-pred";
throw new ParseException(
Translator.localize(parseMsg), 0);
}
pre.add(msg);
continue predfor;
}
}
String parseMsg = "parsing.error.message.pred-not-found";
throw new ParseException(Translator.localize(parseMsg), 0);
}
MsgPtr ptr = new MsgPtr();
recCountPredecessors(umlMessage, ptr);
if (ptr.message != null && !pre.contains(ptr.message)) {
pre.add(ptr.message);
}
Model.getCollaborationsHelper().setPredecessors(umlMessage, pre);
}
}
// in src/org/argouml/notation/providers/uml/AbstractMessageNotationUml.java
protected void handleOperation(Object umlMessage, String fname,
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());
Object callAction = Model.getFacade().getAction(umlMessage);
if (Model.getFacade().isACallAction(callAction)) {
if (ops.size() > 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(
callAction, null);
}
}
}
}
// in src/org/argouml/notation/providers/uml/AbstractMessageNotationUml.java
protected boolean handleSequenceNumber(Object umlMessage,
List<Integer> seqno, boolean refindOperation) throws ParseException {
int i;
if (seqno != null) {
Object/* MMessage */root;
// Find the preceding message, if any, on either end of the
// association.
StringBuilder pname = new StringBuilder();
StringBuilder mname = new StringBuilder();
String gname = generateMessageNumber(umlMessage);
boolean swapRoles = false;
int majval = 0;
if (seqno.get(seqno.size() - 2) != null) {
majval =
Math.max((seqno.get(seqno.size() - 2)).intValue()
- 1,
0);
}
int minval = 0;
if (seqno.get(seqno.size() - 1) != null) {
minval =
Math.max((seqno.get(seqno.size() - 1)).intValue(),
0);
}
for (i = 0; i + 1 < seqno.size(); i += 2) {
int bv = 1;
if (seqno.get(i) != null) {
bv = Math.max((seqno.get(i)).intValue(), 1);
}
int sv = 0;
if (seqno.get(i + 1) != null) {
sv = Math.max((seqno.get(i + 1)).intValue(), 0);
}
if (i > 0) {
mname.append(".");
}
mname.append(Integer.toString(bv) + (char) ('a' + sv));
if (i + 3 < seqno.size()) {
if (i > 0) {
pname.append(".");
}
pname.append(Integer.toString(bv) + (char) ('a' + sv));
}
}
root = null;
if (pname.length() > 0) {
root = findMsg(Model.getFacade().getSender(umlMessage),
pname.toString());
if (root == null) {
root = findMsg(Model.getFacade().getReceiver(umlMessage),
pname.toString());
if (root != null) {
swapRoles = true;
}
}
} else if (!hasMsgWithActivator(Model.getFacade().getSender(umlMessage),
null)
&& hasMsgWithActivator(Model.getFacade().getReceiver(umlMessage),
null)) {
swapRoles = true;
}
if (compareMsgNumbers(mname.toString(), gname.toString())) {
// Do nothing
} else if (isMsgNumberStartOf(gname.toString(), mname.toString())) {
String msg = "parsing.error.message.subtree-rooted-self";
throw new ParseException(Translator.localize(msg), 0);
} else if (Model.getFacade().getPredecessors(umlMessage).size() > 1
&& Model.getFacade().getSuccessors(umlMessage).size() > 1) {
String msg = "parsing.error.message.start-end-many-threads";
throw new ParseException(Translator.localize(msg), 0);
} else if (root == null && pname.length() > 0) {
String msg = "parsing.error.message.activator-not-found";
throw new ParseException(Translator.localize(msg), 0);
} else if (swapRoles
&& Model.getFacade().getActivatedMessages(umlMessage).size() > 0
&& (Model.getFacade().getSender(umlMessage)
!= Model.getFacade().getReceiver(umlMessage))) {
String msg = "parsing.error.message.reverse-direction-message";
throw new ParseException(Translator.localize(msg), 0);
} else {
/* Disconnect the message from the call graph
* Make copies of returned live collections
* since we're modifying
*/
Collection c = new ArrayList(
Model.getFacade().getPredecessors(umlMessage));
Collection c2 = new ArrayList(
Model.getFacade().getSuccessors(umlMessage));
Iterator it;
it = c2.iterator();
while (it.hasNext()) {
Model.getCollaborationsHelper().removeSuccessor(umlMessage,
it.next());
}
it = c.iterator();
while (it.hasNext()) {
Iterator it2 = c2.iterator();
Object pre = /* (MMessage) */it.next();
Model.getCollaborationsHelper().removePredecessor(umlMessage, pre);
while (it2.hasNext()) {
Model.getCollaborationsHelper().addPredecessor(
it2.next(), pre);
}
}
// Connect the message at a new spot
Model.getCollaborationsHelper().setActivator(umlMessage, root);
if (swapRoles) {
Object/* MClassifierRole */r =
Model.getFacade().getSender(umlMessage);
Model.getCollaborationsHelper().setSender(umlMessage,
Model.getFacade().getReceiver(umlMessage));
Model.getCommonBehaviorHelper().setReceiver(umlMessage, r);
}
if (root == null) {
c =
filterWithActivator(
Model.getFacade().getSentMessages(
Model.getFacade().getSender(umlMessage)),
null);
} else {
c = Model.getFacade().getActivatedMessages(root);
}
c2 = findCandidateRoots(c, root, umlMessage);
it = c2.iterator();
// If c2 is empty, then we're done (or there is a
// cycle in the message graph, which would be bad) If
// c2 has more than one element, then the model is
// crappy, but we'll just use one of them anyway
if (majval <= 0) {
while (it.hasNext()) {
Model.getCollaborationsHelper().addSuccessor(umlMessage,
/* (MMessage) */it.next());
}
} else if (it.hasNext()) {
Object/* MMessage */pre =
walk(/* (MMessage) */it.next(), majval - 1, false);
Object/* MMessage */post = successor(pre, minval);
if (post != null) {
Model.getCollaborationsHelper()
.removePredecessor(post, pre);
Model.getCollaborationsHelper()
.addPredecessor(post, umlMessage);
}
insertSuccessor(pre, umlMessage, minval);
}
refindOperation = true;
}
}
return refindOperation;
}
// in src/org/argouml/notation/providers/uml/AbstractMessageNotationUml.java
private List getOperation(Collection classifiers, String name, int params)
throws ParseException {
List<Object> operations = new ArrayList<Object>();
if (name == null || name.length() == 0) {
return operations;
}
for (Object clf : classifiers) {
Collection oe = Model.getFacade().getFeatures(clf);
for (Object operation : oe) {
if (!(Model.getFacade().isAOperation(operation))) {
continue;
}
if (!name.equals(Model.getFacade().getName(operation))) {
continue;
}
if (params != countParameters(operation)) {
continue;
}
operations.add(operation);
}
}
if (operations.size() > 0) {
return operations;
}
Iterator it = classifiers.iterator();
if (it.hasNext()) {
StringBuilder expr = new StringBuilder(name + "(");
int i;
for (i = 0; i < params; i++) {
if (i > 0) {
expr.append(", ");
}
expr.append("param" + (i + 1));
}
expr.append(")");
// Jaap Branderhorst 2002-23-09 added next lines to link
// parameters and operations to the figs that represent
// them
Object cls = it.next();
Object returnType =
ProjectManager.getManager()
.getCurrentProject().getDefaultReturnType();
Object op = Model.getCoreFactory().buildOperation(cls, returnType);
new OperationNotationUml(op).parseOperation(
expr.toString(), op);
operations.add(op);
}
return operations;
}
// in src/org/argouml/notation/providers/uml/ObjectFlowStateStateNotationUml.java
protected Object parseObjectFlowState2(Object objectFlowState, String s)
throws ParseException {
s = s.trim();
/* Let's not be picky about the brackets - just remove them: */
if (s.startsWith("[")) {
s = s.substring(1);
}
if (s.endsWith("]")) {
s = s.substring(0, s.length() - 1);
}
s = s.trim();
Object c = Model.getFacade().getType(objectFlowState); // get the
// classifier
if (c != null) {
if (Model.getFacade().isAClassifierInState(c)) {
Object classifier = Model.getFacade().getType(c);
if ((s == null) || "".equals(s)) {
// the State of a ClassifierInState is removed,
// so let's reduce it to a Classifier.
Model.getCoreHelper().setType(objectFlowState, classifier);
delete(c);
Model.getCoreHelper().setType(objectFlowState, classifier);
return objectFlowState; // the model is changed - job done
}
Collection states =
new ArrayList(Model.getFacade()
.getInStates(c));
Collection statesToBeRemoved = new ArrayList(states);
Collection namesToBeAdded = new ArrayList(); // Strings
StringTokenizer tokenizer = new StringTokenizer(s, ",");
while (tokenizer.hasMoreTokens()) {
String nextToken = tokenizer.nextToken().trim();
boolean found = false;
Iterator i = states.iterator();
while (i.hasNext()) {
Object state = i.next();
if (Model.getFacade().getName(state) == nextToken) {
found = true;
statesToBeRemoved.remove(state);
}
}
if (!found) {
namesToBeAdded.add(nextToken);
}
}
/* Remove the states that did not match. */
states.removeAll(statesToBeRemoved);
Iterator i = namesToBeAdded.iterator();
while (i.hasNext()) {
String name = (String) i.next();
/*
* Now we have to see if any state in any statemachine of
* classifier is named [name]. If so, then we only have to
* link the state to c.
*/
Object state =
Model.getActivityGraphsHelper()
.findStateByName(classifier, name);
if (state != null) {
states.add(state);
// the model is changed - our job is done
} else {
// no state named s is found, so we have to
// reject the user's input
String msg =
"parsing.error.object-flow-state.state-not-found";
Object[] args = {s};
throw new ParseException(Translator.localize(msg, args),
0);
}
}
/* Finally, do the adaptations: */
Model.getActivityGraphsHelper().setInStates(c, states);
} else { // then c is a "normal" Classifier
Collection statesToBeAdded = new ArrayList(); // UML states
StringTokenizer tokenizer = new StringTokenizer(s, ",");
while (tokenizer.hasMoreTokens()) {
String nextToken = tokenizer.nextToken().trim();
Object state =
Model.getActivityGraphsHelper()
.findStateByName(c, nextToken);
if (state != null) {
statesToBeAdded.add(state);
} else {
// no state with the given name is found, so we have to
// reject the complete user's input
String msg =
"parsing.error.object-flow-state.state-not-found";
Object[] args = {s};
throw new ParseException(Translator.localize(msg, args),
0);
}
}
// let's create a new ClassifierInState with the correct links
Object cis =
Model.getActivityGraphsFactory()
.buildClassifierInState(c, statesToBeAdded);
Model.getCoreHelper().setType(objectFlowState, cis);
// the model is changed - our job is done
}
} else {
// if no classifier has been set, then entering a state is
// not useful, so the user's input has to be rejected.
String msg =
"parsing.error.object-flow-state.classifier-not-found";
throw new ParseException(Translator.localize(msg),
0);
}
return objectFlowState;
}
// in src/org/argouml/notation/providers/uml/ClassifierRoleNotationUml.java
protected Object parseClassifierRole(Object cls, String s)
throws ParseException {
String name = null;
String token;
String role = null;
String base = null;
List<String> bases = null;
boolean hasColon = false;
boolean hasSlash = false;
try {
MyTokenizer st = new MyTokenizer(s, " ,\t,/,:,\\,");
while (st.hasMoreTokens()) {
token = st.nextToken();
if (" ".equals(token) || "\t".equals(token)) {
/* Do nothing. */
} else if ("/".equals(token)) {
hasSlash = true;
hasColon = false;
if (base != null) {
if (bases == null) {
bases = new ArrayList<String>();
}
bases.add(base);
}
base = null;
} else if (":".equals(token)) {
hasColon = true;
hasSlash = false;
if (bases == null) {
bases = new ArrayList<String>();
}
if (base != null) {
bases.add(base);
}
base = null;
} else if (",".equals(token)) {
if (base != null) {
if (bases == null) {
bases = new ArrayList<String>();
}
bases.add(base);
}
base = null;
} else if (hasColon) {
if (base != null) {
String msg = "parsing.error.classifier.extra-test";
throw new ParseException(
Translator.localize(msg),
st.getTokenIndex());
}
base = token;
} else if (hasSlash) {
if (role != null) {
String msg = "parsing.error.classifier.extra-test";
throw new ParseException(
Translator.localize(msg),
st.getTokenIndex());
}
role = token;
} else {
if (name != null) {
String msg = "parsing.error.classifier.extra-test";
throw new ParseException(
Translator.localize(msg),
st.getTokenIndex());
}
name = token;
}
}
} catch (NoSuchElementException nsee) {
String msg = "parsing.error.classifier.unexpected-end-attribute";
throw new ParseException(Translator.localize(msg), s.length());
}
if (base != null) {
if (bases == null) {
bases = new ArrayList<String>();
}
bases.add(base);
}
// TODO: What to do about object name???
// if (name != null)
// ;
if (role != null) {
Model.getCoreHelper().setName(cls, role.trim());
}
if (bases != null) {
// Remove bases that aren't there anymore
// copy - can't iterate modify live collection while iterating it
Collection b = new ArrayList(Model.getFacade().getBases(cls));
Iterator it = b.iterator();
Object c;
Object ns = Model.getFacade().getNamespace(cls);
if (ns != null && Model.getFacade().getNamespace(ns) != null) {
ns = Model.getFacade().getNamespace(ns);
} else {
ns = Model.getFacade().getRoot(cls);
}
while (it.hasNext()) {
c = it.next();
if (!bases.contains(Model.getFacade().getName(c))) {
Model.getCollaborationsHelper().removeBase(cls, c);
}
}
it = bases.iterator();
addBases:
while (it.hasNext()) {
String d = ((String) it.next()).trim();
Iterator it2 = b.iterator();
while (it2.hasNext()) {
c = it2.next();
if (d.equals(Model.getFacade().getName(c))) {
continue addBases;
}
}
c = NotationUtilityUml.getType(d, ns);
if (Model.getFacade().isACollaboration(
Model.getFacade().getNamespace(c))) {
Model.getCoreHelper().setNamespace(c, ns);
}
Model.getCollaborationsHelper().addBase(cls, c);
}
}
return cls;
}
// in src/org/argouml/notation/providers/uml/CallStateNotationUml.java
protected Object parseCallState(Object callState, String s1)
throws ParseException {
String s = s1.trim();
int a = s.indexOf("(");
int b = s.indexOf(")");
if (((a < 0) && (b >= 0)) || ((b < 0) && (a >= 0)) || (b < a)) {
throw new ParseException("No matching brackets () found.", 0);
}
/* First we decode the string: */
String newClassName = null;
String newOperationName = null;
StringTokenizer tokenizer = new StringTokenizer(s, "(");
while (tokenizer.hasMoreTokens()) {
String nextToken = tokenizer.nextToken().trim();
if (nextToken.endsWith(")")) {
newClassName = nextToken.substring(0, nextToken.length() - 1);
} else {
newOperationName = nextToken.trim();
}
}
/* Secondly we check the previous model structure: */
String oldOperationName = null;
String oldClassName = null;
Object entry = Model.getFacade().getEntry(callState);
Object operation = null;
Object clazz = null;
if (Model.getFacade().isACallAction(entry)) {
operation = Model.getFacade().getOperation(entry);
if (Model.getFacade().isAOperation(operation)) {
oldOperationName = Model.getFacade().getName(operation);
clazz = Model.getFacade().getOwner(operation);
oldClassName = Model.getFacade().getName(clazz);
}
}
/* And 3rd, we adapt the model: */
boolean found = false;
if ((newClassName != null)
&& newClassName.equals(oldClassName)
&& (newOperationName != null)
&& !newOperationName.equals(oldOperationName)) {
// Same class, other operation
for ( Object op : Model.getFacade().getOperations(clazz)) {
if (newOperationName.equals(
Model.getFacade().getName(op))) {
Model.getCommonBehaviorHelper().setOperation(entry, op);
found = true;
break;
}
}
if (!found) {
throw new ParseException(
"Operation " + newOperationName
+ " not found in " + newClassName + ".", 0);
}
} else if ((newClassName != null)
&& !newClassName.equals(oldClassName)
&& (newOperationName != null)) {
// Other class
Object model =
ProjectManager.getManager().getCurrentProject().getRoot();
Collection c =
Model.getModelManagementHelper().
getAllModelElementsOfKind(model,
Model.getMetaTypes().getClassifier());
Iterator i = c.iterator();
Object classifier = null;
while (i.hasNext()) {
Object cl = i.next();
String cn = Model.getFacade().getName(cl);
if (cn.equals(newClassName)) {
classifier = cl;
break;
}
}
if (classifier == null) {
throw new ParseException(
"Classifier " + newClassName + " not found.", 0);
}
// We found the classifier, now go find the operation:
if (classifier != null) {
Collection ops = Model.getFacade().getOperations(classifier);
Iterator io = ops.iterator();
while (io.hasNext()) {
Object op = io.next();
if (newOperationName.equals(
Model.getFacade().getName(op))) {
/* Here we located the new classifier
* with its operation. */
found = true;
if (!Model.getFacade().isACallAction(entry)) {
entry = Model.getCommonBehaviorFactory()
.buildCallAction(op, "ca");
Model.getStateMachinesHelper().setEntry(
callState, entry);
} else {
Model.getCommonBehaviorHelper().setOperation(
entry, op);
}
break;
}
}
if (!found) {
throw new ParseException(
"Operation " + newOperationName
+ " not found in " + newClassName + ".", 0);
}
}
}
if (!found) {
throw new ParseException(
"Incompatible input found.", 0);
}
return callState;
}
// in src/org/argouml/notation/providers/uml/AttributeNotationUml.java
public void parseAttributeFig(
Object classifier,
Object attribute,
String text) throws ParseException {
if (classifier == null || attribute == null) {
return;
}
/* TODO: We should have all the information that is required in the
* NotationSettings object */
Project project = ProjectManager.getManager().getCurrentProject();
ParseException pex = null;
int start = 0;
int end = NotationUtilityUml.indexOfNextCheckedSemicolon(text, start);
if (end == -1) {
//no text? remove attr!
project.moveToTrash(attribute);
return;
}
String s = text.substring(start, end).trim();
if (s.length() == 0) {
//no non-whitechars in text? remove attr!
project.moveToTrash(attribute);
return;
}
parseAttribute(s, attribute);
int i = Model.getFacade().getFeatures(classifier).indexOf(attribute);
// check for more attributes (';' separated):
start = end + 1;
end = NotationUtilityUml.indexOfNextCheckedSemicolon(text, start);
while (end > start && end <= text.length()) {
s = text.substring(start, end).trim();
if (s.length() > 0) {
// yes, there are more:
Object attrType = project.getDefaultAttributeType();
Object newAttribute = Model.getUmlFactory().buildNode(
Model.getMetaTypes().getAttribute());
Model.getCoreHelper().setType(newAttribute, attrType);
if (newAttribute != null) {
/* We need to set the namespace/owner
* of the new attribute before parsing: */
if (i != -1) {
Model.getCoreHelper().addFeature(
classifier, ++i, newAttribute);
} else {
Model.getCoreHelper().addFeature(
classifier, newAttribute);
}
try {
parseAttribute(s, newAttribute);
/* If the 1st attribute is static,
* then the new ones, too. */
Model.getCoreHelper().setStatic(
newAttribute,
Model.getFacade().isStatic(attribute));
} catch (ParseException ex) {
if (pex == null) {
pex = ex;
}
}
}
}
start = end + 1;
end = NotationUtilityUml.indexOfNextCheckedSemicolon(text, start);
}
if (pex != null) {
throw pex;
}
}
// in src/org/argouml/notation/providers/uml/AttributeNotationUml.java
protected void parseAttribute(
String text,
Object attribute) throws ParseException {
StringBuilder multiplicity = null;
String name = null;
List<String> properties = null;
StringBuilder stereotype = null; // This is null as until
// the first stereotype declaration is seen.
// After that it is non-null.
String token;
String type = null;
StringBuilder value = null;
String visibility = null;
boolean derived = false;
boolean hasColon = false;
boolean hasEq = false;
int multindex = -1;
MyTokenizer st;
text = text.trim();
/* Handle Derived: */
if (text.length() > 0 && "/".indexOf(text.charAt(0)) >= 0) {
derived = true;
text = text.substring(1);
text = text.trim();
}
/* Handle Visibility: */
if (text.length() > 0
&& NotationUtilityUml.VISIBILITYCHARS.indexOf(text.charAt(0))
>= 0) {
visibility = text.substring(0, 1);
text = text.substring(1);
}
try {
st = new MyTokenizer(text,
" ,\t,<<,\u00AB,\u00BB,>>,[,],:,=,{,},\\,",
NotationUtilityUml.attributeCustomSep);
while (st.hasMoreTokens()) {
token = st.nextToken();
if (" ".equals(token) || "\t".equals(token)
|| ",".equals(token)) {
if (hasEq) {
value.append(token);
}
} else if ("<<".equals(token) || "\u00AB".equals(token)) {
if (hasEq) {
value.append(token);
} else {
if (stereotype != null) {
String msg =
"parsing.error.attribute.two-sets-stereotypes";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
stereotype = new StringBuilder();
while (true) {
token = st.nextToken();
if (">>".equals(token) || "\u00BB".equals(token)) {
break;
}
stereotype.append(token);
}
}
} else if ("[".equals(token)) {
if (hasEq) {
value.append(token);
} else {
if (multiplicity != null) {
String msg =
"parsing.error.attribute.two-multiplicities";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
multiplicity = new StringBuilder();
multindex = st.getTokenIndex() + 1;
while (true) {
token = st.nextToken();
if ("]".equals(token)) {
break;
}
multiplicity.append(token);
}
}
} else if ("{".equals(token)) {
StringBuilder propname = new StringBuilder();
String propvalue = null;
if (properties == null) {
properties = new ArrayList<String>();
}
while (true) {
token = st.nextToken();
if (",".equals(token) || "}".equals(token)) {
if (propname.length() > 0) {
properties.add(propname.toString());
properties.add(propvalue);
}
propname = new StringBuilder();
propvalue = null;
if ("}".equals(token)) {
break;
}
} else if ("=".equals(token)) {
if (propvalue != null) {
String msg =
"parsing.error.attribute.prop-two-values";
Object[] args = {propvalue};
throw new ParseException(Translator.localize(
msg, args), st.getTokenIndex());
}
propvalue = "";
} else if (propvalue == null) {
propname.append(token);
} else {
propvalue += token;
}
}
if (propname.length() > 0) {
properties.add(propname.toString());
properties.add(propvalue);
}
} else if (":".equals(token)) {
hasColon = true;
hasEq = false;
} else if ("=".equals(token)) {
if (value != null) {
String msg =
"parsing.error.attribute.two-default-values";
throw new ParseException(Translator.localize(msg), st
.getTokenIndex());
}
value = new StringBuilder();
hasColon = false;
hasEq = true;
} else {
if (hasColon) {
if (type != null) {
String msg = "parsing.error.attribute.two-types";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
if (token.length() > 0
&& (token.charAt(0) == '\"'
|| token.charAt(0) == '\'')) {
String msg = "parsing.error.attribute.quoted";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
if (token.length() > 0 && token.charAt(0) == '(') {
String msg = "parsing.error.attribute.is-expr";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
type = token;
} else if (hasEq) {
value.append(token);
} else {
if (name != null && visibility != null) {
String msg = "parsing.error.attribute.extra-text";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
if (token.length() > 0
&& (token.charAt(0) == '\"'
|| token.charAt(0) == '\'')) {
String msg = "parsing.error.attribute.name-quoted";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
if (token.length() > 0 && token.charAt(0) == '(') {
String msg = "parsing.error.attribute.name-expr";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
if (name == null
&& visibility == null
&& token.length() > 1
&& NotationUtilityUml.VISIBILITYCHARS
.indexOf(token.charAt(0)) >= 0) {
visibility = token.substring(0, 1);
token = token.substring(1);
}
if (name != null) {
visibility = name;
name = token;
} else {
name = token;
}
}
}
}
} catch (NoSuchElementException nsee) {
String msg = "parsing.error.attribute.unexpected-end-attribute";
throw new ParseException(Translator.localize(msg), text.length());
}
// catch & rethrow is not necessary if we don't do nothing (penyaskito)
// catch (ParseException pre) {
// throw pre;
// }
if (LOG.isDebugEnabled()) {
LOG.debug("ParseAttribute [name: " + name
+ " visibility: " + visibility
+ " type: " + type + " value: " + value
+ " stereo: " + stereotype
+ " mult: " + multiplicity);
if (properties != null) {
for (int i = 0; i + 1 < properties.size(); i += 2) {
LOG.debug("\tProperty [name: " + properties.get(i) + " = "
+ properties.get(i + 1) + "]");
}
}
}
dealWithDerived(attribute, derived);
dealWithVisibility(attribute, visibility);
dealWithName(attribute, name);
dealWithType(attribute, type);
dealWithValue(attribute, value);
dealWithMultiplicity(attribute, multiplicity, multindex);
dealWithProperties(attribute, properties);
StereotypeUtility.dealWithStereotypes(attribute, stereotype, true);
}
// in src/org/argouml/notation/providers/uml/AttributeNotationUml.java
private void dealWithMultiplicity(Object attribute,
StringBuilder multiplicity, int multindex) throws ParseException {
if (multiplicity != null) {
try {
Model.getCoreHelper().setMultiplicity(attribute, multiplicity.toString());
} catch (IllegalArgumentException iae) {
String msg = "parsing.error.attribute.bad-multiplicity";
Object[] args = {iae};
throw new ParseException(Translator.localize(msg, args),
multindex);
}
}
}
// in src/org/argouml/notation/providers/java/ModelElementNameNotationJava.java
static void parseModelElement(Object modelElement, String text)
throws ParseException {
MyTokenizer st;
boolean abstrac = false;
boolean fina = false;
boolean publi = false;
boolean privat = false;
boolean protect = false;
String token;
List<String> path = null;
String name = null;
try {
st = new MyTokenizer(text,
" ,.,abstract,final,public,private,protected");
while (st.hasMoreTokens()) {
token = st.nextToken();
if (" ".equals(token)) {
/* skip spaces */
} else if ("abstract".equals(token)) {
abstrac = true;
} else if ("final".equals(token)) {
fina = true;
} else if ("public".equals(token)) {
publi = true;
} else if ("private".equals(token)) {
privat = true;
} else if ("protected".equals(token)) {
protect = true;
} else if (".".equals(token)) {
if (name != null) {
name = name.trim();
}
if (path != null && (name == null || "".equals(name))) {
String msg =
"parsing.error.model-element-name.anon-qualifiers";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
if (path == null) {
path = new ArrayList<String>();
}
if (name != null) {
path.add(name);
}
name = null;
} else { // the name itself
if (name != null) {
String msg =
"parsing.error.model-element-name.twin-names";
throw new ParseException(Translator.localize(msg),
st.getTokenIndex());
}
name = token;
}
}
} catch (NoSuchElementException nsee) {
String msg =
"parsing.error.model-element-name.unexpected-name-element";
throw new ParseException(Translator.localize(msg),
text.length());
} catch (ParseException pre) {
throw pre;
}
if (name != null) {
name = name.trim();
}
if (path != null && (name == null || "".equals(name))) {
String msg = "parsing.error.model-element-name.must-end-with-name";
throw new ParseException(Translator.localize(msg), 0);
}
/* Check the name for validity: */
if (!isValidJavaClassName(name)) {
throw new ParseException(
"Invalid class name for Java: "
+ name, 0);
}
if (path != null) {
Object nspe =
Model.getModelManagementHelper().getElement(
path,
Model.getFacade().getRoot(modelElement));
if (nspe == null || !(Model.getFacade().isANamespace(nspe))) {
String msg =
"parsing.error.model-element-name.namespace-unresolved";
throw new ParseException(Translator.localize(msg),
0);
}
if (!Model.getCoreHelper().isValidNamespace(
modelElement, nspe)) {
String msg =
"parsing.error.model-element-name.namespace-invalid";
throw new ParseException(Translator.localize(msg),
0);
}
Model.getCoreHelper().addOwnedElement(nspe, modelElement);
}
Model.getCoreHelper().setName(modelElement, name);
if (abstrac) {
Model.getCoreHelper().setAbstract(modelElement, abstrac);
}
if (fina) {
Model.getCoreHelper().setLeaf(modelElement, fina);
}
if (publi) {
Model.getCoreHelper().setVisibility(modelElement,
Model.getVisibilityKind().getPublic());
}
if (privat) {
Model.getCoreHelper().setVisibility(modelElement,
Model.getVisibilityKind().getPrivate());
}
if (protect) {
Model.getCoreHelper().setVisibility(modelElement,
Model.getVisibilityKind().getProtected());
}
}