001/* 002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 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 * Contributors: 017 * Nuxeo - initial API and implementation 018 * 019 * $Id$ 020 */ 021 022package org.nuxeo.common.xmap; 023 024import java.util.Map; 025 026import org.nuxeo.common.xmap.annotation.XNodeMap; 027import org.w3c.dom.Element; 028import org.w3c.dom.Node; 029 030/** 031 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 032 */ 033@SuppressWarnings({ "SuppressionAnnotation" }) 034public class XAnnotatedMap extends XAnnotatedList { 035 036 protected static final ElementMapVisitor elementMapVisitor = new ElementMapVisitor(); 037 038 protected static final ElementValueMapVisitor elementVisitor = new ElementValueMapVisitor(); 039 040 protected static final AttributeValueMapVisitor attributeVisitor = new AttributeValueMapVisitor(); 041 042 protected final Path key; 043 044 protected final boolean isNullByDefault; 045 046 public XAnnotatedMap(XMap xmap, XAccessor setter, XNodeMap anno) { 047 super(xmap, setter); 048 path = new Path(anno.value()); 049 trim = anno.trim(); 050 key = new Path(anno.key()); 051 type = anno.type(); 052 componentType = anno.componentType(); 053 valueFactory = xmap.getValueFactory(componentType); 054 xao = xmap.register(componentType); 055 isNullByDefault = anno.nullByDefault(); 056 } 057 058 @SuppressWarnings("unchecked") 059 @Override 060 protected Object getValue(Context ctx, Element base) { 061 Map<String, Object> values; 062 try { 063 values = (Map) type.newInstance(); 064 } catch (InstantiationException e) { 065 throw new IllegalArgumentException(e); 066 } catch (IllegalAccessException e) { 067 throw new IllegalArgumentException(e); 068 } 069 if (xao != null) { 070 DOMHelper.visitMapNodes(ctx, this, base, path, elementMapVisitor, values); 071 } else { 072 if (path.attribute != null) { 073 // attribute list 074 DOMHelper.visitMapNodes(ctx, this, base, path, attributeVisitor, values); 075 } else { 076 // element list 077 DOMHelper.visitMapNodes(ctx, this, base, path, elementVisitor, values); 078 } 079 } 080 if (isNullByDefault && values.isEmpty()) { 081 values = null; 082 } 083 return values; 084 } 085 086 @Override 087 public void toXML(Object instance, Element parent) { 088 Object v = accessor.getValue(instance); 089 if (v != null && v instanceof Map<?, ?>) { 090 Map<String, ?> map = (Map<String, ?>) v; 091 if (xao == null) { 092 for (Map.Entry<String, ?> entry : map.entrySet()) { 093 String entryKey = entry.getKey(); 094 String value = valueFactory.serialize(null, entry.getValue()); 095 Element e = XMLBuilder.addElement(parent, path); 096 Element keyElement = XMLBuilder.getOrCreateElement(e, key); 097 XMLBuilder.fillField(keyElement, entryKey, key.attribute); 098 XMLBuilder.fillField(e, value, null); 099 } 100 } else { 101 for (Map.Entry<String, ?> entry : map.entrySet()) { 102 String entryKey = entry.getKey(); 103 Element e = XMLBuilder.addElement(parent, path); 104 Element keyElement = XMLBuilder.getOrCreateElement(e, key); 105 XMLBuilder.fillField(keyElement, entryKey, key.attribute); 106 XMLBuilder.toXML(entry.getValue(), e, xao); 107 } 108 } 109 } 110 } 111} 112 113class ElementMapVisitor implements DOMHelper.NodeMapVisitor { 114 115 public void visitNode(Context ctx, XAnnotatedMember xam, Node node, String key, Map<String, Object> result) { 116 result.put(key, xam.xao.newInstance(ctx, (Element) node)); 117 } 118} 119 120class ElementValueMapVisitor implements DOMHelper.NodeMapVisitor { 121 public void visitNode(Context ctx, XAnnotatedMember xam, Node node, String key, Map<String, Object> result) { 122 String val = node.getTextContent(); 123 if (xam.trim) { 124 val = val.trim(); 125 } 126 if (xam.valueFactory != null) { 127 result.put(key, xam.valueFactory.deserialize(ctx, val)); 128 } else { 129 // TODO: log warning? 130 result.put(key, val); 131 } 132 } 133} 134 135class AttributeValueMapVisitor implements DOMHelper.NodeMapVisitor { 136 public void visitNode(Context ctx, XAnnotatedMember xam, Node node, String key, Map<String, Object> result) { 137 String val = node.getNodeValue(); 138 if (xam.valueFactory != null) { 139 result.put(key, xam.valueFactory.deserialize(ctx, val)); 140 } else { 141 // TODO: log warning? 142 result.put(key, val); 143 } 144 } 145}