Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
EnumerationLiteralNotationUml |
|
| 6.428571428571429;6.429 |
1 | /* $Id: EnumerationLiteralNotationUml.java 17828 2010-01-12 18:55:12Z linus $ | |
2 | ***************************************************************************** | |
3 | * Copyright (c) 2009 Contributors - see below | |
4 | * All rights reserved. This program and the accompanying materials | |
5 | * are made available under the terms of the Eclipse Public License v1.0 | |
6 | * which accompanies this distribution, and is available at | |
7 | * http://www.eclipse.org/legal/epl-v10.html | |
8 | * | |
9 | * Contributors: | |
10 | * mvw | |
11 | ***************************************************************************** | |
12 | * | |
13 | * Some portions of this file was previously release using the BSD License: | |
14 | */ | |
15 | ||
16 | // Copyright (c) 2008-2009 The Regents of the University of California. All | |
17 | // Rights Reserved. Permission to use, copy, modify, and distribute this | |
18 | // software and its documentation without fee, and without a written | |
19 | // agreement is hereby granted, provided that the above copyright notice | |
20 | // and this paragraph appear in all copies. This software program and | |
21 | // documentation are copyrighted by The Regents of the University of | |
22 | // California. The software program and documentation are supplied "AS | |
23 | // IS", without any accompanying services from The Regents. The Regents | |
24 | // does not warrant that the operation of the program will be | |
25 | // uninterrupted or error-free. The end-user understands that the program | |
26 | // was developed for research purposes and is advised not to rely | |
27 | // exclusively on the program for any reason. IN NO EVENT SHALL THE | |
28 | // UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, | |
29 | // SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, | |
30 | // ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF | |
31 | // THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF | |
32 | // SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY | |
33 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
34 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE | |
35 | // PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF | |
36 | // CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, | |
37 | // UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | |
38 | ||
39 | package org.argouml.notation.providers.uml; | |
40 | ||
41 | import java.text.ParseException; | |
42 | import java.util.NoSuchElementException; | |
43 | ||
44 | import org.argouml.application.events.ArgoEventPump; | |
45 | import org.argouml.application.events.ArgoEventTypes; | |
46 | import org.argouml.application.events.ArgoHelpEvent; | |
47 | import org.argouml.i18n.Translator; | |
48 | import org.argouml.kernel.Project; | |
49 | import org.argouml.kernel.ProjectManager; | |
50 | import org.argouml.model.Model; | |
51 | import org.argouml.notation.NotationSettings; | |
52 | import org.argouml.notation.providers.EnumerationLiteralNotation; | |
53 | import org.argouml.uml.StereotypeUtility; | |
54 | import org.argouml.util.MyTokenizer; | |
55 | ||
56 | /** | |
57 | * The notation for an Enumeration Literal. <p> | |
58 | * | |
59 | * The supported notation is: <pre> | |
60 | * [ "<<" stereotype ">>" ] name [ ";" name ]* | |
61 | * </pre> | |
62 | * This means:<ul><li> | |
63 | * The name is not optional (i.e. leaving it blank | |
64 | * means deletion of the literal). <li> | |
65 | * Multiple literals may be entered at once | |
66 | * by separating the names with a semicolon. <li> | |
67 | * Extra literals are inserted after the one being parsed. <li> | |
68 | * A stereotype may precede the name of any literal. </ul><p> | |
69 | * | |
70 | * As explained in issue 5000, the real implemented BNF is something like: | |
71 | * <pre> | |
72 | * ["<<" stereotype ["," stereotype]* ">>"] name [ ";" ["<<" stereotype ["," stereotype]* ">>"] name]* | |
73 | * </pre> | |
74 | * | |
75 | * @author Michiel | |
76 | */ | |
77 | public class EnumerationLiteralNotationUml extends EnumerationLiteralNotation { | |
78 | ||
79 | /** | |
80 | * The constructor. | |
81 | * | |
82 | * @param enumLiteral the UML element | |
83 | */ | |
84 | public EnumerationLiteralNotationUml(Object enumLiteral) { | |
85 | 0 | super(enumLiteral); |
86 | 0 | } |
87 | ||
88 | @Override | |
89 | public String getParsingHelp() { | |
90 | 0 | return "parsing.help.fig-enumeration-literal"; |
91 | } | |
92 | ||
93 | @Override | |
94 | public void parse(Object modelElement, String text) { | |
95 | try { | |
96 | 0 | parseEnumerationLiteralFig( |
97 | Model.getFacade().getEnumeration(modelElement), | |
98 | modelElement, text); | |
99 | 0 | } catch (ParseException pe) { |
100 | 0 | String msg = "statusmsg.bar.error.parsing.enumeration-literal"; |
101 | 0 | Object[] args = { |
102 | pe.getLocalizedMessage(), | |
103 | Integer.valueOf(pe.getErrorOffset()), | |
104 | }; | |
105 | 0 | ArgoEventPump.fireEvent(new ArgoHelpEvent( |
106 | ArgoEventTypes.HELP_CHANGED, this, | |
107 | Translator.messageFormat(msg, args))); | |
108 | 0 | } |
109 | 0 | } |
110 | ||
111 | /** | |
112 | * Parse a string representing one or more ";" separated | |
113 | * enumeration literals. | |
114 | * | |
115 | * @param enumeration the enumeration that the literal belongs to | |
116 | * @param literal the literal on which the editing will happen | |
117 | * @param text the string to parse | |
118 | * @throws ParseException for invalid input - so that the right | |
119 | * message may be shown to the user | |
120 | */ | |
121 | protected void parseEnumerationLiteralFig( | |
122 | Object enumeration, Object literal, String text) | |
123 | throws ParseException { | |
124 | ||
125 | 0 | if (enumeration == null || literal == null) { |
126 | 0 | return; |
127 | } | |
128 | 0 | Project project = ProjectManager.getManager().getCurrentProject(); |
129 | ||
130 | 0 | ParseException pex = null; |
131 | 0 | int start = 0; |
132 | 0 | int end = NotationUtilityUml.indexOfNextCheckedSemicolon(text, start); |
133 | ||
134 | 0 | if (end == -1) { |
135 | /* No text. We may remove the literal. */ | |
136 | 0 | project.moveToTrash(literal); |
137 | 0 | return; |
138 | } | |
139 | 0 | String s = text.substring(start, end).trim(); |
140 | 0 | if (s.length() == 0) { |
141 | /* No non-white chars in text? remove literal! */ | |
142 | 0 | project.moveToTrash(literal); |
143 | 0 | return; |
144 | } | |
145 | 0 | parseEnumerationLiteral(s, literal); |
146 | ||
147 | 0 | int i = Model.getFacade().getEnumerationLiterals(enumeration) |
148 | .indexOf(literal); | |
149 | // check for more literals (';' separated): | |
150 | 0 | start = end + 1; |
151 | 0 | end = NotationUtilityUml.indexOfNextCheckedSemicolon(text, start); |
152 | 0 | while (end > start && end <= text.length()) { |
153 | 0 | s = text.substring(start, end).trim(); |
154 | 0 | if (s.length() > 0) { |
155 | // yes, there are more: | |
156 | 0 | Object newLiteral = |
157 | Model.getCoreFactory().createEnumerationLiteral(); | |
158 | 0 | if (newLiteral != null) { |
159 | try { | |
160 | 0 | if (i != -1) { |
161 | 0 | Model.getCoreHelper().addLiteral( |
162 | enumeration, ++i, newLiteral); | |
163 | } else { | |
164 | 0 | Model.getCoreHelper().addLiteral( |
165 | enumeration, 0, newLiteral); | |
166 | } | |
167 | 0 | parseEnumerationLiteral(s, newLiteral); |
168 | 0 | } catch (ParseException ex) { |
169 | 0 | if (pex == null) { |
170 | 0 | pex = ex; |
171 | } | |
172 | 0 | } |
173 | } | |
174 | } | |
175 | 0 | start = end + 1; |
176 | 0 | end = NotationUtilityUml.indexOfNextCheckedSemicolon(text, start); |
177 | } | |
178 | 0 | if (pex != null) { |
179 | 0 | throw pex; |
180 | } | |
181 | 0 | } |
182 | ||
183 | protected void parseEnumerationLiteral(String text, Object literal) | |
184 | throws ParseException { | |
185 | 0 | text = text.trim(); |
186 | 0 | if (text.length() == 0) { |
187 | 0 | return; |
188 | } | |
189 | // strip any trailing semi-colons | |
190 | 0 | if (text.charAt(text.length() - 1) == ';') { |
191 | 0 | text = text.substring(0, text.length() - 2); |
192 | } | |
193 | MyTokenizer st; | |
194 | ||
195 | 0 | String name = null; |
196 | 0 | StringBuilder stereotype = null; |
197 | String token; | |
198 | ||
199 | try { | |
200 | 0 | st = new MyTokenizer(text, "<<,\u00AB,\u00BB,>>"); |
201 | 0 | while (st.hasMoreTokens()) { |
202 | 0 | token = st.nextToken(); |
203 | ||
204 | 0 | if ("<<".equals(token) || "\u00AB".equals(token)) { |
205 | 0 | if (stereotype != null) { |
206 | 0 | String msg = |
207 | "parsing.error.model-element-name.twin-stereotypes"; | |
208 | 0 | throw new ParseException(Translator.localize(msg), |
209 | st.getTokenIndex()); | |
210 | } | |
211 | ||
212 | 0 | stereotype = new StringBuilder(); |
213 | while (true) { | |
214 | 0 | token = st.nextToken(); |
215 | 0 | if (">>".equals(token) || "\u00BB".equals(token)) { |
216 | 0 | break; |
217 | } | |
218 | 0 | stereotype.append(token); |
219 | } | |
220 | } else { | |
221 | 0 | if (name != null) { |
222 | 0 | String msg = |
223 | "parsing.error.model-element-name.twin-names"; | |
224 | 0 | throw new ParseException(Translator.localize(msg), |
225 | st.getTokenIndex()); | |
226 | } | |
227 | ||
228 | 0 | name = token; |
229 | } | |
230 | } | |
231 | 0 | } catch (NoSuchElementException nsee) { |
232 | 0 | String msg = |
233 | "parsing.error.model-element-name.unexpected-name-element"; | |
234 | 0 | throw new ParseException(Translator.localize(msg), |
235 | text.length()); | |
236 | 0 | } catch (ParseException pre) { |
237 | 0 | throw pre; |
238 | 0 | } |
239 | ||
240 | 0 | if (name != null) { |
241 | 0 | name = name.trim(); |
242 | } | |
243 | 0 | if (name != null) { |
244 | 0 | Model.getCoreHelper().setName(literal, name); |
245 | } | |
246 | ||
247 | 0 | StereotypeUtility.dealWithStereotypes(literal, stereotype, false); |
248 | ||
249 | 0 | return; |
250 | } | |
251 | ||
252 | private String toString(Object modelElement, boolean useGuillemets) { | |
253 | 0 | String nameStr = ""; |
254 | /* Heuristic algorithm: do not show stereotypes if there is no name. */ | |
255 | 0 | if (Model.getFacade().getName(modelElement) != null) { |
256 | 0 | nameStr = NotationUtilityUml.generateStereotype(modelElement, |
257 | useGuillemets); | |
258 | 0 | if (nameStr.length() > 0) { |
259 | 0 | nameStr += " "; |
260 | } | |
261 | 0 | nameStr += Model.getFacade().getName(modelElement).trim(); |
262 | } | |
263 | 0 | return nameStr; |
264 | } | |
265 | ||
266 | @Override | |
267 | public String toString(Object modelElement, NotationSettings settings) { | |
268 | 0 | return toString(modelElement, settings.isUseGuillemets()); |
269 | } | |
270 | ||
271 | } |