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 *    https://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.dsmlv2.response;
021
022
023import org.apache.directory.api.dsmlv2.ParserUtils;
024import org.apache.directory.api.ldap.codec.api.LdapApiService;
025import org.apache.directory.api.ldap.model.entry.Attribute;
026import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
027import org.apache.directory.api.ldap.model.entry.Entry;
028import org.apache.directory.api.ldap.model.entry.Value;
029import org.apache.directory.api.ldap.model.exception.LdapException;
030import org.apache.directory.api.ldap.model.message.MessageTypeEnum;
031import org.apache.directory.api.ldap.model.message.SearchResultEntry;
032import org.apache.directory.api.ldap.model.message.SearchResultEntryImpl;
033import org.apache.directory.api.ldap.model.name.Dn;
034import org.dom4j.Document;
035import org.dom4j.Element;
036import org.dom4j.Namespace;
037import org.dom4j.QName;
038import org.dom4j.tree.DefaultElement;
039
040
041/**
042 * DSML Decorator for SearchResultEntry
043 *
044 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
045 */
046public class SearchResultEntryDsml
047    extends AbstractResponseDsml<SearchResultEntry>
048    implements SearchResultEntry
049{
050    private static final String SEARCH_RESULT_ENTRY_TAG = "searchResultEntry";
051
052    /** The current attribute being processed */
053    private Attribute currentAttribute;
054
055
056    /**
057     * Creates a new getDecoratedMessage() of SearchResultEntryDsml.
058     * 
059     * @param codec The LDAP Service to use
060     */
061    public SearchResultEntryDsml( LdapApiService codec )
062    {
063        super( codec, new SearchResultEntryImpl() );
064    }
065
066
067    /**
068     * Creates a new getDecoratedMessage() of SearchResultEntryDsml.
069     *
070     * @param codec The LDAP Service to use
071     * @param ldapMessage the message to decorate
072     */
073    public SearchResultEntryDsml( LdapApiService codec, SearchResultEntry ldapMessage )
074    {
075        super( codec, ldapMessage );
076    }
077
078
079    /**
080     * @return The current ATtributeType
081     */
082    public Attribute getCurrentAttribute()
083    {
084        return currentAttribute;
085    }
086
087
088    /**
089     * Create a new attribute
090     * 
091     * @param type The attribute's type
092     * @throws LdapException If we can't add the new attributeType
093     */
094    public void addAttribute( String type ) throws LdapException
095    {
096        currentAttribute = new DefaultAttribute( type );
097
098        getDecorated().getEntry().put( currentAttribute );
099    }
100
101
102    /**
103     * Add a new value to the current attribute
104     * 
105     * @param value The added value
106     * @throws LdapException If we can't add the new attributeType
107     */
108    public void addAttributeValue( Object value ) throws LdapException
109    {
110        if ( value instanceof String )
111        {
112            currentAttribute.add( ( String ) value );
113        }
114        else
115        {
116            currentAttribute.add( ( byte[] ) value );
117        }
118    }
119
120
121    /**
122     * {@inheritDoc}
123     */
124    @Override
125    public MessageTypeEnum getType()
126    {
127        return getDecorated().getType();
128    }
129
130
131    /**
132     * {@inheritDoc}
133     */
134    @Override
135    public Element toDsml( Element root )
136    {
137        Element element;
138
139        if ( root != null )
140        {
141            element = root.addElement( SEARCH_RESULT_ENTRY_TAG );
142        }
143        else
144        {
145            element = new DefaultElement( SEARCH_RESULT_ENTRY_TAG );
146        }
147
148        SearchResultEntry searchResultEntry = getDecorated();
149        element.addAttribute( "dn", searchResultEntry.getObjectName().getName() );
150
151        Entry entry = searchResultEntry.getEntry();
152        for ( Attribute attribute : entry )
153        {
154
155            Element attributeElement = element.addElement( "attr" );
156            attributeElement.addAttribute( "name", attribute.getUpId() );
157
158            for ( Value value : attribute )
159            {
160                if ( ParserUtils.needsBase64Encoding( value.getString() ) )
161                {
162                    Namespace xsdNamespace = new Namespace( ParserUtils.XSD, ParserUtils.XML_SCHEMA_URI );
163                    Namespace xsiNamespace = new Namespace( ParserUtils.XSI, ParserUtils.XML_SCHEMA_INSTANCE_URI );
164                    Document doc = attributeElement.getDocument();
165
166                    if ( doc != null )
167                    {
168                        Element docRoot = doc.getRootElement();
169                        docRoot.add( xsdNamespace );
170                        docRoot.add( xsiNamespace );
171                    }
172
173                    Element valueElement = attributeElement.addElement( "value" ).addText(
174                        ParserUtils.base64Encode( value.getString() ) );
175                    valueElement.addAttribute( new QName( "type", xsiNamespace ), ParserUtils.XSD + ":"
176                        + ParserUtils.BASE64BINARY );
177                }
178                else
179                {
180                    attributeElement.addElement( "value" ).addText( value.getString() );
181                }
182            }
183        }
184
185        return element;
186    }
187
188
189    /**
190     * Get the entry Dn
191     * 
192     * @return Returns the objectName.
193     */
194    @Override
195    public Dn getObjectName()
196    {
197        return getDecorated().getObjectName();
198    }
199
200
201    /**
202     * Set the entry Dn
203     * 
204     * @param objectName The objectName to set.
205     */
206    @Override
207    public void setObjectName( Dn objectName )
208    {
209        getDecorated().setObjectName( objectName );
210    }
211
212
213    /**
214     * Get the entry.
215     * 
216     * @return Returns the entry.
217     */
218    @Override
219    public Entry getEntry()
220    {
221        return getDecorated().getEntry();
222    }
223
224
225    /**
226     * Initialize the entry.
227     * 
228     * @param entry the entry
229     */
230    @Override
231    public void setEntry( Entry entry )
232    {
233        getDecorated().setEntry( entry );
234    }
235}