blob: cf88358e2fdb34967c69d5433ffbbfe3bc964d8e [file] [log] [blame]
/*
* Copyright 2000-2014 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.diagnostic.Logger;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.SmartList;
import com.intellij.util.xmlb.annotations.OptionTag;
import org.jdom.Attribute;
import org.jdom.Content;
import org.jdom.Element;
import org.jdom.Text;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
class OptionTagBinding extends BasePrimitiveBinding {
private static final Logger LOG = Logger.getInstance(OptionTagBinding.class);
private final String myTagName;
private final String myNameAttribute;
private final String myValueAttribute;
public OptionTagBinding(@NotNull Accessor accessor, @Nullable OptionTag optionTag) {
super(accessor, optionTag == null ? null : optionTag.value(), optionTag == null ? null : optionTag.converter());
if (optionTag != null) {
myTagName = optionTag.tag();
myNameAttribute = optionTag.nameAttribute();
myValueAttribute = optionTag.valueAttribute();
}
else {
myTagName = Constants.OPTION;
myNameAttribute = Constants.NAME;
myValueAttribute = Constants.VALUE;
}
}
@Override
public Object serialize(Object o, Object context, SerializationFilter filter) {
Element targetElement = new Element(myTagName);
Object value = myAccessor.read(o);
if (!StringUtil.isEmpty(myNameAttribute)) {
targetElement.setAttribute(myNameAttribute, myName);
}
if (value == null) {
return targetElement;
}
if (myConverter != null) {
targetElement.setAttribute(myValueAttribute, myConverter.toString(value));
}
else {
assert myBinding != null;
Object node = myBinding.serialize(value, targetElement, filter);
if (node instanceof Text) {
Text text = (Text)node;
targetElement.setAttribute(myValueAttribute, text.getText());
}
else if (targetElement != node) {
JDOMUtil.addContent(targetElement, node);
}
}
return targetElement;
}
@Override
public Object deserialize(Object context, @NotNull Object... nodes) {
if (nodes.length > 1) {
LOG.info("Duplicate options for " + context + " will be ignored");
}
assert nodes.length != 0 : "Empty nodes passed to: " + this;
Element element = ((Element)nodes[0]);
Attribute valueAttribute = element.getAttribute(myValueAttribute);
if (valueAttribute != null) {
Object value;
if (myConverter != null) {
value = myConverter.fromString(valueAttribute.getValue());
}
else {
assert myBinding != null;
value = myBinding.deserialize(context, valueAttribute);
}
myAccessor.write(context, value);
}
else {
List<Object> children = new SmartList<Object>();
for (Content child : element.getContent()) {
if (!XmlSerializerImpl.isIgnoredNode(child)) {
children.add(child);
}
}
if (!children.isEmpty()) {
assert myBinding != null;
Object value = myBinding.deserialize(myAccessor.read(context), ArrayUtil.toObjectArray(children));
myAccessor.write(context, value);
}
else {
myAccessor.write(context, null);
}
}
return context;
}
@Override
public boolean isBoundTo(Object node) {
if (!(node instanceof Element)) return false;
Element e = (Element)node;
if (!e.getName().equals(myTagName)) return false;
String name = e.getAttributeValue(myNameAttribute);
if (StringUtil.isEmpty(myNameAttribute)) {
return name == null || name.equals(myName);
}
return name != null && name.equals(myName);
}
@Override
public Class getBoundNodeType() {
throw new UnsupportedOperationException("Method getBoundNodeType is not supported in " + getClass());
}
@NonNls
public String toString() {
return "OptionTagBinding[" + myName + ", binding=" + myBinding + "]";
}
}