001    /* 
002        Licensed to the Apache Software Foundation (ASF) under one
003        or more contributor license agreements.  See the NOTICE file
004        distributed with this work for additional information
005        regarding copyright ownership.  The ASF licenses this file
006        to you under the Apache License, Version 2.0 (the
007        "License"); you may not use this file except in compliance
008        with the License.  You may obtain a copy of the License at
009    
010           http://www.apache.org/licenses/LICENSE-2.0
011    
012        Unless required by applicable law or agreed to in writing,
013        software distributed under the License is distributed on an
014        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015        KIND, either express or implied.  See the License for the
016        specific language governing permissions and limitations
017        under the License.  
018     */
019    package org.apache.wiki.workflow;
020    
021    import java.io.Serializable;
022    
023    /**
024     * Resolution of a workflow Step, such as "approve," "deny," "hold," "task
025     * error," or other potential resolutions.
026     *
027     * @since 2.5
028     */
029    public final class Outcome implements Serializable
030    {
031    
032        private static final long serialVersionUID = -338361947886288073L;
033    
034        /** Complete workflow step (without errors) */
035        public static final Outcome STEP_COMPLETE = new Outcome( "outcome.step.complete", true );
036    
037        /** Terminate workflow step (without errors) */
038        public static final Outcome STEP_ABORT = new Outcome( "outcome.step.abort", true );
039    
040        /** Continue workflow step (without errors) */
041        public static final Outcome STEP_CONTINUE = new Outcome( "outcome.step.continue", false );
042    
043        /** Acknowlege the Decision. */
044        public static final Outcome DECISION_ACKNOWLEDGE = new Outcome( "outcome.decision.acknowledge", true );
045    
046        /** Approve the Decision (and complete the step). */
047        public static final Outcome DECISION_APPROVE = new Outcome( "outcome.decision.approve", true );
048    
049        /** Deny the Decision (and complete the step). */
050        public static final Outcome DECISION_DENY = new Outcome( "outcome.decision.deny", true );
051    
052        /** Put the Decision on hold (and pause the step). */
053        public static final Outcome DECISION_HOLD = new Outcome( "outcome.decision.hold", false );
054    
055        /** Reassign the Decision to another actor (and pause the step). */
056        public static final Outcome DECISION_REASSIGN = new Outcome( "outcome.decision.reassign", false );
057    
058        private static final Outcome[] OUTCOMES = new Outcome[] { STEP_COMPLETE, STEP_ABORT, STEP_CONTINUE, DECISION_ACKNOWLEDGE,
059                                                                   DECISION_APPROVE, DECISION_DENY, DECISION_HOLD, DECISION_REASSIGN };
060    
061        private final String m_key;
062    
063        private final boolean m_completion;
064    
065        /**
066         * Private constructor to prevent direct instantiation.
067         *
068         * @param key
069         *            message key for the Outcome
070         * @param completion
071         *            whether this Outcome should be interpreted as the logical
072         *            completion of a Step.
073         */
074        private Outcome( String key, boolean completion )
075        {
076            if ( key == null )
077            {
078                throw new IllegalArgumentException( "Key cannot be null." );
079            }
080            m_key = key;
081            m_completion = completion;
082        }
083    
084        /**
085         * Returns <code>true</code> if this Outcome represents a completion
086         * condition for a Step.
087         *
088         * @return the result
089         */
090        public boolean isCompletion()
091        {
092            return m_completion;
093        }
094    
095        /**
096         * The i18n key for this outcome, which is prefixed by <code>outcome.</code>.
097         * If calling classes wish to return a locale-specific name for this task
098         * (such as "approve this request"), they can use this method to obtain the
099         * correct key suffix.
100         *
101         * @return the i18n key for this outcome
102         */
103        public String getMessageKey()
104        {
105            return m_key;
106        }
107    
108        /**
109         * The hashcode of an Outcome is identical to the hashcode of its message
110         * key, multiplied by 2 if it is a "completion" Outcome.
111         * @return the hash code
112         */
113        public int hashCode()
114        {
115            return m_key.hashCode() * ( m_completion ? 1 : 2 );
116        }
117    
118        /**
119         * Two Outcome objects are equal if their message keys are equal.
120         * @param obj the object to test
121         * @return <code>true</code> if logically equal, <code>false</code> if not
122         */
123        public boolean equals( Object obj )
124        {
125            if (!(obj instanceof Outcome))
126            {
127                return false;
128            }
129            return m_key.equals( ( (Outcome) obj ).getMessageKey() );
130        }
131    
132        /**
133         * Returns a named Outcome. If an Outcome matching the supplied key is not
134         * found, this method throws a {@link NoSuchOutcomeException}.
135         *
136         * @param key
137         *            the name of the outcome
138         * @return the Outcome
139         * @throws NoSuchOutcomeException
140         *             if an Outcome matching the key isn't found.
141         */
142        public static Outcome forName( String key ) throws NoSuchOutcomeException
143        {
144            if ( key != null )
145            {
146                for (int i = 0; i < OUTCOMES.length; i++)
147                {
148                    if ( OUTCOMES[i].m_key.equals( key ) )
149                    {
150                        return OUTCOMES[i];
151                    }
152                }
153            }
154            throw new NoSuchOutcomeException( "Outcome " + key + " not found." );
155        }
156    
157        /**
158         * {@inheritDoc}
159         */
160        public String toString()
161        {
162            return "[Outcome:" + m_key + "]";
163        }
164    
165    }