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 *
024 *      Copyright 2010 Sun Microsystems, Inc.
025 *      Portions copyright 2012 ForgeRock AS.
026 */
027
028package org.forgerock.opendj.ldap.responses;
029
030import org.forgerock.i18n.LocalizedIllegalArgumentException;
031import org.forgerock.opendj.ldap.ByteString;
032import org.forgerock.opendj.ldap.DN;
033import org.forgerock.opendj.ldap.Entry;
034import org.forgerock.opendj.ldap.LinkedHashMapEntry;
035import org.forgerock.opendj.ldap.ResultCode;
036
037import org.forgerock.util.Reject;
038
039/**
040 * This class contains various methods for creating and manipulating responses.
041 * <p>
042 * All copy constructors of the form {@code copyOfXXXResult} perform deep copies
043 * of their response parameter. More specifically, any controls, modifications,
044 * and attributes contained within the response will be duplicated.
045 * <p>
046 * Similarly, all unmodifiable views of responses returned by methods of the
047 * form {@code unmodifiableXXXResult} return deep unmodifiable views of their
048 * response parameter. More specifically, any controls, modifications, and
049 * attributes contained within the returned response will be unmodifiable.
050 */
051public final class Responses {
052
053    // TODO: search reference from LDAP URL.
054
055    // TODO: referral from LDAP URL.
056
057    // TODO: synchronized requests?
058
059    /**
060     * Creates a new bind result that is an exact copy of the provided result.
061     *
062     * @param result
063     *            The bind result to be copied.
064     * @return The new bind result.
065     * @throws NullPointerException
066     *             If {@code result} was {@code null}.
067     */
068    public static BindResult copyOfBindResult(final BindResult result) {
069        return new BindResultImpl(result);
070    }
071
072    /**
073     * Creates a new compare result that is an exact copy of the provided
074     * result.
075     *
076     * @param result
077     *            The compare result to be copied.
078     * @return The new compare result.
079     * @throws NullPointerException
080     *             If {@code result} was {@code null}.
081     */
082    public static CompareResult copyOfCompareResult(final CompareResult result) {
083        return new CompareResultImpl(result);
084    }
085
086    /**
087     * Creates a new generic extended result that is an exact copy of the
088     * provided result.
089     *
090     * @param result
091     *            The generic extended result to be copied.
092     * @return The new generic extended result.
093     * @throws NullPointerException
094     *             If {@code result} was {@code null}.
095     */
096    public static GenericExtendedResult copyOfGenericExtendedResult(
097            final GenericExtendedResult result) {
098        return new GenericExtendedResultImpl(result);
099    }
100
101    /**
102     * Creates a new generic intermediate response that is an exact copy of the
103     * provided response.
104     *
105     * @param result
106     *            The generic intermediate response to be copied.
107     * @return The new generic intermediate response.
108     * @throws NullPointerException
109     *             If {@code result} was {@code null}.
110     */
111    public static GenericIntermediateResponse copyOfGenericIntermediateResponse(
112            final GenericIntermediateResponse result) {
113        return new GenericIntermediateResponseImpl(result);
114    }
115
116    /**
117     * Creates a new password modify extended result that is an exact copy of
118     * the provided result.
119     *
120     * @param result
121     *            The password modify extended result to be copied.
122     * @return The new password modify extended result.
123     * @throws NullPointerException
124     *             If {@code result} was {@code null}.
125     */
126    public static PasswordModifyExtendedResult copyOfPasswordModifyExtendedResult(
127            final PasswordModifyExtendedResult result) {
128        return new PasswordModifyExtendedResultImpl(result);
129    }
130
131    /**
132     * Creates a new result that is an exact copy of the provided result.
133     *
134     * @param result
135     *            The result to be copied.
136     * @return The new result.
137     * @throws NullPointerException
138     *             If {@code result} was {@code null}.
139     */
140    public static Result copyOfResult(final Result result) {
141        return new ResultImpl(result);
142    }
143
144    /**
145     * Creates a new search result entry that is an exact copy of the provided
146     * result.
147     *
148     * @param entry
149     *            The search result entry to be copied.
150     * @return The new search result entry.
151     * @throws NullPointerException
152     *             If {@code entry} was {@code null}.
153     */
154    public static SearchResultEntry copyOfSearchResultEntry(final SearchResultEntry entry) {
155        return new SearchResultEntryImpl(entry);
156    }
157
158    /**
159     * Creates a new search result reference that is an exact copy of the
160     * provided result.
161     *
162     * @param reference
163     *            The search result reference to be copied.
164     * @return The new search result reference.
165     * @throws NullPointerException
166     *             If {@code reference} was {@code null}.
167     */
168    public static SearchResultReference copyOfSearchResultReference(
169            final SearchResultReference reference) {
170        return new SearchResultReferenceImpl(reference);
171    }
172
173    /**
174     * Creates a new who am I extended result that is an exact copy of the
175     * provided result.
176     *
177     * @param result
178     *            The who am I result to be copied.
179     * @return The new who am I extended result.
180     * @throws NullPointerException
181     *             If {@code result} was {@code null} .
182     */
183    public static WhoAmIExtendedResult copyOfWhoAmIExtendedResult(final WhoAmIExtendedResult result) {
184        return new WhoAmIExtendedResultImpl(result);
185    }
186
187    /**
188     * Creates a new bind result using the provided result code.
189     *
190     * @param resultCode
191     *            The result code.
192     * @return The new bind result.
193     * @throws NullPointerException
194     *             If {@code resultCode} was {@code null}.
195     */
196    public static BindResult newBindResult(final ResultCode resultCode) {
197        Reject.ifNull(resultCode);
198        return new BindResultImpl(resultCode);
199    }
200
201    /**
202     * Creates a new compare result using the provided result code.
203     *
204     * @param resultCode
205     *            The result code.
206     * @return The new compare result.
207     * @throws NullPointerException
208     *             If {@code resultCode} was {@code null}.
209     */
210    public static CompareResult newCompareResult(final ResultCode resultCode) {
211        Reject.ifNull(resultCode);
212        return new CompareResultImpl(resultCode);
213    }
214
215    /**
216     * Creates a new generic extended result using the provided result code.
217     *
218     * @param resultCode
219     *            The result code.
220     * @return The new generic extended result.
221     * @throws NullPointerException
222     *             If {@code resultCode} was {@code null}.
223     */
224    public static GenericExtendedResult newGenericExtendedResult(final ResultCode resultCode) {
225        Reject.ifNull(resultCode);
226        return new GenericExtendedResultImpl(resultCode);
227    }
228
229    /**
230     * Creates a new generic intermediate response with no name or value.
231     *
232     * @return The new generic intermediate response.
233     */
234    public static GenericIntermediateResponse newGenericIntermediateResponse() {
235        return new GenericIntermediateResponseImpl();
236    }
237
238    /**
239     * Creates a new generic intermediate response using the provided response
240     * name and value.
241     * <p>
242     * If the response value is not an instance of {@code ByteString} then it
243     * will be converted using the {@link ByteString#valueOf(Object)} method.
244     *
245     * @param responseName
246     *            The dotted-decimal representation of the unique OID
247     *            corresponding to this intermediate response, which may be
248     *            {@code null} indicating that none was provided.
249     * @param responseValue
250     *            The response value associated with this generic intermediate
251     *            response, which may be {@code null} indicating that none was
252     *            provided.
253     * @return The new generic intermediate response.
254     */
255    public static GenericIntermediateResponse newGenericIntermediateResponse(
256            final String responseName, final Object responseValue) {
257        return new GenericIntermediateResponseImpl().setOID(responseName).setValue(responseValue);
258    }
259
260    /**
261     * Creates a new password modify extended result using the provided result
262     * code, and no generated password.
263     *
264     * @param resultCode
265     *            The result code.
266     * @return The new password modify extended result.
267     * @throws NullPointerException
268     *             If {@code resultCode} was {@code null}.
269     */
270    public static PasswordModifyExtendedResult newPasswordModifyExtendedResult(
271            final ResultCode resultCode) {
272        Reject.ifNull(resultCode);
273        return new PasswordModifyExtendedResultImpl(resultCode);
274    }
275
276    /**
277     * Creates a new result using the provided result code.
278     *
279     * @param resultCode
280     *            The result code.
281     * @return The new result.
282     * @throws NullPointerException
283     *             If {@code resultCode} was {@code null}.
284     */
285    public static Result newResult(final ResultCode resultCode) {
286        Reject.ifNull(resultCode);
287        return new ResultImpl(resultCode);
288    }
289
290    /**
291     * Creates a new search result entry using the provided distinguished name.
292     *
293     * @param name
294     *            The distinguished name of the entry.
295     * @return The new search result entry.
296     * @throws NullPointerException
297     *             If {@code name} was {@code null}.
298     */
299    public static SearchResultEntry newSearchResultEntry(final DN name) {
300        final Entry entry = new LinkedHashMapEntry().setName(name);
301        return new SearchResultEntryImpl(entry);
302    }
303
304    /**
305     * Creates a new search result entry backed by the provided entry.
306     * Modifications made to {@code entry} will be reflected in the returned
307     * search result entry. The returned search result entry supports updates to
308     * its list of controls, as well as updates to the name and attributes if
309     * the underlying entry allows.
310     *
311     * @param entry
312     *            The entry.
313     * @return The new search result entry.
314     * @throws NullPointerException
315     *             If {@code entry} was {@code null} .
316     */
317    public static SearchResultEntry newSearchResultEntry(final Entry entry) {
318        Reject.ifNull(entry);
319        return new SearchResultEntryImpl(entry);
320    }
321
322    /**
323     * Creates a new search result entry using the provided distinguished name
324     * decoded using the default schema.
325     *
326     * @param name
327     *            The distinguished name of the entry.
328     * @return The new search result entry.
329     * @throws LocalizedIllegalArgumentException
330     *             If {@code name} could not be decoded using the default
331     *             schema.
332     * @throws NullPointerException
333     *             If {@code name} was {@code null}.
334     */
335    public static SearchResultEntry newSearchResultEntry(final String name) {
336        final Entry entry = new LinkedHashMapEntry().setName(name);
337        return new SearchResultEntryImpl(entry);
338    }
339
340    /**
341     * Creates a new search result entry using the provided lines of LDIF
342     * decoded using the default schema.
343     *
344     * @param ldifLines
345     *            Lines of LDIF containing an LDIF add change record or an LDIF
346     *            entry record.
347     * @return The new search result entry.
348     * @throws LocalizedIllegalArgumentException
349     *             If {@code ldifLines} was empty, or contained invalid LDIF, or
350     *             could not be decoded using the default schema.
351     * @throws NullPointerException
352     *             If {@code ldifLines} was {@code null} .
353     */
354    public static SearchResultEntry newSearchResultEntry(final String... ldifLines) {
355        return newSearchResultEntry(new LinkedHashMapEntry(ldifLines));
356    }
357
358    /**
359     * Creates a new search result reference using the provided continuation
360     * reference URI.
361     *
362     * @param uri
363     *            The first continuation reference URI to be added to this
364     *            search result reference.
365     * @return The new search result reference.
366     * @throws NullPointerException
367     *             If {@code uri} was {@code null}.
368     */
369    public static SearchResultReference newSearchResultReference(final String uri) {
370        Reject.ifNull(uri);
371        return new SearchResultReferenceImpl(uri);
372    }
373
374    /**
375     * Creates a new who am I extended result with the provided result code and
376     * no authorization ID.
377     *
378     * @param resultCode
379     *            The result code.
380     * @return The new who am I extended result.
381     * @throws NullPointerException
382     *             If {@code resultCode} was {@code null} .
383     */
384    public static WhoAmIExtendedResult newWhoAmIExtendedResult(final ResultCode resultCode) {
385        Reject.ifNull(resultCode);
386        return new WhoAmIExtendedResultImpl(ResultCode.SUCCESS);
387    }
388
389    /**
390     * Creates an unmodifiable bind result using the provided response.
391     *
392     * @param result
393     *            The bind result to be copied.
394     * @return The unmodifiable bind result.
395     * @throws NullPointerException
396     *             If {@code result} was {@code null}.
397     */
398    public static BindResult unmodifiableBindResult(final BindResult result) {
399        if (result instanceof UnmodifiableBindResultImpl) {
400            return result;
401        }
402        return new UnmodifiableBindResultImpl(result);
403    }
404
405    /**
406     * Creates an unmodifiable compare result using the provided response.
407     *
408     * @param result
409     *            The compare result to be copied.
410     * @return The unmodifiable compare result.
411     * @throws NullPointerException
412     *             If {@code result} was {@code null}.
413     */
414    public static CompareResult unmodifiableCompareResult(final CompareResult result) {
415        if (result instanceof UnmodifiableCompareResultImpl) {
416            return result;
417        }
418        return new UnmodifiableCompareResultImpl(result);
419    }
420
421    /**
422     * Creates an unmodifiable generic extended result using the provided
423     * response.
424     *
425     * @param result
426     *            The generic extended result to be copied.
427     * @return The unmodifiable generic extended result.
428     * @throws NullPointerException
429     *             If {@code result} was {@code null}.
430     */
431    public static GenericExtendedResult unmodifiableGenericExtendedResult(
432            final GenericExtendedResult result) {
433        if (result instanceof UnmodifiableGenericExtendedResultImpl) {
434            return result;
435        }
436        return new UnmodifiableGenericExtendedResultImpl(result);
437    }
438
439    /**
440     * Creates an unmodifiable generic intermediate response using the provided
441     * response.
442     *
443     * @param response
444     *            The generic intermediate response to be copied.
445     * @return The unmodifiable generic intermediate response.
446     * @throws NullPointerException
447     *             If {@code response} was {@code null}.
448     */
449    public static GenericIntermediateResponse unmodifiableGenericIntermediateResponse(
450            final GenericIntermediateResponse response) {
451        if (response instanceof UnmodifiableGenericIntermediateResponseImpl) {
452            return response;
453        }
454        return new UnmodifiableGenericIntermediateResponseImpl(response);
455    }
456
457    /**
458     * Creates an unmodifiable password modify extended result using the
459     * provided response.
460     *
461     * @param result
462     *            The password modify extended result to be copied.
463     * @return The unmodifiable password modify extended result.
464     * @throws NullPointerException
465     *             If {@code result} was {@code null}.
466     */
467    public static PasswordModifyExtendedResult unmodifiablePasswordModifyExtendedResult(
468            final PasswordModifyExtendedResult result) {
469        if (result instanceof UnmodifiablePasswordModifyExtendedResultImpl) {
470            return result;
471        }
472        return new UnmodifiablePasswordModifyExtendedResultImpl(result);
473    }
474
475    /**
476     * Creates an unmodifiable result using the provided response.
477     *
478     * @param result
479     *            The result to be copied.
480     * @return The unmodifiable result.
481     * @throws NullPointerException
482     *             If {@code result} was {@code null}.
483     */
484    public static Result unmodifiableResult(final Result result) {
485        if (result instanceof UnmodifiableResultImpl) {
486            return result;
487        }
488        return new UnmodifiableResultImpl(result);
489    }
490
491    /**
492     * Creates an unmodifiable search result entry using the provided response.
493     *
494     * @param entry
495     *            The search result entry to be copied.
496     * @return The unmodifiable search result entry.
497     * @throws NullPointerException
498     *             If {@code entry} was {@code null}.
499     */
500    public static SearchResultEntry unmodifiableSearchResultEntry(final SearchResultEntry entry) {
501        if (entry instanceof UnmodifiableSearchResultEntryImpl) {
502            return entry;
503        }
504        return new UnmodifiableSearchResultEntryImpl(entry);
505    }
506
507    /**
508     * Creates an unmodifiable search result reference using the provided
509     * response.
510     *
511     * @param reference
512     *            The search result reference to be copied.
513     * @return The unmodifiable search result reference.
514     * @throws NullPointerException
515     *             If {@code searchResultReference} was {@code null}.
516     */
517    public static SearchResultReference unmodifiableSearchResultReference(
518            final SearchResultReference reference) {
519        if (reference instanceof UnmodifiableSearchResultReferenceImpl) {
520            return reference;
521        }
522        return new UnmodifiableSearchResultReferenceImpl(reference);
523    }
524
525    /**
526     * Creates an unmodifiable who am I extended result using the provided
527     * response.
528     *
529     * @param result
530     *            The who am I result to be copied.
531     * @return The unmodifiable who am I extended result.
532     * @throws NullPointerException
533     *             If {@code result} was {@code null} .
534     */
535    public static WhoAmIExtendedResult unmodifiableWhoAmIExtendedResult(
536            final WhoAmIExtendedResult result) {
537        if (result instanceof UnmodifiableSearchResultReferenceImpl) {
538            return result;
539        }
540        return new UnmodifiableWhoAmIExtendedResultImpl(result);
541    }
542
543    /** Private constructor. */
544    private Responses() {
545        // Prevent instantiation.
546    }
547}