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 */ 019package org.apache.wiki.workflow; 020 021import java.io.Serializable; 022 023/** 024 * Resolution of a workflow Step, such as "approve," "deny," "hold," "task error," or other potential resolutions. 025 * 026 * @since 2.5 027 */ 028public final class Outcome implements Serializable { 029 030 private static final long serialVersionUID = -338361947886288073L; 031 032 /** Complete workflow step (without errors) */ 033 public static final Outcome STEP_COMPLETE = new Outcome( "outcome.step.complete", true ); 034 035 /** Terminate workflow step (without errors) */ 036 public static final Outcome STEP_ABORT = new Outcome( "outcome.step.abort", true ); 037 038 /** Continue workflow step (without errors) */ 039 public static final Outcome STEP_CONTINUE = new Outcome( "outcome.step.continue", false ); 040 041 /** Acknowlege the Decision. */ 042 public static final Outcome DECISION_ACKNOWLEDGE = new Outcome( "outcome.decision.acknowledge", true ); 043 044 /** Approve the Decision (and complete the step). */ 045 public static final Outcome DECISION_APPROVE = new Outcome( "outcome.decision.approve", true ); 046 047 /** Deny the Decision (and complete the step). */ 048 public static final Outcome DECISION_DENY = new Outcome( "outcome.decision.deny", true ); 049 050 /** Put the Decision on hold (and pause the step). */ 051 public static final Outcome DECISION_HOLD = new Outcome( "outcome.decision.hold", false ); 052 053 /** Reassign the Decision to another actor (and pause the step). */ 054 public static final Outcome DECISION_REASSIGN = new Outcome( "outcome.decision.reassign", false ); 055 056 private static final Outcome[] OUTCOMES = new Outcome[] { STEP_COMPLETE, STEP_ABORT, STEP_CONTINUE, DECISION_ACKNOWLEDGE, 057 DECISION_APPROVE, DECISION_DENY, DECISION_HOLD, DECISION_REASSIGN }; 058 059 private final String m_key; 060 061 private final boolean m_completion; 062 063 /** 064 * Private constructor to prevent direct instantiation. 065 * 066 * @param key message key for the Outcome 067 * @param completion whether this Outcome should be interpreted as the logical completion of a Step. 068 */ 069 private Outcome( final String key, final boolean completion ) { 070 if ( key == null ) { 071 throw new IllegalArgumentException( "Key cannot be null." ); 072 } 073 m_key = key; 074 m_completion = completion; 075 } 076 077 /** 078 * Returns <code>true</code> if this Outcome represents a completion condition for a Step. 079 * 080 * @return the result 081 */ 082 public boolean isCompletion() { 083 return m_completion; 084 } 085 086 /** 087 * The i18n key for this outcome, which is prefixed by <code>outcome.</code>. If calling classes wish to return a locale-specific 088 * name for this task (such as "approve this request"), they can use this method to obtain the correct key suffix. 089 * 090 * @return the i18n key for this outcome 091 */ 092 public String getMessageKey() { 093 return m_key; 094 } 095 096 /** 097 * The hashcode of an Outcome is identical to the hashcode of its message key, multiplied by 2 if it is a "completion" Outcome. 098 * 099 * @return the hash code 100 */ 101 public int hashCode() { 102 return m_key.hashCode() * ( m_completion ? 1 : 2 ); 103 } 104 105 /** 106 * Two Outcome objects are equal if their message keys are equal. 107 * 108 * @param obj the object to test 109 * @return <code>true</code> if logically equal, <code>false</code> if not 110 */ 111 public boolean equals( final Object obj ) { 112 if( !( obj instanceof Outcome ) ) { 113 return false; 114 } 115 return m_key.equals( ( ( Outcome )obj ).getMessageKey() ); 116 } 117 118 /** 119 * Returns a named Outcome. If an Outcome matching the supplied key is not found, this method throws a {@link NoSuchOutcomeException}. 120 * 121 * @param key the name of the outcome 122 * @return the Outcome 123 * @throws NoSuchOutcomeException if an Outcome matching the key isn't found. 124 */ 125 public static Outcome forName( final String key ) throws NoSuchOutcomeException { 126 if( key != null ) { 127 for( final Outcome outcome : OUTCOMES ) { 128 if( outcome.m_key.equals( key ) ) { 129 return outcome; 130 } 131 } 132 } 133 throw new NoSuchOutcomeException( "Outcome " + key + " not found." ); 134 } 135 136 /** 137 * {@inheritDoc} 138 */ 139 public String toString() { 140 return "[Outcome:" + m_key + "]"; 141 } 142 143}