001/*
002 * oauth2-oidc-sdk
003 *
004 * Copyright 2012-2020, 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.factories;
019
020
021import java.util.*;
022
023import net.jcip.annotations.ThreadSafe;
024import net.minidev.json.JSONObject;
025
026import com.nimbusds.openid.connect.sdk.federation.policy.MetadataPolicy;
027import com.nimbusds.openid.connect.sdk.federation.policy.MetadataPolicyEntry;
028import com.nimbusds.openid.connect.sdk.federation.policy.language.PolicyOperation;
029import com.nimbusds.openid.connect.sdk.federation.policy.operations.ValueOperation;
030import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
031import com.nimbusds.openid.connect.sdk.rp.OIDCClientMetadata;
032
033
034/**
035 * The default OpenID relying party metadata policy factory.
036 */
037@ThreadSafe
038public class DefaultRPMetadataPolicyFactory implements RPMetadataPolicyFactory {
039        
040        
041        @Override
042        public MetadataPolicy create(final OIDCClientMetadata initialMetadata, final OIDCClientInformation target)
043                throws PolicyFormulationException {
044                
045                MetadataPolicy policy = new MetadataPolicy();
046                
047                JSONObject initialJSONObject = initialMetadata.toJSONObject();
048                
049                for (Map.Entry<String,Object> en: target.toJSONObject().entrySet()) {
050                        
051                        if (en.equals(new AbstractMap.SimpleImmutableEntry<>(en.getKey(), initialJSONObject.get(en.getKey())))) {
052                                // No policy entry needed
053                                continue;
054                        }
055                        
056                        // Set (override) value
057                        MetadataPolicyEntry policyEntry = new MetadataPolicyEntry(
058                                en.getKey(),
059                                Collections.singletonList((PolicyOperation) createValueOperation(en))
060                        );
061                        
062                        policy.put(policyEntry);
063                }
064                
065                return policy;
066        }
067        
068        
069        private static ValueOperation createValueOperation(final Map.Entry<String,Object> objectEntry)
070                throws PolicyFormulationException {
071                
072                ValueOperation valueOperation = new ValueOperation();
073                
074                if (objectEntry.getValue() instanceof String) {
075                        valueOperation.configure((String)objectEntry.getValue());
076                        
077                } else if (objectEntry.getValue() instanceof Boolean) {
078                        valueOperation.configure((Boolean)objectEntry.getValue());
079                        
080                } else if (objectEntry.getValue() instanceof Number) {
081                        valueOperation.configure((Number)objectEntry.getValue());
082                        
083                } else if (objectEntry.getValue() instanceof List) {
084                        // assume string list
085                        List<String> stringList = new LinkedList<>();
086                        
087                        for (Object item : (List<?>) objectEntry.getValue()) {
088                                if (item instanceof String) {
089                                        stringList.add((String) item);
090                                } else {
091                                        stringList.add(null);
092                                }
093                        }
094                        valueOperation.configure(stringList);
095                } else if (objectEntry.getValue() == null) {
096                        valueOperation.configure((String)null);
097                } else {
098                        throw new PolicyFormulationException("Unsupported type for " + objectEntry.getKey() + ": " + objectEntry.getValue().getClass() + ": " + objectEntry.getValue());
099                }
100                
101                return valueOperation;
102        }
103        
104}