001 package org.nakedobjects.applib.events;
002
003 import java.util.EventObject;
004
005 import org.nakedobjects.applib.Identifier;
006 import org.nakedobjects.applib.util.NameUtils;
007
008
009 /**
010 * Represents an interaction with a domain object or a particular feature (property, collection, action) of a
011 * domain object.
012 *
013 * <p>
014 * Many of the interactions are checks for {@link VisibilityEvent visibility},
015 * {@link UsabilityEvent usability} and {@link ValidityEvent validity}.
016 */
017 public abstract class InteractionEvent extends EventObject {
018
019 private static final long serialVersionUID = 1L;
020
021 private final Identifier identifier;
022 private String reason;
023 private Class<?> advisorClass;
024
025 public InteractionEvent(final Object source, final Identifier identifier) {
026 super(source);
027 this.identifier = identifier;
028 }
029
030
031 /**
032 * The domain object (pojo) against which the interaction occurred.
033 */
034 @Override
035 public Object getSource() {
036 return super.getSource();
037 }
038
039 /**
040 * The {@link Identifier} of the feature of the object being interacted with.
041 *
042 * <p>
043 * Will be consistent with the subclass of {@link InteractionEvent}. So for example a
044 * {@link PropertyModifyEvent} will have an {@link Identifier} that identifies the property being
045 * modified.
046 *
047 * @return
048 */
049 public Identifier getIdentifier() {
050 return identifier;
051 }
052
053 /**
054 * Convenience method that returns the {@link Identifier#getClassName() class name} of the
055 * {@link #getIdentifier() identifier}.
056 *
057 * @see #getIdentifier
058 */
059 public String getClassName() {
060 return identifier.getClassName();
061 }
062
063 /**
064 * As per {@link #getClassName()}, but {@link NameUtils#naturalName(String) naturalized}.
065 */
066 public String getClassNaturalName() {
067 return NameUtils.naturalName(getClassName());
068 }
069
070 /**
071 * Convenience method that returns the {@link Identifier#getMemberName() member name} of the
072 * {@link #getIdentifier() identifier}.
073 *
074 * @see #getIdentifier
075 */
076 public String getMemberName() {
077 return identifier.getMemberName();
078 }
079
080 /**
081 * As per {@link #getMemberName()}, but naturalized.
082 */
083 public String getMemberNaturalName() {
084 return NameUtils.naturalName(getMemberName());
085 }
086
087 /**
088 * Convenience method that returns the {@link Identifier#getClassName() class name} of the
089 * {@link #getIdentifier() identifier}.
090 */
091 public String[] getMemberParameterNames() {
092 return identifier.getMemberParameterNames();
093 }
094
095 /**
096 * As per {@link #getMemberParameterName()}, but naturalized.
097 */
098 public String[] getMemberParameterNaturalNames() {
099 return NameUtils.naturalNames(getMemberParameterNames());
100 }
101
102 /**
103 * The reason, if any, that this interaction may have been vetoed or otherwise disallowed.
104 *
105 * <p>
106 * Intended to be {@link #setReason(String) set} as a result of consulting one of the facets.
107 *
108 * @return
109 */
110 public String getReason() {
111 return reason;
112 }
113
114 /**
115 * The class of the (first) advisor, if any, that provided the {@link #getReason() reason} that this
116 * interaction is {@link #isVeto() vetoed}.
117 *
118 * @return
119 */
120 public Class<?> getAdvisorClass() {
121 return advisorClass;
122 }
123
124 /**
125 * Specify the {@link #getReason() reason} that this interaction has been vetoed and the
126 * {@link #getAdvisorClass() class of the advisor} that did the veto.
127 */
128 public void advised(final String reason, final Class<?> advisorClass) {
129 this.reason = reason;
130 this.advisorClass = advisorClass;
131 }
132
133 /**
134 * Whether this interaction has been vetoed (meaning that {@link #getReason()} and
135 * {@link #getAdvisorClass()} will both be non-<tt>null</tt> and the {@link #getReason() reason}
136 * non-empty.)
137 *
138 * <p>
139 * The interpretation of this depends on the subclass:
140 * <ul>
141 * <li>for {@link VisibilityEvent}, a veto means that the feature (property, collection, action) is
142 * hidden</li>
143 * <li>for {@link UsabilityEvent}, a veto means that the feature is disabled</li>
144 * <li>for {@link ValidityEvent}, a veto means that the proposed modification (property value, object
145 * added/removed, action argument) is invalid</li>
146 * </ul>
147 */
148 public boolean isVeto() {
149 return getReason() != null && getReason().length() > 0;
150 }
151
152 }