Package com.intellij.util.xmlb

Source Code of com.intellij.util.xmlb.MapBinding

/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.intellij.util.xmlb;

import com.intellij.openapi.util.JDOMUtil;
import static com.intellij.util.xmlb.Constants.*;
import com.intellij.util.xmlb.annotations.MapAnnotation;
import com.intellij.util.ArrayUtil;
import org.jdom.Attribute;
import org.jdom.Content;
import org.jdom.Element;
import org.jdom.Text;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.Set;

class MapBinding implements Binding {
  private final Binding myKeyBinding;
  private final Binding myValueBinding;
  private final MapAnnotation myMapAnnotation;
  private static final Comparator<Object> KEY_COMPARATOR = new Comparator<Object>() {
    public int compare(final Object o1, final Object o2) {
      if (o1 instanceof Comparable && o2 instanceof Comparable) {
        Comparable c1 = (Comparable)o1;
        Comparable c2 = (Comparable)o2;
        return c1.compareTo(c2);
      }

      return 0;
    }
  };


  public MapBinding(ParameterizedType type, XmlSerializerImpl serializer, Accessor accessor) {
    Type[] arguments = type.getActualTypeArguments();
    Type keyType = arguments[0];
    Type valueType = arguments[1];

    myKeyBinding = serializer.getBinding(keyType);
    myValueBinding = serializer.getBinding(valueType);
    myMapAnnotation = XmlSerializerImpl.findAnnotation(accessor.getAnnotations(), MapAnnotation.class);
  }

  public Object serialize(Object o, Object context) {
    Map map = (Map)o;

    Element m;

    if (myMapAnnotation == null || myMapAnnotation.surroundWithTag()) {
      m = new Element(Constants.MAP);
    }
    else {
      m = (Element)context;
    }

    final Set keySet = map.keySet();
    final Object[] keys = ArrayUtil.toObjectArray(keySet);
    Arrays.sort(keys, KEY_COMPARATOR);
    for (Object k : keys) {
      Object v = map.get(k);

      Element entry = new Element(getEntryAttributeName());
      m.addContent(entry);

      Object kNode = myKeyBinding.serialize(k, entry);

      if (kNode instanceof Text) {
        Text text = (Text)kNode;
        entry.setAttribute(getKeyAttributeValue(), text.getText());
      }
      else {
        if (myMapAnnotation != null && !myMapAnnotation.surroundKeyWithTag()) {
          entry.addContent((Content)kNode);
        }
        else {
          Element key = new Element(getKeyAttributeValue());
          entry.addContent(key);
          key.addContent((Content)kNode);
        }
      }

      Object vNode = myValueBinding.serialize(v, entry);
      if (vNode instanceof Text) {
        Text text = (Text)vNode;
        entry.setAttribute(getValueAttributeName(), text.getText());
      }
      else {
        if (myMapAnnotation != null && !myMapAnnotation.surroundValueWithTag()) {
          entry.addContent((Element)vNode);
        }
        else {
          Element value = new Element(getValueAttributeName());
          entry.addContent(value);
          value.addContent((Content)vNode);
        }
      }
    }

    return m;
  }

  private String getEntryAttributeName() {
    return myMapAnnotation == null ? ENTRY : myMapAnnotation.entryTagName();
  }

  private String getValueAttributeName() {
    return myMapAnnotation == null ? VALUE : myMapAnnotation.valueAttributeName();
  }

  private String getKeyAttributeValue() {
    return myMapAnnotation == null ? KEY : myMapAnnotation.keyAttributeName();
  }

  public Object deserialize(Object o, Object... nodes) {
    Map map = (Map)o;
    map.clear();

    final Object[] childNodes;

    if (myMapAnnotation == null || myMapAnnotation.surroundWithTag()) {
      assert nodes.length == 1;
      Element m = (Element)nodes[0];
      childNodes = JDOMUtil.getContent(m);
    }
    else {
      childNodes = nodes;
    }


    for (Object childNode : childNodes) {
      if (XmlSerializerImpl.isIgnoredNode(childNode)) continue;
     
      Element entry = (Element)childNode;

      Object k = null;
      Object v = null;

      assert entry.getName().equals(getEntryAttributeName());

      Attribute keyAttr = entry.getAttribute(getKeyAttributeValue());
      if (keyAttr != null) {
        k = myKeyBinding.deserialize(o, keyAttr);
      }
      else {
        if (myMapAnnotation != null && !myMapAnnotation.surroundKeyWithTag()) {
          final Object[] children = JDOMUtil.getContent(entry);
          for (Object child : children) {
            if (myKeyBinding.isBoundTo(child)) {
              k = myKeyBinding.deserialize(o, child);
              break;
            }
          }

          assert k != null : "no key found";
        }
        else {
          final Object keyNode = entry.getChildren(getKeyAttributeValue()).get(0);
          k = myKeyBinding.deserialize(o, JDOMUtil.getContent((Element)keyNode));
        }
      }

      Attribute valueAttr = entry.getAttribute(getValueAttributeName());
      if (valueAttr != null) {
        v = myValueBinding.deserialize(o, valueAttr);
      }
      else {
        if (myMapAnnotation != null && !myMapAnnotation.surroundValueWithTag()) {
          final Object[] children = JDOMUtil.getContent(entry);
          for (Object child : children) {
            if (myValueBinding.isBoundTo(child)) {
              v = myValueBinding.deserialize(o, child);
              break;
            }
          }

          assert v != null : "no value found";
        }
        else {
          final Object valueNode = entry.getChildren(getValueAttributeName()).get(0);
          v = myValueBinding.deserialize(o, XmlSerializerImpl.getNotIgnoredContent((Element)valueNode));
        }
      }

      //noinspection unchecked
      map.put(k, v);
    }

    return map;
  }

  public boolean isBoundTo(Object node) {
    if (!(node instanceof Element)) return false;

    if (myMapAnnotation != null && !myMapAnnotation.surroundWithTag()) {
      return myMapAnnotation.entryTagName().equals(((Element)node).getName());
    }

    return ((Element)node).getName().equals(Constants.MAP);
  }

  public Class getBoundNodeType() {
    return Element.class;
  }

  public void init() {
  }
}
TOP

Related Classes of com.intellij.util.xmlb.MapBinding

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.