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 java.util.ArrayList;
026    import java.util.Collections;
027    import java.util.Iterator;
028    import java.util.List;
029    
030    import com.unboundid.asn1.ASN1Buffer;
031    import com.unboundid.asn1.ASN1BufferSequence;
032    import com.unboundid.asn1.ASN1Element;
033    import com.unboundid.asn1.ASN1OctetString;
034    import com.unboundid.asn1.ASN1Sequence;
035    import com.unboundid.asn1.ASN1StreamReader;
036    import com.unboundid.asn1.ASN1StreamReaderSequence;
037    import com.unboundid.ldap.sdk.Control;
038    import com.unboundid.ldap.sdk.LDAPException;
039    import com.unboundid.ldap.sdk.Modification;
040    import com.unboundid.ldap.sdk.ModifyRequest;
041    import com.unboundid.ldap.sdk.ResultCode;
042    import com.unboundid.util.InternalUseOnly;
043    
044    import static com.unboundid.ldap.protocol.ProtocolMessages.*;
045    import static com.unboundid.util.Debug.*;
046    import static com.unboundid.util.StaticUtils.*;
047    import static com.unboundid.util.Validator.*;
048    
049    
050    
051    /**
052     * This class provides an implementation of an LDAP modify request protocol op.
053     */
054    @InternalUseOnly()
055    public final class ModifyRequestProtocolOp
056           implements ProtocolOp
057    {
058      /**
059       * The serial version UID for this serializable class.
060       */
061      private static final long serialVersionUID = -6294739625253826184L;
062    
063    
064    
065      // The list of modifications for this modify request.
066      private final List<Modification> modifications;
067    
068      // The entry DN for this modify request.
069      private final String dn;
070    
071    
072    
073      /**
074       * Creates a new modify request protocol op with the provided information.
075       *
076       * @param  dn             The entry DN for this modify request.
077       * @param  modifications  The list of modifications to include in this modify
078       *                        request.
079       */
080      public ModifyRequestProtocolOp(final String dn,
081                                     final List<Modification> modifications)
082      {
083        this.dn            = dn;
084        this.modifications = Collections.unmodifiableList(modifications);
085      }
086    
087    
088    
089      /**
090       * Creates a new modify request protocol op from the provided modify request
091       * object.
092       *
093       * @param  request  The modify request object to use to create this protocol
094       *                  op.
095       */
096      public ModifyRequestProtocolOp(final ModifyRequest request)
097      {
098        dn            = request.getDN();
099        modifications = request.getModifications();
100      }
101    
102    
103    
104      /**
105       * Creates a new modify request protocol op read from the provided ASN.1
106       * stream reader.
107       *
108       * @param  reader  The ASN.1 stream reader from which to read the modify
109       *                 request protocol op.
110       *
111       * @throws  LDAPException  If a problem occurs while reading or parsing the
112       *                         modify request.
113       */
114      ModifyRequestProtocolOp(final ASN1StreamReader reader)
115           throws LDAPException
116      {
117        try
118        {
119          reader.beginSequence();
120          dn = reader.readString();
121          ensureNotNull(dn);
122    
123          final ArrayList<Modification> mods = new ArrayList<Modification>(5);
124          final ASN1StreamReaderSequence modSequence = reader.beginSequence();
125          while (modSequence.hasMoreElements())
126          {
127            mods.add(Modification.readFrom(reader));
128          }
129    
130          modifications = Collections.unmodifiableList(mods);
131        }
132        catch (LDAPException le)
133        {
134          debugException(le);
135          throw le;
136        }
137        catch (Exception e)
138        {
139          debugException(e);
140    
141          throw new LDAPException(ResultCode.DECODING_ERROR,
142               ERR_MODIFY_REQUEST_CANNOT_DECODE.get(getExceptionMessage(e)), e);
143        }
144      }
145    
146    
147    
148      /**
149       * Retrieves the target entry DN for this modify request.
150       *
151       * @return  The target entry DN for this modify request.
152       */
153      public String getDN()
154      {
155        return dn;
156      }
157    
158    
159    
160      /**
161       * Retrieves the list of modifications for this modify request.
162       *
163       * @return  The list of modifications for this modify request.
164       */
165      public List<Modification> getModifications()
166      {
167        return modifications;
168      }
169    
170    
171    
172      /**
173       * {@inheritDoc}
174       */
175      public byte getProtocolOpType()
176      {
177        return LDAPMessage.PROTOCOL_OP_TYPE_MODIFY_REQUEST;
178      }
179    
180    
181    
182      /**
183       * {@inheritDoc}
184       */
185      public ASN1Element encodeProtocolOp()
186      {
187        final ArrayList<ASN1Element> modElements =
188             new ArrayList<ASN1Element>(modifications.size());
189        for (final Modification m : modifications)
190        {
191          modElements.add(m.encode());
192        }
193    
194        return new ASN1Sequence(LDAPMessage.PROTOCOL_OP_TYPE_MODIFY_REQUEST,
195             new ASN1OctetString(dn),
196             new ASN1Sequence(modElements));
197      }
198    
199    
200    
201      /**
202       * Decodes the provided ASN.1 element as a modify request protocol op.
203       *
204       * @param  element  The ASN.1 element to be decoded.
205       *
206       * @return  The decoded modify request protocol op.
207       *
208       * @throws  LDAPException  If the provided ASN.1 element cannot be decoded as
209       *                         a modify request protocol op.
210       */
211      public static ModifyRequestProtocolOp decodeProtocolOp(
212                                                 final ASN1Element element)
213             throws LDAPException
214      {
215        try
216        {
217          final ASN1Element[] elements =
218               ASN1Sequence.decodeAsSequence(element).elements();
219          final String dn =
220               ASN1OctetString.decodeAsOctetString(elements[0]).stringValue();
221    
222          final ASN1Element[] modElements =
223               ASN1Sequence.decodeAsSequence(elements[1]).elements();
224          final ArrayList<Modification> mods =
225               new ArrayList<Modification>(modElements.length);
226          for (final ASN1Element e : modElements)
227          {
228            mods.add(Modification.decode(ASN1Sequence.decodeAsSequence(e)));
229          }
230    
231          return new ModifyRequestProtocolOp(dn, mods);
232        }
233        catch (final Exception e)
234        {
235          debugException(e);
236          throw new LDAPException(ResultCode.DECODING_ERROR,
237               ERR_MODIFY_REQUEST_CANNOT_DECODE.get(getExceptionMessage(e)),
238               e);
239        }
240      }
241    
242    
243    
244      /**
245       * {@inheritDoc}
246       */
247      public void writeTo(final ASN1Buffer writer)
248      {
249        final ASN1BufferSequence opSequence =
250             writer.beginSequence(LDAPMessage.PROTOCOL_OP_TYPE_MODIFY_REQUEST);
251        writer.addOctetString(dn);
252    
253        final ASN1BufferSequence modSequence = writer.beginSequence();
254        for (final Modification m : modifications)
255        {
256          m.writeTo(writer);
257        }
258        modSequence.end();
259        opSequence.end();
260      }
261    
262    
263    
264      /**
265       * Creates a modify request from this protocol op.
266       *
267       * @param  controls  The set of controls to include in the modify request.
268       *                   It may be empty or {@code null} if no controls should be
269       *                   included.
270       *
271       * @return  The modify request that was created.
272       */
273      public ModifyRequest toModifyRequest(final Control... controls)
274      {
275        return new ModifyRequest(dn, modifications, controls);
276      }
277    
278    
279    
280      /**
281       * Retrieves a string representation of this protocol op.
282       *
283       * @return  A string representation of this protocol op.
284       */
285      @Override()
286      public String toString()
287      {
288        final StringBuilder buffer = new StringBuilder();
289        toString(buffer);
290        return buffer.toString();
291      }
292    
293    
294    
295      /**
296       * {@inheritDoc}
297       */
298      public void toString(final StringBuilder buffer)
299      {
300        buffer.append("ModifyRequestProtocolOp(dn='");
301        buffer.append(dn);
302        buffer.append("', mods={");
303    
304        final Iterator<Modification> iterator = modifications.iterator();
305        while (iterator.hasNext())
306        {
307          iterator.next().toString(buffer);
308          if (iterator.hasNext())
309          {
310            buffer.append(',');
311          }
312        }
313    
314        buffer.append("})");
315      }
316    }