001/* 002 * Copyright 2015 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 */ 016package org.ametys.core.util.dom; 017 018import java.util.ArrayList; 019import java.util.Collections; 020import java.util.HashMap; 021import java.util.List; 022import java.util.Map; 023import java.util.Map.Entry; 024 025import org.w3c.dom.Element; 026import org.w3c.dom.Node; 027import org.w3c.dom.NodeList; 028 029/** 030 * DOM Layer over a Map. Only String, List<Object> and Map<String, Object> values are allowed (recursively). 031 */ 032public class MapElement extends AbstractAmetysElement 033{ 034 private Map<String, ? extends Object> _values; 035 private Map<String, String> _attributes; 036 037 /** 038 * Constructor. 039 * @param tagName the tag name. 040 * @param values the values. 041 */ 042 public MapElement(String tagName, Map<String, ? extends Object> values) 043 { 044 this(tagName, Collections.emptyMap(), values); 045 } 046 047 /** 048 * Constructor. 049 * @param tagName the tag name. 050 * @param attributes The attributes names and values. 051 * @param values the values. 052 */ 053 public MapElement(String tagName, Map<String, String> attributes, Map<String, ? extends Object> values) 054 { 055 super(tagName); 056 _values = values; 057 _attributes = attributes; 058 } 059 060 /** 061 * Constructor. 062 * @param tagName the tag name. 063 * @param values the values. 064 * @param parent the parent {@link Element} if any. 065 */ 066 public MapElement(String tagName, Map<String, ? extends Object> values, Element parent) 067 { 068 super(tagName, parent); 069 _values = values; 070 } 071 072 /** 073 * Constructor. 074 * @param tagName the tag name. 075 * @param attributes The attributes names and values. 076 * @param values the values. 077 * @param parent the parent {@link Element} if any. 078 */ 079 public MapElement(String tagName, Map<String, String> attributes, Map<String, ? extends Object> values, Element parent) 080 { 081 super(tagName, parent); 082 _values = values; 083 _attributes = attributes; 084 } 085 086 087 @Override 088 protected Map<String, AmetysAttribute> _lookupAttributes() 089 { 090 Map<String, AmetysAttribute> attrs = new HashMap<>(); 091 092 if (_attributes != null) 093 { 094 for (String name : _attributes.keySet()) 095 { 096 attrs.put(name, new AmetysAttribute(name, name, null, _attributes.get(name), this)); 097 } 098 } 099 100 return attrs; 101 } 102 103 @Override 104 public Node getFirstChild() 105 { 106 NodeList list = getChildNodes(); 107 108 if (list.getLength() == 0) 109 { 110 return null; 111 } 112 113 return list.item(0); 114 } 115 116 @Override 117 @SuppressWarnings("unchecked") 118 protected NodeList _getChildNodes() 119 { 120 List<Element> list = new ArrayList<>(); 121 122 if (_values != null) 123 { 124 for (Entry<String, ? extends Object> entry : _values.entrySet()) 125 { 126 Object rawValue = entry.getValue(); 127 List<Object> values = new ArrayList<>(); 128 if (rawValue instanceof List) 129 { 130 values.addAll((List) rawValue); 131 } 132 else 133 { 134 values.add(rawValue); 135 } 136 137 for (Object value : values) 138 { 139 Object realValue = value; 140 Map<String, String> attributes = null; 141 if (value instanceof MapNode) 142 { 143 realValue = ((MapNode) value).getValue(); 144 attributes = ((MapNode) value).getAttributes(); 145 } 146 147 if (realValue == null) 148 { 149 list.add(new StringElement(entry.getKey(), attributes, "", this)); 150 } 151 else if (realValue instanceof String) 152 { 153 list.add(new StringElement(entry.getKey(), attributes, (String) realValue, this)); 154 } 155 else if (realValue instanceof Map) 156 { 157 list.add(new MapElement(entry.getKey(), attributes, (Map<String, ? extends Object>) realValue, this)); 158 } 159 else 160 { 161 throw new IllegalArgumentException("MapElement only handles String, List<Object> or Map<String, Object> recursively"); 162 } 163 } 164 } 165 } 166 167 return new AmetysNodeList(list); 168 } 169 170 /** 171 * This class represents a element 172 * 173 */ 174 public static class MapNode 175 { 176 private Object _value; 177 private Map<String, String> _attrs; 178 179 /** 180 * Constructor 181 * @param value The value 182 * @param attributes The attributes 183 */ 184 public MapNode (Object value, Map<String, String> attributes) 185 { 186 _value = value; 187 _attrs = attributes; 188 } 189 190 /** 191 * Get the attributes 192 * @return the attributes 193 */ 194 public Map<String, String> getAttributes() 195 { 196 return _attrs; 197 } 198 199 /** 200 * Get the value 201 * @return the value 202 */ 203 public Object getValue () 204 { 205 return _value; 206 } 207 } 208}