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