001: package org.andromda.cartridges.bpm4struts.metafacades;
002:
003: import java.util.ArrayList;
004: import java.util.Collection;
005: import java.util.Collections;
006: import java.util.Iterator;
007: import java.util.LinkedHashMap;
008: import java.util.LinkedHashSet;
009: import java.util.List;
010: import java.util.Map;
011: import java.util.TreeMap;
012:
013: import javax.swing.tree.DefaultMutableTreeNode;
014: import javax.swing.tree.TreeNode;
015:
016: import org.andromda.cartridges.bpm4struts.Bpm4StrutsGlobals;
017: import org.andromda.cartridges.bpm4struts.Bpm4StrutsProfile;
018: import org.andromda.cartridges.bpm4struts.Bpm4StrutsUtils;
019: import org.andromda.metafacades.uml.ActivityGraphFacade;
020: import org.andromda.metafacades.uml.FrontEndActivityGraph;
021: import org.andromda.metafacades.uml.Role;
022: import org.andromda.utils.StringUtilsHelper;
023: import org.apache.commons.lang.StringUtils;
024:
025: /**
026: * MetafacadeLogic implementation.
027: *
028: * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsUseCase
029: */
030: public class StrutsUseCaseLogicImpl extends StrutsUseCaseLogic {
031: public StrutsUseCaseLogicImpl(java.lang.Object metaObject,
032: java.lang.String context) {
033: super (metaObject, context);
034: }
035:
036: protected String handleGetTitleKey() {
037: return StringUtilsHelper
038: .toResourceMessageKey(normalizeMessages() ? getTitleValue()
039: : getName())
040: + ".title";
041: }
042:
043: protected String handleGetTitleValue() {
044: return StringUtilsHelper.toPhrase(getName());
045: }
046:
047: protected String handleGetOnlineHelpKey() {
048: return StringUtilsHelper.toResourceMessageKey(getName())
049: + ".online.help";
050: }
051:
052: protected String handleGetOnlineHelpValue() {
053: final String crlf = "<br/>";
054: final StringBuffer buffer = new StringBuffer();
055:
056: final String value = StringUtilsHelper
057: .toResourceMessage(getDocumentation("", 64, false));
058: buffer
059: .append((value == null) ? "No use-case documentation has been specified"
060: : value);
061: buffer.append(crlf);
062:
063: return StringUtilsHelper.toResourceMessage(buffer.toString());
064: }
065:
066: protected String handleGetActionPath() {
067: String actionPath = null;
068:
069: final StrutsActivityGraph graph = (StrutsActivityGraph) getActivityGraph();
070: if (graph != null) {
071: final StrutsAction action = graph.getFirstAction();
072: if (action != null) {
073: actionPath = action.getActionPath();
074: }
075: }
076: return actionPath;
077: }
078:
079: protected String handleGetActionPathRoot() {
080: String actionPathRoot = null;
081:
082: final StrutsActivityGraph graph = (StrutsActivityGraph) getActivityGraph();
083: if (graph != null) {
084: final StrutsAction action = graph.getFirstAction();
085: if (action != null) {
086: actionPathRoot = action.getActionPathRoot();
087: }
088: }
089: return actionPathRoot;
090: }
091:
092: /**
093: * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsUseCase#isCyclic()
094: */
095: protected boolean handleIsCyclic() {
096: boolean selfTargetting = false;
097: final ActivityGraphFacade graph = getActivityGraph();
098: if (graph != null) {
099: final Collection finalStates = graph.getFinalStates();
100: for (final Iterator finalStateIterator = finalStates
101: .iterator(); finalStateIterator.hasNext()
102: && !selfTargetting;) {
103: final StrutsFinalState finalState = (StrutsFinalState) finalStateIterator
104: .next();
105: if (this .equals(finalState.getTargetUseCase())) {
106: selfTargetting = true;
107: }
108: }
109: }
110: return selfTargetting;
111: }
112:
113: protected String handleGetActionRoles() {
114: final Collection users = this .getRoles();
115: final StringBuffer rolesBuffer = new StringBuffer();
116: boolean first = true;
117: for (final Iterator userIterator = users.iterator(); userIterator
118: .hasNext();) {
119: if (first) {
120: first = false;
121: } else {
122: rolesBuffer.append(',');
123: }
124: final Role role = (Role) userIterator.next();
125: rolesBuffer.append(role.getName());
126: }
127: return rolesBuffer.toString();
128: }
129:
130: public Collection getOperations() {
131: return Collections.EMPTY_LIST;
132: }
133:
134: protected List handleGetPages() {
135: return this .getViews();
136: }
137:
138: protected List handleGetAllPages() {
139: final List pagesList = new ArrayList();
140: final Collection allActionStates = getModel()
141: .getAllActionStates();
142:
143: for (final Iterator actionStateIterator = allActionStates
144: .iterator(); actionStateIterator.hasNext();) {
145: final Object actionState = actionStateIterator.next();
146: if (actionState instanceof StrutsJsp)
147: pagesList.add(actionState);
148: }
149: return pagesList;
150: }
151:
152: protected List handleGetFormFields() {
153: final List formFields = new ArrayList(); // parameter names are supposed to be unique
154:
155: final Collection pages = getPages();
156: for (final Iterator pageIterator = pages.iterator(); pageIterator
157: .hasNext();) {
158: final StrutsJsp jsp = (StrutsJsp) pageIterator.next();
159: final Collection variables = jsp.getPageVariables();
160: for (final Iterator variableIterator = variables.iterator(); variableIterator
161: .hasNext();) {
162: formFields.add(variableIterator.next());
163: }
164: final Collection parameters = jsp.getAllActionParameters();
165: for (final Iterator parameterIterator = parameters
166: .iterator(); parameterIterator.hasNext();) {
167: formFields.add(parameterIterator.next());
168: }
169: }
170: return formFields;
171: }
172:
173: protected boolean handleIsValidationRequired() {
174: final Collection allPages = this .getAllPages();
175: for (final Iterator iterator = allPages.iterator(); iterator
176: .hasNext();) {
177: final StrutsJsp jsp = (StrutsJsp) iterator.next();
178: if (jsp.isValidationRequired()) {
179: return true;
180: }
181: }
182: return false;
183: }
184:
185: protected boolean handleIsApplicationValidationRequired() {
186: final Collection useCases = this .getAllUseCases();
187: for (final Iterator iterator = useCases.iterator(); iterator
188: .hasNext();) {
189: final StrutsUseCase useCase = (StrutsUseCase) iterator
190: .next();
191: if (useCase.isValidationRequired()) {
192: return true;
193: }
194: }
195: return false;
196: }
197:
198: /**
199: * Overriden because StrutsAction does not extend FrontEndAction.
200: *
201: * @see org.andromda.metafacades.uml.FrontEndUseCase#getActions()
202: */
203: public List getActions() {
204: final Collection actions = new LinkedHashSet();
205:
206: final Collection pages = getPages();
207: for (final Iterator pageIterator = pages.iterator(); pageIterator
208: .hasNext();) {
209: final StrutsJsp jsp = (StrutsJsp) pageIterator.next();
210: actions.addAll(jsp.getActions());
211: }
212:
213: final StrutsActivityGraph graph = (StrutsActivityGraph) getActivityGraph();
214: if (graph != null) {
215: final StrutsAction action = graph.getFirstAction();
216: if (action != null)
217: actions.add(action);
218: }
219:
220: return new ArrayList(actions);
221: }
222:
223: protected List handleGetPageVariables() {
224: return this .getViewVariables();
225: }
226:
227: protected boolean handleIsApplicationUseCase() {
228: return this .isEntryUseCase();
229: }
230:
231: protected String handleGetCssFileName() {
232: return this .getPackagePath() + '/'
233: + Bpm4StrutsUtils.toWebFileName(this .getName())
234: + ".css";
235: }
236:
237: protected TreeNode handleGetApplicationHierarchyRoot() {
238: final UseCaseNode root = new UseCaseNode(this );
239: this .createHierarchy(root);
240: return root;
241: }
242:
243: protected TreeNode handleGetHierarchyRoot() {
244: UseCaseNode hierarchy = null;
245:
246: final Collection allUseCases = this .getAllUseCases();
247: for (final Iterator useCaseIterator = allUseCases.iterator(); useCaseIterator
248: .hasNext();) {
249: final StrutsUseCase useCase = (StrutsUseCase) useCaseIterator
250: .next();
251: if (useCase.isApplicationUseCase()) {
252: final UseCaseNode root = (UseCaseNode) useCase
253: .getApplicationHierarchyRoot();
254: hierarchy = this .findNode(root, this );
255: }
256: }
257: return hierarchy;
258: }
259:
260: /**
261: * Recursively creates a hierarchy of use-cases, starting with the argument use-case as the root. This is primarily
262: * meant to build a set of menu items.
263: */
264: private void createHierarchy(UseCaseNode root) {
265: final StrutsUseCase useCase = (StrutsUseCase) root
266: .getUserObject();
267:
268: final FrontEndActivityGraph graph = useCase.getActivityGraph();
269: if (graph != null) {
270: final Collection finalStates = graph.getFinalStates();
271: for (final Iterator finalStateIterator = finalStates
272: .iterator(); finalStateIterator.hasNext();) {
273: final StrutsFinalState finalState = (StrutsFinalState) finalStateIterator
274: .next();
275: final StrutsUseCase targetUseCase = (StrutsUseCase) finalState
276: .getTargetUseCase();
277: if (targetUseCase != null) {
278: final UseCaseNode useCaseNode = new UseCaseNode(
279: targetUseCase);
280: if (!isNodeAncestor(root, useCaseNode)) {
281: root.add(useCaseNode);
282: createHierarchy(useCaseNode);
283: }
284: }
285: }
286: }
287: }
288:
289: /**
290: * <code>true</code> if the argument ancestor node is actually an ancestor of the first node.
291: * <p/>
292: * <em>Note: DefaultMutableTreeNode's isNodeAncestor does not work because of its specific impl.</em>
293: */
294: private boolean isNodeAncestor(UseCaseNode node,
295: UseCaseNode ancestorNode) {
296: boolean ancestor = false;
297:
298: if (node.getUseCase().equals(ancestorNode.getUseCase())) {
299: ancestor = true;
300: }
301: while (!ancestor && node.getParent() != null) {
302: node = (UseCaseNode) node.getParent();
303: if (this .isNodeAncestor(node, ancestorNode)) {
304: ancestor = true;
305: }
306: }
307: return ancestor;
308: }
309:
310: /**
311: * Given a root use-case, finds the node in the hierarchy that represent the argument StrutsUseCase node.
312: */
313: private UseCaseNode findNode(UseCaseNode root, StrutsUseCase useCase) {
314: UseCaseNode useCaseNode = null;
315:
316: final List nodeList = Collections.list(root
317: .breadthFirstEnumeration());
318: for (final Iterator nodeIterator = nodeList.iterator(); nodeIterator
319: .hasNext()
320: && useCaseNode == null;) {
321: UseCaseNode node = (UseCaseNode) nodeIterator.next();
322: if (useCase.equals(node.getUserObject())) {
323: useCaseNode = node;
324: }
325: }
326: return useCaseNode;
327: }
328:
329: public final static class UseCaseNode extends
330: DefaultMutableTreeNode {
331: public UseCaseNode(StrutsUseCase useCase) {
332: super (useCase);
333: }
334:
335: public StrutsUseCase getUseCase() {
336: return (StrutsUseCase) getUserObject();
337: }
338: }
339:
340: private boolean normalizeMessages() {
341: final String normalizeMessages = (String) getConfiguredProperty(Bpm4StrutsGlobals.PROPERTY_NORMALIZE_MESSAGES);
342: return Boolean.valueOf(normalizeMessages).booleanValue();
343: }
344:
345: protected Map handleGetAllMessages() {
346: final boolean normalize = this .normalizeMessages();
347: final Map messages = (normalize) ? (Map) new TreeMap()
348: : (Map) new LinkedHashMap();
349:
350: if (this .isApplicationUseCase()) {
351: final List useCases = this .getAllUseCases();
352: for (int i = 0; i < useCases.size(); i++) {
353: // USECASE
354: final StrutsUseCase useCase = (StrutsUseCase) useCases
355: .get(i);
356: messages.put(useCase.getTitleKey(), useCase
357: .getTitleValue());
358: messages.put(useCase.getOnlineHelpKey(), useCase
359: .getOnlineHelpValue());
360:
361: final List actions = useCase.getActions();
362: for (int j = 0; j < actions.size(); j++) {
363: final StrutsAction action = (StrutsAction) actions
364: .get(j);
365:
366: // FORWARDS
367: final List transitions = action.getTransitions();
368: for (int l = 0; l < transitions.size(); l++) {
369: final StrutsForward forward = (StrutsForward) transitions
370: .get(l);
371: messages.putAll(forward.getSuccessMessages());
372: messages.putAll(forward.getWarningMessages());
373: }
374:
375: // EXCEPTION FORWARDS
376: final List exceptions = action
377: .getActionExceptions();
378:
379: if (normalize) {
380: if (exceptions.isEmpty()) {
381: if (!action.isUseCaseStart()) {
382: messages.put(action.getMessageKey()
383: + ".exception",
384: "{0} (java.lang.Exception)");
385: }
386: } else {
387: for (int l = 0; l < exceptions.size(); l++) {
388: final StrutsExceptionHandler exception = (StrutsExceptionHandler) exceptions
389: .get(l);
390: messages.put(action.getMessageKey()
391: + '.'
392: + exception.getExceptionKey(),
393: "{0}");
394: }
395: }
396: } else {
397: if (exceptions.isEmpty()) {
398: if (!action.isUseCaseStart()) {
399: messages.put(action.getMessageKey()
400: + ".exception",
401: "{0} (java.lang.Exception)");
402: }
403: } else {
404: for (int l = 0; l < exceptions.size(); l++) {
405: final StrutsExceptionHandler exception = (StrutsExceptionHandler) exceptions
406: .get(l);
407: // we construct the key using the action message too because the exception can
408: // belong to more than one action (therefore it cannot return the correct value
409: // in .getExceptionKey())
410: messages
411: .put(
412: action.getMessageKey()
413: + '.'
414: + exception
415: .getExceptionKey(),
416: "{0} ("
417: + exception
418: .getExceptionType()
419: + ")");
420: }
421: }
422: }
423:
424: // TRIGGER
425: final StrutsTrigger trigger = action
426: .getActionTrigger();
427: if (trigger != null) {
428: // only add these when a trigger is present, otherwise it's no use having them
429: messages.put(action.getOnlineHelpKey(), action
430: .getOnlineHelpValue());
431: messages.put(action.getDocumentationKey(),
432: action.getDocumentationValue());
433:
434: // the regular trigger messages
435: messages.put(trigger.getTitleKey(), trigger
436: .getTitleValue());
437: messages.put(trigger.getNotAllowedTitleKey(),
438: trigger.getNotAllowedTitleValue());
439: messages.put(trigger.getResetMessageKey(),
440: trigger.getResetMessageValue());
441: messages.put(trigger
442: .getResetNotAllowedTitleKey(), trigger
443: .getResetNotAllowedTitleValue());
444: messages.put(trigger.getResetTitleKey(),
445: trigger.getResetTitleValue());
446: // this one is the same as doing: action.getMessageKey()
447: messages.put(trigger.getTriggerKey(), trigger
448: .getTriggerValue());
449:
450: // IMAGE LINK
451: if (action.isImageLink()) {
452: messages.put(action.getImageMessageKey(),
453: action.getImagePath());
454: }
455: }
456: }
457:
458: final List pages = useCase.getPages();
459: for (int j = 0; j < pages.size(); j++) {
460: // PAGE
461: final StrutsJsp page = (StrutsJsp) pages.get(j);
462: messages.put(page.getTitleKey(), page
463: .getTitleValue());
464: messages.put(page.getMessageKey(), page
465: .getMessageValue());
466: messages.put(page.getOnlineHelpKey(), page
467: .getOnlineHelpValue());
468: messages.put(page.getDocumentationKey(), page
469: .getDocumentationValue());
470:
471: final List pageVariables = page.getPageVariables();
472: for (int k = 0; k < pageVariables.size(); k++) {
473: // PAGE-VARIABLE
474: final StrutsParameter parameter = (StrutsParameter) pageVariables
475: .get(k);
476:
477: messages.put(parameter.getMessageKey(),
478: parameter.getMessageValue());
479: /*
480: if (normalize)
481: {
482: // the next line is in comment because it's not actually being used
483: //messages.put(parameter.getTitleKey(), parameter.getTitleValue());
484: messages.put(parameter.getMessageKey(), parameter.getMessageValue());
485: }
486: else
487: {
488: // the next line is in comment because it's not actually being used
489: //messages.put(page.getTitleKey() + '.' + parameter.getTitleKey(), parameter.getTitleValue());
490: messages.put(page.getTitleKey() + '.' + parameter.getMessageKey(),
491: parameter.getMessageValue());
492: }
493: */
494:
495: // TABLE
496: if (parameter.isTable()) {
497: final Collection columnNames = parameter
498: .getTableColumnNames();
499: for (final Iterator columnNameIterator = columnNames
500: .iterator(); columnNameIterator
501: .hasNext();) {
502: final String columnName = (String) columnNameIterator
503: .next();
504: messages
505: .put(
506: parameter
507: .getTableColumnMessageKey(columnName),
508: parameter
509: .getTableColumnMessageValue(columnName));
510: }
511: }
512: }
513:
514: for (int k = 0; k < actions.size(); k++) {
515: // ACTION
516: final StrutsAction action = (StrutsAction) actions
517: .get(k);
518:
519: // ACTION PARAMETERS
520: final List parameters = action
521: .getActionParameters();
522: for (int l = 0; l < parameters.size(); l++) {
523: final StrutsParameter parameter = (StrutsParameter) parameters
524: .get(l);
525: messages.put(parameter.getMessageKey(),
526: parameter.getMessageValue());
527: messages.put(parameter.getOnlineHelpKey(),
528: parameter.getOnlineHelpValue());
529: messages.put(parameter
530: .getDocumentationKey(), parameter
531: .getDocumentationValue());
532: messages.put(parameter.getTitleKey(),
533: parameter.getTitleValue());
534:
535: if (parameter.getValidWhen() != null) {
536: // this key needs to be fully qualified since the valid when value can be different
537: final String completeKeyPrefix = (normalize) ? parameter
538: .getMessageKey()
539: : useCase.getTitleKey()
540: + '.'
541: + page.getMessageKey()
542: + '.'
543: + action
544: .getMessageKey()
545: + '.'
546: + parameter
547: .getMessageKey();
548: messages
549: .put(
550: completeKeyPrefix
551: + "_validwhen",
552: "{0} is only valid when "
553: + parameter
554: .getValidWhen());
555: }
556:
557: if (parameter.getOptionCount() > 0) {
558: final List optionKeys = parameter
559: .getOptionKeys();
560: final List optionValues = parameter
561: .getOptionValues();
562:
563: for (int m = 0; m < optionKeys.size(); m++) {
564: messages.put(optionKeys.get(m),
565: optionValues.get(m));
566: messages.put(optionKeys.get(m)
567: + ".title", optionValues
568: .get(m));
569: }
570: }
571: }
572: }
573: }
574: }
575: }
576:
577: return messages;
578: }
579:
580: protected String handleGetOnlineHelpPagePath() {
581: final StringBuffer buffer = new StringBuffer();
582:
583: if (StringUtils.isNotBlank(this .getPackagePath())) {
584: buffer.append('/');
585: buffer.append(this .getPackagePath());
586: }
587: buffer.append('/');
588: buffer.append(StringUtilsHelper.separate(this .getName(), "-"));
589: buffer.append("_help");
590:
591: return buffer.toString();
592: }
593:
594: protected String handleGetOnlineHelpActionPath() {
595: final StringBuffer buffer = new StringBuffer();
596:
597: if (StringUtils.isNotBlank(this .getPackagePath())) {
598: buffer.append('/');
599: buffer.append(this .getPackagePath());
600: }
601: buffer.append('/');
602: buffer.append(StringUtilsHelper.upperCamelCaseName(this
603: .getName()));
604: buffer.append("Help");
605:
606: return buffer.toString();
607: }
608:
609: /**
610: * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsUseCase#getFormKey()
611: */
612: protected String handleGetFormKey() {
613: final Object formKeyValue = this
614: .findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_ACTION_FORM_KEY);
615: return formKeyValue == null ? Bpm4StrutsProfile.TAGGEDVALUE_ACTION_FORM_DEFAULT_KEY
616: : String.valueOf(formKeyValue);
617: }
618:
619: }
|