001    /*
002     * Copyright 2009-2015 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2015 UnboundID Corp.
007     *
008     * This program is free software; you can redistribute it and/or modify
009     * it under the terms of the GNU General Public License (GPLv2 only)
010     * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011     * as published by the Free Software Foundation.
012     *
013     * This program is distributed in the hope that it will be useful,
014     * but WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016     * GNU General Public License for more details.
017     *
018     * You should have received a copy of the GNU General Public License
019     * along with this program; if not, see <http://www.gnu.org/licenses>.
020     */
021    package com.unboundid.ldap.sdk.unboundidds.controls;
022    
023    
024    
025    import java.io.Serializable;
026    
027    import com.unboundid.asn1.ASN1Element;
028    import com.unboundid.asn1.ASN1Null;
029    import com.unboundid.asn1.ASN1OctetString;
030    import com.unboundid.ldap.sdk.LDAPException;
031    import com.unboundid.ldap.sdk.ResultCode;
032    import com.unboundid.util.NotMutable;
033    import com.unboundid.util.ThreadSafety;
034    import com.unboundid.util.ThreadSafetyLevel;
035    
036    import static com.unboundid.ldap.sdk.unboundidds.controls.ControlMessages.*;
037    import static com.unboundid.util.StaticUtils.*;
038    import static com.unboundid.util.Validator.*;
039    
040    
041    
042    /**
043     * <BLOCKQUOTE>
044     *   <B>NOTE:</B>  This class is part of the Commercial Edition of the UnboundID
045     *   LDAP SDK for Java.  It is not available for use in applications that
046     *   include only the Standard Edition of the LDAP SDK, and is not supported for
047     *   use in conjunction with non-UnboundID products.
048     * </BLOCKQUOTE>
049     * This class provides a data structure which may be used to indicate the base
050     * DN to use for a join request.  See the class-level documentation for the
051     * {@link JoinRequestControl} class for additional information and an example
052     * demonstrating its use.
053     */
054    @NotMutable()
055    @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
056    public final class JoinBaseDN
057           implements Serializable
058    {
059      /**
060       * The base type which indicates that the base DN for join processing should
061       * be the same as the base DN from the search request.
062       */
063      public static final byte BASE_TYPE_SEARCH_BASE = (byte) 0x80;
064    
065    
066    
067      /**
068       * The base type which indicates that the base DN for join processing should
069       * be the DN of the source entry.
070       */
071      public static final byte BASE_TYPE_SOURCE_ENTRY_DN = (byte) 0x81;
072    
073    
074    
075      /**
076       * The base type which indicates that the base DN for join processing should
077       * be a custom base DN.
078       */
079      public static final byte BASE_TYPE_CUSTOM = (byte) 0x82;
080    
081    
082    
083      /**
084       * The singleton instance that will be used for the "useSearchBaseDN" type.
085       */
086      private static final JoinBaseDN USE_SEARCH_BASE_DN = new JoinBaseDN(
087           BASE_TYPE_SEARCH_BASE, null);
088    
089    
090    
091      /**
092       * The singleton instance that will be used for the "useSourceEntryDN" type.
093       */
094      private static final JoinBaseDN USE_SOURCE_ENTRY_DN = new JoinBaseDN(
095           BASE_TYPE_SOURCE_ENTRY_DN, null);
096    
097    
098    
099      /**
100       * The serial version UID for this serializable class.
101       */
102      private static final long serialVersionUID = -330303461586380445L;
103    
104    
105    
106      // The base type value for this join base DN.
107      private final byte type;
108    
109      // The base DN value to use if the custom type is used.
110      private final String customBaseDN;
111    
112    
113    
114      /**
115       * Creates a new join base DN with the provided information.
116       *
117       * @param  type          The base type value for this join base DN.
118       * @param  customBaseDN  The custom base DN to use, if appropriate.
119       */
120      private JoinBaseDN(final byte type, final String customBaseDN)
121      {
122        this.type         = type;
123        this.customBaseDN = customBaseDN;
124      }
125    
126    
127    
128      /**
129       * Creates a join base DN object which indicates that join processing should
130       * use the base DN from the search request.
131       *
132       * @return  A join base DN object which indicates that join processing should
133       *          use the base DN from the search request.
134       */
135      public static JoinBaseDN createUseSearchBaseDN()
136      {
137        return USE_SEARCH_BASE_DN;
138      }
139    
140    
141    
142      /**
143       * Creates a join base DN object which indicates that join processing should
144       * use the DN of the source entry.
145       *
146       * @return  A join base DN object which indicates that join processing should
147       *          use the DN of the source entry.
148       */
149      public static JoinBaseDN createUseSourceEntryDN()
150      {
151        return USE_SOURCE_ENTRY_DN;
152      }
153    
154    
155    
156      /**
157       * Creates a join base DN object which indicates that join processing should
158       * use the provided base DN.
159       *
160       * @param  baseDN  The custom base DN to use.  It must not be {@code null}.
161       *
162       * @return  A join base DN object which indicates that join processing should
163       *          use the provided base DN.
164       */
165      public static JoinBaseDN createUseCustomBaseDN(final String baseDN)
166      {
167        ensureNotNull(baseDN);
168        return new JoinBaseDN(BASE_TYPE_CUSTOM, baseDN);
169      }
170    
171    
172    
173      /**
174       * Retrieves the base type for this join base DN.
175       *
176       * @return  The base type for this join base DN.
177       */
178      public byte getType()
179      {
180        return type;
181      }
182    
183    
184    
185      /**
186       * Retrieves the base DN value to use for the custom base DN type.
187       *
188       * @return  The base DN value to use for the custom base DN type, or
189       *          {@code null} if the base DN should be the search base DN or the
190       *          source entry DN.
191       */
192      public String getCustomBaseDN()
193      {
194        return customBaseDN;
195      }
196    
197    
198    
199      /**
200       * Encodes this join base DN as appropriate for inclusion in an LDAP join
201       * request control.
202       *
203       * @return  The encoded representation of this join base DN.
204       */
205      ASN1Element encode()
206      {
207        switch (type)
208        {
209          case BASE_TYPE_SEARCH_BASE:
210          case BASE_TYPE_SOURCE_ENTRY_DN:
211            return new ASN1Null(type);
212    
213          case BASE_TYPE_CUSTOM:
214            return new ASN1OctetString(type, customBaseDN);
215    
216          default:
217            // This should never happen.
218            return null;
219        }
220      }
221    
222    
223    
224      /**
225       * Decodes the provided ASN.1 element as a join rule.
226       *
227       * @param  element  The element to be decoded.
228       *
229       * @return  The decoded join rule.
230       *
231       * @throws  LDAPException  If a problem occurs while attempting to decode the
232       *                         provided element as a join rule.
233       */
234      static JoinBaseDN decode(final ASN1Element element)
235             throws LDAPException
236      {
237        switch (element.getType())
238        {
239          case BASE_TYPE_SEARCH_BASE:
240            return USE_SEARCH_BASE_DN;
241    
242          case BASE_TYPE_SOURCE_ENTRY_DN:
243            return USE_SOURCE_ENTRY_DN;
244    
245          case BASE_TYPE_CUSTOM:
246            return new JoinBaseDN(element.getType(),
247                 element.decodeAsOctetString().stringValue());
248    
249          default:
250            throw new LDAPException(ResultCode.DECODING_ERROR,
251                 ERR_JOIN_BASE_DECODE_INVALID_TYPE.get(toHex(element.getType())));
252        }
253      }
254    
255    
256    
257      /**
258       * Retrieves a string representation of this join base DN.
259       *
260       * @return  A string representation of this join base DN.
261       */
262      @Override()
263      public String toString()
264      {
265        final StringBuilder buffer = new StringBuilder();
266        toString(buffer);
267        return buffer.toString();
268      }
269    
270    
271    
272      /**
273       * Appends a string representation of this join base DN to the provided
274       * buffer.
275       *
276       * @param  buffer  The buffer to which the information should be appended.
277       */
278      public void toString(final StringBuilder buffer)
279      {
280        switch (type)
281        {
282          case BASE_TYPE_SEARCH_BASE:
283            buffer.append("useSearchBaseDN");
284            break;
285    
286          case BASE_TYPE_SOURCE_ENTRY_DN:
287            buffer.append("useSourceEntryDN");
288            break;
289    
290          case BASE_TYPE_CUSTOM:
291            buffer.append("useCustomBaseDN(baseDN='");
292            buffer.append(customBaseDN);
293            buffer.append("')");
294            break;
295        }
296      }
297    }