Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
CrUML |
|
| 2.076923076923077;2.077 |
1 | /* $Id: CrUML.java 17849 2010-01-12 19:50:34Z 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 | * tfmorris | |
11 | ***************************************************************************** | |
12 | * | |
13 | * Some portions of this file was previously release using the BSD License: | |
14 | */ | |
15 | ||
16 | // Copyright (c) 1996-2006 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.uml.cognitive.critics; | |
40 | ||
41 | import org.apache.log4j.Logger; | |
42 | import org.argouml.cognitive.Critic; | |
43 | import org.argouml.cognitive.Designer; | |
44 | import org.argouml.cognitive.ListSet; | |
45 | import org.argouml.cognitive.ToDoItem; | |
46 | import org.argouml.cognitive.Translator; | |
47 | import org.argouml.model.Model; | |
48 | import org.argouml.ocl.CriticOclEvaluator; | |
49 | import org.argouml.uml.cognitive.UMLToDoItem; | |
50 | import org.tigris.gef.ocl.ExpansionException; | |
51 | ||
52 | /** | |
53 | * "Abstract" Critic subclass that captures commonalities among all | |
54 | * critics in the UML domain. This class also defines and registers | |
55 | * the categories of design decisions that the critics can | |
56 | * address. IT also deals with particular UMLToDoItems. | |
57 | * | |
58 | * @see org.argouml.cognitive.Designer | |
59 | * @see org.argouml.cognitive.DecisionModel | |
60 | * | |
61 | * @author jrobbins | |
62 | */ | |
63 | public class CrUML extends Critic { | |
64 | /** | |
65 | * Logger. | |
66 | */ | |
67 | 900 | private static final Logger LOG = Logger.getLogger(CrUML.class); |
68 | ||
69 | /** | |
70 | * By default looks for the localized strings at the <code>critics</code> | |
71 | * Resource, but critics defined elsewhere (out of ArgoUML main tree) | |
72 | * may override this parameter | |
73 | */ | |
74 | 93600 | private String localizationPrefix = "critics"; |
75 | ||
76 | /** | |
77 | * The constructor for this class. | |
78 | */ | |
79 | 93600 | public CrUML() { |
80 | 93600 | } |
81 | ||
82 | /** | |
83 | * The constructor for this class overriding the default | |
84 | * localization resource. | |
85 | * | |
86 | * @param nonDefaultLocalizationPrefix the overriding localization resource | |
87 | */ | |
88 | 0 | public CrUML(String nonDefaultLocalizationPrefix) { |
89 | 0 | if (nonDefaultLocalizationPrefix != null) { |
90 | 0 | this.localizationPrefix = nonDefaultLocalizationPrefix; |
91 | 0 | setupHeadAndDesc(); |
92 | } | |
93 | 0 | } |
94 | ||
95 | /** | |
96 | * Set the resources for this critic based on the class name. | |
97 | * | |
98 | * @param key is the class name. | |
99 | */ | |
100 | public void setResource(String key) { | |
101 | 77400 | super.setHeadline(getLocalizedString(key, "-head")); |
102 | 77400 | super.setDescription(getLocalizedString(key, "-desc")); |
103 | 77400 | } |
104 | ||
105 | /** | |
106 | * Returns a localized string for the current critic class. | |
107 | * | |
108 | * @param suffix the suffix of the key | |
109 | * @return the localized string | |
110 | */ | |
111 | protected String getLocalizedString(String suffix) { | |
112 | 47491 | return getLocalizedString(getClassSimpleName(), suffix); |
113 | } | |
114 | ||
115 | /** | |
116 | * Returns a localized string for the given key and suffix. | |
117 | * | |
118 | * @param key the main key | |
119 | * @param suffix the suffix of the key | |
120 | * @return the localized string | |
121 | */ | |
122 | protected String getLocalizedString(String key, String suffix) { | |
123 | 202291 | return Translator.localize(localizationPrefix + "." + key + suffix); |
124 | } | |
125 | ||
126 | /** | |
127 | * Loads the localized wizard's instruction. | |
128 | * | |
129 | * @return the instructions | |
130 | */ | |
131 | protected String getInstructions() { | |
132 | 47491 | return getLocalizedString("-ins"); |
133 | } | |
134 | ||
135 | /** | |
136 | * Loads the localized wizard's default suggestion. | |
137 | * | |
138 | * @return the default suggestion | |
139 | */ | |
140 | protected String getDefaultSuggestion() { | |
141 | 0 | return getLocalizedString("-sug"); |
142 | } | |
143 | ||
144 | /** | |
145 | * @see org.argouml.cognitive.Critic#setHeadline(java.lang.String) | |
146 | * | |
147 | * Set up the locale specific text for the critic headline | |
148 | * (the one liner that appears in the to-do pane) | |
149 | * and the critic description (the detailed explanation that | |
150 | * appears in the to-do tab of the details pane). | |
151 | * | |
152 | * MVW: Maybe we can make it part of the constructor CrUML()? | |
153 | * | |
154 | * FIXME: why override if nobody uses? | |
155 | */ | |
156 | //@Override | |
157 | //public final void setHeadline(String s) { | |
158 | //setupHeadAndDesc(); | |
159 | //} | |
160 | ||
161 | /** | |
162 | * Set up the locale specific text for the critic headline | |
163 | * (the one liner that appears in the to-do pane) | |
164 | * and the critic description (the detailed explanation that | |
165 | * appears in the to-do tab of the details pane). | |
166 | */ | |
167 | public final void setupHeadAndDesc() { | |
168 | 77400 | setResource(getClassSimpleName()); |
169 | 77400 | } |
170 | ||
171 | /* | |
172 | * @see org.argouml.cognitive.critics.Critic#predicate( java.lang.Object, | |
173 | * org.argouml.cognitive.Designer) | |
174 | */ | |
175 | @Override | |
176 | public boolean predicate(Object dm, Designer dsgr) { | |
177 | 387128 | if (Model.getFacade().isAModelElement(dm) |
178 | && Model.getUmlFactory().isRemoved(dm)) { | |
179 | 1 | return NO_PROBLEM; |
180 | } else { | |
181 | 387127 | return predicate2(dm, dsgr); |
182 | } | |
183 | } | |
184 | ||
185 | /** | |
186 | * This is the decision routine for the critic. | |
187 | * | |
188 | * @param dm is the UML entity that is being checked. | |
189 | * @param dsgr is for future development and can be ignored. | |
190 | * | |
191 | * @return boolean problem found | |
192 | */ | |
193 | public boolean predicate2(Object dm, Designer dsgr) { | |
194 | 0 | return super.predicate(dm, dsgr); |
195 | } | |
196 | ||
197 | //////////////////////////////////////////////////////////////// | |
198 | // display related methods | |
199 | private static final String OCL_START = "<ocl>"; | |
200 | private static final String OCL_END = "</ocl>"; | |
201 | ||
202 | /** | |
203 | * Expand text with ocl brackets in it. | |
204 | * No recursive expansion. | |
205 | * | |
206 | * @return the expanded text | |
207 | * @param res is the text to expand. | |
208 | * @param offs is the elements to replace | |
209 | */ | |
210 | public String expand(String res, ListSet offs) { | |
211 | ||
212 | 94662 | if (offs.size() == 0) { |
213 | 0 | return res; |
214 | } | |
215 | ||
216 | 94662 | Object off1 = offs.get(0); |
217 | ||
218 | 94662 | StringBuffer beginning = new StringBuffer(""); |
219 | 94662 | int matchPos = res.indexOf(OCL_START); |
220 | ||
221 | // replace all occurances of OFFENDER with the name of the | |
222 | // first offender | |
223 | 188576 | while (matchPos != -1) { |
224 | 93915 | int endExpr = res.indexOf(OCL_END, matchPos + 1); |
225 | // check if there is no OCL_END; if so, the critic expression | |
226 | // is not correct and can not be expanded | |
227 | 93915 | if (endExpr == -1) { |
228 | 0 | break; |
229 | } | |
230 | 93915 | if (matchPos > 0) { |
231 | 93915 | beginning.append(res.substring(0, matchPos)); |
232 | } | |
233 | 93915 | String expr = res.substring(matchPos + OCL_START.length(), endExpr); |
234 | 93915 | String evalStr = null; |
235 | try { | |
236 | 93915 | evalStr = |
237 | CriticOclEvaluator.getInstance().evalToString(off1, expr); | |
238 | 0 | } catch (ExpansionException e) { |
239 | // Really ought to have a CriticException to throw here. | |
240 | 0 | LOG.error("Failed to evaluate critic expression", e); |
241 | 93914 | } |
242 | 93914 | if (expr.endsWith("") && evalStr.equals("")) { |
243 | 0 | evalStr = Translator.localize("misc.name.anon"); |
244 | } | |
245 | 93914 | beginning.append(evalStr); |
246 | 93914 | res = res.substring(endExpr + OCL_END.length()); |
247 | 93914 | matchPos = res.indexOf(OCL_START); |
248 | 93914 | } |
249 | 94661 | if (beginning.length() == 0) { |
250 | // return original string if no replacements made | |
251 | 747 | return res; |
252 | } else { | |
253 | 93914 | return beginning.append(res).toString(); |
254 | } | |
255 | } | |
256 | ||
257 | /* | |
258 | * @see org.argouml.cognitive.critics.Critic#toDoItem(Object, Designer) | |
259 | */ | |
260 | @Override | |
261 | public ToDoItem toDoItem(Object dm, Designer dsgr) { | |
262 | 94664 | return new UMLToDoItem(this, dm, dsgr); |
263 | } | |
264 | ||
265 | /** | |
266 | * Get the name of the current class. | |
267 | * | |
268 | * @return the name of the current class without any leading packages | |
269 | */ | |
270 | private final String getClassSimpleName() { | |
271 | // TODO: This method can be replaced by getClass().getSimpleName() | |
272 | // when Argo drops support for Java versions < 1.5 | |
273 | 124891 | String className = getClass().getName(); |
274 | 124891 | return className.substring(className.lastIndexOf('.') + 1); |
275 | } | |
276 | ||
277 | /** | |
278 | * The UID. | |
279 | */ | |
280 | private static final long serialVersionUID = 1785043010468681602L; | |
281 | } |