1 package org.andromda.core.simpleuml;
2
3 import java.io.IOException;
4 import java.util.Collection;
5 import java.util.Iterator;
6 import java.util.Vector;
7
8 import org.andromda.core.common.HTMLAnalyzer;
9 import org.andromda.core.common.StringUtilsHelper;
10 import org.andromda.core.uml14.UMLStaticHelper;
11 import org.omg.uml.foundation.core.AssociationEnd;
12 import org.omg.uml.foundation.core.Attribute;
13 import org.omg.uml.foundation.core.Classifier;
14 import org.omg.uml.foundation.core.Operation;
15 import org.omg.uml.foundation.core.Parameter;
16 import org.omg.uml.foundation.datatypes.ParameterDirectionKindEnum;
17
18 /***
19 * This script helper simulates the old-style UML2EJB SimpleOO based
20 * script helper, and is provided mostly for backward compatability
21 * with the UML2EJB code generation scripts - it would be nice to
22 * deprecate it at some point, but at present there is no plan to do so.
23 *
24 * @author <A HREF="http://www.amowers.com">Anthony Mowers</A>
25 */
26 public class SimpleOOHelper extends UMLStaticHelper
27 {
28 private final static String PRIMARY_KEY = "PrimaryKey";
29 private final static String ENTITY_BEAN = "Entity";
30
31 public Object getModel()
32 {
33 return PModel.newInstance(this, this.model);
34 }
35
36 public Collection getModelElements()
37 {
38 Collection elements = new Vector();
39 for (Iterator i = super.getModelElements().iterator();
40 i.hasNext();
41 )
42 {
43 Object o = i.next();
44 if (o instanceof Classifier)
45 {
46 o = PClassifier.newInstance(this, (Classifier) o);
47 }
48 elements.add(o);
49 }
50
51 return elements;
52 }
53
54 public org
55 .andromda
56 .core
57 .uml14
58 .DirectionalAssociationEnd getAssociationData(
59 Object object)
60 {
61 if ((object == null) || !(object instanceof AssociationEnd))
62 {
63 return null;
64 }
65
66 AssociationEnd ae = (AssociationEnd) object;
67
68 return new DirectionalAssociationEnd(this, ae);
69 }
70
71 /***
72 * <p>Formats an HTML String as a collection of paragraphs.
73 * Each paragraph has a getLines() method that returns a collection
74 * of Strings.</p>
75 *
76 * @param string the String to be formatted
77 * @return Collection the collection of paragraphs found.
78 */
79 public Collection formatHTMLStringAsParagraphs(String string)
80 {
81 try
82 {
83 return new HTMLAnalyzer().htmlToParagraphs(string);
84 }
85 catch (IOException e)
86 {
87 e.printStackTrace();
88 return null;
89 }
90 }
91
92 /***
93 * Gets the primaryKeyAttribute attribute of the UMLScriptHelper object
94 *
95 *@param object Description of the Parameter
96 *@return The primaryKeyAttribute value
97 */
98 public Attribute getPrimaryKeyAttribute(Object object)
99 {
100 Collection attributes = getAttributes(object);
101 for (Iterator i = attributes.iterator(); i.hasNext();)
102 {
103 Object attribute = i.next();
104 if (getStereotypeNames(attribute).contains(PRIMARY_KEY))
105 {
106 return (Attribute) attribute;
107 }
108 }
109
110 return null;
111 }
112
113 /***
114 * Returns a string indicating whether the Bean is
115 * a local or remotely accessable bean.
116 *
117 * @param object Bean class
118 * @return String 'local' or 'remote'
119 */
120 public String getEjbRefViewType(Object object)
121 {
122 if (ENTITY_BEAN.equals(getStereotype(object)))
123 {
124 return "local";
125 }
126
127 return "remote";
128 }
129
130 /***
131 * Returns a string representing the name of the
132 * home interface for the Bean.
133 *
134 *@param object bean class
135 *@return string homeInterfaceName
136 */
137 public String getHomeInterfaceName(Object object)
138 {
139 if (getStereotypeNames(object).contains(ENTITY_BEAN))
140 {
141 return getName(object) + "LocalHome";
142 }
143
144 return getName(object) + "Home";
145 }
146
147 /***
148 * Returns a string representing the component name
149 * for the Bean. It does not append the 'local' suffix
150 * any more (deprecated).
151 *
152 * @param object
153 * @return String
154 */
155 public String getComponentInterfaceName(Object object)
156 {
157 return getName(object);
158 }
159
160 /***
161 * Returns a list of attributes for a class. The list is
162 * useful for generating method signatures for constructors and/or
163 * generating code for calling such a constructor
164 *
165 * @param object class object
166 * @param withTypeNames should attribute types appear in the list
167 * @param includePK should primary key be included in the list
168 * @return String representation of attribute list
169 */
170 public String getAttributesAsList(
171 Object object,
172 boolean withTypeNames,
173 boolean includePK)
174 {
175 StringBuffer sb = new StringBuffer();
176 String separator = "";
177 sb.append("(");
178
179 for (Iterator it = getAttributes(object).iterator(); it.hasNext();)
180 {
181 Attribute a = (Attribute) it.next();
182
183
184
185 if (includePK || !getStereotypeNames(a).contains(PRIMARY_KEY))
186 {
187 sb.append(separator);
188 if (withTypeNames)
189 {
190 String typeName = findFullyQualifiedName(a.getType());
191 sb.append(typeName);
192 sb.append(" ");
193 sb.append(a.getName());
194 }
195 else
196 {
197 sb.append("get");
198 sb.append(
199 StringUtilsHelper.upperCaseFirstLetter(
200 a.getName()));
201 sb.append("()");
202 }
203 separator = ", ";
204 }
205 }
206 sb.append(")");
207 return sb.toString();
208 }
209
210 /***
211 * <p>Builds a call to the operation with a list of parameters.
212 * that can easily be used from the Velocity script.</p>
213 *
214 * <p>This is good to generate business delegates.
215 * See feature request #638931.</p>
216 *
217 * @param o the operation
218 * @return String the complete call to the operation
219 */
220 public String getOperationCall(Object object)
221 {
222 if ((object == null) || !(object instanceof Operation))
223 {
224 return null;
225 }
226 Operation o = (Operation) object;
227
228 StringBuffer sb = new StringBuffer();
229 sb.append(o.getName());
230 sb.append("(");
231 sb.append(getOperationParameterNames(o));
232 sb.append(")");
233
234 return sb.toString();
235 }
236
237 /***
238 * Builds a comma-separated list of parameter names of an operation.
239 *
240 * @param o the operation
241 * @return String the list of parameter names
242 */
243 public String getOperationParameterNames(Operation o)
244 {
245 StringBuffer sb = new StringBuffer();
246
247 Iterator it = o.getParameter().iterator();
248
249 boolean commaNeeded = false;
250 while (it.hasNext())
251 {
252 Parameter p = (Parameter) it.next();
253
254 if (!ParameterDirectionKindEnum.PDK_RETURN.equals(p.getKind()))
255 {
256 if (commaNeeded)
257 {
258 sb.append(", ");
259 }
260 sb.append(p.getName());
261 commaNeeded = true;
262 }
263 }
264 return sb.toString();
265 }
266
267 /***
268 * returns a string representation for the Java signature for
269 * a given operation. Note: The return type is not included (any more)!
270 *
271 * @param model element representing the operation
272 * @return String representation of the operation signature
273 */
274 public String getOperationSignature(Object object)
275 {
276 if ((object == null) || !(object instanceof Operation))
277 {
278 return null;
279 }
280
281 Operation o = (Operation) object;
282 Iterator it = o.getParameter().iterator();
283 if (!it.hasNext())
284 {
285 return o.getName() + "()";
286 }
287
288 StringBuffer sb = new StringBuffer();
289 sb.append(o.getName());
290 sb.append("(");
291 sb.append(getOperationTypedParameterList(o));
292 sb.append(")");
293
294 return sb.toString();
295 }
296
297
298 /***
299 * Builds a comma-separated parameter list
300 * (type and name of each parameter) of an operation.
301 *
302 * @param o the operation
303 * @return String the parameter list
304 */
305 public String getOperationTypedParameterList(Operation o)
306 {
307 StringBuffer sb = new StringBuffer();
308 Iterator it = o.getParameter().iterator();
309
310 boolean commaNeeded = false;
311 while (it.hasNext())
312 {
313 Parameter p = (Parameter) it.next();
314
315 if (!ParameterDirectionKindEnum.PDK_RETURN.equals(p.getKind()))
316 {
317 String type;
318 if (p.getType() == null)
319 {
320 type = "int";
321 }
322 else
323 {
324 type = getFullyQualifiedName(p.getType());
325 }
326
327 if (commaNeeded)
328 {
329 sb.append(", ");
330 }
331 sb.append(type);
332 sb.append(" ");
333 sb.append(p.getName());
334 commaNeeded = true;
335 }
336 }
337 return sb.toString();
338 }
339
340 /***
341 * Provided only for backward compatability with old velocity scripts.
342 * In truth all model elements can be assigned more than one stereotype.
343 *
344 * @param object
345 * @return String
346 */
347 public String getStereotype(Object object)
348 {
349 Iterator i = getStereotypeNames(object).iterator();
350
351 if (i.hasNext())
352 {
353 String stereotype = (String) i.next();
354
355 return stereotype;
356 }
357
358 return "";
359
360 }
361
362 /***
363 * Returns the fully qualified name of the given
364 * model element. The fully qualified name includes
365 * complete package qualified name of the model element.
366 *
367 * @param object model element
368 * @return String fully qualified name
369 */
370 public String findFullyQualifiedName(Object object)
371 {
372 return getFullyQualifiedName(object);
373 }
374
375 /***
376 * <p>Returns the JDBC type for an attribute. It gets the type
377 * from the tag <code>andromda.persistence.JDBCType</code> for this.
378 * </p>
379 *
380 * @param attribute the attribute
381 * @return String the string to be used with JDBC
382 */
383 public String findAttributeJDBCType(Attribute attribute)
384 {
385 if (attribute == null)
386 return null;
387
388 String value = findTagValue(attribute, "andromda.persistence.JDBCType", true);
389
390 if (null == value)
391 {
392 Object type = attribute.getType();
393 value = findFullyQualifiedName(type);
394 if (typeMappings != null)
395 {
396 value = typeMappings.getJDBCType(value);
397 }
398 }
399
400 return value;
401 }
402
403 /***
404 * <p>Returns the length for the SQL type of an attribute. It
405 * gets the length from the tag
406 * <code>andromda.persistence.SQLFieldLength</code>. This might return "50"
407 * for a VARCHAR field or "12,2" for a DECIMAL field.</p>
408 *
409 * @param attribute the attribute
410 * @return String the length of the underlying SQL field
411 */
412 public String findAttributeSQLFieldLength(Attribute attribute)
413 {
414 String value = findTagValue(attribute, "andromda.persistence.SQLFieldLength", true);
415 return value;
416 }
417
418 /***
419 * <p>Returns the SQL type for an attribute. Normally it gets the
420 * type from the tag <code>andromda.persistence.SQLType</code>. If this tag
421 * doesn't exist, it uses {@link #findAttributeSQLFieldLength(Attribute)
422 * findAttributeSQLFieldLength()} and combines it's result with the standard
423 * SQL type for the attributes type from the type mapping configuration
424 * file.</p>
425 *
426 * @param attribute the attribute
427 * @return String the string to be used as SQL type
428 */
429 public String findAttributeSQLType(Attribute attribute)
430 {
431 String value = findTagValue(attribute, "andromda.persistence.SQLType", true);
432
433 if (null == value)
434 {
435 Object type = attribute.getType();
436 String typeName = findFullyQualifiedName(type);
437 value = this.typeMappings.getSQLType(typeName, findAttributeSQLFieldLength(attribute));
438 }
439 return value;
440 }
441
442 /***
443 * Returns the name of the package that contains the
444 * given model element.
445 *
446 *@param object model element
447 *@return fully qualified name of the package
448 */
449 public String findPackageName(Object object)
450 {
451 return getPackageName(object);
452 }
453
454 /***
455 * Provided only for backward compatability with
456 * UML2EJB code generation scripts. It does nothing
457 * in this implementation except return the object that is passed
458 * into it.
459 *
460 * @param object
461 * @return Object
462 */
463 public Object findClassById(Object object)
464 {
465 if (object instanceof Classifier)
466 {
467 return object;
468 }
469
470 return null;
471 }
472
473 /***
474 * Provided only for backward compatability with UML2EJB
475 * code generation scripts. It does not except
476 * return the object that it was passed in.
477 *
478 * @param object a model element
479 * @return the model element that was passed
480 */
481 public Object convertToType(Object object)
482 {
483 return object;
484 }
485
486 }