001    /*
002     * Copyright 2009-2014 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2009-2014 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.protocol;
022    
023    
024    
025    import com.unboundid.asn1.ASN1Boolean;
026    import com.unboundid.asn1.ASN1Buffer;
027    import com.unboundid.asn1.ASN1BufferSequence;
028    import com.unboundid.asn1.ASN1Element;
029    import com.unboundid.asn1.ASN1OctetString;
030    import com.unboundid.asn1.ASN1Sequence;
031    import com.unboundid.asn1.ASN1StreamReader;
032    import com.unboundid.asn1.ASN1StreamReaderSequence;
033    import com.unboundid.ldap.sdk.Control;
034    import com.unboundid.ldap.sdk.LDAPException;
035    import com.unboundid.ldap.sdk.ModifyDNRequest;
036    import com.unboundid.ldap.sdk.ResultCode;
037    import com.unboundid.util.InternalUseOnly;
038    
039    import static com.unboundid.ldap.protocol.ProtocolMessages.*;
040    import static com.unboundid.util.Debug.*;
041    import static com.unboundid.util.StaticUtils.*;
042    
043    
044    
045    /**
046     * This class provides an implementation of an LDAP modify DN request protocol
047     * op.
048     */
049    @InternalUseOnly()
050    public final class ModifyDNRequestProtocolOp
051           implements ProtocolOp
052    {
053      /**
054       * The BER type for the newSuperior element.
055       */
056      public static final byte TYPE_NEW_SUPERIOR = (byte) 0x80;
057    
058    
059    
060      /**
061       * The serial version UID for this serializable class.
062       */
063      private static final long serialVersionUID = 7514385089303489375L;
064    
065    
066    
067      // The deleteOldRDN flag for this modify DN request.
068      private final boolean deleteOldRDN;
069    
070      // The entry DN for this modify DN request.
071      private final String dn;
072    
073      // The new RDN for this modify DN request.
074      private final String newRDN;
075    
076      // The new superior DN for this modify DN request.
077      private final String newSuperiorDN;
078    
079    
080    
081      /**
082       * Creates a new modify DN request protocol op with the provided information.
083       *
084       * @param  dn             The entry DN for this modify DN request.
085       * @param  newRDN         The new RDN for this modify DN request.
086       * @param  deleteOldRDN   Indicates whether to delete the old RDN values.
087       * @param  newSuperiorDN  The new superior DN for this modify DN request, or
088       *                        {@code null} if there is none.
089       */
090      public ModifyDNRequestProtocolOp(final String dn, final String newRDN,
091                                       final boolean deleteOldRDN,
092                                       final String newSuperiorDN)
093      {
094        this.dn            = dn;
095        this.newRDN        = newRDN;
096        this.deleteOldRDN  = deleteOldRDN;
097        this.newSuperiorDN = newSuperiorDN;
098      }
099    
100    
101    
102      /**
103       * Creates a new modify DN request protocol op from the provided modify DN
104       * request object.
105       *
106       * @param  request  The modify DN request object to use to create this
107       *                  protocol op.
108       */
109      public ModifyDNRequestProtocolOp(final ModifyDNRequest request)
110      {
111        dn            = request.getDN();
112        newRDN        = request.getNewRDN();
113        deleteOldRDN  = request.deleteOldRDN();
114        newSuperiorDN = request.getNewSuperiorDN();
115      }
116    
117    
118    
119      /**
120       * Creates a new modify DN request protocol op read from the provided ASN.1
121       * stream reader.
122       *
123       * @param  reader  The ASN.1 stream reader from which to read the modify DN
124       *                 request protocol op.
125       *
126       * @throws  LDAPException  If a problem occurs while reading or parsing the
127       *                         modify DN request.
128       */
129      ModifyDNRequestProtocolOp(final ASN1StreamReader reader)
130           throws LDAPException
131      {
132        try
133        {
134          final ASN1StreamReaderSequence opSequence = reader.beginSequence();
135    
136          dn           = reader.readString();
137          newRDN       = reader.readString();
138          deleteOldRDN = reader.readBoolean();
139    
140          if (opSequence.hasMoreElements())
141          {
142            newSuperiorDN = reader.readString();
143          }
144          else
145          {
146            newSuperiorDN = null;
147          }
148        }
149        catch (Exception e)
150        {
151          debugException(e);
152    
153          throw new LDAPException(ResultCode.DECODING_ERROR,
154               ERR_MODIFY_DN_REQUEST_CANNOT_DECODE.get(getExceptionMessage(e)), e);
155        }
156      }
157    
158    
159    
160      /**
161       * Retrieves the target entry DN for this modify DN request.
162       *
163       * @return  The target entry DN for this modify DN request.
164       */
165      public String getDN()
166      {
167        return dn;
168      }
169    
170    
171    
172      /**
173       * Retrieves the new RDN for this modify DN request.
174       *
175       * @return  The new RDN for this modify DN request.
176       */
177      public String getNewRDN()
178      {
179        return newRDN;
180      }
181    
182    
183    
184      /**
185       * Indicates whether to delete the old RDN values from the target entry.
186       *
187       * @return  {@code true} if the old RDN values should be removed from the
188       *          entry, or {@code false} if not.
189       */
190      public boolean deleteOldRDN()
191      {
192        return deleteOldRDN;
193      }
194    
195    
196    
197      /**
198       * Retrieves the new superior DN for this modify DN request, if any.
199       *
200       * @return  The new superior DN for this modify DN request, or {@code null} if
201       *          there is none.
202       */
203      public String getNewSuperiorDN()
204      {
205        return newSuperiorDN;
206      }
207    
208    
209    
210      /**
211       * {@inheritDoc}
212       */
213      public byte getProtocolOpType()
214      {
215        return LDAPMessage.PROTOCOL_OP_TYPE_MODIFY_DN_REQUEST;
216      }
217    
218    
219    
220      /**
221       * {@inheritDoc}
222       */
223      public ASN1Element encodeProtocolOp()
224      {
225        if (newSuperiorDN == null)
226        {
227          return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_MODIFY_DN_REQUEST,
228               new ASN1OctetString(dn),
229               new ASN1OctetString(newRDN),
230               new ASN1Boolean(deleteOldRDN));
231        }
232        else
233        {
234          return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_MODIFY_DN_REQUEST,
235               new ASN1OctetString(dn),
236               new ASN1OctetString(newRDN),
237               new ASN1Boolean(deleteOldRDN),
238               new ASN1OctetString(TYPE_NEW_SUPERIOR, newSuperiorDN));
239        }
240      }
241    
242    
243    
244      /**
245       * Decodes the provided ASN.1 element as a modify DN request protocol op.
246       *
247       * @param  element  The ASN.1 element to be decoded.
248       *
249       * @return  The decoded modify DN request protocol op.
250       *
251       * @throws  LDAPException  If the provided ASN.1 element cannot be decoded as
252       *                         a modify DN request protocol op.
253       */
254      public static ModifyDNRequestProtocolOp decodeProtocolOp(
255                                                   final ASN1Element element)
256             throws LDAPException
257      {
258        try
259        {
260          final ASN1Element[] elements =
261               ASN1Sequence.decodeAsSequence(element).elements();
262          final String dn =
263               ASN1OctetString.decodeAsOctetString(elements[0]).stringValue();
264          final String newRDN =
265               ASN1OctetString.decodeAsOctetString(elements[1]).stringValue();
266          final boolean deleteOldRDN =
267               ASN1Boolean.decodeAsBoolean(elements[2]).booleanValue();
268    
269          final String newSuperiorDN;
270          if (elements.length > 3)
271          {
272            newSuperiorDN =
273                 ASN1OctetString.decodeAsOctetString(elements[3]).stringValue();
274          }
275          else
276          {
277            newSuperiorDN = null;
278          }
279    
280          return new ModifyDNRequestProtocolOp(dn, newRDN, deleteOldRDN,
281               newSuperiorDN);
282        }
283        catch (final Exception e)
284        {
285          debugException(e);
286          throw new LDAPException(ResultCode.DECODING_ERROR,
287               ERR_MODIFY_DN_REQUEST_CANNOT_DECODE.get(getExceptionMessage(e)),
288               e);
289        }
290      }
291    
292    
293    
294      /**
295       * {@inheritDoc}
296       */
297      public void writeTo(final ASN1Buffer buffer)
298      {
299        final ASN1BufferSequence opSequence =
300             buffer.beginSequence(LDAPMessage.PROTOCOL_OP_TYPE_MODIFY_DN_REQUEST);
301        buffer.addOctetString(dn);
302        buffer.addOctetString(newRDN);
303        buffer.addBoolean(deleteOldRDN);
304    
305        if (newSuperiorDN != null)
306        {
307          buffer.addOctetString(TYPE_NEW_SUPERIOR, newSuperiorDN);
308        }
309        opSequence.end();
310      }
311    
312    
313    
314      /**
315       * Creates a modify DN request from this protocol op.
316       *
317       * @param  controls  The set of controls to include in the modify DN request.
318       *                   It may be empty or {@code null} if no controls should be
319       *                   included.
320       *
321       * @return  The modify DN request that was created.
322       */
323      public ModifyDNRequest toModifyDNRequest(final Control... controls)
324      {
325        return new ModifyDNRequest(dn, newRDN, deleteOldRDN, newSuperiorDN,
326             controls);
327      }
328    
329    
330    
331      /**
332       * Retrieves a string representation of this protocol op.
333       *
334       * @return  A string representation of this protocol op.
335       */
336      @Override()
337      public String toString()
338      {
339        final StringBuilder buffer = new StringBuilder();
340        toString(buffer);
341        return buffer.toString();
342      }
343    
344    
345    
346      /**
347       * {@inheritDoc}
348       */
349      public void toString(final StringBuilder buffer)
350      {
351        buffer.append("ModifyDNRequestProtocolOp(dn='");
352        buffer.append(dn);
353        buffer.append("', newRDN='");
354        buffer.append(newRDN);
355        buffer.append("', deleteOldRDN=");
356        buffer.append(deleteOldRDN);
357    
358        if (newSuperiorDN != null)
359        {
360          buffer.append(", newSuperiorDN='");
361          buffer.append(newSuperiorDN);
362          buffer.append('\'');
363        }
364    
365        buffer.append(')');
366      }
367    }