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