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     */
020    package org.apache.directory.shared.dsmlv2.request;
021    
022    
023    import java.util.List;
024    
025    import org.apache.directory.shared.dsmlv2.ParserUtils;
026    import org.apache.directory.shared.ldap.codec.AttributeValueAssertion;
027    import org.apache.directory.shared.ldap.codec.LdapConstants;
028    import org.apache.directory.shared.ldap.codec.MessageTypeEnum;
029    import org.apache.directory.shared.ldap.codec.search.AndFilter;
030    import org.apache.directory.shared.ldap.codec.search.AttributeValueAssertionFilter;
031    import org.apache.directory.shared.ldap.codec.search.ExtensibleMatchFilter;
032    import org.apache.directory.shared.ldap.codec.search.Filter;
033    import org.apache.directory.shared.ldap.codec.search.NotFilter;
034    import org.apache.directory.shared.ldap.codec.search.OrFilter;
035    import org.apache.directory.shared.ldap.codec.search.PresentFilter;
036    import org.apache.directory.shared.ldap.codec.search.SearchRequestCodec;
037    import org.apache.directory.shared.ldap.codec.search.SubstringFilter;
038    import org.apache.directory.shared.ldap.entry.EntryAttribute;
039    import org.apache.directory.shared.ldap.filter.SearchScope;
040    import org.dom4j.Element;
041    import org.dom4j.Namespace;
042    import org.dom4j.QName;
043    
044    
045    /**
046     * DSML Decorator for SearchRequest
047     *
048     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
049     * @version $Rev$, $Date$
050     */
051    public class SearchRequestDsml extends AbstractRequestDsml
052    {
053        /**
054         * Creates a new instance of SearchRequestDsml.
055         */
056        public SearchRequestDsml()
057        {
058            super( new SearchRequestCodec() );
059        }
060    
061    
062        /**
063         * Creates a new instance of SearchRequestDsml.
064         *
065         * @param ldapMessage
066         *      the message to decorate
067         */
068        public SearchRequestDsml( SearchRequestCodec ldapMessage )
069        {
070            super( ldapMessage );
071        }
072    
073    
074        /**
075         * {@inheritDoc}
076         */
077        public MessageTypeEnum getMessageType()
078        {
079            return instance.getMessageType();
080        }
081    
082    
083        /**
084         * {@inheritDoc}
085         */
086        public Element toDsml( Element root )
087        {
088            Element element = super.toDsml( root );
089    
090            SearchRequestCodec request = ( SearchRequestCodec ) instance;
091    
092            // DN
093            if ( request.getBaseObject() != null )
094            {
095                element.addAttribute( "dn", request.getBaseObject().getName() );
096            }
097    
098            // Scope
099            SearchScope scope = request.getScope();
100            if ( scope != null )
101            {
102                if ( scope == SearchScope.OBJECT )
103                {
104                    element.addAttribute( "scope", "baseObject" );
105                }
106                else if ( scope == SearchScope.ONELEVEL )
107                {
108                    element.addAttribute( "scope", "singleLevel" );
109                }
110                else if ( scope == SearchScope.SUBTREE )
111                {
112                    element.addAttribute( "scope", "wholeSubtree" );
113                }
114            }
115    
116            // DerefAliases
117            int derefAliases = request.getDerefAliases();
118            if ( derefAliases == LdapConstants.NEVER_DEREF_ALIASES )
119            {
120                element.addAttribute( "derefAliases", "neverDerefAliases" );
121            }
122            else if ( derefAliases == LdapConstants.DEREF_IN_SEARCHING )
123            {
124                element.addAttribute( "derefAliases", "derefInSearching" );
125            }
126            else if ( derefAliases == LdapConstants.DEREF_FINDING_BASE_OBJ )
127            {
128                element.addAttribute( "derefAliases", "derefFindingBaseObj" );
129            }
130            else if ( derefAliases == LdapConstants.DEREF_ALWAYS )
131            {
132                element.addAttribute( "derefAliases", "derefAlways" );
133            }
134    
135            // SizeLimit
136            if ( request.getSizeLimit() != 0L )
137            {
138                element.addAttribute( "sizeLimit", "" + request.getSizeLimit() );
139            }
140    
141            // TimeLimit
142            if ( request.getTimeLimit() != 0 )
143            {
144                element.addAttribute( "timeLimit", "" + request.getTimeLimit() );
145            }
146    
147            // TypesOnly
148            if ( request.isTypesOnly() )
149            {
150                element.addAttribute( "typesOnly", "true" );
151            }
152    
153            // Filter
154            Element filterElement = element.addElement( "filter" );
155            toDsml( filterElement, request.getFilter() );
156    
157            // Attributes
158            List<EntryAttribute> attributes = request.getAttributes();
159            if ( attributes.size() > 0 )
160            {
161                Element attributesElement = element.addElement( "attributes" );
162    
163                for ( EntryAttribute entryAttribute : attributes )
164                {
165                    attributesElement.addElement( "attribute" ).addAttribute( "name", entryAttribute.getId() );
166                }
167            }
168    
169            return element;
170        }
171    
172    
173        /**
174         * Recursively converts the filter of the Search Request into a DSML representation and adds 
175         * it to the XML Element corresponding to the Search Request
176         *
177         * @param element
178         *      the parent Element
179         * @param filter
180         *      the filter to convert
181         */
182        private void toDsml( Element element, Filter filter )
183        {
184            // AND FILTER
185            if ( filter instanceof AndFilter )
186            {
187                Element newElement = element.addElement( "and" );
188    
189                List<Filter> filterList = ( ( AndFilter ) filter ).getAndFilter();
190                for ( int i = 0; i < filterList.size(); i++ )
191                {
192                    toDsml( newElement, filterList.get( i ) );
193                }
194            }
195    
196            // OR FILTER
197            else if ( filter instanceof OrFilter )
198            {
199                Element newElement = element.addElement( "or" );
200    
201                List<Filter> filterList = ( ( OrFilter ) filter ).getOrFilter();
202                for ( int i = 0; i < filterList.size(); i++ )
203                {
204                    toDsml( newElement, filterList.get( i ) );
205                }
206            }
207    
208            // NOT FILTER
209            else if ( filter instanceof NotFilter )
210            {
211                Element newElement = element.addElement( "not" );
212    
213                toDsml( newElement, ( ( NotFilter ) filter ).getNotFilter() );
214            }
215    
216            // SUBSTRING FILTER
217            else if ( filter instanceof SubstringFilter )
218            {
219                Element newElement = element.addElement( "substrings" );
220    
221                SubstringFilter substringFilter = ( SubstringFilter ) filter;
222    
223                newElement.addAttribute( "name", substringFilter.getType() );
224    
225                String initial = substringFilter.getInitialSubstrings();
226                if ( ( initial != null ) && ( !"".equals( initial ) ) )
227                {
228                    newElement.addElement( "initial" ).setText( initial );
229                }
230    
231                List<String> anyList = substringFilter.getAnySubstrings();
232                for ( int i = 0; i < anyList.size(); i++ )
233                {
234                    newElement.addElement( "any" ).setText( anyList.get( i ) );
235                }
236    
237                String finalString = substringFilter.getFinalSubstrings();
238                if ( ( finalString != null ) && ( !"".equals( finalString ) ) )
239                {
240                    newElement.addElement( "final" ).setText( finalString );
241                }
242            }
243    
244            // APPROXMATCH, EQUALITYMATCH, GREATEROREQUALS & LESSOREQUAL FILTERS
245            else if ( filter instanceof AttributeValueAssertionFilter )
246            {
247                AttributeValueAssertionFilter avaFilter = ( AttributeValueAssertionFilter ) filter;
248    
249                Element newElement = null;
250                int filterType = avaFilter.getFilterType();
251                if ( filterType == LdapConstants.APPROX_MATCH_FILTER )
252                {
253                    newElement = element.addElement( "approxMatch" );
254                }
255                else if ( filterType == LdapConstants.EQUALITY_MATCH_FILTER )
256                {
257                    newElement = element.addElement( "equalityMatch" );
258                }
259                else if ( filterType == LdapConstants.GREATER_OR_EQUAL_FILTER )
260                {
261                    newElement = element.addElement( "greaterOrEqual" );
262                }
263                else if ( filterType == LdapConstants.LESS_OR_EQUAL_FILTER )
264                {
265                    newElement = element.addElement( "lessOrEqual" );
266                }
267    
268                AttributeValueAssertion assertion = avaFilter.getAssertion();
269                if ( assertion != null )
270                {
271                    newElement.addAttribute( "name", assertion.getAttributeDesc() );
272    
273                    Object value = assertion.getAssertionValue();
274                    if ( value != null )
275                    {
276                        if ( ParserUtils.needsBase64Encoding( value ) )
277                        {
278                            Namespace xsdNamespace = new Namespace( "xsd", ParserUtils.XML_SCHEMA_URI );
279                            Namespace xsiNamespace = new Namespace( "xsi", ParserUtils.XML_SCHEMA_INSTANCE_URI );
280                            element.getDocument().getRootElement().add( xsdNamespace );
281                            element.getDocument().getRootElement().add( xsiNamespace );
282    
283                            Element valueElement = newElement.addElement( "value" ).addText(
284                                ParserUtils.base64Encode( value ) );
285                            valueElement
286                                .addAttribute( new QName( "type", xsiNamespace ), "xsd:" + ParserUtils.BASE64BINARY );
287                        }
288                        else
289                        {
290                            newElement.addElement( "value" ).setText( ( String ) value );
291                        }
292                    }
293                }
294            }
295    
296            // PRESENT FILTER
297            else if ( filter instanceof PresentFilter )
298            {
299                Element newElement = element.addElement( "present" );
300    
301                newElement.addAttribute( "name", ( ( PresentFilter ) filter ).getAttributeDescription() );
302            }
303    
304            // EXTENSIBLEMATCH
305            else if ( filter instanceof ExtensibleMatchFilter )
306            {
307                Element newElement = element.addElement( "extensibleMatch" );
308    
309                ExtensibleMatchFilter extensibleMatchFilter = ( ExtensibleMatchFilter ) filter;
310    
311                Object value = extensibleMatchFilter.getMatchValue();
312                if ( value != null )
313                {
314                    if ( ParserUtils.needsBase64Encoding( value ) )
315                    {
316                        Namespace xsdNamespace = new Namespace( "xsd", ParserUtils.XML_SCHEMA_URI );
317                        Namespace xsiNamespace = new Namespace( "xsi", ParserUtils.XML_SCHEMA_INSTANCE_URI );
318                        element.getDocument().getRootElement().add( xsdNamespace );
319                        element.getDocument().getRootElement().add( xsiNamespace );
320    
321                        Element valueElement = newElement.addElement( "value" ).addText( ParserUtils.base64Encode( value ) );
322                        valueElement.addAttribute( new QName( "type", xsiNamespace ), "xsd:" + ParserUtils.BASE64BINARY );
323                    }
324                    else
325                    {
326                        newElement.addElement( "value" ).setText( ( String ) value );
327                    }
328                }
329    
330                if ( extensibleMatchFilter.isDnAttributes() )
331                {
332                    newElement.addAttribute( "dnAttributes", "true" );
333                }
334    
335                String matchingRule = extensibleMatchFilter.getMatchingRule();
336                if ( ( matchingRule != null ) && ( "".equals( matchingRule ) ) )
337                {
338                    newElement.addAttribute( "matchingRule", matchingRule );
339                }
340            }
341        }
342    }