001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *
010 *    https://www.apache.org/licenses/LICENSE-2.0
011 *
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License.
018 *
019 */
020package org.apache.directory.api.ldap.codec.factory;
021
022import java.util.Collection;
023import java.util.Iterator;
024
025import org.apache.directory.api.asn1.ber.tlv.BerValue;
026import org.apache.directory.api.asn1.util.Asn1Buffer;
027import org.apache.directory.api.ldap.codec.api.LdapApiService;
028import org.apache.directory.api.ldap.codec.api.LdapCodecConstants;
029import org.apache.directory.api.ldap.model.entry.Attribute;
030import org.apache.directory.api.ldap.model.entry.Modification;
031import org.apache.directory.api.ldap.model.entry.ModificationOperation;
032import org.apache.directory.api.ldap.model.entry.Value;
033import org.apache.directory.api.ldap.model.message.Message;
034import org.apache.directory.api.ldap.model.message.ModifyRequest;
035import org.apache.directory.api.util.CollectionUtils;
036
037/**
038 * The ModifyRequest factory.
039 *
040 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
041 */
042public final class ModifyRequestFactory implements Messagefactory
043{
044    /** The static instance */
045    public static final ModifyRequestFactory INSTANCE = new ModifyRequestFactory();
046
047    private ModifyRequestFactory()
048    {
049        // Nothing to do
050    }
051
052
053    /**
054     * Encode the values, in reverse order
055     * <pre>
056     * 0x04 LL attributeValue
057     * ...
058     * 0x04 LL attributeValue
059     * </pre>
060     *
061     * @param buffer The buffer where to put the PDU
062     * @param values the values to encode
063     */
064    private void encodeValues( Asn1Buffer buffer, Iterator<Value> values )
065    {
066        values = CollectionUtils.reverse( values );
067        while ( values.hasNext() )
068        {
069            Value value = values.next();
070
071            // The value
072            if ( value.isHumanReadable() )
073            {
074                BerValue.encodeOctetString( buffer, value.getString() );
075            }
076            else
077            {
078                BerValue.encodeOctetString( buffer, value.getBytes() );
079            }
080        }
081    }
082
083    /**
084     * Encode the modifications, starting from the last one.
085     * <pre>
086     * 0x30 LL modification sequence
087     *   0x0A 0x01 operation
088     *   0x30 LL modification
089     *     0x04 LL type
090     *     0x31 LL vals
091     *       0x04 LL attributeValue
092     *       ...
093     *       0x04 LL attributeValue
094     * </pre>
095     *
096     * @param buffer The buffer where to put the PDU
097     * @param modifications the modifications to encode
098     */
099    private void encodeModifications( Asn1Buffer buffer, Iterator<Modification> modifications )
100    {
101        modifications = CollectionUtils.reverse( modifications );
102        while ( modifications.hasNext() )
103        {
104            Modification modification = modifications.next();
105
106            int start = buffer.getPos();
107
108            // The Attribute
109            Attribute attribute = modification.getAttribute();
110
111            // The values, if any
112            if ( modification.getAttribute().size() != 0 )
113            {
114                encodeValues( buffer, modification.getAttribute().iterator() );
115
116                // the value set
117                BerValue.encodeSet( buffer, start );
118            }
119            else if ( modification.getOperation() != ModificationOperation.INCREMENT_ATTRIBUTE )
120            {
121                // the value set, if not a INCREMENT operation
122                BerValue.encodeSet( buffer, start );
123            }
124
125            // The attribute type
126            BerValue.encodeOctetString( buffer, attribute.getUpId() );
127
128            // The attribute sequence
129            BerValue.encodeSequence( buffer, start );
130
131            // The operation
132            BerValue.encodeEnumerated( buffer, modification.getOperation().getValue() );
133
134            // The modification sequence
135            BerValue.encodeSequence( buffer, start );
136        }
137    }
138
139    /**
140     * Encode the ModifyRequest message to a PDU.
141     * <br>
142     * ModifyRequest :
143     * <pre>
144     * 0x66 LL
145     *   0x04 LL object
146     *   0x30 LL modifications
147     *     0x30 LL modification sequence
148     *       0x0A 0x01 operation
149     *       0x30 LL modification
150     *         0x04 LL type
151     *         0x31 LL vals
152     *           0x04 LL attributeValue
153     *           ...
154     *           0x04 LL attributeValue
155     *     ...
156     *     0x30 LL modification sequence
157     *       0x0A 0x01 operation
158     *       0x30 LL modification
159     *         0x04 LL type
160     *         0x31 LL vals
161     *           0x04 LL attributeValue
162     *           ...
163     *           0x04 LL attributeValue
164     * </pre>
165     *
166     * @param codec The LdapApiService instance
167     * @param buffer The buffer where to put the PDU
168     * @param message the ModifyRequest to encode
169     */
170    @Override
171    public void encodeReverse( LdapApiService codec, Asn1Buffer buffer, Message message )
172    {
173        int start = buffer.getPos();
174        ModifyRequest modifyRequest = ( ModifyRequest ) message;
175
176        // The modifications, if any
177        Collection<Modification> modifications = modifyRequest.getModifications();
178
179        if ( ( modifications != null ) && ( !modifications.isEmpty() ) )
180        {
181            encodeModifications( buffer, modifications.iterator() );
182
183            // The modifications sequence
184            BerValue.encodeSequence( buffer, start );
185        }
186
187        // The entry DN
188        BerValue.encodeOctetString( buffer, modifyRequest.getName().getName() );
189
190        // The ModifyRequest tag
191        BerValue.encodeSequence( buffer, LdapCodecConstants.MODIFY_REQUEST_TAG, start );
192    }
193}