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 legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *      Copyright 2011 ForgeRock AS
024 */
025
026package org.forgerock.opendj.ldif;
027
028import static com.forgerock.opendj.ldap.CoreMessages.REJECTED_CHANGE_FAIL_ADD_DUPE;
029import static com.forgerock.opendj.ldap.CoreMessages.REJECTED_CHANGE_FAIL_MODIFYDN_DUPE;
030
031import org.forgerock.i18n.LocalizableMessage;
032import org.forgerock.opendj.ldap.DecodeException;
033import org.forgerock.opendj.ldap.Entry;
034import org.forgerock.opendj.ldap.requests.AddRequest;
035import org.forgerock.opendj.ldap.requests.DeleteRequest;
036import org.forgerock.opendj.ldap.requests.ModifyDNRequest;
037import org.forgerock.opendj.ldap.requests.ModifyRequest;
038
039/**
040 * A listener interface which is notified whenever a change record cannot be
041 * applied to an entry. This may occur when an attempt is made to update a
042 * non-existent entry, or add an entry which already exists.
043 * <p>
044 * By default the {@link #FAIL_FAST} listener is used.
045 */
046public interface RejectedChangeRecordListener {
047    /**
048     * A handler which terminates processing by throwing a
049     * {@code DecodeException} as soon as a change is rejected.
050     */
051    RejectedChangeRecordListener FAIL_FAST = new RejectedChangeRecordListener() {
052
053        public Entry handleDuplicateEntry(final AddRequest change, final Entry existingEntry) throws DecodeException {
054            throw DecodeException.error(REJECTED_CHANGE_FAIL_ADD_DUPE.get(change.getName()));
055        }
056
057        public Entry handleDuplicateEntry(final ModifyDNRequest change, final Entry existingEntry,
058                final Entry renamedEntry) throws DecodeException {
059            throw DecodeException.error(REJECTED_CHANGE_FAIL_MODIFYDN_DUPE.get(renamedEntry.getName()));
060        }
061
062        public void handleRejectedChangeRecord(final AddRequest change, final LocalizableMessage reason)
063                throws DecodeException {
064            throw DecodeException.error(reason);
065        }
066
067        public void handleRejectedChangeRecord(final DeleteRequest change, final LocalizableMessage reason)
068                throws DecodeException {
069            throw DecodeException.error(reason);
070        }
071
072        public void handleRejectedChangeRecord(final ModifyRequest change, final LocalizableMessage reason)
073                throws DecodeException {
074            throw DecodeException.error(reason);
075        }
076
077        public void handleRejectedChangeRecord(final ModifyDNRequest change, final LocalizableMessage reason)
078                throws DecodeException {
079            throw DecodeException.error(reason);
080        }
081
082    };
083
084    /**
085     * The default handler which ignores changes applied to missing entries and
086     * tolerates duplicate entries by overwriting the existing entry with the
087     * new entry.
088     */
089    RejectedChangeRecordListener OVERWRITE = new RejectedChangeRecordListener() {
090
091        public Entry handleDuplicateEntry(final AddRequest change, final Entry existingEntry) throws DecodeException {
092            // Overwrite existing entries.
093            return change;
094        }
095
096        public Entry handleDuplicateEntry(final ModifyDNRequest change, final Entry existingEntry,
097                final Entry renamedEntry) throws DecodeException {
098            // Overwrite existing entries.
099            return renamedEntry;
100        }
101
102        public void handleRejectedChangeRecord(AddRequest change, LocalizableMessage reason) throws DecodeException {
103            // Ignore.
104        }
105
106        public void handleRejectedChangeRecord(DeleteRequest change, LocalizableMessage reason)
107                throws DecodeException {
108            // Ignore.
109        }
110
111        public void handleRejectedChangeRecord(ModifyRequest change, LocalizableMessage reason)
112                throws DecodeException {
113            // Ignore.
114        }
115
116        public void handleRejectedChangeRecord(ModifyDNRequest change, LocalizableMessage reason)
117                throws DecodeException {
118            // Ignore.
119        }
120
121    };
122
123    /**
124     * Invoked when an attempt was made to add an entry which already exists.
125     *
126     * @param change
127     *            The conflicting add request.
128     * @param existingEntry
129     *            The pre-existing entry.
130     * @return The entry which should be kept.
131     * @throws DecodeException
132     *             If processing should terminate.
133     */
134    Entry handleDuplicateEntry(AddRequest change, Entry existingEntry) throws DecodeException;
135
136    /**
137     * Invoked when an attempt was made to rename an entry which already exists.
138     *
139     * @param change
140     *            The conflicting add request.
141     * @param existingEntry
142     *            The pre-existing entry.
143     * @param renamedEntry
144     *            The renamed entry.
145     * @return The entry which should be kept.
146     * @throws DecodeException
147     *             If processing should terminate.
148     */
149    Entry handleDuplicateEntry(ModifyDNRequest change, Entry existingEntry, Entry renamedEntry)
150            throws DecodeException;
151
152    /**
153     * Invoked when an attempt to add an entry was rejected. This may be because
154     * the target parent entry was not found, or controls provided with the
155     * request are not supported. This method will not be called when the entry
156     * to be added already exists, since this is handled by
157     * {@link #handleDuplicateEntry(AddRequest, Entry)}.
158     *
159     * @param change
160     *            The rejected add request.
161     * @param reason
162     *            The reason why the record was rejected.
163     * @throws DecodeException
164     *             If processing should terminate.
165     */
166    void handleRejectedChangeRecord(AddRequest change, LocalizableMessage reason)
167            throws DecodeException;
168
169    /**
170     * Invoked when an attempt to delete an entry was rejected. This may be
171     * because the target entry was not found, or controls provided with the
172     * request are not supported.
173     *
174     * @param change
175     *            The rejected delete request.
176     * @param reason
177     *            The reason why the record was rejected.
178     * @throws DecodeException
179     *             If processing should terminate.
180     */
181    void handleRejectedChangeRecord(DeleteRequest change, LocalizableMessage reason)
182            throws DecodeException;
183
184    /**
185     * Invoked when an attempt to modify an entry was rejected. This may be
186     * because the target entry was not found, or controls provided with the
187     * request are not supported.
188     *
189     * @param change
190     *            The rejected modify request.
191     * @param reason
192     *            The reason why the record was rejected.
193     * @throws DecodeException
194     *             If processing should terminate.
195     */
196    void handleRejectedChangeRecord(ModifyRequest change, LocalizableMessage reason)
197            throws DecodeException;
198
199    /**
200     * Invoked when an attempt to rename an entry was rejected. This may be
201     * because the target entry was not found, or controls provided with the
202     * request are not supported. This method will not be called when a renamed
203     * entry already exists, since this is handled by
204     * {@link #handleDuplicateEntry(ModifyDNRequest, Entry, Entry)}.
205     *
206     * @param change
207     *            The rejected modify DN request.
208     * @param reason
209     *            The reason why the record was rejected.
210     * @throws DecodeException
211     *             If processing should terminate.
212     */
213    void handleRejectedChangeRecord(ModifyDNRequest change, LocalizableMessage reason)
214            throws DecodeException;
215
216}