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 Object serialize(Object o, Object context, SerializationFilter filter) {
    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);

    if (myMapAnnotation == null || myMapAnnotation.sortBeforeSave()) {
      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, filter);

      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, filter);
      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;
  }
  public Object deserialize(Object o, @NotNull 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;
  }
 private String getKeyAttributeValue() {
   return myMapAnnotation == null ? KEY : myMapAnnotation.keyAttributeName();
 }
 private String getValueAttributeName() {
   return myMapAnnotation == null ? VALUE : myMapAnnotation.valueAttributeName();
 }
 private String getEntryAttributeName() {
   return myMapAnnotation == null ? ENTRY : myMapAnnotation.entryTagName();
 }