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