1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
|
20 | |
|
21 | |
|
22 | |
|
23 | |
|
24 | |
|
25 | |
|
26 | |
|
27 | |
|
28 | |
|
29 | |
|
30 | |
|
31 | |
|
32 | |
|
33 | |
|
34 | |
|
35 | |
|
36 | |
|
37 | |
|
38 | |
|
39 | |
package org.argouml.notation.providers.uml; |
40 | |
|
41 | |
import java.text.ParseException; |
42 | |
import java.util.ArrayList; |
43 | |
import java.util.List; |
44 | |
import java.util.NoSuchElementException; |
45 | |
|
46 | |
import org.apache.log4j.Logger; |
47 | |
import org.argouml.application.events.ArgoEventPump; |
48 | |
import org.argouml.application.events.ArgoEventTypes; |
49 | |
import org.argouml.application.events.ArgoHelpEvent; |
50 | |
import org.argouml.i18n.Translator; |
51 | |
import org.argouml.kernel.Project; |
52 | |
import org.argouml.kernel.ProjectManager; |
53 | |
import org.argouml.kernel.ProjectSettings; |
54 | |
import org.argouml.model.InvalidElementException; |
55 | |
import org.argouml.model.Model; |
56 | |
import org.argouml.notation.NotationSettings; |
57 | |
import org.argouml.notation.providers.AttributeNotation; |
58 | |
import org.argouml.uml.StereotypeUtility; |
59 | |
import org.argouml.util.MyTokenizer; |
60 | |
|
61 | |
|
62 | |
|
63 | |
|
64 | |
|
65 | |
|
66 | |
public class AttributeNotationUml extends AttributeNotation { |
67 | |
|
68 | |
|
69 | |
|
70 | |
|
71 | 0 | private static final Logger LOG = |
72 | |
Logger.getLogger(AttributeNotationUml.class); |
73 | |
|
74 | |
|
75 | |
|
76 | |
|
77 | |
|
78 | |
public AttributeNotationUml(Object attribute) { |
79 | 0 | super(attribute); |
80 | 0 | } |
81 | |
|
82 | |
|
83 | |
|
84 | |
|
85 | |
public void parse(Object modelElement, String text) { |
86 | |
try { |
87 | 0 | parseAttributeFig(Model.getFacade().getOwner(modelElement), |
88 | |
modelElement, text); |
89 | 0 | } catch (ParseException pe) { |
90 | 0 | String msg = "statusmsg.bar.error.parsing.attribute"; |
91 | 0 | Object[] args = { |
92 | |
pe.getLocalizedMessage(), |
93 | |
Integer.valueOf(pe.getErrorOffset()), |
94 | |
}; |
95 | 0 | ArgoEventPump.fireEvent(new ArgoHelpEvent( |
96 | |
ArgoEventTypes.HELP_CHANGED, this, |
97 | |
Translator.messageFormat(msg, args))); |
98 | 0 | } |
99 | 0 | } |
100 | |
|
101 | |
|
102 | |
|
103 | |
|
104 | |
|
105 | |
|
106 | |
|
107 | |
|
108 | |
|
109 | |
|
110 | |
|
111 | |
public void parseAttributeFig( |
112 | |
Object classifier, |
113 | |
Object attribute, |
114 | |
String text) throws ParseException { |
115 | |
|
116 | 0 | if (classifier == null || attribute == null) { |
117 | 0 | return; |
118 | |
} |
119 | |
|
120 | |
|
121 | |
|
122 | 0 | Project project = ProjectManager.getManager().getCurrentProject(); |
123 | |
|
124 | 0 | ParseException pex = null; |
125 | 0 | int start = 0; |
126 | 0 | int end = NotationUtilityUml.indexOfNextCheckedSemicolon(text, start); |
127 | 0 | if (end == -1) { |
128 | |
|
129 | 0 | project.moveToTrash(attribute); |
130 | 0 | return; |
131 | |
} |
132 | 0 | String s = text.substring(start, end).trim(); |
133 | 0 | if (s.length() == 0) { |
134 | |
|
135 | 0 | project.moveToTrash(attribute); |
136 | 0 | return; |
137 | |
} |
138 | 0 | parseAttribute(s, attribute); |
139 | 0 | int i = Model.getFacade().getFeatures(classifier).indexOf(attribute); |
140 | |
|
141 | 0 | start = end + 1; |
142 | 0 | end = NotationUtilityUml.indexOfNextCheckedSemicolon(text, start); |
143 | 0 | while (end > start && end <= text.length()) { |
144 | 0 | s = text.substring(start, end).trim(); |
145 | 0 | if (s.length() > 0) { |
146 | |
|
147 | 0 | Object attrType = project.getDefaultAttributeType(); |
148 | |
|
149 | 0 | Object newAttribute = Model.getUmlFactory().buildNode( |
150 | |
Model.getMetaTypes().getAttribute()); |
151 | |
|
152 | 0 | Model.getCoreHelper().setType(newAttribute, attrType); |
153 | |
|
154 | 0 | if (newAttribute != null) { |
155 | |
|
156 | |
|
157 | 0 | if (i != -1) { |
158 | 0 | Model.getCoreHelper().addFeature( |
159 | |
classifier, ++i, newAttribute); |
160 | |
} else { |
161 | 0 | Model.getCoreHelper().addFeature( |
162 | |
classifier, newAttribute); |
163 | |
} |
164 | |
try { |
165 | 0 | parseAttribute(s, newAttribute); |
166 | |
|
167 | |
|
168 | 0 | Model.getCoreHelper().setStatic( |
169 | |
newAttribute, |
170 | |
Model.getFacade().isStatic(attribute)); |
171 | 0 | } catch (ParseException ex) { |
172 | 0 | if (pex == null) { |
173 | 0 | pex = ex; |
174 | |
} |
175 | 0 | } |
176 | |
} |
177 | |
} |
178 | 0 | start = end + 1; |
179 | 0 | end = NotationUtilityUml.indexOfNextCheckedSemicolon(text, start); |
180 | |
} |
181 | 0 | if (pex != null) { |
182 | 0 | throw pex; |
183 | |
} |
184 | 0 | } |
185 | |
|
186 | |
|
187 | |
|
188 | |
|
189 | |
|
190 | |
|
191 | |
|
192 | |
|
193 | |
|
194 | |
|
195 | |
|
196 | |
|
197 | |
|
198 | |
|
199 | |
|
200 | |
|
201 | |
|
202 | |
|
203 | |
|
204 | |
|
205 | |
|
206 | |
|
207 | |
|
208 | |
|
209 | |
|
210 | |
|
211 | |
|
212 | |
|
213 | |
|
214 | |
|
215 | |
|
216 | |
|
217 | |
|
218 | |
|
219 | |
|
220 | |
|
221 | |
|
222 | |
|
223 | |
|
224 | |
protected void parseAttribute( |
225 | |
String text, |
226 | |
Object attribute) throws ParseException { |
227 | 0 | StringBuilder multiplicity = null; |
228 | 0 | String name = null; |
229 | 0 | List<String> properties = null; |
230 | 0 | StringBuilder stereotype = null; |
231 | |
|
232 | |
|
233 | |
String token; |
234 | 0 | String type = null; |
235 | 0 | StringBuilder value = null; |
236 | 0 | String visibility = null; |
237 | 0 | boolean hasColon = false; |
238 | 0 | boolean hasEq = false; |
239 | 0 | int multindex = -1; |
240 | |
MyTokenizer st; |
241 | |
|
242 | 0 | text = text.trim(); |
243 | 0 | if (text.length() > 0 |
244 | |
&& NotationUtilityUml.VISIBILITYCHARS.indexOf(text.charAt(0)) |
245 | |
>= 0) { |
246 | 0 | visibility = text.substring(0, 1); |
247 | 0 | text = text.substring(1); |
248 | |
} |
249 | |
|
250 | |
try { |
251 | 0 | st = new MyTokenizer(text, |
252 | |
" ,\t,<<,\u00AB,\u00BB,>>,[,],:,=,{,},\\,", |
253 | |
NotationUtilityUml.attributeCustomSep); |
254 | 0 | while (st.hasMoreTokens()) { |
255 | 0 | token = st.nextToken(); |
256 | 0 | if (" ".equals(token) || "\t".equals(token) |
257 | |
|| ",".equals(token)) { |
258 | 0 | if (hasEq) { |
259 | 0 | value.append(token); |
260 | |
} |
261 | 0 | } else if ("<<".equals(token) || "\u00AB".equals(token)) { |
262 | 0 | if (hasEq) { |
263 | 0 | value.append(token); |
264 | |
} else { |
265 | 0 | if (stereotype != null) { |
266 | 0 | String msg = |
267 | |
"parsing.error.attribute.two-sets-stereotypes"; |
268 | 0 | throw new ParseException(Translator.localize(msg), |
269 | |
st.getTokenIndex()); |
270 | |
} |
271 | 0 | stereotype = new StringBuilder(); |
272 | |
while (true) { |
273 | 0 | token = st.nextToken(); |
274 | 0 | if (">>".equals(token) || "\u00BB".equals(token)) { |
275 | 0 | break; |
276 | |
} |
277 | 0 | stereotype.append(token); |
278 | |
} |
279 | |
} |
280 | 0 | } else if ("[".equals(token)) { |
281 | 0 | if (hasEq) { |
282 | 0 | value.append(token); |
283 | |
} else { |
284 | 0 | if (multiplicity != null) { |
285 | 0 | String msg = |
286 | |
"parsing.error.attribute.two-multiplicities"; |
287 | 0 | throw new ParseException(Translator.localize(msg), |
288 | |
st.getTokenIndex()); |
289 | |
} |
290 | 0 | multiplicity = new StringBuilder(); |
291 | 0 | multindex = st.getTokenIndex() + 1; |
292 | |
while (true) { |
293 | 0 | token = st.nextToken(); |
294 | 0 | if ("]".equals(token)) { |
295 | 0 | break; |
296 | |
} |
297 | 0 | multiplicity.append(token); |
298 | |
} |
299 | |
} |
300 | 0 | } else if ("{".equals(token)) { |
301 | 0 | StringBuilder propname = new StringBuilder(); |
302 | 0 | String propvalue = null; |
303 | |
|
304 | 0 | if (properties == null) { |
305 | 0 | properties = new ArrayList<String>(); |
306 | |
} |
307 | |
while (true) { |
308 | 0 | token = st.nextToken(); |
309 | 0 | if (",".equals(token) || "}".equals(token)) { |
310 | 0 | if (propname.length() > 0) { |
311 | 0 | properties.add(propname.toString()); |
312 | 0 | properties.add(propvalue); |
313 | |
} |
314 | 0 | propname = new StringBuilder(); |
315 | 0 | propvalue = null; |
316 | |
|
317 | 0 | if ("}".equals(token)) { |
318 | 0 | break; |
319 | |
} |
320 | 0 | } else if ("=".equals(token)) { |
321 | 0 | if (propvalue != null) { |
322 | 0 | String msg = |
323 | |
"parsing.error.attribute.prop-two-values"; |
324 | 0 | Object[] args = {propvalue}; |
325 | |
|
326 | 0 | throw new ParseException(Translator.localize( |
327 | |
msg, args), st.getTokenIndex()); |
328 | |
} |
329 | 0 | propvalue = ""; |
330 | 0 | } else if (propvalue == null) { |
331 | 0 | propname.append(token); |
332 | |
} else { |
333 | 0 | propvalue += token; |
334 | |
} |
335 | |
} |
336 | 0 | if (propname.length() > 0) { |
337 | 0 | properties.add(propname.toString()); |
338 | 0 | properties.add(propvalue); |
339 | |
} |
340 | 0 | } else if (":".equals(token)) { |
341 | 0 | hasColon = true; |
342 | 0 | hasEq = false; |
343 | 0 | } else if ("=".equals(token)) { |
344 | 0 | if (value != null) { |
345 | 0 | String msg = |
346 | |
"parsing.error.attribute.two-default-values"; |
347 | 0 | throw new ParseException(Translator.localize(msg), st |
348 | |
.getTokenIndex()); |
349 | |
} |
350 | 0 | value = new StringBuilder(); |
351 | 0 | hasColon = false; |
352 | 0 | hasEq = true; |
353 | |
} else { |
354 | 0 | if (hasColon) { |
355 | 0 | if (type != null) { |
356 | 0 | String msg = "parsing.error.attribute.two-types"; |
357 | 0 | throw new ParseException(Translator.localize(msg), |
358 | |
st.getTokenIndex()); |
359 | |
} |
360 | 0 | if (token.length() > 0 |
361 | |
&& (token.charAt(0) == '\"' |
362 | |
|| token.charAt(0) == '\'')) { |
363 | 0 | String msg = "parsing.error.attribute.quoted"; |
364 | 0 | throw new ParseException(Translator.localize(msg), |
365 | |
st.getTokenIndex()); |
366 | |
} |
367 | 0 | if (token.length() > 0 && token.charAt(0) == '(') { |
368 | 0 | String msg = "parsing.error.attribute.is-expr"; |
369 | 0 | throw new ParseException(Translator.localize(msg), |
370 | |
st.getTokenIndex()); |
371 | |
} |
372 | 0 | type = token; |
373 | 0 | } else if (hasEq) { |
374 | 0 | value.append(token); |
375 | |
} else { |
376 | 0 | if (name != null && visibility != null) { |
377 | 0 | String msg = "parsing.error.attribute.extra-text"; |
378 | 0 | throw new ParseException(Translator.localize(msg), |
379 | |
st.getTokenIndex()); |
380 | |
} |
381 | 0 | if (token.length() > 0 |
382 | |
&& (token.charAt(0) == '\"' |
383 | |
|| token.charAt(0) == '\'')) { |
384 | 0 | String msg = "parsing.error.attribute.name-quoted"; |
385 | 0 | throw new ParseException(Translator.localize(msg), |
386 | |
st.getTokenIndex()); |
387 | |
} |
388 | 0 | if (token.length() > 0 && token.charAt(0) == '(') { |
389 | 0 | String msg = "parsing.error.attribute.name-expr"; |
390 | 0 | throw new ParseException(Translator.localize(msg), |
391 | |
st.getTokenIndex()); |
392 | |
} |
393 | |
|
394 | 0 | if (name == null |
395 | |
&& visibility == null |
396 | |
&& token.length() > 1 |
397 | |
&& NotationUtilityUml.VISIBILITYCHARS |
398 | |
.indexOf(token.charAt(0)) >= 0) { |
399 | 0 | visibility = token.substring(0, 1); |
400 | 0 | token = token.substring(1); |
401 | |
} |
402 | |
|
403 | 0 | if (name != null) { |
404 | 0 | visibility = name; |
405 | 0 | name = token; |
406 | |
} else { |
407 | 0 | name = token; |
408 | |
} |
409 | |
} |
410 | |
} |
411 | |
} |
412 | 0 | } catch (NoSuchElementException nsee) { |
413 | 0 | String msg = "parsing.error.attribute.unexpected-end-attribute"; |
414 | 0 | throw new ParseException(Translator.localize(msg), text.length()); |
415 | 0 | } |
416 | |
|
417 | |
|
418 | |
|
419 | |
|
420 | |
|
421 | 0 | if (LOG.isDebugEnabled()) { |
422 | 0 | LOG.debug("ParseAttribute [name: " + name |
423 | |
+ " visibility: " + visibility |
424 | |
+ " type: " + type + " value: " + value |
425 | |
+ " stereo: " + stereotype |
426 | |
+ " mult: " + multiplicity); |
427 | 0 | if (properties != null) { |
428 | 0 | for (int i = 0; i + 1 < properties.size(); i += 2) { |
429 | 0 | LOG.debug("\tProperty [name: " + properties.get(i) + " = " |
430 | |
+ properties.get(i + 1) + "]"); |
431 | |
} |
432 | |
} |
433 | |
} |
434 | |
|
435 | 0 | dealWithVisibility(attribute, visibility); |
436 | 0 | dealWithName(attribute, name); |
437 | 0 | dealWithType(attribute, type); |
438 | 0 | dealWithValue(attribute, value); |
439 | 0 | dealWithMultiplicity(attribute, multiplicity, multindex); |
440 | 0 | dealWithProperties(attribute, properties); |
441 | 0 | StereotypeUtility.dealWithStereotypes(attribute, stereotype, true); |
442 | 0 | } |
443 | |
|
444 | |
private void dealWithProperties(Object attribute, List<String> properties) { |
445 | 0 | if (properties != null) { |
446 | 0 | NotationUtilityUml.setProperties(attribute, properties, |
447 | |
NotationUtilityUml.attributeSpecialStrings); |
448 | |
} |
449 | 0 | } |
450 | |
|
451 | |
private void dealWithMultiplicity(Object attribute, |
452 | |
StringBuilder multiplicity, int multindex) throws ParseException { |
453 | 0 | if (multiplicity != null) { |
454 | |
try { |
455 | 0 | Model.getCoreHelper().setMultiplicity(attribute, multiplicity.toString()); |
456 | 0 | } catch (IllegalArgumentException iae) { |
457 | 0 | String msg = "parsing.error.attribute.bad-multiplicity"; |
458 | 0 | Object[] args = {iae}; |
459 | |
|
460 | 0 | throw new ParseException(Translator.localize(msg, args), |
461 | |
multindex); |
462 | 0 | } |
463 | |
} |
464 | 0 | } |
465 | |
|
466 | |
private void dealWithValue(Object attribute, StringBuilder value) { |
467 | 0 | if (value != null) { |
468 | 0 | Project project = |
469 | |
ProjectManager.getManager().getCurrentProject(); |
470 | 0 | ProjectSettings ps = project.getProjectSettings(); |
471 | 0 | Object initExpr = Model.getDataTypesFactory().createExpression( |
472 | |
ps.getNotationLanguage(), value.toString().trim()); |
473 | 0 | Model.getCoreHelper().setInitialValue(attribute, initExpr); |
474 | |
} |
475 | 0 | } |
476 | |
|
477 | |
private void dealWithType(Object attribute, String type) { |
478 | 0 | if (type != null) { |
479 | 0 | Object ow = Model.getFacade().getOwner(attribute); |
480 | 0 | Object ns = null; |
481 | 0 | if (ow != null && Model.getFacade().getNamespace(ow) != null) { |
482 | 0 | ns = Model.getFacade().getNamespace(ow); |
483 | |
} else { |
484 | 0 | ns = Model.getFacade().getRoot(attribute); |
485 | |
} |
486 | 0 | Model.getCoreHelper().setType(attribute, |
487 | |
NotationUtilityUml.getType(type.trim(), ns)); |
488 | |
} |
489 | 0 | } |
490 | |
|
491 | |
private void dealWithName(Object attribute, String name) { |
492 | 0 | if (name != null) { |
493 | 0 | Model.getCoreHelper().setName(attribute, name.trim()); |
494 | 0 | } else if (Model.getFacade().getName(attribute) == null |
495 | |
|| "".equals(Model.getFacade().getName(attribute))) { |
496 | 0 | Model.getCoreHelper().setName(attribute, "anonymous"); |
497 | |
} |
498 | 0 | } |
499 | |
|
500 | |
private void dealWithVisibility(Object attribute, String visibility) { |
501 | 0 | if (visibility != null) { |
502 | 0 | Model.getCoreHelper().setVisibility(attribute, |
503 | |
NotationUtilityUml.getVisibility(visibility.trim())); |
504 | |
} |
505 | 0 | } |
506 | |
|
507 | |
|
508 | |
|
509 | |
|
510 | |
public String getParsingHelp() { |
511 | 0 | return "parsing.help.attribute"; |
512 | |
} |
513 | |
|
514 | |
@Override |
515 | |
public String toString(Object modelElement, NotationSettings settings) { |
516 | 0 | return toString(modelElement, settings.isUseGuillemets(), settings |
517 | |
.isShowVisibilities(), settings.isShowMultiplicities(), settings |
518 | |
.isShowTypes(), settings.isShowInitialValues(), |
519 | |
settings.isShowProperties()); |
520 | |
} |
521 | |
|
522 | |
|
523 | |
|
524 | |
|
525 | |
|
526 | |
|
527 | |
|
528 | |
|
529 | |
|
530 | |
private String toString(Object modelElement, boolean useGuillemets, |
531 | |
boolean showVisibility, boolean showMultiplicity, boolean showTypes, |
532 | |
boolean showInitialValues, boolean showProperties) { |
533 | |
try { |
534 | 0 | String stereo = NotationUtilityUml.generateStereotype(modelElement, |
535 | |
useGuillemets); |
536 | 0 | String name = Model.getFacade().getName(modelElement); |
537 | 0 | String multiplicity = generateMultiplicity( |
538 | |
Model.getFacade().getMultiplicity(modelElement)); |
539 | 0 | String type = ""; |
540 | 0 | if (Model.getFacade().getType(modelElement) != null) { |
541 | 0 | type = Model.getFacade().getName( |
542 | |
Model.getFacade().getType(modelElement)); |
543 | |
} |
544 | |
|
545 | 0 | StringBuilder sb = new StringBuilder(20); |
546 | 0 | if ((stereo != null) && (stereo.length() > 0)) { |
547 | 0 | sb.append(stereo).append(" "); |
548 | |
} |
549 | 0 | if (showVisibility) { |
550 | 0 | String visibility = NotationUtilityUml |
551 | |
.generateVisibility2(modelElement); |
552 | 0 | if (visibility != null && visibility.length() > 0) { |
553 | 0 | sb.append(visibility); |
554 | |
} |
555 | |
} |
556 | 0 | if ((name != null) && (name.length() > 0)) { |
557 | 0 | sb.append(name).append(" "); |
558 | |
} |
559 | 0 | if ((multiplicity != null) |
560 | |
&& (multiplicity.length() > 0) |
561 | |
&& showMultiplicity) { |
562 | 0 | sb.append("[").append(multiplicity).append("]").append(" "); |
563 | |
} |
564 | 0 | if ((type != null) && (type.length() > 0) |
565 | |
|
566 | |
|
567 | |
|
568 | |
|
569 | |
|
570 | |
&& showTypes) { |
571 | 0 | sb.append(": ").append(type).append(" "); |
572 | |
} |
573 | 0 | if (showInitialValues) { |
574 | 0 | Object iv = Model.getFacade().getInitialValue(modelElement); |
575 | 0 | if (iv != null) { |
576 | 0 | String initialValue = |
577 | |
(String) Model.getFacade().getBody(iv); |
578 | 0 | if (initialValue != null && initialValue.length() > 0) { |
579 | 0 | sb.append(" = ").append(initialValue).append(" "); |
580 | |
} |
581 | |
} |
582 | |
} |
583 | 0 | if (showProperties) { |
584 | 0 | String changeableKind = ""; |
585 | 0 | if (Model.getFacade().isReadOnly(modelElement)) { |
586 | 0 | changeableKind = "frozen"; |
587 | |
} |
588 | 0 | if (Model.getFacade().getChangeability(modelElement) != null) { |
589 | 0 | if (Model.getChangeableKind().getAddOnly().equals( |
590 | |
Model.getFacade().getChangeability(modelElement))) { |
591 | 0 | changeableKind = "addOnly"; |
592 | |
} |
593 | |
} |
594 | 0 | StringBuilder properties = new StringBuilder(); |
595 | 0 | if (changeableKind.length() > 0) { |
596 | 0 | properties.append("{ ").append(changeableKind).append(" }"); |
597 | |
} |
598 | |
|
599 | 0 | if (properties.length() > 0) { |
600 | 0 | sb.append(properties); |
601 | |
} |
602 | |
} |
603 | 0 | return sb.toString().trim(); |
604 | 0 | } catch (InvalidElementException e) { |
605 | |
|
606 | 0 | return ""; |
607 | |
} |
608 | |
} |
609 | |
|
610 | |
private static String generateMultiplicity(Object m) { |
611 | 0 | if (m == null || "1".equals(Model.getFacade().toString(m))) { |
612 | 0 | return ""; |
613 | |
} |
614 | 0 | return Model.getFacade().toString(m); |
615 | |
} |
616 | |
|
617 | |
} |