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 static org.apache.directory.api.ldap.codec.controls.sort.SortRequestDecorator.ORDERING_RULE_TAG; 024import static org.apache.directory.api.ldap.codec.controls.sort.SortRequestDecorator.REVERSE_ORDER_TAG; 025 026import org.apache.directory.api.asn1.DecoderException; 027import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar; 028import org.apache.directory.api.asn1.ber.grammar.Grammar; 029import org.apache.directory.api.asn1.ber.grammar.GrammarAction; 030import org.apache.directory.api.asn1.ber.grammar.GrammarTransition; 031import org.apache.directory.api.asn1.ber.tlv.BerValue; 032import org.apache.directory.api.asn1.ber.tlv.BooleanDecoder; 033import org.apache.directory.api.asn1.ber.tlv.BooleanDecoderException; 034import org.apache.directory.api.asn1.ber.tlv.UniversalTag; 035import org.apache.directory.api.ldap.model.message.controls.SortKey; 036import org.apache.directory.api.util.Strings; 037import org.slf4j.Logger; 038import org.slf4j.LoggerFactory; 039 040 041/** 042 * Grammar used for decoding a SortRequestControl. It's defined in https://tools.ietf.org/html/rfc2891 043 * 044 * <pre> 045 * SortKeyList ::= SEQUENCE OF SEQUENCE { 046 * attributeType AttributeDescription, 047 * orderingRule [0] MatchingRuleId OPTIONAL, 048 * reverseOrder [1] BOOLEAN DEFAULT FALSE } 049 * </pre> 050 * 051 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 052 */ 053public final class SortRequestGrammar extends AbstractGrammar<SortRequestContainer> 054{ 055 /** The logger */ 056 static final Logger LOG = LoggerFactory.getLogger( SortRequestGrammar.class ); 057 058 /** Speedup for logs */ 059 static final boolean IS_DEBUG = LOG.isDebugEnabled(); 060 061 /** The instance of grammar. SortRequestGrammar is a singleton */ 062 private static Grammar<SortRequestContainer> instance = new SortRequestGrammar(); 063 064 065 @SuppressWarnings("unchecked") 066 private SortRequestGrammar() 067 { 068 setName( SortRequestGrammar.class.getName() ); 069 070 GrammarAction<SortRequestContainer> addSortKey = new GrammarAction<SortRequestContainer>() 071 { 072 073 @Override 074 public void action( SortRequestContainer container ) throws DecoderException 075 { 076 BerValue value = container.getCurrentTLV().getValue(); 077 078 String atDesc = Strings.utf8ToString( value.getData() ); 079 if ( IS_DEBUG ) 080 { 081 LOG.debug( "AttributeTypeDesc = " + atDesc ); 082 } 083 084 SortKey sk = new SortKey( atDesc ); 085 container.setCurrentKey( sk ); 086 container.getControl().addSortKey( sk ); 087 container.setGrammarEndAllowed( true ); 088 } 089 090 }; 091 092 GrammarAction<SortRequestContainer> storeReverseOrder = new GrammarAction<SortRequestContainer>() 093 { 094 095 @Override 096 public void action( SortRequestContainer container ) throws DecoderException 097 { 098 BerValue value = container.getCurrentTLV().getValue(); 099 100 try 101 { 102 boolean reverseOrder = BooleanDecoder.parse( value ); 103 104 if ( IS_DEBUG ) 105 { 106 LOG.debug( "ReverseOrder = " + reverseOrder ); 107 } 108 109 container.getCurrentKey().setReverseOrder( reverseOrder ); 110 111 container.setGrammarEndAllowed( true ); 112 } 113 catch ( BooleanDecoderException bde ) 114 { 115 throw new DecoderException( bde.getMessage(), bde ); 116 } 117 } 118 119 }; 120 121 // Create the transitions table 122 super.transitions = new GrammarTransition[SortRequestStates.END_STATE.ordinal()][256]; 123 124 super.transitions[SortRequestStates.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] = 125 new GrammarTransition<SortRequestContainer>( SortRequestStates.START_STATE, 126 SortRequestStates.SEQUENCE_OF_SEQUENCE_STATE, 127 UniversalTag.SEQUENCE.getValue(), null ); 128 129 super.transitions[SortRequestStates.SEQUENCE_OF_SEQUENCE_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] = 130 new GrammarTransition<SortRequestContainer>( SortRequestStates.SEQUENCE_OF_SEQUENCE_STATE, 131 SortRequestStates.SORT_KEY_SEQUENCE_STATE, 132 UniversalTag.SEQUENCE.getValue(), null ); 133 134 super.transitions[SortRequestStates.SORT_KEY_SEQUENCE_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] = 135 new GrammarTransition<SortRequestContainer>( SortRequestStates.SORT_KEY_SEQUENCE_STATE, 136 SortRequestStates.AT_DESC_STATE, 137 UniversalTag.OCTET_STRING.getValue(), addSortKey ); 138 139 super.transitions[SortRequestStates.AT_DESC_STATE.ordinal()][ORDERING_RULE_TAG] = 140 new GrammarTransition<SortRequestContainer>( SortRequestStates.AT_DESC_STATE, 141 SortRequestStates.ORDER_RULE_STATE, 142 ORDERING_RULE_TAG, new GrammarAction<SortRequestContainer>() 143 { 144 145 @Override 146 public void action( SortRequestContainer container ) throws DecoderException 147 { 148 BerValue value = container.getCurrentTLV().getValue(); 149 150 String matchingRuleOid = Strings.utf8ToString( value.getData() ); 151 152 if ( IS_DEBUG ) 153 { 154 LOG.debug( "MatchingRuleOid = " + matchingRuleOid ); 155 } 156 157 container.getCurrentKey().setMatchingRuleId( matchingRuleOid ); 158 container.setGrammarEndAllowed( true ); 159 } 160 161 } ); 162 163 super.transitions[SortRequestStates.ORDER_RULE_STATE.ordinal()][REVERSE_ORDER_TAG] = 164 new GrammarTransition<SortRequestContainer>( SortRequestStates.ORDER_RULE_STATE, 165 SortRequestStates.REVERSE_ORDER_STATE, 166 REVERSE_ORDER_TAG, storeReverseOrder ); 167 168 super.transitions[SortRequestStates.AT_DESC_STATE.ordinal()][REVERSE_ORDER_TAG] = 169 new GrammarTransition<SortRequestContainer>( SortRequestStates.AT_DESC_STATE, 170 SortRequestStates.REVERSE_ORDER_STATE, 171 REVERSE_ORDER_TAG, storeReverseOrder ); 172 173 super.transitions[SortRequestStates.REVERSE_ORDER_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] = 174 new GrammarTransition<SortRequestContainer>( SortRequestStates.REVERSE_ORDER_STATE, 175 SortRequestStates.SORT_KEY_SEQUENCE_STATE, 176 UniversalTag.SEQUENCE.getValue(), null ); 177 178 super.transitions[SortRequestStates.AT_DESC_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] = 179 new GrammarTransition<SortRequestContainer>( SortRequestStates.AT_DESC_STATE, 180 SortRequestStates.SORT_KEY_SEQUENCE_STATE, 181 UniversalTag.SEQUENCE.getValue(), null ); 182 183 } 184 185 186 /** 187 * This class is a singleton. 188 * 189 * @return An instance on this grammar 190 */ 191 public static Grammar<?> getInstance() 192 { 193 return instance; 194 } 195}