/*******************************************************************************
* Copyright (c) 2011, 2016 Eurotech and/or its affiliates
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Eurotech
*******************************************************************************/
package org.eclipse.kura.core.configuration.util.serializers;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.kura.configuration.metatype.AD;
import org.eclipse.kura.configuration.metatype.Icon;
import org.eclipse.kura.configuration.metatype.Option;
import org.eclipse.kura.configuration.metatype.Scalar;
import org.eclipse.kura.core.configuration.metatype.Tad;
import org.eclipse.kura.core.configuration.metatype.Tdesignate;
import org.eclipse.kura.core.configuration.metatype.Ticon;
import org.eclipse.kura.core.configuration.metatype.Tmetadata;
import org.eclipse.kura.core.configuration.metatype.Tobject;
import org.eclipse.kura.core.configuration.metatype.Tocd;
import org.eclipse.kura.core.configuration.metatype.Toption;
import org.eclipse.kura.core.configuration.metatype.Tscalar;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class XmlJavaMetadataMapper implements XmlJavaDataMapper {
private final static String METADATA_LOCALIZATION = "localization";
private static final String METADATA_OCD = "OCD";
private final static String METADATA_OCD_NAME = "name";
private final static String METADATA_OCD_ID = "id";
private final static String METADATA_OCD_DESCRIPTION = "description";
private final static String METADATA_ICON = "Icon";
private final static String METADATA_ICON_RESOURCE = "resource";
private final static String METADATA_ICON_SIZE = "size";
private final static String METADATA_AD = "AD";
private final static String METADATA_AD_ID = "id";
private final static String METADATA_AD_NAME = "name";
private final static String METADATA_AD_TYPE = "type";
private final static String METADATA_AD_CARDINALITY = "cardinality";
private final static String METADATA_AD_REQUIRED = "required";
private final static String METADATA_AD_DEFAULT = "default";
private final static String METADATA_AD_DESCRIPTION = "description";
private final static String METADATA_AD_MIN = "min";
private final static String METADATA_AD_MAX = "max";
private final static String METADATA_AD_OPTION = "Option";
private final static String METADATA_AD_OPTION_LABEL = "label";
private final static String METADATA_AD_OPTION_VALUE = "value";
private final static String METADATA_DESIGNATE_OBJECT = "Object";
private final static String METADATA_DESIGNATE_PID = "pid";
private final static String METADATA_DESIGNATE_FACTORY_PID = "factoryPid";
private final static String METADATA_DESIGNATE_BUNDLE = "bundle";
private final static String METADATA_DESIGNATE_OPTIONAL = "optional";
private final static String METADATA_DESIGNATE_MERGE = "merge";
private final static String METADATA_DESIGNATE_OBJECT_ATTRIBUTE = "Attribute";
private final static String METADATA_DESIGNATE_OBJECT_OCDREF = "ocdref";
private Document mashallDoc = null;
//
// Public methods
//
@Override
public Element marshal(Document doc, Object o) throws Exception {
this.mashallDoc = doc;
if (o instanceof Tocd) {
Tocd configOCD = (Tocd) o;
String ocdName = configOCD.getName();
String ocdDescription = configOCD.getDescription();
String ocdID = configOCD.getId();
List<Icon> ocdIcons = configOCD.getIcon();
List<AD> ocdADs = configOCD.getAD();
configOCD.getAny();
configOCD.getOtherAttributes();
Element ocd = this.mashallDoc.createElement(OCD_NAMESPACE + ":" + METADATA_OCD);
if (ocdName != null && !ocdName.trim().isEmpty()) {
Attr ocdAttrName = this.mashallDoc.createAttribute(METADATA_OCD_NAME);
ocdAttrName.setNodeValue(ocdName);
ocd.setAttributeNode(ocdAttrName);
}
if (ocdDescription != null && !ocdDescription.trim().isEmpty()) {
Attr ocdAttrDescription = this.mashallDoc.createAttribute(METADATA_OCD_DESCRIPTION);
ocdAttrDescription.setNodeValue(ocdDescription);
ocd.setAttributeNode(ocdAttrDescription);
}
if (ocdID != null && !ocdID.trim().isEmpty()) {
Attr ocdAttrId = this.mashallDoc.createAttribute(METADATA_OCD_ID);
ocdAttrId.setNodeValue(ocdID);
ocd.setAttributeNode(ocdAttrId);
}
if (ocdADs != null) {
for (AD ocdAD : ocdADs) {
Element ad = this.mashallDoc.createElement(OCD_NAMESPACE + ":" + METADATA_AD);
marshallAD(ocdAD, ad);
ocd.appendChild(ad);
}
}
if (ocdIcons != null) {
for (Icon ocdIcon : ocdIcons) {
Element icon = this.mashallDoc.createElement(OCD_NAMESPACE + ":" + METADATA_ICON);
marshallIcon(ocdIcon, icon);
ocd.appendChild(icon);
}
}
return ocd;
}
return null;
}
@SuppressWarnings("unchecked")
@Override
public <T> T unmarshal(Document doc) {
Element metadata = doc.getDocumentElement();
Tmetadata tMetadata = parseMetadataAttributes(metadata);
NodeList metadataChilds = metadata.getChildNodes();
Element[] metadataChildsArray = getElementNodes(metadataChilds);
for (Element node : metadataChildsArray) {
String localName = node.getNodeName();
if (localName.equals("OCD")) {
Tocd tocd = parseOCD(node);
tMetadata.setOCD(tocd);
} else if (localName.equals("Designate")) {
Tdesignate tDesignate = parseDesignate(node);
tMetadata.setDesignate(tDesignate);
}
}
return (T) tMetadata;
}
//
// Private methods
//
private void marshallIcon(Icon ocdIcon, Element icon) {
String iconResource = ocdIcon.getResource();
BigInteger iconSize = ocdIcon.getSize();
if (iconResource != null && !iconResource.trim().isEmpty()) {
Attr attrResource = this.mashallDoc.createAttribute(METADATA_ICON_RESOURCE);
attrResource.setNodeValue(iconResource);
icon.setAttributeNode(attrResource);
}
if (iconSize != null) {
Attr attrSize = this.mashallDoc.createAttribute(METADATA_ICON_SIZE);
attrSize.setNodeValue(iconSize.toString());
icon.setAttributeNode(attrSize);
}
}
private void marshallAD(AD ocdAD, Element ad) {
String adId = ocdAD.getId();
String adName = ocdAD.getName();
Scalar adType = ocdAD.getType();
Integer adCardinality = ocdAD.getCardinality();
Boolean adRequired = ocdAD.isRequired();
String adDefault = ocdAD.getDefault();
String adDescription = ocdAD.getDescription();
String adMin = ocdAD.getMin();
String adMax = ocdAD.getMax();
List<Option> adOptions = ocdAD.getOption();
if (adName != null) {
Attr attrName = this.mashallDoc.createAttribute(METADATA_AD_NAME);
attrName.setNodeValue(adName);
ad.setAttributeNode(attrName);
}
if (adId != null) {
Attr attrId = this.mashallDoc.createAttribute(METADATA_AD_ID);
attrId.setNodeValue(adId);
ad.setAttributeNode(attrId);
}
if (adType != null) {
Attr attrType = this.mashallDoc.createAttribute(METADATA_AD_TYPE);
attrType.setNodeValue(adType.value());
ad.setAttributeNode(attrType);
}
if (adCardinality != null) {
Attr attrCardinality = this.mashallDoc.createAttribute(METADATA_AD_CARDINALITY);
attrCardinality.setNodeValue(adCardinality.toString());
ad.setAttributeNode(attrCardinality);
}
if (adRequired != null) {
Attr attrRequired = this.mashallDoc.createAttribute(METADATA_AD_REQUIRED);
attrRequired.setNodeValue(adRequired.toString());
ad.setAttributeNode(attrRequired);
}
if (adDefault != null) {
Attr attrDefault = this.mashallDoc.createAttribute(METADATA_AD_DEFAULT);
attrDefault.setNodeValue(adDefault);
ad.setAttributeNode(attrDefault);
}
if (adDescription != null) {
Attr attrDescription = this.mashallDoc.createAttribute(METADATA_AD_DESCRIPTION);
attrDescription.setNodeValue(adDescription);
ad.setAttributeNode(attrDescription);
}
if (adMin != null) {
Attr attrMin = this.mashallDoc.createAttribute(METADATA_AD_MIN);
attrMin.setNodeValue(adMin);
ad.setAttributeNode(attrMin);
}
if (adMax != null) {
Attr attrMax = this.mashallDoc.createAttribute(METADATA_AD_MAX);
attrMax.setNodeValue(adMax);
ad.setAttributeNode(attrMax);
}
if (adOptions != null) {
for (Option adOption : adOptions) {
Element option = this.mashallDoc.createElement(OCD_NAMESPACE + ":" + METADATA_AD_OPTION);
marshallOption(adOption, option);
ad.appendChild(option);
}
}
}
private void marshallOption(Option adOption, Element option) {
String label = adOption.getLabel();
String value = adOption.getValue();
if (!label.trim().isEmpty()) {
Attr attrLabel = this.mashallDoc.createAttribute(METADATA_AD_OPTION_LABEL);
attrLabel.setNodeValue(label);
option.setAttributeNode(attrLabel);
}
if (!value.trim().isEmpty()) {
Attr attrValue = this.mashallDoc.createAttribute(METADATA_AD_OPTION_VALUE);
attrValue.setNodeValue(value);
option.setAttributeNode(attrValue);
}
}
private Tocd parseOCD(Element ocd) {
String ocdName = ocd.getAttribute(METADATA_OCD_NAME);
String ocdID = ocd.getAttribute(METADATA_OCD_ID);
String ocdDescription = ocd.getAttribute(METADATA_OCD_DESCRIPTION);
Tocd tocd = new Tocd();
if (ocdID != null && !ocdID.trim().isEmpty()) {
tocd.setId(ocdID);
}
if (ocdName != null && !ocdName.trim().isEmpty()) {
tocd.setName(ocdName);
}
if (ocdDescription != null && !ocdDescription.trim().isEmpty()) {
tocd.setDescription(ocdDescription);
}
NodeList ocdChilds = ocd.getChildNodes();
Element[] ocdChildElements = getElementNodes(ocdChilds);
for (Element node : ocdChildElements) {
String localName = node.getNodeName();
if (localName.equals(METADATA_ICON)) {
// parse Icon
Ticon tIcon = parseIcon(node);
tocd.setIcon(tIcon);
} else if (localName.equals(METADATA_AD)) {
// parse AD
Tad tad = parseAD(node);
tocd.addAD(tad);
}
}
return tocd;
}
private Tdesignate parseDesignate(Element designate) {
String pid = designate.getAttribute(METADATA_DESIGNATE_PID);
String factoryPid = designate.getAttribute(METADATA_DESIGNATE_FACTORY_PID);
String bundle = designate.getAttribute(METADATA_DESIGNATE_BUNDLE);
Boolean optional = Boolean.parseBoolean(designate.getAttribute(METADATA_DESIGNATE_OPTIONAL));
Boolean merge = Boolean.parseBoolean(designate.getAttribute(METADATA_DESIGNATE_MERGE));
Tdesignate tDesignate = new Tdesignate();
if (!pid.trim().isEmpty()) {
tDesignate.setPid(pid);
}
if (!factoryPid.trim().isEmpty()) {
tDesignate.setFactoryPid(factoryPid);
}
if (!bundle.trim().isEmpty()) {
tDesignate.setBundle(bundle);
}
tDesignate.setOptional(optional);
tDesignate.setMerge(merge);
NodeList objectsChilds = designate.getChildNodes();
Element[] objectsChildElements = getElementNodes(objectsChilds);
for (Element node : objectsChildElements) {
String localName = node.getNodeName();
if (localName.equals(METADATA_DESIGNATE_OBJECT)) {
// parse Object
Tobject tObject = parseObject(node);
tDesignate.setObject(tObject);
}
}
return tDesignate;
}
private Tobject parseObject(Element object) {
String ocdref = object.getAttribute(METADATA_DESIGNATE_OBJECT_OCDREF);
Tobject tObject = new Tobject();
if (!ocdref.trim().isEmpty()) {
tObject.setOcdref(ocdref);
}
NodeList attributeChilds = object.getChildNodes();
Element[] attributeChildElements = getElementNodes(attributeChilds);
for (Element node : attributeChildElements) {
String localName = node.getNodeName();
if (localName.equals(METADATA_DESIGNATE_OBJECT_ATTRIBUTE)) {
// parse Attribute
// TODO
}
}
return tObject;
}
private Ticon parseIcon(Element icon) {
Ticon result = new Ticon();
String resource = icon.getAttribute(METADATA_ICON_RESOURCE);
if (resource != null && !resource.trim().isEmpty()) {
result.setResource(resource);
}
String iconSize = icon.getAttribute(METADATA_ICON_SIZE);
if (iconSize != null) {
try {
BigInteger size = new BigInteger(iconSize);
if (size.signum() >= 0) {
result.setSize(size);
} else {
result.setSize(new BigInteger("0"));
}
} catch (NumberFormatException e) {
result.setSize(new BigInteger("0"));
}
}
return result;
}
private Tad parseAD(Element adElement) {
Tad tad = new Tad();
String id = adElement.getAttribute(METADATA_AD_ID);
String name = adElement.getAttribute(METADATA_AD_NAME);
Tscalar type = Tscalar.fromValue(adElement.getAttribute(METADATA_AD_TYPE));
Integer cardinality;
try {
cardinality = Integer.parseInt(adElement.getAttribute(METADATA_AD_CARDINALITY));
} catch (NumberFormatException e) {
cardinality = null;
}
Boolean required = null;
String requiredAttr = adElement.getAttribute(METADATA_AD_REQUIRED);
if (requiredAttr != null && !requiredAttr.trim().isEmpty()) {
required = Boolean.parseBoolean(adElement.getAttribute(METADATA_AD_REQUIRED));
}
String defaultVal = adElement.getAttribute(METADATA_AD_DEFAULT);
String description = adElement.getAttribute(METADATA_AD_DESCRIPTION);
String min = adElement.getAttribute(METADATA_AD_MIN);
String max = adElement.getAttribute(METADATA_AD_MAX);
if (id != null && !id.trim().isEmpty()) {
tad.setId(id);
}
if (name != null && !name.trim().isEmpty()) {
tad.setName(name);
}
if (type != null) {
tad.setType(type);
}
if (cardinality != null) {
tad.setCardinality(cardinality);
}
if (required != null) {
tad.setRequired(required);
}
if (defaultVal != null && !defaultVal.trim().isEmpty()) {
tad.setDefault(defaultVal);
}
if (description != null && !description.trim().isEmpty()) {
tad.setDescription(description);
}
if (min != null && !min.trim().isEmpty()) {
tad.setMin(min);
}
if (max != null && !max.trim().isEmpty()) {
tad.setMax(max);
}
// parse Option
NodeList optionChilds = adElement.getChildNodes();
Element[] optionChildElements = getElementNodes(optionChilds);
for (Element node : optionChildElements) {
String localName = node.getNodeName();
if (localName.equals(METADATA_AD_OPTION)) {
// parse Option
Toption tOption = parseOption(node);
tad.setOption(tOption);
}
}
return tad;
}
private Toption parseOption(Element option) {
Toption tOption = new Toption();
String label = option.getAttribute(METADATA_AD_OPTION_LABEL);
String value = option.getAttribute(METADATA_AD_OPTION_VALUE);
if (label != null && !label.trim().isEmpty()) {
tOption.setLabel(label);
}
if (value != null && !value.trim().isEmpty()) {
tOption.setValue(value);
}
return tOption;
}
private Tmetadata parseMetadataAttributes(Element metadata) {
Tmetadata tMetadata = new Tmetadata();
String localization = metadata.getAttribute(METADATA_LOCALIZATION);
if (localization != null && !localization.trim().isEmpty()) {
tMetadata.setLocalization(localization);
}
return tMetadata;
}
private Element[] getElementNodes(NodeList propertiesList) {
List<Element> elementList = new ArrayList<Element>();
for (int propIndex = 0; propIndex < propertiesList.getLength(); propIndex++) {
Node currentNode = propertiesList.item(propIndex);
if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
Element el = (Element) currentNode;
elementList.add(el);
}
}
return elementList.toArray(new Element[0]);
}
}