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 * http://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.controls.sort; 021 022 023import java.nio.ByteBuffer; 024import java.util.ArrayList; 025import java.util.List; 026 027import org.apache.directory.api.asn1.Asn1Object; 028import org.apache.directory.api.asn1.DecoderException; 029import org.apache.directory.api.asn1.EncoderException; 030import org.apache.directory.api.asn1.ber.Asn1Decoder; 031import org.apache.directory.api.asn1.ber.tlv.BerValue; 032import org.apache.directory.api.asn1.ber.tlv.TLV; 033import org.apache.directory.api.asn1.ber.tlv.UniversalTag; 034import org.apache.directory.api.i18n.I18n; 035import org.apache.directory.api.ldap.codec.api.ControlDecorator; 036import org.apache.directory.api.ldap.codec.api.LdapApiService; 037import org.apache.directory.api.ldap.model.message.controls.SortKey; 038import org.apache.directory.api.ldap.model.message.controls.SortRequest; 039import org.apache.directory.api.ldap.model.message.controls.SortRequestControlImpl; 040import org.apache.directory.api.util.Strings; 041 042 043/** 044 * Decorator of SortRequestControl. 045 * 046 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 047 */ 048public class SortRequestDecorator extends ControlDecorator<SortRequest> implements SortRequest 049{ 050 private Asn1Decoder decoder = new Asn1Decoder(); 051 052 private int sortReqLen = 0; 053 054 private List<Integer> sortKeyLenList = new ArrayList<Integer>(); 055 056 057 /** 058 * Creates a new instance of SortRequestDecorator. 059 * 060 * @param codec the LDAP codec 061 */ 062 public SortRequestDecorator( LdapApiService codec ) 063 { 064 super( codec, new SortRequestControlImpl() ); 065 } 066 067 068 /** 069 * Creates a new instance of SortRequestDecorator. 070 * 071 * @param codec the LDAP codec 072 * @param control the control instance 073 */ 074 public SortRequestDecorator( LdapApiService codec, SortRequest control ) 075 { 076 super( codec, control ); 077 } 078 079 080 /** 081 * 082 */ 083 @Override 084 public int computeLength() 085 { 086 sortReqLen = 0; 087 sortKeyLenList.clear(); 088 valueLength = 0; 089 090 for ( SortKey sk : getSortKeys() ) 091 { 092 int skLen = 0; 093 094 byte[] atBytes = Strings.getBytesUtf8( sk.getAttributeTypeDesc() ); 095 skLen += 1 + TLV.getNbBytes( atBytes.length ) + atBytes.length; 096 097 if ( sk.getMatchingRuleId() != null ) 098 { 099 byte[] mrBytes = Strings.getBytesUtf8( sk.getMatchingRuleId() ); 100 skLen += 1 + TLV.getNbBytes( mrBytes.length ) + mrBytes.length; 101 } 102 103 // reverse order flag 104 skLen += 1 + 1 + 1; 105 106 sortKeyLenList.add( skLen ); 107 108 // the sequence 109 sortReqLen += 1 + TLV.getNbBytes( skLen ) + skLen; 110 } 111 112 valueLength = 1 + TLV.getNbBytes( sortReqLen ) + sortReqLen; 113 114 return valueLength; 115 } 116 117 118 @Override 119 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException 120 { 121 if ( buffer == null ) 122 { 123 throw new EncoderException( I18n.err( I18n.ERR_04023 ) ); 124 } 125 126 buffer.put( UniversalTag.SEQUENCE.getValue() ); 127 buffer.put( TLV.getBytes( sortReqLen ) ); 128 129 List<SortKey> lst = getSortKeys(); 130 131 for ( int i = 0; i < lst.size(); i++ ) 132 { 133 SortKey sk = lst.get( i ); 134 int skLen = sortKeyLenList.get( i ); 135 136 buffer.put( UniversalTag.SEQUENCE.getValue() ); 137 buffer.put( TLV.getBytes( skLen ) ); 138 139 BerValue.encode( buffer, sk.getAttributeTypeDesc() ); 140 141 if ( sk.getMatchingRuleId() != null ) 142 { 143 BerValue.encode( buffer, sk.getMatchingRuleId() ); 144 } 145 146 BerValue.encode( buffer, sk.isReverseOrder() ); 147 } 148 149 return buffer; 150 } 151 152 153 @Override 154 public Asn1Object decode( byte[] controlBytes ) throws DecoderException 155 { 156 ByteBuffer buffer = ByteBuffer.wrap( controlBytes ); 157 SortRequestContainer container = new SortRequestContainer( getCodecService(), this ); 158 decoder.decode( buffer, container ); 159 return this; 160 } 161 162 163 /** 164 * {@inheritDoc} 165 */ 166 public byte[] getValue() 167 { 168 if ( value == null ) 169 { 170 try 171 { 172 computeLength(); 173 ByteBuffer buffer = ByteBuffer.allocate( valueLength ); 174 175 value = encode( buffer ).array(); 176 } 177 catch ( Exception e ) 178 { 179 return null; 180 } 181 } 182 183 return value; 184 } 185 186 187 @Override 188 public void setSortKeys( List<SortKey> sortKeys ) 189 { 190 getDecorated().setSortKeys( sortKeys ); 191 } 192 193 194 @Override 195 public List<SortKey> getSortKeys() 196 { 197 return getDecorated().getSortKeys(); 198 } 199 200 201 @Override 202 public void addSortKey( SortKey sortKey ) 203 { 204 getDecorated().addSortKey( sortKey ); 205 } 206 207}