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.data.ametysobject.ModelLessDataAwareAmetysObject;
032import org.ametys.plugins.repository.metadata.CompositeMetadata;
033import org.ametys.plugins.repository.metadata.CompositeMetadata.MetadataType;
034import org.ametys.plugins.repository.metadata.MetadataAwareAmetysObject;
035import org.ametys.runtime.model.type.ElementType;
036import org.ametys.runtime.model.type.ModelItemType;
037
038/**
039 * Implementation of {@link Element} wrapping an {@link AmetysObject}.<br>
040 * Only methods useful for XPath processing are implemented.
041 * @param <A> the actual type of the wrapped {@link AmetysObject}.
042 */
043public class AmetysObjectElement<A extends AmetysObject> extends AbstractWrappingAmetysElement<A>
044{
045    /**
046     * Constructor.
047     * @param object the underlying {@link AmetysObject}.
048     */
049    public AmetysObjectElement(A object)
050    {
051        this(object, null);
052    }
053    
054    /**
055     * Constructor.
056     * @param object the underlying {@link AmetysObject}.
057     * @param parent the parent {@link Element}.
058     */
059    public AmetysObjectElement(A object, AmetysObjectElement<? extends TraversableAmetysObject> parent)
060    {
061        super(object, parent);
062    }
063
064    @Override
065    public String getTagName()
066    {
067        return _object.getName();
068    }
069    
070    /**
071     * This implementation returns all non-composite metadata.
072     */
073    @Override
074    protected Map<String, AmetysAttribute> _lookupAttributes()
075    {
076        Map<String, AmetysAttribute> result = new HashMap<>();
077        
078        if (_object instanceof ModelLessDataAwareAmetysObject)
079        {
080            ModelLessDataAwareAmetysObject dataHolder = (ModelLessDataAwareAmetysObject) _object;
081            
082            for (String name : dataHolder.getDataNames())
083            {
084                ModelItemType type = dataHolder.getType(name);
085                if (type instanceof ElementType && !dataHolder.isMultiple(name))
086                {
087                    Object value = dataHolder.getValue(name);
088                    @SuppressWarnings("unchecked")
089                    String valueAsString = ((ElementType) type).toString(value);
090                    result.put(name, new AmetysAttribute(name, name, null, valueAsString, this));
091                }
092            }
093        }
094        else if (_object instanceof MetadataAwareAmetysObject)
095        {
096            CompositeMetadata metadata = ((MetadataAwareAmetysObject) _object).getMetadataHolder();
097            
098            String[] names = metadata.getMetadataNames();
099            
100            for (String name : names)
101            {
102                MetadataType type = metadata.getType(name);
103                if (type != MetadataType.COMPOSITE && type != MetadataType.USER && type != MetadataType.BINARY && type != MetadataType.RICHTEXT && type != MetadataType.OBJECT_COLLECTION && !metadata.isMultiple(name))
104                {
105                    String value = metadata.getString(name);
106                    result.put(name, new AmetysAttribute(name, name, null, value, this));
107                }
108            }
109        }
110        
111        return result;
112    }
113    
114    @Override
115    public boolean hasChildNodes()
116    {
117        if (_object instanceof TraversableAmetysObject)
118        {
119            AmetysObjectIterable<AmetysObject> children = ((TraversableAmetysObject) _object).getChildren();
120            
121            return children.iterator().hasNext();
122        }
123        
124        return false;
125    }
126    
127    @SuppressWarnings("unchecked")
128    @Override
129    public Node getFirstChild()
130    {
131        if (_object instanceof TraversableAmetysObject)
132        {
133            AmetysObjectIterable<AmetysObject> children = ((TraversableAmetysObject) _object).getChildren();
134            Iterator<AmetysObject> it = children.iterator();
135            
136            if (!it.hasNext())
137            {
138                return null;
139            }
140            
141            return new AmetysObjectElement<>(it.next(), (AmetysObjectElement<TraversableAmetysObject>) this);
142        }
143        
144        return null;
145    }
146    
147    @SuppressWarnings("unchecked")
148    @Override
149    public Node getNextSibling()
150    {
151        if (_parent == null)
152        {
153            return null;
154        }
155        
156        TraversableAmetysObject parent = (TraversableAmetysObject) ((AbstractWrappingAmetysElement) _parent).getWrappedObject();
157        
158        AmetysObjectIterable<AmetysObject> children = parent.getChildren();
159        
160        boolean isNext = false;
161        AmetysObject nextSibling = null;
162        Iterator<AmetysObject> it = children.iterator();
163        
164        while (nextSibling == null && it.hasNext())
165        {
166            AmetysObject child = it.next();
167            
168            if (isNext)
169            {
170                nextSibling = child;
171            }
172            else if (_object.getId().equals(child.getId()))
173            {
174                isNext = true;
175            }
176        }
177        
178        return nextSibling == null ? null : new AmetysObjectElement<>(nextSibling, (AmetysObjectElement< ? extends TraversableAmetysObject>) _parent);
179    }
180}