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