001/*
002 *  Copyright 2011 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016
017package org.ametys.plugins.repository.dom;
018
019import java.util.HashMap;
020import java.util.Iterator;
021import java.util.Map;
022
023import org.w3c.dom.Element;
024import org.w3c.dom.Node;
025
026import org.ametys.core.util.dom.AbstractWrappingAmetysElement;
027import org.ametys.core.util.dom.AmetysAttribute;
028import org.ametys.plugins.repository.AmetysObject;
029import org.ametys.plugins.repository.AmetysObjectIterable;
030import org.ametys.plugins.repository.TraversableAmetysObject;
031import org.ametys.plugins.repository.metadata.CompositeMetadata;
032import org.ametys.plugins.repository.metadata.CompositeMetadata.MetadataType;
033import org.ametys.plugins.repository.metadata.MetadataAwareAmetysObject;
034
035/**
036 * Implementation of {@link Element} wrapping an {@link AmetysObject}.<br>
037 * Only methods useful for XPath processing are implemented.
038 * @param <A> the actual type of the wrapped {@link AmetysObject}.
039 */
040public class AmetysObjectElement<A extends AmetysObject> extends AbstractWrappingAmetysElement<A>
041{
042    /**
043     * Constructor.
044     * @param object the underlying {@link AmetysObject}.
045     */
046    public AmetysObjectElement(A object)
047    {
048        this(object, null);
049    }
050    
051    /**
052     * Constructor.
053     * @param object the underlying {@link AmetysObject}.
054     * @param parent the parent {@link Element}.
055     */
056    public AmetysObjectElement(A object, AmetysObjectElement<? extends TraversableAmetysObject> parent)
057    {
058        super(object, parent);
059    }
060
061    @Override
062    public String getTagName()
063    {
064        return _object.getName();
065    }
066    
067    /**
068     * This implementation returns all non-composite metadata.
069     */
070    @Override
071    protected Map<String, AmetysAttribute> _lookupAttributes()
072    {
073        Map<String, AmetysAttribute> result = new HashMap<>();
074        
075        if (_object instanceof MetadataAwareAmetysObject)
076        {
077            CompositeMetadata metadata = ((MetadataAwareAmetysObject) _object).getMetadataHolder();
078            
079            String[] names = metadata.getMetadataNames();
080            
081            for (String name : names)
082            {
083                MetadataType type = metadata.getType(name);
084                if (type != MetadataType.COMPOSITE && type != MetadataType.USER && type != MetadataType.BINARY && type != MetadataType.RICHTEXT && type != MetadataType.OBJECT_COLLECTION && !metadata.isMultiple(name))
085                {
086                    String value = metadata.getString(name);
087                    result.put(name, new AmetysAttribute(name, name, null, value, this));
088                }
089            }
090        }
091        
092        return result;
093    }
094    
095    @Override
096    public boolean hasChildNodes()
097    {
098        if (_object instanceof TraversableAmetysObject)
099        {
100            AmetysObjectIterable<AmetysObject> children = ((TraversableAmetysObject) _object).getChildren();
101            
102            return children.iterator().hasNext();
103        }
104        
105        return false;
106    }
107    
108    @SuppressWarnings("unchecked")
109    @Override
110    public Node getFirstChild()
111    {
112        if (_object instanceof TraversableAmetysObject)
113        {
114            AmetysObjectIterable<AmetysObject> children = ((TraversableAmetysObject) _object).getChildren();
115            Iterator<AmetysObject> it = children.iterator();
116            
117            if (!it.hasNext())
118            {
119                return null;
120            }
121            
122            return new AmetysObjectElement<>(it.next(), (AmetysObjectElement<TraversableAmetysObject>) this);
123        }
124        
125        return null;
126    }
127    
128    @SuppressWarnings("unchecked")
129    @Override
130    public Node getNextSibling()
131    {
132        if (_parent == null)
133        {
134            return null;
135        }
136        
137        TraversableAmetysObject parent = (TraversableAmetysObject) ((AbstractWrappingAmetysElement) _parent).getWrappedObject();
138        
139        AmetysObjectIterable<AmetysObject> children = parent.getChildren();
140        
141        boolean isNext = false;
142        AmetysObject nextSibling = null;
143        Iterator<AmetysObject> it = children.iterator();
144        
145        while (nextSibling == null && it.hasNext())
146        {
147            AmetysObject child = it.next();
148            
149            if (isNext)
150            {
151                nextSibling = child;
152            }
153            else if (_object.getId().equals(child.getId()))
154            {
155                isNext = true;
156            }
157        }
158        
159        return nextSibling == null ? null : new AmetysObjectElement<>(nextSibling, (AmetysObjectElement< ? extends TraversableAmetysObject>) _parent);
160    }
161}