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