001: /*
002: * Copyright 2004-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.springframework.webflow.action;
017:
018: import org.springframework.core.JdkVersion;
019: import org.springframework.core.enums.LabeledEnum;
020: import org.springframework.webflow.execution.Event;
021: import org.springframework.webflow.execution.RequestContext;
022: import org.springframework.webflow.execution.support.EventFactorySupport;
023:
024: /**
025: * Result object-to-event adapter interface that tries to do a
026: * sensible conversion of the result object into a web flow event.
027: * It uses the following conversion table:
028: * <table border="1">
029: * <tr>
030: * <th>Result object type</th>
031: * <th>Event id</th>
032: * <th>Remarks</th>
033: * </tr>
034: * <tr>
035: * <td>null</td>
036: * <td>{@link org.springframework.webflow.execution.support.EventFactorySupport#getNullEventId()}</td>
037: * <td> </td>
038: * </tr>
039: * <tr>
040: * <td>{@link java.lang.Boolean} or boolean</td>
041: * <td>{@link org.springframework.webflow.execution.support.EventFactorySupport#getYesEventId()}/
042: * {@link org.springframework.webflow.execution.support.EventFactorySupport#getNoEventId()}</td>
043: * <td> </td>
044: * </tr>
045: * <tr>
046: * <td>{@link org.springframework.core.enums.LabeledEnum}</td>
047: * <td>{@link org.springframework.core.enums.LabeledEnum#getLabel()}</td>
048: * <td>The result object will included in the event as an attribute
049: * named "result".</td>
050: * </tr>
051: * <tr>
052: * <td>{@link java.lang.Enum}</td>
053: * <td>{@link java.lang.Enum#name()}</td>
054: * <td>The result object will included in the event as an attribute
055: * named "result".</td>
056: * </tr>
057: * <tr>
058: * <td>{@link java.lang.String}</td>
059: * <td>The string.</td>
060: * <td> </td>
061: * </tr>
062: * <tr>
063: * <td>{@link org.springframework.webflow.execution.Event}</td>
064: * <td>The resulting event object.</td>
065: * <td> </td>
066: * </tr>
067: * </table>
068: *
069: * @author Keith Donald
070: * @author Erwin Vervaet
071: */
072: public class ResultObjectBasedEventFactory extends EventFactorySupport
073: implements ResultEventFactory {
074:
075: public Event createResultEvent(Object source, Object resultObject,
076: RequestContext context) {
077: if (resultObject == null) {
078: // this handles the case where the declared result return type is mapped
079: // by this class but the value is null
080: return event(source, getNullEventId());
081: } else if (isBoolean(resultObject.getClass())) {
082: return event(source, ((Boolean) resultObject)
083: .booleanValue());
084: } else if (isLabeledEnum(resultObject.getClass())) {
085: String resultId = ((LabeledEnum) resultObject).getLabel();
086: return event(source, resultId, getResultAttributeName(),
087: resultObject);
088: } else if (isJdk5Enum(resultObject.getClass())) {
089: String eventId = EnumNameResolver.getEnumName(resultObject);
090: return event(source, eventId, getResultAttributeName(),
091: resultObject);
092: } else if (isString(resultObject.getClass())) {
093: return event(source, (String) resultObject);
094: } else if (isEvent(resultObject.getClass())) {
095: return (Event) resultObject;
096: } else {
097: throw new IllegalArgumentException(
098: "Cannot deal with result object '" + resultObject
099: + "' of type '" + resultObject.getClass()
100: + "'");
101: }
102: }
103:
104: /**
105: * Check whether or not given type is mapped to a corresponding
106: * event using special mapping rules.
107: */
108: public boolean isMappedValueType(Class type) {
109: return isBoolean(type) || isLabeledEnum(type)
110: || isJdk5Enum(type) || isString(type) || isEvent(type);
111: }
112:
113: // internal helpers to determine the 'type' of a class
114:
115: private boolean isBoolean(Class type) {
116: return Boolean.class.equals(type) || boolean.class.equals(type);
117: }
118:
119: private boolean isLabeledEnum(Class type) {
120: return LabeledEnum.class.isAssignableFrom(type);
121: }
122:
123: private boolean isJdk5Enum(Class type) {
124: if (JdkVersion.getMajorJavaVersion() >= JdkVersion.JAVA_15) {
125: return type.isEnum();
126: } else {
127: return false;
128: }
129: }
130:
131: private boolean isString(Class type) {
132: return String.class.equals(type);
133: }
134:
135: private boolean isEvent(Class type) {
136: return Event.class.isAssignableFrom(type);
137: }
138:
139: /**
140: * Simple helper class with Java 5 specific code factored out to keep
141: * the containing class JDK 1.3 compatible.
142: */
143: private static class EnumNameResolver {
144: public static String getEnumName(Object enumValue) {
145: return ((java.lang.Enum) enumValue).name();
146: }
147: }
148: }
|