Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
ClassifierRoleNotationUml |
|
| 7.333333333333333;7.333 |
1 | /* $Id: ClassifierRoleNotationUml.java 18852 2010-11-20 19:27:11Z mvw $ | |
2 | ***************************************************************************** | |
3 | * Copyright (c) 2009-2010 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 | * Michiel van der Wulp | |
11 | ***************************************************************************** | |
12 | * | |
13 | * Some portions of this file was previously release using the BSD License: | |
14 | */ | |
15 | ||
16 | // Copyright (c) 2006-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.ArrayList; | |
43 | import java.util.Collection; | |
44 | import java.util.Iterator; | |
45 | import java.util.List; | |
46 | import java.util.NoSuchElementException; | |
47 | ||
48 | import org.argouml.application.events.ArgoEventPump; | |
49 | import org.argouml.application.events.ArgoEventTypes; | |
50 | import org.argouml.application.events.ArgoHelpEvent; | |
51 | import org.argouml.i18n.Translator; | |
52 | import org.argouml.model.Model; | |
53 | import org.argouml.notation.NotationSettings; | |
54 | import org.argouml.notation.providers.ClassifierRoleNotation; | |
55 | import org.argouml.util.MyTokenizer; | |
56 | ||
57 | /** | |
58 | * The UML notation for a ClassifierRole. <p> | |
59 | * | |
60 | * The following is supported: <p> | |
61 | * | |
62 | * <pre> | |
63 | * baselist := [base] [, base]* | |
64 | * classifierRole := [name] [/ role] [: baselist] | |
65 | * </pre> | |
66 | * | |
67 | * The <code>role </code> and <code>baselist</code> can be given in | |
68 | * any order.<p> | |
69 | * | |
70 | * The <code>name</code> is the Instance name, not used for a ClassifierRole.<p> | |
71 | * | |
72 | * This syntax is compatible with the UML 1.3 and 1.4 specification. | |
73 | * | |
74 | * @author Michiel van der Wulp | |
75 | */ | |
76 | public class ClassifierRoleNotationUml extends ClassifierRoleNotation { | |
77 | ||
78 | ||
79 | /** | |
80 | * The Constructor. | |
81 | * | |
82 | * @param classifierRole the UML ClassifierRole | |
83 | */ | |
84 | public ClassifierRoleNotationUml(Object classifierRole) { | |
85 | 0 | super(classifierRole); |
86 | 0 | } |
87 | ||
88 | /* | |
89 | * @see org.argouml.notation.providers.NotationProvider#getParsingHelp() | |
90 | */ | |
91 | public String getParsingHelp() { | |
92 | 0 | return "parsing.help.fig-classifierrole"; |
93 | } | |
94 | ||
95 | /* | |
96 | * @see org.argouml.notation.providers.NotationProvider#parse(java.lang.Object, java.lang.String) | |
97 | */ | |
98 | public void parse(Object modelElement, String text) { | |
99 | try { | |
100 | 0 | parseClassifierRole(modelElement, text); |
101 | 0 | } catch (ParseException pe) { |
102 | 0 | String msg = "statusmsg.bar.error.parsing.classifierrole"; |
103 | 0 | Object[] args = {pe.getLocalizedMessage(), |
104 | Integer.valueOf(pe.getErrorOffset()), }; | |
105 | 0 | ArgoEventPump.fireEvent(new ArgoHelpEvent( |
106 | ArgoEventTypes.HELP_CHANGED, this, | |
107 | Translator.messageFormat(msg, args))); | |
108 | 0 | } |
109 | 0 | } |
110 | ||
111 | /** | |
112 | * Parses a ClassifierRole represented by the following line of the format: | |
113 | * | |
114 | * <pre> | |
115 | * baselist := [base] [, base]* | |
116 | * classifierRole := [name] [/ role] [: baselist] | |
117 | * </pre> | |
118 | * | |
119 | * <code>role </code> and <code>baselist</code> can be given in | |
120 | * any order.<p> | |
121 | * | |
122 | * This syntax is compatible with the UML 1.3 specification. | |
123 | * | |
124 | * (formerly: "name: base" ) | |
125 | * | |
126 | * @param cls the classifier role to apply any changes to | |
127 | * @param s the String to parse | |
128 | * @return the classifier role with the applied changes | |
129 | * @throws ParseException when it detects an error in the attribute string. | |
130 | * See also ParseError.getErrorOffset(). | |
131 | */ | |
132 | protected Object parseClassifierRole(Object cls, String s) | |
133 | throws ParseException { | |
134 | ||
135 | 0 | String name = null; |
136 | String token; | |
137 | 0 | String role = null; |
138 | 0 | String base = null; |
139 | 0 | List<String> bases = null; |
140 | 0 | boolean hasColon = false; |
141 | 0 | boolean hasSlash = false; |
142 | ||
143 | try { | |
144 | 0 | MyTokenizer st = new MyTokenizer(s, " ,\t,/,:,\\,"); |
145 | ||
146 | 0 | while (st.hasMoreTokens()) { |
147 | 0 | token = st.nextToken(); |
148 | 0 | if (" ".equals(token) || "\t".equals(token)) { |
149 | /* Do nothing. */ | |
150 | 0 | } else if ("/".equals(token)) { |
151 | 0 | hasSlash = true; |
152 | 0 | hasColon = false; |
153 | ||
154 | 0 | if (base != null) { |
155 | 0 | if (bases == null) { |
156 | 0 | bases = new ArrayList<String>(); |
157 | } | |
158 | 0 | bases.add(base); |
159 | } | |
160 | 0 | base = null; |
161 | 0 | } else if (":".equals(token)) { |
162 | 0 | hasColon = true; |
163 | 0 | hasSlash = false; |
164 | ||
165 | 0 | if (bases == null) { |
166 | 0 | bases = new ArrayList<String>(); |
167 | } | |
168 | 0 | if (base != null) { |
169 | 0 | bases.add(base); |
170 | } | |
171 | 0 | base = null; |
172 | 0 | } else if (",".equals(token)) { |
173 | 0 | if (base != null) { |
174 | 0 | if (bases == null) { |
175 | 0 | bases = new ArrayList<String>(); |
176 | } | |
177 | 0 | bases.add(base); |
178 | } | |
179 | 0 | base = null; |
180 | 0 | } else if (hasColon) { |
181 | 0 | if (base != null) { |
182 | 0 | String msg = "parsing.error.classifier.extra-test"; |
183 | 0 | throw new ParseException( |
184 | Translator.localize(msg), | |
185 | st.getTokenIndex()); | |
186 | } | |
187 | ||
188 | 0 | base = token; |
189 | 0 | } else if (hasSlash) { |
190 | 0 | if (role != null) { |
191 | 0 | String msg = "parsing.error.classifier.extra-test"; |
192 | 0 | throw new ParseException( |
193 | Translator.localize(msg), | |
194 | st.getTokenIndex()); | |
195 | } | |
196 | ||
197 | 0 | role = token; |
198 | } else { | |
199 | 0 | if (name != null) { |
200 | 0 | String msg = "parsing.error.classifier.extra-test"; |
201 | 0 | throw new ParseException( |
202 | Translator.localize(msg), | |
203 | st.getTokenIndex()); | |
204 | } | |
205 | ||
206 | 0 | name = token; |
207 | } | |
208 | } | |
209 | 0 | } catch (NoSuchElementException nsee) { |
210 | 0 | String msg = "parsing.error.classifier.unexpected-end-attribute"; |
211 | 0 | throw new ParseException(Translator.localize(msg), s.length()); |
212 | 0 | } |
213 | ||
214 | 0 | if (base != null) { |
215 | 0 | if (bases == null) { |
216 | 0 | bases = new ArrayList<String>(); |
217 | } | |
218 | 0 | bases.add(base); |
219 | } | |
220 | ||
221 | // TODO: What to do about object name??? | |
222 | // if (name != null) | |
223 | // ; | |
224 | ||
225 | 0 | if (role != null) { |
226 | 0 | Model.getCoreHelper().setName(cls, role.trim()); |
227 | } | |
228 | ||
229 | 0 | if (bases != null) { |
230 | // Remove bases that aren't there anymore | |
231 | ||
232 | // copy - can't iterate modify live collection while iterating it | |
233 | 0 | Collection b = new ArrayList(Model.getFacade().getBases(cls)); |
234 | 0 | Iterator it = b.iterator(); |
235 | Object c; | |
236 | 0 | Object ns = Model.getFacade().getNamespace(cls); |
237 | 0 | if (ns != null && Model.getFacade().getNamespace(ns) != null) { |
238 | 0 | ns = Model.getFacade().getNamespace(ns); |
239 | } else { | |
240 | 0 | ns = Model.getFacade().getRoot(cls); |
241 | } | |
242 | ||
243 | 0 | while (it.hasNext()) { |
244 | 0 | c = it.next(); |
245 | 0 | if (!bases.contains(Model.getFacade().getName(c))) { |
246 | 0 | Model.getCollaborationsHelper().removeBase(cls, c); |
247 | } | |
248 | } | |
249 | ||
250 | 0 | it = bases.iterator(); |
251 | addBases: | |
252 | 0 | while (it.hasNext()) { |
253 | 0 | String d = ((String) it.next()).trim(); |
254 | ||
255 | 0 | Iterator it2 = b.iterator(); |
256 | 0 | while (it2.hasNext()) { |
257 | 0 | c = it2.next(); |
258 | 0 | if (d.equals(Model.getFacade().getName(c))) { |
259 | 0 | continue addBases; |
260 | } | |
261 | } | |
262 | 0 | c = NotationUtilityUml.getType(d, ns); |
263 | 0 | if (Model.getFacade().isACollaboration( |
264 | Model.getFacade().getNamespace(c))) { | |
265 | 0 | Model.getCoreHelper().setNamespace(c, ns); |
266 | } | |
267 | 0 | Model.getCollaborationsHelper().addBase(cls, c); |
268 | 0 | } |
269 | } | |
270 | ||
271 | 0 | return cls; |
272 | } | |
273 | ||
274 | private String toString(Object modelElement) { | |
275 | 0 | String nameString = Model.getFacade().getName(modelElement); |
276 | 0 | if (nameString == null) { |
277 | 0 | nameString = ""; |
278 | } | |
279 | 0 | nameString = nameString.trim(); |
280 | // Loop through all base classes, building a comma separated list | |
281 | 0 | StringBuilder baseString = NotationUtilityUml.formatNameList( |
282 | Model.getFacade().getBases(modelElement)); | |
283 | 0 | baseString = new StringBuilder(baseString.toString().trim()); |
284 | // Build the final string | |
285 | 0 | if (nameString.length() != 0) { |
286 | 0 | nameString = "/" + nameString; |
287 | } | |
288 | 0 | if (baseString.length() != 0) { |
289 | 0 | baseString = baseString.insert(0, ":"); |
290 | } | |
291 | 0 | return nameString + baseString.toString(); |
292 | } | |
293 | ||
294 | @Override | |
295 | public String toString(Object modelElement, NotationSettings settings) { | |
296 | 0 | return toString(modelElement); |
297 | } | |
298 | ||
299 | } |