You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2005/06/07 00:29:29 UTC
svn commit: r185068 -
/directory/sandbox/trunk/asn1-new-codec/src/java/org/apache/asn1/ldap/codec/grammars/FilterGrammar.java
Author: elecharny
Date: Mon Jun 6 15:29:28 2005
New Revision: 185068
URL: http://svn.apache.org/viewcvs?rev=185068&view=rev
Log:
Added the first SearchRequest sub-grammar, and the most important part of it : FilterGrammar.
Not finished yet, some transitions need to be added.
Added:
directory/sandbox/trunk/asn1-new-codec/src/java/org/apache/asn1/ldap/codec/grammars/FilterGrammar.java
Added: directory/sandbox/trunk/asn1-new-codec/src/java/org/apache/asn1/ldap/codec/grammars/FilterGrammar.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trunk/asn1-new-codec/src/java/org/apache/asn1/ldap/codec/grammars/FilterGrammar.java?rev=185068&view=auto
==============================================================================
--- directory/sandbox/trunk/asn1-new-codec/src/java/org/apache/asn1/ldap/codec/grammars/FilterGrammar.java (added)
+++ directory/sandbox/trunk/asn1-new-codec/src/java/org/apache/asn1/ldap/codec/grammars/FilterGrammar.java Mon Jun 6 15:29:28 2005
@@ -0,0 +1,665 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.asn1.ldap.codec.grammars;
+
+import org.apache.asn1.AbstractPOJO;
+import org.apache.asn1.DecoderException;
+import org.apache.asn1.ber.containers.IAsn1Container;
+import org.apache.asn1.ber.grammar.AbstractGrammar;
+import org.apache.asn1.ber.grammar.GrammarAction;
+import org.apache.asn1.ber.grammar.GrammarTransition;
+import org.apache.asn1.ber.grammar.IGrammar;
+import org.apache.asn1.ber.tlv.TLV;
+import org.apache.asn1.ldap.codec.LdapMessageContainer;
+import org.apache.asn1.ldap.codec.primitives.LdapString;
+import org.apache.asn1.ldap.pojo.AttributeValueAssertionPOJO;
+import org.apache.asn1.ldap.pojo.LdapMessagePOJO;
+import org.apache.asn1.ldap.pojo.SearchRequestPOJO;
+import org.apache.asn1.ldap.pojo.filters.AndFilterPOJO;
+import org.apache.asn1.ldap.pojo.filters.AttributeValueAssertionFilterPOJO;
+import org.apache.asn1.ldap.pojo.filters.FilterPOJO;
+import org.apache.asn1.ldap.pojo.filters.NotFilterPOJO;
+import org.apache.asn1.ldap.pojo.filters.OrFilterPOJO;
+import org.apache.asn1.primitives.OctetString;
+import org.apache.asn1.util.MutableString;
+
+import org.apache.log4j.Logger;
+
+
+/**
+ * This class implements the Filter grammar. All the actions are declared in this
+ * class. As it is a singleton, these declaration are only done once.
+ *
+ * If an action is to be added or modified, this is where the work is to be done !
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class FilterGrammar extends AbstractGrammar implements IGrammar
+{
+ //~ Static fields/initializers -----------------------------------------------------------------
+
+ /** The logger */
+ private static final Logger log = Logger.getLogger( FilterGrammar.class );
+
+ /** Logging speed up */
+ private static final boolean DEBUG = log.isDebugEnabled();
+
+ /** The instance of grammar. FilterGrammar is a singleton */
+ private static IGrammar instance = new FilterGrammar();
+
+ //~ Constructors -------------------------------------------------------------------------------
+
+ /**
+ * Creates a new LdapResultGrammar object.
+ */
+ private FilterGrammar()
+ {
+ name = FilterGrammar.class.getName();
+ statesEnum = LdapStatesEnum.getInstance();
+
+ super.transitions = new GrammarTransition[LdapStatesEnum.LAST_FILTER_STATE][256];
+
+ //============================================================================================
+ // Search Request And Filter
+ // This is quite complicated, because we have a tree structure to build,
+ // and we may have many elements on each node. For instance, considering the
+ // search filter :
+ // (& (| (a = b) (c = d)) (! (e = f)) (attr =* h))
+ // We will have to create an And filter with three children :
+ // - an Or child,
+ // - a Not child
+ // - and a Present child.
+ // The Or child will also have two children.
+ //
+ // We know when we have a children while decoding the PDU, because the length
+ // of its father has not yet reached its expected length.
+ //
+ // This search filter :
+ // (&(|(objectclass=top)(ou=contacts))(!(objectclass=ttt))(objectclass=*top))
+ // is encoded like this :
+ // +----------------+---------------+
+ // | ExpectedLength | CurrentLength |
+ //+-----------------------------+----------------+---------------+
+ //|A0 52 | 82 | 0 | new level 1
+ //| A1 24 | 82 36 | 0 0 | new level 2
+ //| A3 12 | 82 36 18 | 0 0 0 | new level 3
+ //| 04 0B 'objectclass' | 82 36 18 | 0 0 13 |
+ //| 04 03 'top' | 82 36 18 | 0 20 18 |
+ //| | ^ ^ |
+ //| | | | |
+ //| | +---------------+ |
+ //+-----------------------------* end level 3 -------------------*
+ //| A3 0E | 82 36 14 | 0 0 0 | new level 3
+ //| 04 02 'ou' | 82 36 14 | 0 0 4 |
+ //| 04 08 'contacts' | 82 36 14 | 38 36 14 |
+ //| | ^ ^ ^ ^ |
+ //| | | | | | |
+ //| | | +-------------|--+ |
+ //| | +----------------+ |
+ //+-----------------------------* end level 3, end level 2 ------*
+ //| A2 14 | 82 20 | 38 0 | new level 2
+ //| A3 12 | 82 20 18 | 38 0 0 | new level 3
+ //| 04 0B 'objectclass' | 82 20 18 | 38 0 13 |
+ //| 04 03 'ttt' | 82 20 18 | 60 20 18 |
+ //| | ^ ^ ^ ^ |
+ //| | | | | | |
+ //| | | +-------------|--+ |
+ //| | +----------------+ |
+ //+-----------------------------* end level 3, end level 2 ------*
+ //| A4 14 | 82 20 | 60 0 | new level 2
+ //| 04 0B 'objectclass' | 82 20 | 60 13 |
+ //| 30 05 | 82 20 | 60 13 |
+ //| 82 03 'top' | 82 20 | 82 20 |
+ //| | ^ ^ ^ ^ |
+ //| | | | | | |
+ //| | | +-------------|--+ |
+ //| | +----------------+ |
+ //+-----------------------------* end level 2, end level 1 ------*
+ //+-----------------------------+----------------+---------------+
+ //
+ // When the current length equals the expected length of the father PDU,
+ // then we are able to 'close' the father : it has all its children. This
+ // is propagated through all the tree, until either there are no more
+ // parents, or the expected length of the father is different from the
+ // current length.
+ //
+ //============================================================================================
+ // Filter ::= CHOICE {
+ // and [0] SET OF Filter, (Tag)
+ // ...
+ // Nothing to do
+ super.transitions[LdapStatesEnum.FILTER_TAG][0xA0] = new GrammarTransition(
+ LdapStatesEnum.FILTER_TAG, LdapStatesEnum.FILTER_AND_LENGTH, null );
+
+ // Filter ::= CHOICE {
+ // ...
+ // or [1] SET OF Filter, (Tag)
+ // ...
+ // Nothing to do
+ super.transitions[LdapStatesEnum.FILTER_TAG][0xA1] = new GrammarTransition(
+ LdapStatesEnum.FILTER_TAG, LdapStatesEnum.FILTER_OR_LENGTH, null );
+
+ // Filter ::= CHOICE {
+ // ...
+ // not [2] Filter, (Tag)
+ // ...
+ // Nothing to do
+ super.transitions[LdapStatesEnum.FILTER_TAG][0xA2] = new GrammarTransition(
+ LdapStatesEnum.FILTER_TAG, LdapStatesEnum.FILTER_NOT_LENGTH, null );
+
+ // Filter ::= CHOICE {
+ // ...
+ // equalityMatch [3] AttributeValueAssertion, (Tag)
+ // ...
+ // Nothing to do
+ super.transitions[LdapStatesEnum.FILTER_TAG][0xA3] = new GrammarTransition(
+ LdapStatesEnum.FILTER_TAG, LdapStatesEnum.FILTER_EQUALITY_MATCH_LENGTH, null );
+
+ // Filter ::= CHOICE {
+ // ...
+ // substrings [4] SubstringFilter, (Tag)
+ // ...
+ // Nothing to do
+ super.transitions[LdapStatesEnum.FILTER_TAG][0xA4] = new GrammarTransition(
+ LdapStatesEnum.FILTER_TAG, LdapStatesEnum.FILTER_SUBSTRINGS_LENGTH, null );
+
+ // Filter ::= CHOICE {
+ // ...
+ // greaterOrEqual [5] AttributeValueAssertion, (Tag)
+ // ...
+ // Nothing to do
+ super.transitions[LdapStatesEnum.FILTER_TAG][0xA5] = new GrammarTransition(
+ LdapStatesEnum.FILTER_TAG, LdapStatesEnum.FILTER_GREATER_OR_EQUAL_LENGTH, null );
+
+ // Filter ::= CHOICE {
+ // ...
+ // lessOrEqual [6] AttributeValueAssertion, (Tag)
+ // ...
+ // Nothing to do
+ super.transitions[LdapStatesEnum.FILTER_TAG][0xA6] = new GrammarTransition(
+ LdapStatesEnum.FILTER_TAG, LdapStatesEnum.FILTER_LESS_OR_EQUAL_LENGTH, null );
+
+ // Filter ::= CHOICE {
+ // ...
+ // present [7] AttributeDescription, (Tag)
+ // ...
+ // Nothing to do
+ super.transitions[LdapStatesEnum.FILTER_TAG][0x87] = new GrammarTransition(
+ LdapStatesEnum.FILTER_TAG, LdapStatesEnum.FILTER_PRESENT_LENGTH, null );
+
+ // Filter ::= CHOICE {
+ // ...
+ // approxMatch [8] AttributeValueAssertion, (Tag)
+ // ...
+ // Nothing to do
+ super.transitions[LdapStatesEnum.FILTER_TAG][0xA8] = new GrammarTransition(
+ LdapStatesEnum.FILTER_TAG, LdapStatesEnum.FILTER_APPROX_MATCH_LENGTH, null );
+
+ // Filter ::= CHOICE {
+ // ...
+ // extensibleMatch [9] MatchingRuleAssertion } (Tag)
+ // Nothing to do
+ super.transitions[LdapStatesEnum.FILTER_TAG][0xA9] = new GrammarTransition(
+ LdapStatesEnum.FILTER_TAG, LdapStatesEnum.FILTER_EXTENSIBLE_MATCH_LENGTH, null );
+
+ // Filter ::= CHOICE {
+ // and [0] SET OF Filter, (Length)
+ // ...
+ // We have to control the length to know if we have a completed level or not.
+ super.transitions[LdapStatesEnum.FILTER_AND_LENGTH][0xA0] = new GrammarTransition(
+ LdapStatesEnum.FILTER_AND_LENGTH, LdapStatesEnum.FILTER_AND_VALUE,
+ new GrammarAction( "Init And Filter" )
+ {
+ public void action( IAsn1Container container ) throws DecoderException
+ {
+ LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer )
+ container;
+ LdapMessagePOJO ldapMessage =
+ ldapMessageContainer.getLdapMessage();
+ SearchRequestPOJO searchRequest = ldapMessage.getSearchRequest();
+
+ TLV tlv = ldapMessageContainer.getCurrentTLV();
+
+ // We can allocate the SearchRequestPOJO
+ FilterPOJO andFilter = new AndFilterPOJO();
+
+ // Get the parent, if any
+ FilterPOJO currentFilter = searchRequest.getCurrentFilter();
+
+ if (currentFilter != null)
+ {
+ // Ok, we have a parent. The new Filter will be added to
+ // this parent, then. We also have to check the length
+ // against the parent.
+ checkLength( currentFilter, tlv );
+ currentFilter.addFilter(andFilter);
+ andFilter.setFather( currentFilter );
+ }
+ else
+ {
+ // No parent. This Filter will become the root.
+ // First, check the length to see if it does not exceed its father
+ // expected length. (If there is no parent, we have to check the
+ // length against the SearchRequestPOJO )
+ checkLength( searchRequest, tlv );
+
+ searchRequest.setCurrentFilter(andFilter);
+ searchRequest.setFilter(andFilter);
+ andFilter.setFather( searchRequest );
+ }
+
+ // As this is a new Constructed object, we have to init its length
+ int expectedLength = tlv.getLength().getLength();
+
+ andFilter.setExpectedLength( expectedLength );
+ andFilter.setCurrentLength( 0 );
+ }
+ } );
+
+ // Filter ::= CHOICE {
+ // and [0] SET OF Filter, (Value)
+ // ...
+ // We just have to switch to the initial state of Filter, because this is what
+ // we will get !
+ super.transitions[LdapStatesEnum.FILTER_AND_VALUE][0xA0] = new GrammarTransition(
+ LdapStatesEnum.FILTER_AND_VALUE, LdapStatesEnum.FILTER_TAG, null);
+
+ // Filter ::= CHOICE {
+ // or [1] SET OF Filter, (Length)
+ // ...
+ // We have to control the length to know if we have a completed level or not.
+ super.transitions[LdapStatesEnum.FILTER_OR_LENGTH][0xA1] = new GrammarTransition(
+ LdapStatesEnum.FILTER_OR_LENGTH, LdapStatesEnum.FILTER_OR_VALUE,
+ new GrammarAction( "Init Or Filter" )
+ {
+ public void action( IAsn1Container container ) throws DecoderException
+ {
+ LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer )
+ container;
+ LdapMessagePOJO ldapMessage =
+ ldapMessageContainer.getLdapMessage();
+ SearchRequestPOJO searchRequest = ldapMessage.getSearchRequest();
+
+ TLV tlv = ldapMessageContainer.getCurrentTLV();
+
+ // We can allocate the SearchRequestPOJO
+ FilterPOJO orFilter = new OrFilterPOJO();
+
+ // Get the parent, if any
+ FilterPOJO currentFilter = searchRequest.getCurrentFilter();
+
+ if (currentFilter != null)
+ {
+ // Ok, we have a parent. The new Filter will be added to
+ // this parent, then. We also have to check the length
+ // against the parent.
+ checkLength( currentFilter, tlv );
+ currentFilter.addFilter(orFilter);
+ orFilter.setFather( currentFilter );
+ }
+ else
+ {
+ // No parent. This Filter will become the root.
+ // First, check the length to see if it does not exceed its father
+ // expected length. (If there is no parent, we have to check the
+ // length against the SearchRequestPOJO )
+ checkLength( searchRequest, tlv );
+ searchRequest.setFilter(orFilter);
+ orFilter.setFather( searchRequest );
+ }
+
+ searchRequest.setCurrentFilter(orFilter);
+
+ // As this is a new Constructed object, we have to init its length
+ int expectedLength = tlv.getLength().getLength();
+
+ orFilter.setExpectedLength( expectedLength );
+ orFilter.setCurrentLength( 0 );
+ }
+ } );
+
+ // Filter ::= CHOICE {
+ // or [1] SET OF Filter, (Value)
+ // ...
+ // We just have to switch to the initial state of Filter, because this is what
+ // we will get !
+ super.transitions[LdapStatesEnum.FILTER_OR_VALUE][0xA1] = new GrammarTransition(
+ LdapStatesEnum.FILTER_OR_VALUE, LdapStatesEnum.FILTER_TAG, null);
+
+ // Filter ::= CHOICE {
+ // not [2] Filter, (Length)
+ // ...
+ // We have to control the length to know if we have a completed level or not.
+ super.transitions[LdapStatesEnum.FILTER_NOT_LENGTH][0xA2] = new GrammarTransition(
+ LdapStatesEnum.FILTER_NOT_LENGTH, LdapStatesEnum.FILTER_TAG,
+ new GrammarAction( "Init Not Filter" )
+ {
+ public void action( IAsn1Container container ) throws DecoderException
+ {
+ LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer )
+ container;
+ LdapMessagePOJO ldapMessage =
+ ldapMessageContainer.getLdapMessage();
+ SearchRequestPOJO searchRequest = ldapMessage.getSearchRequest();
+
+ TLV tlv = ldapMessageContainer.getCurrentTLV();
+
+ // We can allocate the SearchRequestPOJO
+ FilterPOJO notFilter = new NotFilterPOJO();
+
+ // Get the parent, if any
+ FilterPOJO currentFilter = searchRequest.getCurrentFilter();
+
+ if (currentFilter != null)
+ {
+ // Ok, we have a parent. The new Filter will be added to
+ // this parent, then. We also have to check the length
+ // against the parent.
+ checkLength( currentFilter, tlv );
+ currentFilter.addFilter(notFilter);
+ notFilter.setFather( currentFilter );
+ }
+ else
+ {
+ // No parent. This Filter will become the root.
+ // First, check the length to see if it does not exceed its father
+ // expected length. (If there is no parent, we have to check the
+ // length against the SearchRequestPOJO )
+ checkLength( searchRequest, tlv );
+
+ searchRequest.setCurrentFilter(notFilter);
+ searchRequest.setFilter(notFilter);
+ notFilter.setFather( searchRequest );
+ }
+
+ searchRequest.setCurrentFilter(notFilter);
+
+ // As this is a new Constructed object, we have to init its length
+ int expectedLength = tlv.getLength().getLength();
+
+ notFilter.setExpectedLength( expectedLength );
+ notFilter.setCurrentLength( 0 );
+ }
+ } );
+
+ // Filter ::= CHOICE {
+ // not [2] Filter, (Value)
+ // ...
+ // We just have to switch to the initial state of Filter, because this is what
+ // we will get !
+ super.transitions[LdapStatesEnum.FILTER_NOT_VALUE][0xA2] = new GrammarTransition(
+ LdapStatesEnum.FILTER_NOT_VALUE, LdapStatesEnum.FILTER_TAG, null);
+
+ // Filter ::= CHOICE {
+ // equalityMatch [3] AttributeValueAssertion, (Length)
+ // ...
+ // We have to control the length to know if we have a completed level or not.
+ super.transitions[LdapStatesEnum.FILTER_EQUALITY_MATCH_LENGTH][0xA3] = new GrammarTransition(
+ LdapStatesEnum.FILTER_EQUALITY_MATCH_LENGTH, LdapStatesEnum.FILTER_EQUALITY_MATCH_VALUE,
+ new GrammarAction( "Init Equality Match Filter" )
+ {
+ public void action( IAsn1Container container ) throws DecoderException
+ {
+ LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer )
+ container;
+ LdapMessagePOJO ldapMessage =
+ ldapMessageContainer.getLdapMessage();
+ SearchRequestPOJO searchRequest = ldapMessage.getSearchRequest();
+
+ TLV tlv = ldapMessageContainer.getCurrentTLV();
+
+ // We can allocate the SearchRequestPOJO
+ FilterPOJO equalityMatchFilter = new AttributeValueAssertionFilterPOJO();
+
+ // Get the parent, if any
+ FilterPOJO currentFilter = searchRequest.getCurrentFilter();
+
+ if (currentFilter != null)
+ {
+ // Ok, we have a parent. The new Filter will be added to
+ // this parent, then. We also have to check the length
+ // against the parent.
+ checkLength( currentFilter, tlv );
+ currentFilter.addFilter(equalityMatchFilter);
+ equalityMatchFilter.setFather( currentFilter );
+ }
+ else
+ {
+ // No parent. This Filter will become the root.
+ // First, check the length to see if it does not exceed its father
+ // expected length. (If there is no parent, we have to check the
+ // length against the SearchRequestPOJO )
+ checkLength( searchRequest, tlv );
+
+ searchRequest.setCurrentFilter(equalityMatchFilter);
+ equalityMatchFilter.setFather( searchRequest );
+ searchRequest.setFilter(equalityMatchFilter);
+ }
+
+ searchRequest.setCurrentFilter(equalityMatchFilter);
+
+ // As this is a new Constructed object, we have to init its length
+ int expectedLength = tlv.getLength().getLength();
+
+ equalityMatchFilter.setExpectedLength( expectedLength );
+ equalityMatchFilter.setCurrentLength( 0 );
+ }
+ } );
+
+ // Filter ::= CHOICE {
+ // equalityMatch [3] AttributeValueAssertion, (Value)
+ // ...
+ // We will create the filter container (as this is an equalityMatch filter,
+ // we will create an AttributeValueAssertionFilterPOJO).
+ super.transitions[LdapStatesEnum.FILTER_EQUALITY_MATCH_VALUE][0xA3] = new GrammarTransition(
+ LdapStatesEnum.FILTER_EQUALITY_MATCH_VALUE, LdapStatesEnum.FILTER_ATTRIBUTE_DESC_TAG, null);
+
+ // AttributeValueAssertion ::= SEQUENCE {
+ // attributeDesc AttributeDescription, (TAG)
+ // ...
+ // Nothing to do.
+ super.transitions[LdapStatesEnum.FILTER_ATTRIBUTE_DESC_TAG][0x04] = new GrammarTransition(
+ LdapStatesEnum.FILTER_ATTRIBUTE_DESC_TAG, LdapStatesEnum.FILTER_ATTRIBUTE_DESC_LENGTH, null);
+
+ // AttributeValueAssertion ::= SEQUENCE {
+ // attributeDesc AttributeDescription, (LENGTH)
+ // ...
+ // We have to check the length
+ super.transitions[LdapStatesEnum.FILTER_ATTRIBUTE_DESC_LENGTH][0x04] = new GrammarTransition(
+ LdapStatesEnum.FILTER_ATTRIBUTE_DESC_LENGTH, LdapStatesEnum.FILTER_ATTRIBUTE_DESC_VALUE,
+ new GrammarAction( "Check AttributeDesc length" )
+ {
+ public void action( IAsn1Container container ) throws DecoderException
+ {
+ // We will check the length against the current filter
+ LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer )
+ container;
+ LdapMessagePOJO ldapMessage =
+ ldapMessageContainer.getLdapMessage();
+ SearchRequestPOJO searchRequest = ldapMessage.getSearchRequest();
+
+ FilterPOJO currentFilter =
+ searchRequest.getCurrentFilter();
+
+ TLV tlv = ldapMessageContainer.getCurrentTLV();
+
+ checkLength( currentFilter, tlv );
+ return;
+ }
+ });
+
+ // AttributeValueAssertion ::= SEQUENCE {
+ // attributeDesc AttributeDescription, (VALUE)
+ // ...
+ // We have to set the attribute description in the current filter.
+ // It could be an equalityMatch, greaterOrEqual, lessOrEqual or an
+ // approxMatch filter.
+ super.transitions[LdapStatesEnum.FILTER_ATTRIBUTE_DESC_VALUE][0x04] = new GrammarTransition(
+ LdapStatesEnum.FILTER_ATTRIBUTE_DESC_VALUE, LdapStatesEnum.FILTER_ASSERTION_VALUE_TAG,
+ new GrammarAction( "Init attributeDesc Value" )
+ {
+ public void action( IAsn1Container container ) throws DecoderException
+ {
+ LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer )
+ container;
+ LdapMessagePOJO ldapMessage =
+ ldapMessageContainer.getLdapMessage();
+ SearchRequestPOJO searchRequest = ldapMessage.getSearchRequest();
+
+ TLV tlv = ldapMessageContainer.getCurrentTLV();
+ MutableString attributeDesc = LdapString.parse(tlv.getValue().getData());
+
+ AttributeValueAssertionPOJO assertion = new AttributeValueAssertionPOJO();
+ assertion.setAttributeDesc(attributeDesc);
+
+ AttributeValueAssertionFilterPOJO currentFilter = (AttributeValueAssertionFilterPOJO)searchRequest.getCurrentFilter();
+ currentFilter.setAssertion(assertion);
+ }
+ });
+
+ // AttributeValueAssertion ::= SEQUENCE {
+ // ...
+ // assertionValue AssertionValue } (TAG)
+ // Nothing to do.
+ super.transitions[LdapStatesEnum.FILTER_ASSERTION_VALUE_TAG][0x04] = new GrammarTransition(
+ LdapStatesEnum.FILTER_ASSERTION_VALUE_TAG, LdapStatesEnum.FILTER_ASSERTION_VALUE_LENGTH, null);
+
+ // AttributeValueAssertion ::= SEQUENCE {
+ // ...
+ // assertionValue AssertionValue } (LENGTH)
+ // We have to check the length
+ super.transitions[LdapStatesEnum.FILTER_ASSERTION_VALUE_LENGTH][0x04] = new GrammarTransition(
+ LdapStatesEnum.FILTER_ASSERTION_VALUE_LENGTH, LdapStatesEnum.FILTER_ASSERTION_VALUE_VALUE,
+ new GrammarAction( "Check AssertionValue length" )
+ {
+ public void action( IAsn1Container container ) throws DecoderException
+ {
+ // We will check the length against the current filter
+ LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer )
+ container;
+ LdapMessagePOJO ldapMessage =
+ ldapMessageContainer.getLdapMessage();
+ SearchRequestPOJO searchRequest = ldapMessage.getSearchRequest();
+
+ FilterPOJO currentFilter =
+ searchRequest.getCurrentFilter();
+
+ TLV tlv = ldapMessageContainer.getCurrentTLV();
+
+ checkLength( currentFilter, tlv );
+ return;
+ }
+ });
+
+ // AttributeValueAssertion ::= SEQUENCE {
+ // ...
+ // assertionValue AssertionValue } (VALUE)
+ // We have to set the attribute description in the current filter.
+ // It could be an equalityMatch, greaterOrEqual, lessOrEqual or an
+ // approxMatch filter.
+ // Whgen finished, we will transit to the first state.
+ super.transitions[LdapStatesEnum.FILTER_ASSERTION_VALUE_VALUE][0x04] = new GrammarTransition(
+ LdapStatesEnum.FILTER_ASSERTION_VALUE_VALUE, LdapStatesEnum.FILTER_TAG,
+ new GrammarAction( "Init AssertionValue Value" )
+ {
+ public void action( IAsn1Container container ) throws DecoderException
+ {
+ LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer )
+ container;
+ LdapMessagePOJO ldapMessage =
+ ldapMessageContainer.getLdapMessage();
+ SearchRequestPOJO searchRequest = ldapMessage.getSearchRequest();
+
+ TLV tlv = ldapMessageContainer.getCurrentTLV();
+ OctetString assertionValue = new OctetString();
+ assertionValue.setData(tlv.getValue().getData());
+
+ AttributeValueAssertionFilterPOJO currentFilter = (AttributeValueAssertionFilterPOJO)searchRequest.getCurrentFilter();
+ AttributeValueAssertionPOJO assertion = currentFilter.getAssertion();
+ assertion.setAssertionValue(assertionValue);
+
+ // We now have to get back to the nearest filter which is not terminal.
+ unstackCurrent(searchRequest);
+ }
+ });
+
+ }
+
+ //~ Methods ------------------------------------------------------------------------------------
+
+ /**
+ * This class is a singleton.
+ *
+ * @return An instance on this grammar
+ */
+ public static IGrammar getInstance()
+ {
+ return instance;
+ }
+
+ /**
+ * This method is used to clear the filter's stack for terminated elements. An element
+ * is considered as terminated either if :
+ * - it's a final element (ie an element which cannot contains a Filter)
+ * - its current length equals its expected length.
+ *
+ * @param searchRequest The request being decoded
+ */
+ private void unstackCurrent(SearchRequestPOJO searchRequest)
+ {
+ FilterPOJO currentFilter = searchRequest.getCurrentFilter();
+
+ while (currentFilter != null)
+ {
+ if ( ( currentFilter instanceof AndFilterPOJO ) | ( currentFilter instanceof OrFilterPOJO ) | ( currentFilter instanceof NotFilterPOJO ) )
+ {
+ if ( currentFilter.getExpectedLength() == currentFilter.getCurrentLength())
+ {
+ // The current element is not terminal, but it has been fully decoded
+ // so we will pop it from the stack
+ AbstractPOJO element = currentFilter.getFather();
+
+ // We have to check that the father is a FilterPOJO.
+ if (element instanceof FilterPOJO)
+ {
+ currentFilter = (FilterPOJO)element;
+ }
+ else
+ {
+ // The element is a SearchRequestPOJO, so the stack is
+ // empty. It's over !
+ currentFilter = null;
+ return;
+ }
+ }
+ else
+ {
+ // Ok, we have a non terminal element which is not fully decoded.
+ searchRequest.setCurrentFilter(currentFilter);
+ return;
+ }
+ }
+ else
+ {
+ // The current element is a terminal element
+ currentFilter = (FilterPOJO)currentFilter.getFather();
+ }
+ }
+
+ return;
+ }
+}