001: package org.andromda.cartridges.jsf.metafacades;
002:
003: import java.security.MessageDigest;
004: import java.security.NoSuchAlgorithmException;
005: import java.util.ArrayList;
006: import java.util.Collection;
007: import java.util.Collections;
008: import java.util.Iterator;
009: import java.util.LinkedHashMap;
010: import java.util.List;
011: import java.util.Map;
012:
013: import org.andromda.cartridges.jsf.JSFGlobals;
014: import org.andromda.cartridges.jsf.JSFProfile;
015: import org.andromda.cartridges.jsf.JSFUtils;
016: import org.andromda.metafacades.uml.EventFacade;
017: import org.andromda.metafacades.uml.FrontEndAction;
018: import org.andromda.metafacades.uml.ModelElementFacade;
019: import org.andromda.metafacades.uml.UseCaseFacade;
020: import org.andromda.utils.StringUtilsHelper;
021: import org.apache.commons.collections.CollectionUtils;
022: import org.apache.commons.collections.Predicate;
023: import org.apache.commons.lang.ObjectUtils;
024: import org.apache.commons.lang.StringUtils;
025:
026: /**
027: * MetafacadeLogic implementation for org.andromda.cartridges.jsf.metafacades.JSFAction.
028: *
029: * @see org.andromda.cartridges.jsf.metafacades.JSFAction
030: */
031: public class JSFActionLogicImpl extends JSFActionLogic {
032: public JSFActionLogicImpl(Object metaObject, String context) {
033: super (metaObject, context);
034: }
035:
036: /**
037: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#getFormBeanName()
038: */
039: protected java.lang.String handleGetFormBeanName() {
040: return this .getFormBeanName(true);
041: }
042:
043: /**
044: * Constructs the form bean name, with our without prefixing the use case name.
045: *
046: * @param withUseCaseName whether or not to prefix the use case name.
047: * @return the constructed form bean name.
048: */
049: private String getFormBeanName(boolean withUseCaseName) {
050: final String pattern = ObjectUtils.toString(this
051: .getConfiguredProperty(JSFGlobals.FORM_BEAN_PATTERN));
052: final ModelElementFacade useCase = this .getUseCase();
053: final String useCaseName = withUseCaseName && useCase != null ? StringUtilsHelper
054: .lowerCamelCaseName(useCase.getName())
055: : "";
056: final String formBeanName = pattern.replaceFirst("\\{0\\}",
057: useCaseName);
058: final String triggerName = !pattern.equals(formBeanName) ? StringUtils
059: .capitalize(this .getTriggerName())
060: : this .getTriggerName();
061: return formBeanName.replaceFirst("\\{1\\}", triggerName);
062: }
063:
064: /**
065: * @see org.andromda.metafacades.uml.ModelElementFacade#getName()
066: */
067: public String getName() {
068: return JSFUtils.toWebResourceName(this .getUseCase().getName()
069: + "-" + super .getName());
070: }
071:
072: /**
073: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#getTriggerName()
074: */
075: protected String handleGetTriggerName() {
076: String name = null;
077: if (this .isExitingInitialState()) {
078: final JSFUseCase useCase = (JSFUseCase) this .getUseCase();
079: if (useCase != null) {
080: name = useCase.getName();
081: }
082: } else {
083: final EventFacade trigger = this .getTrigger();
084: final String suffix = trigger == null ? this .getTarget()
085: .getName() : trigger.getName();
086: name = this .getSource().getName() + ' ' + suffix;
087: }
088: return StringUtilsHelper.lowerCamelCaseName(name);
089: }
090:
091: /**
092: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#getFormImplementationName()
093: */
094: protected java.lang.String handleGetFormImplementationName() {
095: final String pattern = ObjectUtils
096: .toString(this
097: .getConfiguredProperty(JSFGlobals.FORM_IMPLEMENTATION_PATTERN));
098: return pattern.replaceFirst("\\{0\\}", StringUtils
099: .capitalize(this .getTriggerName()));
100: }
101:
102: /**
103: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#getFullyQualifiedFormImplementationName()
104: */
105: protected boolean handleIsTableAction() {
106: return JSFGlobals.ACTION_TYPE_TABLE.equals(this
107: .findTaggedValue(JSFProfile.TAGGEDVALUE_ACTION_TYPE));
108: }
109:
110: /**
111: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#getFullyQualifiedFormImplementationName()
112: */
113: protected java.lang.String handleGetFullyQualifiedFormImplementationName() {
114: final StringBuffer fullyQualifiedName = new StringBuffer();
115: final String packageName = this .getPackageName();
116: if (StringUtils.isNotBlank(packageName)) {
117: fullyQualifiedName.append(packageName + '.');
118: }
119: return fullyQualifiedName.append(
120: this .getFormImplementationName()).toString();
121: }
122:
123: /**
124: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#getFullyQualifiedFormImplementationPath()
125: */
126: protected java.lang.String handleGetFullyQualifiedFormImplementationPath() {
127: return this .getFullyQualifiedFormImplementationName().replace(
128: '.', '/');
129: }
130:
131: /**
132: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#getFullyQualifiedFormImplementationPath()
133: */
134: protected String handleGetFormScope() {
135: String scope = ObjectUtils
136: .toString(this
137: .findTaggedValue(JSFProfile.TAGGEDVALUE_ACTION_FORM_SCOPE));
138: if (StringUtils.isEmpty(scope)) {
139: scope = ObjectUtils.toString(this
140: .getConfiguredProperty(JSFGlobals.FORM_SCOPE));
141: }
142: return scope;
143: }
144:
145: /**
146: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#getFormImplementationInterfaceList()
147: */
148: protected String handleGetFormImplementationInterfaceList() {
149: final List deferredOperations = this .getDeferredOperations();
150: for (final Iterator iterator = deferredOperations.iterator(); iterator
151: .hasNext();) {
152: // - remove any forms that don't have arguments
153: final JSFControllerOperation operation = (JSFControllerOperation) iterator
154: .next();
155: if (operation.getArguments().isEmpty()) {
156: iterator.remove();
157: }
158: }
159: final StringBuffer list = new StringBuffer();
160: for (final Iterator iterator = deferredOperations.iterator(); iterator
161: .hasNext();) {
162: final JSFControllerOperation operation = (JSFControllerOperation) iterator
163: .next();
164: list.append(operation.getFormName());
165: if (iterator.hasNext()) {
166: list.append(", ");
167: }
168: }
169: return list.toString();
170: }
171:
172: /**
173: * @see org.andromda.cartridges.jsf.metafacades.JSFActionLogic#handleGetPath()
174: */
175: protected String handleGetPath() {
176: String path = this .getPathRoot() + '/'
177: + JSFUtils.toWebResourceName(this .getTriggerName());
178: if (this .isExitingInitialState()) {
179: final JSFUseCase useCase = (JSFUseCase) this .getUseCase();
180: if (useCase != null && useCase.isViewHasNameOfUseCase()) {
181: // - add the uc prefix to make the trigger name unique
182: // when a view contained within the use case has the same name
183: // as the use case
184: path = path + "uc";
185: }
186: }
187: return path;
188: }
189:
190: /**
191: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#getPathRoot()
192: */
193: protected String handleGetPathRoot() {
194: final StringBuffer pathRoot = new StringBuffer();
195: final JSFUseCase useCase = (JSFUseCase) this .getUseCase();
196: if (useCase != null) {
197: pathRoot.append(useCase.getPathRoot());
198: }
199: return pathRoot.toString();
200: }
201:
202: /**
203: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#getMessageKey()
204: */
205: protected String handleGetMessageKey() {
206: String messageKey = null;
207:
208: final Object trigger = this .getTrigger();
209: if (trigger instanceof JSFEvent) {
210: final JSFEvent actionTrigger = (JSFEvent) trigger;
211: if (actionTrigger != null) {
212: messageKey = actionTrigger.getMessageKey();
213: }
214: }
215: return messageKey;
216: }
217:
218: /**
219: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#getDocumentationKey()
220: */
221: protected String handleGetDocumentationKey() {
222: final Object trigger = this .getTrigger();
223: JSFEvent event = null;
224: if (trigger instanceof JSFEvent) {
225: event = (JSFEvent) trigger;
226: }
227: return (event == null ? this .getMessageKey()
228: + ".is.an.action.without.trigger" : event
229: .getMessageKey())
230: + '.' + JSFGlobals.DOCUMENTATION_MESSAGE_KEY_SUFFIX;
231: }
232:
233: /**
234: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#getDocumentationValue()
235: */
236: protected String handleGetDocumentationValue() {
237: final String value = StringUtilsHelper
238: .toResourceMessage(getDocumentation("", 64, false));
239: return value == null ? "" : value;
240: }
241:
242: /**
243: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#getViewFragmentPath()
244: */
245: protected String handleGetViewFragmentPath() {
246: return '/' + this .getPackageName().replace('.', '/') + '/'
247: + JSFUtils.toWebResourceName(this .getTriggerName());
248: }
249:
250: /**
251: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#getTableLinkName()
252: */
253: protected String handleGetTableLinkName() {
254: String tableLink = null;
255:
256: final Object value = findTaggedValue(JSFProfile.TAGGEDVALUE_ACTION_TABLELINK);
257: if (value != null) {
258: tableLink = StringUtils.trimToNull(value.toString());
259:
260: if (tableLink != null) {
261: final int columnOffset = tableLink.indexOf('.');
262: tableLink = columnOffset == -1 ? tableLink : tableLink
263: .substring(0, columnOffset);
264: }
265: }
266:
267: return tableLink;
268: }
269:
270: /**
271: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#getTableLinkColumnName()
272: */
273: protected String handleGetTableLinkColumnName() {
274: String tableLink = null;
275: final Object value = findTaggedValue(JSFProfile.TAGGEDVALUE_ACTION_TABLELINK);
276: if (value != null) {
277: tableLink = StringUtils.trimToNull(value.toString());
278:
279: if (tableLink != null) {
280: final int columnOffset = tableLink.indexOf('.');
281: tableLink = (columnOffset == -1 || columnOffset == tableLink
282: .length() - 1) ? null : tableLink
283: .substring(columnOffset + 1);
284: }
285: }
286: return tableLink;
287: }
288:
289: /**
290: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#isTableLink()
291: */
292: protected Object handleGetTableLinkParameter() {
293: JSFParameter tableLinkParameter = null;
294: final String tableLinkName = this .getTableLinkName();
295: if (tableLinkName != null) {
296: final JSFView view = (JSFView) this .getInput();
297: if (view != null) {
298: final List tables = view.getTables();
299: for (int ctr = 0; ctr < tables.size()
300: && tableLinkParameter == null; ctr++) {
301: final Object object = tables.get(ctr);
302: if (object instanceof JSFParameter) {
303: final JSFParameter table = (JSFParameter) object;
304: if (tableLinkName.equals(table.getName())) {
305: tableLinkParameter = table;
306: }
307: }
308: }
309: }
310: }
311: return tableLinkParameter;
312: }
313:
314: /**
315: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#isTableLink()
316: */
317: protected boolean handleIsTableLink() {
318: return this .getTableLinkParameter() != null;
319: }
320:
321: /**
322: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#isHyperlink()
323: */
324: protected boolean handleIsHyperlink() {
325: final Object value = findTaggedValue(JSFProfile.TAGGEDVALUE_ACTION_TYPE);
326: return JSFGlobals.ACTION_TYPE_HYPERLINK
327: .equalsIgnoreCase(value == null ? null : value
328: .toString());
329: }
330:
331: /**
332: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#getActionClassName()
333: */
334: protected String handleGetActionClassName() {
335: return StringUtilsHelper.upperCamelCaseName(this
336: .getTriggerName());
337: }
338:
339: /**
340: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#getFullyQualifiedActionClassPath()
341: */
342: protected String handleGetFullyQualifiedActionClassPath() {
343: return this .getFullyQualifiedActionClassName()
344: .replace('.', '/')
345: + ".java";
346: }
347:
348: /**
349: * Overriddent to provide the owning use case's package name.
350: *
351: * @see org.andromda.metafacades.uml.ModelElementFacade#getPackageName()
352: */
353: public String getPackageName() {
354: final UseCaseFacade useCase = this .getUseCase();
355: return useCase != null ? useCase.getPackageName() : "";
356: }
357:
358: /**
359: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#getControllerAction()
360: */
361: protected String handleGetControllerAction() {
362: return this .getTriggerName();
363: }
364:
365: /**
366: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#getFullyQualifiedActionClassName()
367: */
368: protected String handleGetFullyQualifiedActionClassName() {
369: final StringBuffer path = new StringBuffer();
370: final JSFUseCase useCase = (JSFUseCase) this .getUseCase();
371: if (useCase != null) {
372: final String packageName = useCase.getPackageName();
373: if (StringUtils.isNotBlank(packageName)) {
374: path.append(packageName);
375: path.append('.');
376: }
377: }
378: path.append(this .getActionClassName());
379: return path.toString();
380: }
381:
382: /**
383: * @see org.andromda.cartridges.struts.metafacades.JSFAction#isResettable()
384: */
385: protected boolean handleIsResettable() {
386: final Object value = findTaggedValue(JSFProfile.TAGGEDVALUE_ACTION_RESETTABLE);
387: return this .isTrue(value == null ? null : value.toString());
388: }
389:
390: /**
391: * Convenient method to detect whether or not a String instance represents a boolean <code>true</code> value.
392: */
393: private boolean isTrue(String string) {
394: return "yes".equalsIgnoreCase(string)
395: || "true".equalsIgnoreCase(string)
396: || "on".equalsIgnoreCase(string)
397: || "1".equalsIgnoreCase(string);
398: }
399:
400: /**
401: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#getOtherUseCaseFormActions()
402: */
403: protected List handleGetOtherUseCaseFormActions() {
404: final List otherActions = new ArrayList(this .getUseCase()
405: .getActions());
406: for (final Iterator iterator = otherActions.iterator(); iterator
407: .hasNext();) {
408: final FrontEndAction action = (FrontEndAction) iterator
409: .next();
410:
411: // - remove this action and any forms that don't have form fields
412: if (action.equals(this .THIS())
413: || action.getFormFields().isEmpty()) {
414: iterator.remove();
415: }
416: }
417: return otherActions;
418: }
419:
420: /**
421: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#getFormKey()
422: */
423: protected String handleGetFormKey() {
424: final Object formKeyValue = this
425: .findTaggedValue(JSFProfile.TAGGEDVALUE_ACTION_FORM_KEY);
426: return formKeyValue == null ? ObjectUtils.toString(this
427: .getConfiguredProperty(JSFGlobals.ACTION_FORM_KEY))
428: : String.valueOf(formKeyValue);
429: }
430:
431: /**
432: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#handleGetHiddenParameters()
433: */
434: protected List handleGetHiddenParameters() {
435: final List hiddenParameters = new ArrayList(this
436: .getParameters());
437: CollectionUtils.filter(hiddenParameters, new Predicate() {
438: public boolean evaluate(final Object object) {
439: boolean valid = false;
440: if (object instanceof JSFParameter) {
441: final JSFParameter parameter = (JSFParameter) object;
442: valid = parameter.isInputHidden();
443: if (!valid) {
444: for (final Iterator iterator = parameter
445: .getAttributes().iterator(); iterator
446: .hasNext();) {
447: JSFAttribute attribute = (JSFAttribute) iterator
448: .next();
449: valid = attribute.isInputHidden();
450: if (valid) {
451: break;
452: }
453: }
454: }
455: }
456: return valid;
457: }
458: });
459: return hiddenParameters;
460: }
461:
462: /**
463: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#handleGetHiddenParameters()
464: */
465: protected boolean handleIsValidationRequired() {
466: boolean required = false;
467: final Collection actionParameters = this .getParameters();
468: for (final Iterator iterator = actionParameters.iterator(); iterator
469: .hasNext();) {
470: final Object object = iterator.next();
471: if (object instanceof JSFParameter) {
472: final JSFParameter parameter = (JSFParameter) object;
473: if (parameter.isValidationRequired()) {
474: required = true;
475: break;
476: }
477: }
478: }
479: return required;
480: }
481:
482: /**
483: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#isPopup()
484: */
485: protected boolean handleIsPopup() {
486: boolean popup = ObjectUtils
487: .toString(
488: this
489: .findTaggedValue(JSFProfile.TAGGEDVALUE_ACTION_TYPE))
490: .equalsIgnoreCase(JSFGlobals.VIEW_TYPE_POPUP);
491: if (!popup) {
492: for (final Iterator iterator = this .getTargetViews()
493: .iterator(); iterator.hasNext();) {
494: final JSFView view = (JSFView) iterator.next();
495: popup = view.isPopup();
496: if (!popup) {
497: break;
498: }
499: }
500: }
501: return popup;
502: }
503:
504: /**
505: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#isFormResetRequired()
506: */
507: protected boolean handleIsFormResetRequired() {
508: boolean resetRequired = this .isFormReset();
509: if (!resetRequired) {
510: for (final Iterator iterator = this .getParameters()
511: .iterator(); iterator.hasNext();) {
512: final Object object = iterator.next();
513: if (object instanceof JSFParameter) {
514: final JSFParameter parameter = (JSFParameter) object;
515: resetRequired = parameter.isReset();
516: if (resetRequired) {
517: break;
518: }
519: }
520: }
521: }
522: return resetRequired;
523: }
524:
525: /**
526: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#getFormSerialVersionUID()
527: */
528: protected String handleGetFormSerialVersionUID() {
529: final StringBuffer buffer = new StringBuffer();
530:
531: buffer.append(this .getName());
532:
533: final ModelElementFacade input = this .getInput();
534: buffer.append(input != null ? input.getName() : "");
535:
536: final ModelElementFacade guard = this .getGuard();
537: buffer.append(guard != null ? guard.getName() : "");
538:
539: final ModelElementFacade effect = this .getEffect();
540: buffer.append(effect != null ? effect.getName() : "");
541:
542: final ModelElementFacade decisionsTrigger = this
543: .getDecisionTrigger();
544: buffer.append(decisionsTrigger != null ? decisionsTrigger
545: .getName() : "");
546:
547: buffer.append(StringUtils
548: .trimToEmpty(this .getActionClassName()));
549:
550: for (final Iterator iterator = this .getParameters().iterator(); iterator
551: .hasNext();) {
552: final ModelElementFacade parameter = (ModelElementFacade) iterator
553: .next();
554: buffer.append(parameter.getName());
555: }
556:
557: for (final Iterator iterator = this .getActionForwards()
558: .iterator(); iterator.hasNext();) {
559: final ModelElementFacade forward = (ModelElementFacade) iterator
560: .next();
561: buffer.append(forward.getName());
562: }
563:
564: for (final Iterator iterator = this .getActions().iterator(); iterator
565: .hasNext();) {
566: final ModelElementFacade action = (ModelElementFacade) iterator
567: .next();
568: buffer.append(action.getName());
569: }
570:
571: for (final Iterator iterator = this .getActionStates()
572: .iterator(); iterator.hasNext();) {
573: final ModelElementFacade state = (ModelElementFacade) iterator
574: .next();
575: buffer.append(state.getName());
576: }
577: final String signature = buffer.toString();
578:
579: String serialVersionUID = String.valueOf(0L);
580: try {
581: MessageDigest md = MessageDigest.getInstance("SHA");
582: byte[] hashBytes = md.digest(signature.getBytes());
583:
584: long hash = 0;
585: for (int ctr = Math.min(hashBytes.length, 8) - 1; ctr >= 0; ctr--) {
586: hash = (hash << 8) | (hashBytes[ctr] & 0xFF);
587: }
588: serialVersionUID = String.valueOf(hash);
589: } catch (final NoSuchAlgorithmException exception) {
590: final String message = "Error performing JSFAction.getFormSerialVersionUID";
591: logger.error(message, exception);
592: }
593: return serialVersionUID;
594: }
595:
596: /**
597: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#isFormRequired()
598: */
599: protected boolean handleIsFormReset() {
600: return Boolean
601: .valueOf(
602: ObjectUtils
603: .toString(this
604: .findTaggedValue(JSFProfile.TAGGEDVALUE_ACTION_FORM_RESET)))
605: .booleanValue();
606: }
607:
608: /**
609: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#getFormImplementationGetter()
610: */
611: protected String handleGetFormImplementationGetter() {
612: return "get"
613: + StringUtils.capitalize(this .getFormBeanName(false))
614: + "()";
615: }
616:
617: /**
618: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#isFinalStateTarget()
619: */
620: protected boolean handleIsFinalStateTarget() {
621: return this .getTarget() instanceof JSFFinalState;
622: }
623:
624: /**
625: * @see org.andromda.cartridges.jsf.metafacades.JSFAction#getFromOutcome()
626: */
627: protected String handleGetFromOutcome() {
628: return this .getName();
629: }
630:
631: protected boolean handleIsSuccessMessagesPresent() {
632: return !this .getSuccessMessages().isEmpty();
633: }
634:
635: protected boolean handleIsWarningMessagesPresent() {
636: return !this .getWarningMessages().isEmpty();
637: }
638:
639: /**
640: * Collects specific messages in a map.
641: *
642: * @param taggedValue the tagged value from which to read the message
643: * @return maps message keys to message values, but only those that match the arguments
644: * will have been recorded
645: */
646: private Map getMessages(String taggedValue) {
647: Map messages;
648:
649: final Collection taggedValues = this
650: .findTaggedValues(taggedValue);
651: if (taggedValues.isEmpty()) {
652: messages = Collections.EMPTY_MAP;
653: } else {
654: messages = new LinkedHashMap(); // we want to keep the order
655:
656: for (final Iterator iterator = taggedValues.iterator(); iterator
657: .hasNext();) {
658: final String value = (String) iterator.next();
659: messages.put(StringUtilsHelper
660: .toResourceMessageKey(value), value);
661: }
662: }
663:
664: return messages;
665: }
666:
667: protected Map handleGetSuccessMessages() {
668: return this
669: .getMessages(JSFProfile.TAGGEDVALUE_ACTION_SUCCESS_MESSAGE);
670: }
671:
672: protected Map handleGetWarningMessages() {
673: return this
674: .getMessages(JSFProfile.TAGGEDVALUE_ACTION_WARNING_MESSAGE);
675: }
676: }
|