64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr/*
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * The contents of this file are subject to the terms of the Common Development and
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * Distribution License (the License). You may not use this file except in compliance with the
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * License.
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr *
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * specific language governing permission and limitations under the License.
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr *
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * When distributing Covered Software, include this CDDL Header Notice in each file and include
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * Header, with the fields enclosed by brackets [] replaced by your own identifying
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * information: "Portions copyright [year] [name of copyright owner]".
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr *
f2b7e2373c5d1aacf05b91ab8e316d6aea0b948bDavid Luna * Copyright 2014-2016 ForgeRock AS.
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr */
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayrpackage com.sun.identity.common.configuration;
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayrimport com.sun.identity.sm.ServiceAttributeValidator;
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayrimport java.util.Set;
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayrimport java.util.regex.Matcher;
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayrimport java.util.regex.Pattern;
f2b7e2373c5d1aacf05b91ab8e316d6aea0b948bDavid Lunaimport org.forgerock.openam.utils.CollectionUtils;
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr/**
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * Validates map value properties in Agent Properties. e.g.
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * <code>com.sun.identity.agents.config.response.attribute.mapping[]=</code>
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * Map values should be Strings of the form:
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * [somekey] = somevalue
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * etc
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * l.h.s is key value surrounded by brackets
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * separator is mandatory "=" equals sign
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * r.h.s is some string value, anything since this is not so fined-
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * grained to test values of any one specific property's value set.
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * r.h.s can be empty or just whitespace
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * l.h.s key value can NOT be empty
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * l.h.s key values can not be duplicates
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * white space is allowed everywhere
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * blank or empty values are allowed as some props dont have any value
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * to be specified
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr *
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * Some strange examples that would be acceptable values:
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * blank or empty set
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * [a_key_but_no_value]= (note no value on r.h.s)
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * []= (a common default value)
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * [ ] = (variation on default value)
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * [key_and_or_value_contains_=_sign] == (equal sign is valid data)
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr *
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * Note:
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * brackets are not allowed as part of key or value data
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * exact duplicate keys are allowed
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr *
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr */
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayrpublic class DuplicateKeyMapValueValidator implements ServiceAttributeValidator {
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr private static final String regularExpression = MapValueValidator.KEY_WITH_NO_BRACKETS
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr + "|" + MapValueValidator.DEFAULT_NO_KEY_JUST_BRACKETS;
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr private static final Pattern pattern = Pattern.compile(regularExpression);
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr /**
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * Returns <code>true</code> if values are of map type format.
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr *
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * @param values contains the set of values to be validated
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr * @return <code>true</code> if values are of map type format
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr */
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr @Override
f2b7e2373c5d1aacf05b91ab8e316d6aea0b948bDavid Luna public boolean validate(Set<String> values) {
f2b7e2373c5d1aacf05b91ab8e316d6aea0b948bDavid Luna boolean valid = true; //blank or empty values set are valid
f2b7e2373c5d1aacf05b91ab8e316d6aea0b948bDavid Luna if (!CollectionUtils.isEmpty(values)) {
f2b7e2373c5d1aacf05b91ab8e316d6aea0b948bDavid Luna for (String val : values) {
f2b7e2373c5d1aacf05b91ab8e316d6aea0b948bDavid Luna final String trimmed = val.trim();
f2b7e2373c5d1aacf05b91ab8e316d6aea0b948bDavid Luna if (trimmed.length() > 0) {
f2b7e2373c5d1aacf05b91ab8e316d6aea0b948bDavid Luna Matcher matcher = pattern.matcher(trimmed);
f2b7e2373c5d1aacf05b91ab8e316d6aea0b948bDavid Luna valid = matcher.matches();
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr }
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr }
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr }
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr return valid;
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr }
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr
64b8bb9abaf1a8b80d4e1b12e8b44afd6481e33eBernhard Thalmayr}