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