001/**
002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003 *
004 * Copyright (c) 2008 Sun Microsystems Inc. All Rights Reserved
005 *
006 * The contents of this file are subject to the terms
007 * of the Common Development and Distribution License
008 * (the License). You may not use this file except in
009 * compliance with the License.
010 *
011 * You can obtain a copy of the License at
012 * https://opensso.dev.java.net/public/CDDLv1.0.html or
013 * opensso/legal/CDDLv1.0.txt
014 * See the License for the specific language governing
015 * permission and limitations under the License.
016 *
017 * When distributing Covered Code, include this CDDL
018 * Header Notice in each file and include the License file
019 * at opensso/legal/CDDLv1.0.txt.
020 * If applicable, add the following below the CDDL Header,
021 * with the fields enclosed by brackets [] replaced by
022 * your own identifying information:
023 * "Portions Copyrighted [year] [name of copyright owner]"
024 *
025 * $Id: ConditionDecision.java,v 1.3 2009/09/05 00:24:04 veiming Exp $
026 *
027 * Portions copyright 2010-2015 ForgeRock AS.
028 */
029package com.sun.identity.entitlement;
030
031import org.forgerock.util.Reject;
032
033import java.util.Collections;
034import java.util.HashMap;
035import java.util.Map;
036import java.util.Set;
037
038/**
039 * Class to represent {@link EntitlementCondition} evaluation match result and - if applicable - its advice.
040 *
041 * @supported.all.api
042 */
043public class ConditionDecision {
044
045    private final Map<String, Set<String>> responseAttributes;
046    private final Map<String, Set<String>> advice;
047    private final long timeToLive;
048    private final boolean satisfied;
049
050
051    /**
052     * Constructs an instance of <code>ConditionDecision</code>.
053     * <p/>
054     * Deprecated, favour the factory methods.
055     *
056     * @param satisfied
057     *         result of this <code>ConditionDecision</code>.
058     * @param advices
059     *         Advice map of this <code>ConditionDecision</code>.
060     */
061    @Deprecated
062    public ConditionDecision(boolean satisfied, Map<String, Set<String>> advices) {
063        this(satisfied, advices, Long.MAX_VALUE);
064    }
065
066    /**
067     * Constructs an instance of <code>ConditionDecision</code>.
068     * <p/>
069     * Deprecated, favour the factory methods.
070     *
071     * @param satisfied
072     *         Result of this <code>ConditionDecision</code>.
073     * @param advices
074     *         Advice map of this <code>ConditionDecision</code>.
075     * @param ttl
076     *         The TTL of this <code>ConditionDecision</code>.
077     */
078    @Deprecated
079    public ConditionDecision(boolean satisfied, Map<String, Set<String>> advices, long ttl) {
080        this.satisfied = satisfied;
081        this.advice = new HashMap<>(advices);
082        this.responseAttributes = new HashMap<>();
083        this.timeToLive = ttl;
084    }
085
086    private ConditionDecision(Builder builder) {
087        satisfied = builder.satisfied;
088        advice = builder.advice;
089        responseAttributes = builder.responseAttributes;
090        timeToLive = builder.timeToLive;
091    }
092
093    /**
094     * Whether this <code>ConditionDecision</code> is satisfied.
095     *
096     * @return <code>true</code> if <code>ConditionDecision</code> is fulfilled.
097     */
098    public boolean isSatisfied() {
099        return satisfied;
100    }
101
102    /**
103     * Advices associated with this <code>ConditionDecision</code>.
104     *
105     * @return advice of <code>ConditionDecision</code>.
106     */
107    public Map<String, Set<String>> getAdvice() {
108        return Collections.unmodifiableMap(advice);
109    }
110
111    /**
112     * Retrieves the response attributes.
113     *
114     * @return the response attributes
115     */
116    public Map<String, Set<String>> getResponseAttributes() {
117        return Collections.unmodifiableMap(responseAttributes);
118    }
119
120    /**
121     * Returns the time to live (TTL) of this <code>ConditionDecision</code>.
122     *
123     * @return The TTL time in ms.
124     */
125    public long getTimeToLive() {
126        return timeToLive;
127    }
128
129    /**
130     * Clears the current advice associated with this <code>ConditionDecision</code>.
131     * <p/>
132     * Deprecated method as a given instance should be immutable.
133     */
134    @Deprecated
135    public void clearAdvices() {
136        advice.clear();
137    }
138
139    /**
140     * Adds an advice (from another <code>ConditionDecision</code>) to this <code>ConditionDecision</code>.
141     * <p/>
142     * Deprecated method as a given instance should be immutable.
143     *
144     * @param decision
145     *         The <code>ConditionDecision</code> whose advice should be added to this
146     *         <code>ConditionDecision</code>.
147     */
148    @Deprecated
149    public void addAdvices(ConditionDecision decision) {
150        if (decision != null) {
151            Map<String, Set<String>> otherAdvices = decision.getAdvice();
152            if (otherAdvices != null && !otherAdvices.isEmpty()) {
153                advice.putAll(otherAdvices);
154            }
155        }
156    }
157
158    /**
159     * New decision builder.
160     *
161     * @param satisfied
162     *         whether the decision represents a successful evaluation or not
163     *
164     * @return new builder instance
165     */
166    public static Builder newBuilder(boolean satisfied) {
167        return new Builder(satisfied);
168    }
169
170    /**
171     * New builder representing a satisfied.
172     *
173     * @return new builder instance
174     */
175    public static Builder newSuccessBuilder() {
176        return new Builder(true);
177    }
178
179    /**
180     * New builder representing a failure.
181     *
182     * @return new builder instance
183     */
184    public static Builder newFailureBuilder() {
185        return new Builder(false);
186    }
187
188    /**
189     * Builder to help construct decisions.
190     */
191    public static final class Builder {
192
193        private final boolean satisfied;
194        private Map<String, Set<String>> advice;
195        private Map<String, Set<String>> responseAttributes;
196        private long timeToLive;
197
198        private Builder(boolean success) {
199            this.satisfied = success;
200            advice = new HashMap<>();
201            responseAttributes = new HashMap<>();
202            timeToLive = Long.MAX_VALUE;
203        }
204
205        /**
206         * Sets the advice.
207         *
208         * @param advice
209         *         the advice
210         *
211         * @return this builder instance
212         */
213        public Builder setAdvice(Map<String, Set<String>> advice) {
214            Reject.ifNull(advice);
215            this.advice = advice;
216            return this;
217        }
218
219        /**
220         * Sets the response attributes.
221         *
222         * @param responseAttributes
223         *         the response attributes
224         *
225         * @return this builder instance
226         */
227        public Builder setResponseAttributes(Map<String, Set<String>> responseAttributes) {
228            Reject.ifNull(responseAttributes);
229            this.responseAttributes = responseAttributes;
230            return this;
231        }
232
233        /**
234         * Sets the time to live.
235         *
236         * @param timeToLive
237         *         the time to live
238         *
239         * @return this builder instance
240         */
241        public Builder setTimeToLive(long timeToLive) {
242            Reject.ifTrue(timeToLive < 0);
243            this.timeToLive = timeToLive;
244            return this;
245        }
246
247        /**
248         * Builds the decision.
249         *
250         * @return the decision instance
251         */
252        public ConditionDecision build() {
253            return new ConditionDecision(this);
254        }
255
256    }
257
258}