001/*
002 * oauth2-oidc-sdk
003 *
004 * Copyright 2012-2016, Connect2id Ltd and contributors.
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
007 * this file except in compliance with the License. You may obtain a copy of the
008 * License at
009 *
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software distributed
013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
015 * specific language governing permissions and limitations under the License.
016 */
017
018package com.nimbusds.openid.connect.sdk.federation.policy.operations;
019
020
021import java.util.List;
022import java.util.concurrent.atomic.AtomicBoolean;
023
024import com.nimbusds.oauth2.sdk.ParseException;
025import com.nimbusds.oauth2.sdk.util.JSONUtils;
026import com.nimbusds.openid.connect.sdk.federation.policy.language.*;
027
028
029/**
030 * Values set (value) operation.
031 *
032 * <p>Example policy:
033 *
034 * <pre>
035 * "require_auth_time" : { "value": true }
036 * </pre>
037 *
038 * <p>Input:
039 *
040 * <pre>
041 * "require_auth_time" : false
042 * </pre>
043 *
044 * <p>Result:
045 *
046 * <pre>
047 * "require_auth_time" : true
048 * </pre>
049 *
050 * <p>Related specifications:
051 *
052 * <ul>
053 *     <li>OpenID Connect Federation 1.0, section 4.1.5.
054 * </ul>
055 */
056public class ValueOperation implements PolicyOperation,
057        BooleanConfiguration, StringConfiguration, StringListConfiguration,
058        UntypedOperation {
059        
060        
061        public static final OperationName NAME = new OperationName("value");
062        
063        
064        private AtomicBoolean isInit = new AtomicBoolean(false);
065        
066        
067        private boolean booleanValue;
068        
069        
070        private String stringValue;
071        
072        
073        private List<String> stringListValue;
074        
075        
076        @Override
077        public OperationName getOperationName() {
078                return NAME;
079        }
080        
081        
082        @Override
083        public void configure(final boolean parameter) {
084                isInit.set(true);
085                this.booleanValue = parameter;
086        }
087        
088        
089        @Override
090        public void configure(final String parameter) {
091                isInit.set(true);
092                this.stringValue = parameter;
093        }
094        
095        
096        @Override
097        public void configure(final List<String> parameter) {
098                isInit.set(true);
099                this.stringListValue = parameter;
100        }
101        
102        
103        @Override
104        public void parseConfiguration(final Object jsonEntity) throws ParseException {
105                if (jsonEntity instanceof Boolean) {
106                        configure(JSONUtils.toBoolean(jsonEntity));
107                } else if (jsonEntity instanceof String) {
108                        configure(JSONUtils.toString(jsonEntity));
109                } else {
110                        configure(JSONUtils.toStringList(jsonEntity));
111                }
112        }
113        
114        
115        @Override
116        public boolean getBooleanConfiguration() {
117                return booleanValue;
118        }
119        
120        
121        @Override
122        public String getStringConfiguration() {
123                return stringValue;
124        }
125        
126        
127        @Override
128        public List<String> getStringListConfiguration() {
129                return stringListValue;
130        }
131        
132        
133        @Override
134        public PolicyOperation merge(final PolicyOperation other)
135                throws PolicyViolationException {
136                
137                ValueOperation otherTyped = Utils.castForMerge(other, ValueOperation.class);
138                
139                if (! isInit.get() || ! otherTyped.isInit.get()) {
140                        throw new PolicyViolationException("The value operation is not initialized");
141                }
142                
143                if (getStringListConfiguration() != null) {
144                        
145                        if (getStringListConfiguration().equals(otherTyped.getStringListConfiguration())) {
146                                
147                                ValueOperation copy = new ValueOperation();
148                                copy.configure(getStringListConfiguration());
149                                return copy;
150                        }
151                        
152                        throw new PolicyViolationException("Value mismatch");
153                        
154                } else if (getStringConfiguration() != null) {
155                        
156                        if (getStringConfiguration().equals(otherTyped.getStringConfiguration())) {
157                                
158                                ValueOperation copy = new ValueOperation();
159                                copy.configure(getStringConfiguration());
160                                return copy;
161                        }
162                        
163                        throw new PolicyViolationException("Value mismatch");
164                        
165                } else if (getBooleanConfiguration() == otherTyped.getBooleanConfiguration()) {
166                        
167                        ValueOperation copy = new ValueOperation();
168                        copy.configure(getBooleanConfiguration());
169                        return copy;
170                } else {
171                        throw new PolicyViolationException("Value mismatch");
172                }
173        }
174        
175        
176        @Override
177        public Object apply(final Object value) {
178                
179                if (! isInit.get()) {
180                        throw new IllegalStateException("The policy is not initialized");
181                }
182                
183                if (stringListValue != null) {
184                        return stringListValue;
185                }
186                if (stringValue != null) {
187                        return stringValue;
188                }
189                
190                // boolean last because it cannot be null
191                return booleanValue;
192        }
193}