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.model.filter;
021
022
023import org.apache.directory.api.i18n.I18n;
024import org.apache.directory.api.ldap.model.constants.SchemaConstants;
025import org.apache.directory.api.ldap.model.entry.Value;
026import org.apache.directory.api.ldap.model.schema.AttributeType;
027
028
029/**
030 * A simple assertion value node.
031 * 
032 * @param <T> The Value type
033 * 
034 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
035 */
036public abstract class SimpleNode<T> extends LeafNode
037{
038    /** the value */
039    protected Value<T> value;
040
041    /** Constants for comparisons : &gt; */
042    public static final boolean EVAL_GREATER = true;
043
044    /** Constants for comparisons : &lt; */
045    public static final boolean EVAL_LESSER = false;
046
047
048    /**
049     * Creates a new SimpleNode object.
050     * 
051     * @param attribute the attribute name
052     * @param value the value to test for
053     * @param assertionType the type of assertion represented by this ExprNode
054     */
055    protected SimpleNode( String attribute, Value<T> value, AssertionType assertionType )
056    {
057        super( attribute, assertionType );
058        this.value = value;
059    }
060
061
062    /**
063     * Creates a new SimpleNode object.
064     * 
065     * @param attributeType the attribute name
066     * @param value the value to test for
067     * @param assertionType the type of assertion represented by this ExprNode
068     */
069    protected SimpleNode( AttributeType attributeType, Value<T> value, AssertionType assertionType )
070    {
071        super( attributeType, assertionType );
072        this.value = value;
073    }
074
075
076    /**
077     * Makes a full clone in new memory space of the current node and children
078     */
079    @SuppressWarnings("unchecked")
080    @Override
081    public ExprNode clone()
082    {
083        ExprNode clone = super.clone();
084
085        // Clone the value
086        ( ( SimpleNode<T> ) clone ).value = value.clone();
087
088        return clone;
089    }
090
091
092    /**
093     * Gets the value.
094     * 
095     * @return the value
096     */
097    public final Value<T> getValue()
098    {
099        return value;
100    }
101
102
103    /** 
104     * @return representation of value, escaped for use in a filter if required 
105     */
106    public Value<?> getEscapedValue()
107    {
108        return escapeFilterValue( value );
109    }
110
111
112    /**
113     * Sets the value of this node.
114     * 
115     * @param value the value for this node
116     */
117    public void setValue( Value<T> value )
118    {
119        this.value = value;
120    }
121
122
123    /**
124     * Pretty prints this expression node along with annotation information.
125     *
126     * @param buf the buffer to print into
127     * @return the same buf argument returned for call chaining
128     */
129    public StringBuilder printToBuffer( StringBuilder buf )
130    {
131        if ( ( null != getAnnotations() ) && getAnnotations().containsKey( "count" ) )
132        {
133            buf.append( ":[" );
134            buf.append( getAnnotations().get( "count" ).toString() );
135            buf.append( "] " );
136        }
137
138        buf.append( ')' );
139
140        return buf;
141    }
142
143
144    /**
145     * @see ExprNode#printRefinementToBuffer(StringBuilder)
146     * @return The buffer in which the refinement has been appended
147     * @throws UnsupportedOperationException if this node isn't a part of a refinement.
148     */
149    @Override
150    public StringBuilder printRefinementToBuffer( StringBuilder buf )
151    {
152        if ( isSchemaAware )
153        {
154            if ( !attributeType.getOid().equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
155            {
156                throw new UnsupportedOperationException( I18n.err( I18n.ERR_04162, attribute ) );
157            }
158        }
159        else
160        {
161            if ( ( attribute == null )
162                || !( SchemaConstants.OBJECT_CLASS_AT.equalsIgnoreCase( attribute )
163                || SchemaConstants.OBJECT_CLASS_AT_OID.equalsIgnoreCase( attribute ) ) )
164            {
165                throw new UnsupportedOperationException( I18n.err( I18n.ERR_04162, attribute ) );
166            }
167        }
168
169        buf.append( "item: " ).append( value );
170
171        return buf;
172    }
173
174
175    /**
176     * @see Object#hashCode()
177     * @return the instance's hash code 
178     */
179    @Override
180    public int hashCode()
181    {
182        int h = 37;
183
184        h = h * 17 + super.hashCode();
185        h = h * 17 + ( value == null ? 0 : value.hashCode() );
186
187        return h;
188    }
189
190
191    /**
192     * @see java.lang.Object#equals(java.lang.Object)
193     */
194    @Override
195    public boolean equals( Object other )
196    {
197        if ( this == other )
198        {
199            return true;
200        }
201
202        if ( !( other instanceof SimpleNode<?> ) )
203        {
204            return false;
205        }
206
207        if ( other.getClass() != this.getClass() )
208        {
209            return false;
210        }
211
212        if ( !super.equals( other ) )
213        {
214            return false;
215        }
216
217        SimpleNode<?> otherNode = ( SimpleNode<?> ) other;
218
219        if ( value == null )
220        {
221            return otherNode.value == null;
222        }
223        else
224        {
225            return value.equals( otherNode.value );
226        }
227    }
228}