001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at 010 * docs/licenses/cddl.txt 011 * or http://www.opensource.org/licenses/cddl1.php. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * docs/licenses/cddl.txt. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2017-2021 Ping Identity Corporation 026 */ 027package com.unboundid.directory.sdk.common.types; 028 029import com.unboundid.ldap.sdk.LDAPException; 030import com.unboundid.util.ThreadSafety; 031import com.unboundid.util.ThreadSafetyLevel; 032 033import java.util.List; 034 035/** 036 * A ValueConstructor is used to build String values using a value-pattern 037 * template that references attribute values within an Entry. An instance is 038 * created by calling {@link ServerContext#createValueConstructor}. 039 * 040 * <h2>Referencing Attribute Values</h2> 041 * 042 * Any text provided in the value-pattern is copied verbatim into the 043 * constructed value with the exception of attribute names embedded 044 * in '{}'s. For instance, a value template of "{uid}@example.com" 045 * and an entry with a uid value of "jsmith" would produce a value 046 * of "jsmith@example.com". 047 * 048 * <p> 049 * If a value template references multiple attributes, at most one may be 050 * multivalued. If one attribute is multivalued then the returned value 051 * will be multivalued with the same number of values. 052 * For example a template of '{givenName} {sn}' would produce 053 * values ['Jim Smith', 'James Smith'] if givenName had values of ['Jim', 054 * 'James'] and sn had a value of 'Smith'. If the source entry has no 055 * value or if there are multiple multivalued attributes, the attribute 056 * value construction will fail. 057 * 058 * <p> 059 * To include a '{' in the constructed value (when constructing JSON for 060 * instance) use '{{' in the value-pattern. Likewise, '}}' will result in '}' 061 * in the value pattern. 062 * 063 * <h2>Regular Expressions</h2> 064 * 065 * A regular expression with a substitution pattern can be used 066 * to further manipulate an individual attribute 067 * value. The java.util.regex.Pattern and java.util.regex.Matcher 068 * classes are used to perform the substitution. 069 * The regular expression with replacement value uses this syntax 070 * '{attr-name:/regex/replacement/flags}'. 071 * <ul> 072 * <li> 073 * 'attr-name' is an attribute name such as 'cn'. 074 * </li> 075 * <li> 076 * 'regex' is a regular expression using the syntax described in the 077 * java.util.regex.Pattern javadoc. The optional flag value can also 078 * be used to change how this regular expression is interpreted. 079 * </li> 080 * <li> 081 * 'replacement' is a replacement value that is passed to the 082 * java.util.regex.Matcher#replaceFirst or java.util.regex.Matcher#replaceAll 083 * method to perform the replacement. The 'g' (global) flag controls 084 * whether replaceFirst or replaceAll is called. 085 * </li> 086 * <li> 087 * 'flags' is an optional set of single character flags that 088 * control how the regular expression is interpreted and how the replacement 089 * is performed. The flags are: 090 * <ul> 091 * <li> 092 * 'g' : Matcher#replaceAll is called instead of Matcher#replaceFirst to 093 * replace all matching values instead of just the first one. 094 * </li> 095 * <li> 096 * 'i' : the regex pattern is compiled with Pattern.CASE_INSENSITIVE. 097 * </li> 098 * <li> 099 * 'x' : the regex pattern is compiled with Pattern.COMMENTS. 100 * </li> 101 * <li> 102 * 's' : the regex pattern is compiled with Pattern.DOTALL. 103 * </li> 104 * <li> 105 * 'm' : the regex pattern is compiled with Pattern.MULTILINE. 106 * </li> 107 * <li> 108 * 'u' : the regex pattern is compiled with Pattern.UNICODE_CASE. 109 * </li> 110 * <li> 111 * 'd' : the regex pattern is compiled with Pattern.UNIX_LINES. 112 * </li> 113 * </ul> 114 * </ul> 115 * 116 * The substitution value is constructed using Java code equivalent to: 117 * <pre> 118 * Pattern pattern = Pattern.compile(regex, flagsMask); 119 * Matcher matcher = pattern.matcher(attributeValueInput); 120 * String substitutionValueOutput = matcher.replaceFirst(replacement); 121 * </pre> 122 * 123 * <h2>JSON Attribute Values</h2> 124 * 125 * To extract JSON fields within JSON attributes append '.' and then the 126 * JSON field to extract to the attribute name. For example, if 127 * 'ubidEmailJSON' is a JSON attribute and the 'value' field is to be 128 * extracted then 'ubidEmailJSON.value' could be specified for the attribute 129 * name resulting in '{ubidEmailJSON.value}' or 130 * '{ubidEmailJSON.value:/regex/replacement/flags}' if a regular expression 131 * is to be used. 132 * 133 * <h2>Escaping and Transforming Attribute Values</h2> 134 * 135 * To apply modifiers to the values extracted append ':' and then the name 136 * of the modifier to apply. For example, if attribute 'mail' is to be 137 * included in a constructed JSON value then modifier 'jsonEscape' could be 138 * specified resulting in '{{ "userMail":"{mail:jsonEscape}" }}' or 139 * '{{ "userMail":"{mail:/regex/replacement/flags:jsonEscape}" }}' if a 140 * regular expression is to be used. Note that '{{' expands to '{' and 141 * '}}' to '}'. 142 * 143 * <p> 144 * The modifiers are: 145 * <ul> 146 * <li> 147 * 'dnEscape' : Escape text for use in a DN value. 148 * </li> 149 * <li> 150 * 'jsonEscape' : Escape text for use in a JSON value. 151 * </li> 152 * <li> 153 * 'ldapFilterEscape' : Escape text for use in an LDAP filter. 154 * </li> 155 * <li> 156 * 'lowerCase' : Convert text to lower case. 157 * </li> 158 * <li> 159 * 'trim' : Remove leading and trailing whitespace. 160 * </li> 161 * <li> 162 * 'upperCase' : Convert text to upper case. 163 * </li> 164 * </ul> 165 * 166 * <h2>Example</h2> 167 * Here is an example to summarize these points. Suppose, the 'uid' 168 * field of the target entry needs to be populated with the initials of 169 * the first and last name followed by the user's employee number which 170 * is stored in the 'eid' attribute. For example, 'John Smith' with an 171 * employee id of 12345, would get a uid of 'js12345'. The value-pattern 172 * would be 173 * '{givenname:/^(.)(.*)/$1/s:lowerCase}{sn:/^(.)(.*)/$1/s:lowerCase}{eid}'. 174 * The employee's initials are extracted from the 'givenname' and 'sn' 175 * attributes. The '^(.)(.*)' regular expression used for these attributes 176 * matches the entire value and stores the initial character in the $1 177 * variable, which is used for the replacement. (The 's' flag is used to 178 * guard against the unlikely event that the user's 'givenname' or 'sn' 179 * attribute includes a newline character.) The lowerCase modifier converts 180 * the initial to lowercase. 181 */ 182@ThreadSafety(level= ThreadSafetyLevel.INTERFACE_THREADSAFE) 183public interface ValueConstructor 184{ 185 /** 186 * Returns a list of values constructed using the value template that was 187 * used to create this ValueConstructor substituting attribute values from 188 * the provided entry where they appear in the value template. 189 * 190 * @param entry Attributes referenced in the value template are pulled from 191 * this entry. 192 * 193 * @return The list of attribute values based on the value template and the 194 * specified entry. 195 * 196 * @throws LDAPException If the provided entry does not include values for 197 * all attributes that appear in the value template; 198 * if the value template includes regular expressions 199 * for extracting portions of an attribute value, and 200 * the attribute value does not match the regular 201 * expression; or if the value template references 202 * multiple attributes that have more than one value. 203 */ 204 List<String> constructValues(com.unboundid.ldap.sdk.Entry entry) 205 throws LDAPException; 206 207 208 /** 209 * Returns a list of values constructed using the value template that was 210 * used to create this ValueConstructor substituting attribute values from 211 * the provided entry where they appear in the value template. 212 * 213 * @param entry Attributes referenced in the value template are pulled from 214 * this entry. 215 * 216 * @return The list of attribute values based on the value template and the 217 * specified entry. 218 * 219 * @throws LDAPException If the provided entry does not include values for 220 * all attributes that appear in the value template; 221 * if the value template includes regular expressions 222 * for extracting portions of an attribute value, and 223 * the attribute value does not match the regular 224 * expression; or if the value template references 225 * multiple attributes that have more than one value. 226 */ 227 List<String> constructValues( 228 com.unboundid.directory.sdk.common.types.Entry entry) 229 throws LDAPException; 230}