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-2015 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.util.promise.Promise;
030
031/** An attribute mapper is responsible for converting JSON values to and from LDAP attributes. */
032public abstract class AttributeMapper {
033    /*
034     * This interface is an abstract class so that methods can be made package
035     * private until API is finalized.
036     */
037
038    AttributeMapper() {
039        // Nothing to do.
040    }
041
042    /**
043     * Maps a JSON value to one or more LDAP attributes, returning a promise
044     * once the transformation has completed. This method is invoked when a REST
045     * resource is created using a create request.
046     * <p>
047     * If the JSON value corresponding to this mapper is not present in the
048     * resource then this method will be invoked with a value of {@code null}.
049     * It is the responsibility of the mapper implementation to take appropriate
050     * action in this case, perhaps by substituting default LDAP values, or by
051     * returning a failed promise with an appropriate {@link ResourceException}.
052     *
053     * @param requestState
054     *            The request state.
055     * @param path
056     *            The pointer from the root of the JSON resource to this
057     *            attribute mapper. This may be used when constructing error
058     *            messages.
059     * @param v
060     *            The JSON value to be converted to LDAP attributes, which may
061     *            be {@code null} indicating that the JSON value was not present
062     *            in the resource.
063     * @return A {@link Promise} containing the result of the operation.
064     */
065    abstract Promise<List<Attribute>, ResourceException> create(
066            RequestState requestState, JsonPointer path, JsonValue v);
067
068    /**
069     * Adds the names of the LDAP attributes required by this attribute mapper
070     * to the provided set.
071     * <p>
072     * Implementations should only add the names of attributes found in the LDAP
073     * entry directly associated with the resource.
074     *
075     * @param requestState
076     *            The request state.
077     * @param path
078     *            The pointer from the root of the JSON resource to this
079     *            attribute mapper. This may be used when constructing error
080     *            messages.
081     * @param subPath
082     *            The targeted JSON field relative to this attribute mapper, or
083     *            root if all attributes associated with this mapper have been
084     *            targeted.
085     * @param ldapAttributes
086     *            The set into which the required LDAP attribute names should be
087     *            put.
088     */
089    abstract void getLDAPAttributes(
090            RequestState requestState, JsonPointer path, JsonPointer subPath, Set<String> ldapAttributes);
091
092    /**
093     * Transforms the provided REST comparison filter parameters to an LDAP
094     * filter representation, returning a promise once the transformation has
095     * completed.
096     * <p>
097     * If an error occurred while constructing the LDAP filter, then a failed
098     * promise must be returned with an appropriate {@link ResourceException}
099     * indicating the problem which occurred.
100     *
101     * @param requestState
102     *            The request state.
103     * @param path
104     *            The pointer from the root of the JSON resource to this
105     *            attribute mapper. This may be used when constructing error
106     *            messages.
107     * @param subPath
108     *            The targeted JSON field relative to this attribute mapper, or
109     *            root if all attributes associated with this mapper have been
110     *            targeted.
111     * @param type
112     *            The type of REST comparison filter.
113     * @param operator
114     *            The name of the extended operator to use for the comparison,
115     *            or {@code null} if {@code type} is not
116     *            {@link FilterType#EXTENDED}.
117     * @param valueAssertion
118     *            The value assertion, or {@code null} if {@code type} is
119     *            {@link FilterType#PRESENT}.
120     * @return A {@link Promise} containing the result of the operation.
121     */
122    abstract Promise<Filter, ResourceException> getLDAPFilter(RequestState requestState, JsonPointer path,
123            JsonPointer subPath, FilterType type, String operator, Object valueAssertion);
124
125    /**
126     * Maps a JSON patch operation to one or more LDAP modifications, returning
127     * a promise once the transformation has completed. This method is invoked
128     * when a REST resource is modified using a patch request.
129     *
130     * @param requestState
131     *            The request state.
132     * @param path
133     *            The pointer from the root of the JSON resource to this
134     *            attribute mapper. This may be used when constructing error
135     *            messages.
136     * @param operation
137     *            The JSON patch operation to be converted to LDAP
138     *            modifications. The targeted JSON field will be relative to
139     *            this attribute mapper, or root if all attributes associated
140     *            with this mapper have been targeted.
141     * @return A {@link Promise} containing the result of the operation.
142     */
143    abstract Promise<List<Modification>, ResourceException> patch(
144            RequestState requestState, JsonPointer path, PatchOperation operation);
145
146    /**
147     * Maps one or more LDAP attributes to their JSON representation, returning
148     * a promise once the transformation has completed.
149     * <p>
150     * This method is invoked whenever an LDAP entry is converted to a REST
151     * resource, i.e. when responding to read, query, create, put, or patch
152     * requests.
153     * <p>
154     * If the LDAP attributes are not present in the entry, perhaps because they
155     * are optional, then implementations should return a successful promise
156     * with a result of {@code null}. If the LDAP attributes cannot be mapped
157     * for any other reason, perhaps because they are required but missing, or
158     * they contain unexpected content, then a failed promise must be returned
159     * with an appropriate exception indicating the problem which occurred.
160     *
161     * @param requestState
162     *            The request state.
163     * @param path
164     *            The pointer from the root of the JSON resource to this
165     *            attribute mapper. This may be used when constructing error
166     *            messages.
167     * @param e
168     *            The LDAP entry to be converted to JSON.
169     * @return A {@link Promise} containing the result of the operation.
170     */
171    abstract Promise<JsonValue, ResourceException> read(RequestState requestState, JsonPointer path, Entry e);
172
173    /**
174     * Maps a JSON value to one or more LDAP modifications, returning a promise
175     * once the transformation has completed. This method is invoked when a REST
176     * resource is modified using an update request.
177     * <p>
178     * If the JSON value corresponding to this mapper is not present in the
179     * resource then this method will be invoked with a value of {@code null}.
180     * It is the responsibility of the mapper implementation to take appropriate
181     * action in this case, perhaps by substituting default LDAP values, or by
182     * returning a failed promise with an appropriate {@link ResourceException}.
183     *
184     * @param requestState
185     *            The request state.
186     * @param v
187     *            The JSON value to be converted to LDAP attributes, which may
188     *            be {@code null} indicating that the JSON value was not present
189     *            in the resource.
190     * @return A {@link Promise} containing the result of the operation.
191     */
192    abstract Promise<List<Modification>, ResourceException> update(
193            RequestState requestState, JsonPointer path, Entry e, JsonValue v);
194
195    // TODO: methods for obtaining schema information (e.g. name, description, type information).
196    // TODO: methods for creating sort controls.
197}