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.AbstractMap;
022import java.util.List;
023import java.util.Map;
024
025import com.nimbusds.oauth2.sdk.ParseException;
026import com.nimbusds.oauth2.sdk.util.JSONUtils;
027import com.nimbusds.openid.connect.sdk.federation.policy.language.*;
028
029
030/**
031 * Default (default) value operation.
032 *
033 * <p>Example policy:
034 *
035 * <pre>
036 * "require_auth_time": { "default" : true }
037 * </pre>
038 *
039 * <p>Related specifications:
040 *
041 * <ul>
042 *     <li>OpenID Connect Federation 1.0, section 4.1.6.
043 * </ul>
044 */
045public class DefaultOperation implements PolicyOperation,
046        BooleanConfiguration, StringConfiguration, StringListConfiguration,
047        UntypedOperation {
048        
049        
050        public static final OperationName NAME = new OperationName("default");
051        
052        
053        private ConfigurationType configType;
054        
055        
056        private boolean booleanValue;
057        
058        
059        private String stringValue;
060        
061        
062        private List<String> stringListValue;
063        
064        
065        @Override
066        public OperationName getOperationName() {
067                return NAME;
068        }
069        
070        
071        @Override
072        public void configure(final boolean parameter) {
073                configType = ConfigurationType.BOOLEAN;
074                this.booleanValue = parameter;
075        }
076        
077        
078        @Override
079        public void configure(final String parameter) {
080                configType = ConfigurationType.STRING;
081                this.stringValue = parameter;
082        }
083        
084        
085        @Override
086        public void configure(final List<String> parameter) {
087                configType = ConfigurationType.STRING_LIST;
088                this.stringListValue = parameter;
089        }
090        
091        
092        @Override
093        public void parseConfiguration(final Object jsonEntity) throws ParseException {
094                if (jsonEntity instanceof Boolean) {
095                        configure(JSONUtils.toBoolean(jsonEntity));
096                } else if (jsonEntity instanceof String) {
097                        configure(JSONUtils.toString(jsonEntity));
098                } else {
099                        configure(JSONUtils.toStringList(jsonEntity));
100                }
101        }
102        
103        
104        @Override
105        public Map.Entry<String,Object> toJSONObjectEntry() {
106                if (configType == null) {
107                        throw new IllegalStateException("The policy is not initialized");
108                }
109                Object value;
110                if (configType.equals(ConfigurationType.BOOLEAN)) {
111                        value = getBooleanConfiguration();
112                } else if (configType.equals(ConfigurationType.STRING_LIST)) {
113                        value = getStringListConfiguration();
114                } else if (configType.equals(ConfigurationType.STRING)) {
115                        value = getStringConfiguration();
116                } else {
117                        throw new IllegalStateException("Unsupported configuration type: " + configType);
118                }
119                return new AbstractMap.SimpleImmutableEntry<>(getOperationName().getValue(), value);
120        }
121        
122        
123        @Override
124        public boolean getBooleanConfiguration() {
125                return booleanValue;
126        }
127        
128        
129        @Override
130        public String getStringConfiguration() {
131                return stringValue;
132        }
133        
134        
135        @Override
136        public List<String> getStringListConfiguration() {
137                return stringListValue;
138        }
139        
140        
141        @Override
142        public PolicyOperation merge(final PolicyOperation other)
143                throws PolicyViolationException {
144                
145                DefaultOperation otherTyped = Utils.castForMerge(other, DefaultOperation.class);
146                
147                if (configType == null || otherTyped.configType == null) {
148                        throw new PolicyViolationException("The default operation is not initialized");
149                }
150                
151                if (configType.equals(ConfigurationType.STRING_LIST)) {
152                        
153                        if (getStringListConfiguration() != null && getStringListConfiguration().equals(otherTyped.getStringListConfiguration())) {
154                                DefaultOperation copy = new DefaultOperation();
155                                copy.configure(getStringListConfiguration());
156                                return copy;
157                        }
158                }
159                
160                if (configType.equals(ConfigurationType.STRING)) {
161                        
162                        if (getStringConfiguration() != null && getStringConfiguration().equals(otherTyped.getStringConfiguration())) {
163                                DefaultOperation copy = new DefaultOperation();
164                                copy.configure(getStringConfiguration());
165                                return copy;
166                        }
167                        
168                }
169                
170                if (configType.equals(ConfigurationType.BOOLEAN)) {
171                        
172                        if (getBooleanConfiguration() == otherTyped.getBooleanConfiguration()) {
173                                DefaultOperation copy = new DefaultOperation();
174                                copy.configure(getBooleanConfiguration());
175                                return copy;
176                        }
177                }
178                
179                throw new PolicyViolationException("Default value mismatch");
180        }
181        
182        
183        @Override
184        public Object apply(final Object value) {
185                
186                if (configType == null) {
187                        throw new IllegalStateException("The policy is not initialized");
188                }
189                
190                if (value != null) {
191                        return value;
192                }
193                
194                // Return default value
195                
196                if (stringListValue != null) {
197                        return stringListValue;
198                }
199                if (stringValue != null) {
200                        return stringValue;
201                }
202                return booleanValue;
203        }
204}