001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2012-2016 ForgeRock AS.
015 */
016package org.forgerock.opendj.rest2ldap;
017
018import java.util.List;
019import java.util.Set;
020
021import org.forgerock.json.JsonPointer;
022import org.forgerock.json.JsonValue;
023import org.forgerock.json.resource.PatchOperation;
024import org.forgerock.json.resource.ResourceException;
025import org.forgerock.opendj.ldap.Attribute;
026import org.forgerock.opendj.ldap.Entry;
027import org.forgerock.opendj.ldap.Filter;
028import org.forgerock.opendj.ldap.Modification;
029import org.forgerock.services.context.Context;
030import org.forgerock.util.promise.Promise;
031
032/** An property mapper is responsible for converting JSON values to and from LDAP attributes. */
033public abstract class PropertyMapper {
034    /*
035     * This interface is an abstract class so that methods can be made package
036     * private until API is finalized.
037     */
038
039    PropertyMapper() {
040        // Nothing to do.
041    }
042
043    abstract boolean isRequired();
044
045    abstract boolean isMultiValued();
046
047    /**
048     * Maps a JSON value to one or more LDAP attributes, returning a promise
049     * once the transformation has completed. This method is invoked when a REST
050     * resource is created using a create request.
051     * <p>
052     * If the JSON value corresponding to this mapper is not present in the
053     * resource then this method will be invoked with a value of {@code null}.
054     * It is the responsibility of the mapper implementation to take appropriate
055     * action in this case, perhaps by substituting default LDAP values, or by
056     * returning a failed promise with an appropriate {@link ResourceException}.
057     *
058     * @param context The request context.
059     * @param resource The exact type of resource being created.
060     * @param path
061     *            The pointer from the root of the JSON resource to this
062     *            property mapper. This may be used when constructing error
063     *            messages.
064     * @param v
065     *            The JSON value to be converted to LDAP attributes, which may
066     *            be {@code null} indicating that the JSON value was not present
067     *            in the resource.
068     * @return A {@link Promise} containing the result of the operation.
069     */
070    abstract Promise<List<Attribute>, ResourceException> create(Context context, Resource resource,
071                                                                JsonPointer path, JsonValue v);
072
073    /**
074     * Adds the names of the LDAP attributes required by this property mapper
075     * to the provided set.
076     * <p>
077     * Implementations should only add the names of attributes found in the LDAP
078     * entry directly associated with the resource.
079     *
080     * @param path
081     *            The pointer from the root of the JSON resource to this
082     *            property mapper. This may be used when constructing error
083     *            messages.
084     * @param subPath
085     *            The targeted JSON field relative to this property mapper, or
086     *            root if all attributes associated with this mapper have been
087     *            targeted.
088     * @param ldapAttributes
089 *            The set into which the required LDAP attribute names should be
090     */
091    abstract void getLdapAttributes(JsonPointer path, JsonPointer subPath, Set<String> ldapAttributes);
092
093    /**
094     * Transforms the provided REST comparison filter parameters to an LDAP
095     * filter representation, returning a promise once the transformation has
096     * completed.
097     * <p>
098     * If an error occurred while constructing the LDAP filter, then a failed
099     * promise must be returned with an appropriate {@link ResourceException}
100     * indicating the problem which occurred.
101     *
102     * @param context The request context.
103     * @param resource The type of resource being queried.
104     * @param path
105     *            The pointer from the root of the JSON resource to this
106     *            property mapper. This may be used when constructing error
107     *            messages.
108     * @param subPath
109     *            The targeted JSON field relative to this property mapper, or
110     *            root if all attributes associated with this mapper have been
111     *            targeted.
112     * @param type
113     *            The type of REST comparison filter.
114     * @param operator
115     *            The name of the extended operator to use for the comparison,
116     *            or {@code null} if {@code type} is not
117     *            {@link FilterType#EXTENDED}.
118     * @param valueAssertion
119     *            The value assertion, or {@code null} if {@code type} is
120     *            {@link FilterType#PRESENT}.
121     * @return A {@link Promise} containing the result of the operation.
122     */
123    abstract Promise<Filter, ResourceException> getLdapFilter(Context context, Resource resource,
124                                                              JsonPointer path, JsonPointer subPath, FilterType type,
125                                                              String operator, Object valueAssertion);
126
127    /**
128     * Maps a JSON patch operation to one or more LDAP modifications, returning
129     * a promise once the transformation has completed. This method is invoked
130     * when a REST resource is modified using a patch request.
131     *
132     * @param context The request context.
133     * @param resource The exact type of resource being patched.
134     * @param path
135     *            The pointer from the root of the JSON resource to this
136     *            property mapper. This may be used when constructing error
137     *            messages.
138     * @param operation
139     *            The JSON patch operation to be converted to LDAP
140     *            modifications. The targeted JSON field will be relative to
141     *            this property mapper, or root if all attributes associated
142     *            with this mapper have been targeted.
143     * @return A {@link Promise} containing the result of the operation.
144     */
145    abstract Promise<List<Modification>, ResourceException> patch(Context context, Resource resource,
146                                                                  JsonPointer path, PatchOperation operation);
147
148    /**
149     * Maps one or more LDAP attributes to their JSON representation, returning
150     * a promise once the transformation has completed.
151     * <p>
152     * This method is invoked whenever an LDAP entry is converted to a REST
153     * resource, i.e. when responding to read, query, create, put, or patch
154     * requests.
155     * <p>
156     * If the LDAP attributes are not present in the entry, perhaps because they
157     * are optional, then implementations should return a successful promise
158     * with a result of {@code null}. If the LDAP attributes cannot be mapped
159     * for any other reason, perhaps because they are required but missing, or
160     * they contain unexpected content, then a failed promise must be returned
161     * with an appropriate exception indicating the problem which occurred.
162     *
163     * @param context The request context.
164     * @param resource The exact type of resource being read.
165     * @param path
166     *            The pointer from the root of the JSON resource to this
167     *            property mapper. This may be used when constructing error
168     *            messages.
169     * @param e
170     *            The LDAP entry to be converted to JSON.
171     * @return A {@link Promise} containing the result of the operation.
172     */
173    abstract Promise<JsonValue, ResourceException> read(Context context, Resource resource,
174                                                        JsonPointer path, Entry e);
175
176    /**
177     * Maps a JSON value to one or more LDAP modifications, returning a promise
178     * once the transformation has completed. This method is invoked when a REST
179     * resource is modified using an update request.
180     * <p>
181     * If the JSON value corresponding to this mapper is not present in the
182     * resource then this method will be invoked with a value of {@code null}.
183     * It is the responsibility of the mapper implementation to take appropriate
184     * action in this case, perhaps by substituting default LDAP values, or by
185     * returning a failed promise with an appropriate {@link ResourceException}.
186     *
187     * @param context The request context.
188     * @param resource The exact type of resource being updated.
189     * @param path the path to update.
190     * @param e the entry containing the new value.
191     * @param v
192     *            The JSON value to be converted to LDAP attributes, which may
193     *            be {@code null} indicating that the JSON value was not present
194     *            in the resource.
195     * @return A {@link Promise} containing the result of the operation.
196     */
197    abstract Promise<List<Modification>, ResourceException> update(Context context, Resource resource,
198                                                                   JsonPointer path, Entry e, JsonValue v);
199
200    // TODO: methods for creating sort controls.
201
202    /**
203     * Returns the non-null JSON schema for this property mapper.
204     *
205     * @return the non-null JSON schema for this property mapper
206     */
207    abstract JsonValue toJsonSchema();
208}