cern.c2mon.shared.common.datatag.address.impl.HardwareAddressImpl.java Source code

Java tutorial

Introduction

Here is the source code for cern.c2mon.shared.common.datatag.address.impl.HardwareAddressImpl.java

Source

/******************************************************************************
 * Copyright (C) 2010-2016 CERN. All rights not expressly granted are reserved.
 *
 * This file is part of the CERN Control and Monitoring Platform 'C2MON'.
 * C2MON is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the license.
 *
 * C2MON is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
 * more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with C2MON. If not, see <http://www.gnu.org/licenses/>.
 *****************************************************************************/
package cern.c2mon.shared.common.datatag.address.impl;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.ArrayUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import cern.c2mon.shared.common.ConfigurationException;
import cern.c2mon.shared.common.datatag.address.HardwareAddress;
import cern.c2mon.shared.common.datatag.address.HardwareAddressFactory;
import cern.c2mon.shared.util.parser.SimpleXMLParser;

/**
 * Implementation of the HardwareAddress interface and of the abstract HardwareAddressFactory class.
 *
 * @author J. Stowisek
 * @version $Revision: 1.4 $ ($Date: 2009/04/02 16:54:50 $ - $State: Exp $)
 */
@Slf4j
public class HardwareAddressImpl extends HardwareAddressFactory implements HardwareAddress {

    /** Serial UID */
    private static final long serialVersionUID = -7336624461787666236L;

    private static SimpleXMLParser xmlParser = null;

    /**
     * Decodes a field name from XML notation (e.g. my-field-name) to a valid Java field name (e.g. myFieldName)
     */
    private static final String decodeFieldName(final String pXmlFieldName) {
        // StringBuilder for constructing the resulting field name
        StringBuilder str = new StringBuilder();
        // Number of characters in the XML-encoded field name
        int fieldNameLength = pXmlFieldName.length();

        char currentChar;
        for (int i = 0; i < fieldNameLength; i++) {
            currentChar = pXmlFieldName.charAt(i);
            if (currentChar == '-') {
                str.append(Character.toUpperCase(pXmlFieldName.charAt(++i)));
            } else {
                str.append(currentChar);
            }
        }
        return str.toString();
    }

    /**
     * Encodes a field name in Java notation (e.g. myFieldName) to an XML field name (e.g. my-field-name).
     */
    private final String encodeFieldName(final String pFieldName) {
        StringBuilder str = new StringBuilder();
        int fieldNameLength = pFieldName.length();

        char currentChar;
        for (int i = 0; i != fieldNameLength; i++) {
            currentChar = pFieldName.charAt(i);
            if (Character.isUpperCase(currentChar)) {
                str.append('-');
                str.append(Character.toLowerCase(currentChar));
            } else {
                str.append(currentChar);
            }
        }
        return str.toString();
    }

    /**
     * Create a HardwareAddress object from its XML representation.
     *
     * @param pElement DOM element containing the XML representation of a HardwareAddress object, as created by the
     *                 toConfigXML() method.
     * @throws RuntimeException if unable to instantiate the Hardware address
     * @see cern.c2mon.shared.common.datatag.address.HardwareAddress#toConfigXML()
     */
    public final synchronized HardwareAddress fromConfigXML(Element pElement) {
        Class hwAddressClass = null;
        HardwareAddressImpl hwAddress = null;

        try {
            hwAddressClass = Class.forName(pElement.getAttribute("class"));
            hwAddress = (HardwareAddressImpl) hwAddressClass.newInstance();
        } catch (ClassNotFoundException cnfe) {
            cnfe.printStackTrace();
            throw new RuntimeException("Exception caught when instantiating a hardware address from XML", cnfe);
        } catch (IllegalAccessException iae) {
            iae.printStackTrace();
            throw new RuntimeException("Exception caught when instantiating a hardware address from XML", iae);
        } catch (InstantiationException ie) {
            ie.printStackTrace();
            throw new RuntimeException("Exception caught when instantiating a hardware address from XML", ie);
        }

        NodeList fields = pElement.getChildNodes();
        Node fieldNode = null;
        int fieldsCount = fields.getLength();
        String fieldName;
        String fieldValueString;
        String fieldTypeName = "";

        for (int i = 0; i < fieldsCount; i++) {
            fieldNode = fields.item(i);
            if (fieldNode.getNodeType() == Node.ELEMENT_NODE) {
                fieldName = fieldNode.getNodeName();

                if (fieldNode.getFirstChild() != null) {
                    fieldValueString = fieldNode.getFirstChild().getNodeValue();
                } else {
                    fieldValueString = "";
                }
                try {
                    Field field = hwAddressClass.getDeclaredField(decodeFieldName(fieldName));
                    fieldTypeName = field.getType().getName();

                    if (fieldTypeName.equals("short")) {
                        field.setShort(hwAddress, Short.parseShort(fieldValueString));
                    } else if (fieldTypeName.equals("java.lang.Short")) {
                        field.set(hwAddress, new Integer(Integer.parseInt(fieldValueString)));
                    } else if (fieldTypeName.equals("int")) {
                        field.setInt(hwAddress, Integer.parseInt(fieldValueString));
                    } else if (fieldTypeName.equals("java.lang.Integer")) {
                        field.set(hwAddress, new Integer(Integer.parseInt(fieldValueString)));
                    } else if (fieldTypeName.equals("float")) {
                        field.setFloat(hwAddress, Float.parseFloat(fieldValueString));
                    } else if (fieldTypeName.equals("java.lang.Float")) {
                        field.set(hwAddress, new Float(Float.parseFloat(fieldValueString)));
                    } else if (fieldTypeName.equals("double")) {
                        field.setDouble(hwAddress, Double.parseDouble(fieldValueString));
                    } else if (fieldTypeName.equals("java.lang.Double")) {
                        field.set(hwAddress, new Double(Double.parseDouble(fieldValueString)));
                    } else if (fieldTypeName.equals("long")) {
                        field.setLong(hwAddress, Long.parseLong(fieldValueString));
                    } else if (fieldTypeName.equals("java.lang.Long")) {
                        field.set(hwAddress, new Long(Long.parseLong(fieldValueString)));
                    } else if (fieldTypeName.equals("byte")) {
                        field.setByte(hwAddress, Byte.parseByte(fieldValueString));
                    } else if (fieldTypeName.equals("java.lang.Byte")) {
                        field.set(hwAddress, new Byte(Byte.parseByte(fieldValueString)));
                    } else if (fieldTypeName.equals("char")) {
                        field.setChar(hwAddress, fieldValueString.charAt(0));
                    } else if (fieldTypeName.equals("java.lang.Character")) {
                        field.set(hwAddress, new Character(fieldValueString.charAt(0)));
                    } else if (fieldTypeName.equals("boolean")) {
                        field.setBoolean(hwAddress, Boolean.getBoolean(fieldValueString));
                    } else if (fieldTypeName.equals("java.lang.Boolean")) {
                        field.set(hwAddress, new Boolean(Boolean.getBoolean(fieldValueString)));
                    } else if (fieldTypeName.equals("java.util.HashMap")) {
                        field.set(hwAddress, SimpleXMLParser.domNodeToMap(fieldNode));
                    } else if (field.getType().isEnum()) {
                        Object[] enumConstants = field.getType().getEnumConstants();
                        for (Object enumConstant : enumConstants) {
                            if (enumConstant.toString().equals(fieldValueString)) {
                                field.set(hwAddress, enumConstant);
                            }
                        }
                    } else {
                        field.set(hwAddress, fieldValueString);
                    }
                } catch (NoSuchFieldException nsfe) {
                    String errorMsg = "fromConfigXML(...) - Error occured while parsing XML <HardwareAddress> tag. "
                            + "The following variable does not exist in " + hwAddressClass.toString() + ": \""
                            + decodeFieldName(fieldName) + "\"";
                    log.error(errorMsg);
                    throw new IllegalArgumentException(errorMsg);
                } catch (IllegalAccessException iae) {
                    iae.printStackTrace();
                    throw new RuntimeException(iae);
                } catch (NumberFormatException npe) {
                    String errorMsg = "fromConfigXML(...) - Error occured while parsing XML <HardwareAddress> tag. Field \""
                            + fieldName + "\" shall not be empty since we expect a \"" + fieldTypeName
                            + "\" value. Please correct the XML configuration for " + hwAddressClass.toString();
                    log.error(errorMsg);
                    throw new IllegalArgumentException(errorMsg);
                }
            }
        }
        return hwAddress;
    }

    public final synchronized HardwareAddress fromConfigXML(final String pXML) {
        try {
            if (xmlParser == null) {
                xmlParser = new SimpleXMLParser();
            }
            return fromConfigXML(xmlParser.parse(pXML).getDocumentElement());
        } catch (Exception e) {
            return null;
        }
    }

    public final synchronized HardwareAddress fromConfigXML(final Document pDocument) {
        return fromConfigXML(pDocument.getDocumentElement());
    }

    /**
     * Returns an XML representation of the HardwareAddress object.
     *
     * @throws RuntimeException if Illegal access to fields
     */
    public final synchronized String toConfigXML() {
        Class handlerClass = this.getClass();
        Field[] fields = handlerClass.getDeclaredFields();

        StringBuilder str = new StringBuilder();

        str.append("        <HardwareAddress class=\"");
        str.append(getClass().getName());
        str.append("\">\n");

        for (int i = 0; i < fields.length; i++) {
            if (Modifier.isProtected(fields[i].getModifiers()) && !Modifier.isFinal(fields[i].getModifiers())) {
                try {
                    if (fields[i].get(this) != null) {
                        str.append("          <");
                        String fieldXMLName = encodeFieldName(fields[i].getName());

                        str.append(fieldXMLName);
                        str.append(">");
                        try {
                            str.append(fields[i].get(this));
                        } catch (IllegalAccessException iae) {
                            iae.printStackTrace();
                        }
                        str.append("</");
                        str.append(fieldXMLName);
                        str.append(">\n");
                    }
                } catch (IllegalAccessException iae) {
                    iae.printStackTrace();
                    throw new RuntimeException("Exception caught while converting HardwareAddress to XML.", iae);
                }
            }
        }

        str.append("        </HardwareAddress>\n");
        return str.toString();
    }

    @Override
    public HardwareAddressImpl clone() {
        try {
            return (HardwareAddressImpl) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            throw new RuntimeException("Exception caught while cloning a HardwareAddress", e);
        }
    }

    public final String toConfigXML(HardwareAddress address) {
        return address.toConfigXML();
    }

    public void validate() throws ConfigurationException {

    }

    /**
     * The two addresses are considered equals if they're of the same type and all their non-static attributes are equal
     */
    @Override
    public final boolean equals(final Object copy) {

        boolean result = copy != null && copy instanceof HardwareAddress && this.getClass().equals(copy.getClass());

        if (result) {

            Field[] fields = this.getClass().getDeclaredFields();
            for (Field field : fields) {
                if (!Modifier.isFinal(field.getModifiers()) && !Modifier.isStatic(field.getModifiers())
                        && !Modifier.isTransient(field.getModifiers())) {
                    try {

                        if ((field.get(this) != null && field.get(copy) == null)
                                || (field.get(this) == null && field.get(copy) != null)) {
                            result = false;
                        } else if (field.get(this) != null && field.get(copy) != null) {

                            if (field.getType().isArray()) {

                                if (Object[].class.isAssignableFrom(field.getType())) {
                                    result = Arrays.equals((Object[]) field.get(this), (Object[]) field.get(copy));
                                } else {
                                    result = ArrayUtils.isEquals(field.get(this), field.get(copy));
                                }

                            } else {
                                result = field.get(this).equals(field.get(copy));
                            }
                        }
                    } catch (Exception e) {
                        result = false;
                    }
                }

                if (!result) {
                    break;
                }
            }
        }

        return result;
    }

    @Override
    public final int hashCode() {

        int result = 0;

        Field[] fields = this.getClass().getDeclaredFields();

        for (Field field : fields) {
            // compare non-final, non-static and non-transient fields only
            if (!Modifier.isFinal(field.getModifiers()) && !Modifier.isStatic(field.getModifiers())
                    && !Modifier.isTransient(field.getModifiers())) {
                try {

                    // skip arrays
                    if (!field.getType().isArray() && field.get(this) != null) {
                        // for string take its length
                        if (field.getType().equals(String.class)) {
                            result ^= ((String) field.get(this)).length();
                        } else if (field.getType().equals(short.class) || field.getType().equals(Short.class)) {
                            result ^= field.getShort(this);
                        } else if (field.getType().equals(int.class) || field.getType().equals(Integer.class)) {
                            result ^= field.getInt(this);
                        } else if (field.getType().equals(float.class) || field.getType().equals(Float.class)) {
                            result ^= (int) field.getFloat(this);
                        } else if (field.getType().equals(double.class) || field.getType().equals(Double.class)) {
                            result ^= (int) field.getDouble(this);
                        } else if (field.getType().equals(long.class) || field.getType().equals(Long.class)) {
                            result ^= (int) field.getLong(this);
                        } else if (field.getType().equals(byte.class) || field.getType().equals(Byte.class)) {
                            result ^= field.getByte(this);
                        } else if (field.getType().equals(boolean.class) || field.getType().equals(Boolean.class)) {
                            result ^= field.getBoolean(this) == Boolean.TRUE ? 1 : 0;
                        }
                    }
                } catch (Exception e) {
                    log.error(e.toString());
                    throw new RuntimeException("Exception caught while calculating HardwareAddress hashcode.", e);
                }
            }
        }
        return result;
    }

    @Override
    public String toString() {
        return toConfigXML();
    }
}