/**
 * EasyBeans
 * Copyright (C) 2006 Bull S.A.S.
 * Contact: easybeans@objectweb.org
 *
 * This library 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 2.1 of the License, or any later version.
 *
 * This library 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 this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id: AbsMetadata.java 5276 2010-01-08 16:22:04Z benoitf $
 * --------------------------------------------------------------------------
 */

package org.ow2.spec.testengine.metadata;

import java.util.Arrays;
import java.util.List;

import org.ow2.spec.testengine.ComparisonError;
import org.ow2.spec.testengine.SignatureResultSet;

public abstract class AbsMetadata {

    public String toXML() {
        return toXML("");
    }

    public abstract String toXML(String indent);

    private static String encode(Object o) {
        String val = o.toString();
        val = val.replaceAll("&", "&amp;");
        val = val.replaceAll("\"", "&quot;");
        val = val.replaceAll("<", "&lt;");
        val = val.replaceAll(">", "&gt;");
        return val;
    }

    public void addObjectToSB(String name, Object o, StringBuilder sb) {
        if (o != null) {
            sb.append(" ");
            sb.append(name);
            sb.append("=\"");
            sb.append(encode(o));
            sb.append("\"");
        }
    }

    public void addArrayObjectToSB(String name, Object[] array, StringBuilder sb, String indent) {
        if (array != null) {
            for (int i = 0; i < array.length; i++) {
                sb.append("\n");
                sb.append(indent);
                sb.append("<");
                sb.append(name);
                sb.append(" name=\"");
                sb.append(array[i]);
                sb.append("\" />");
            }
        }
    }

    public static <T extends AbsMetadata> void addListToSB(List<T> list, StringBuilder sb, String indent) {
        if (list != null) {
            for (T obj : list) {
                sb.append(obj.toXML(indent));
            }
        }
    }

    public void compare(String name, Object o1, Object o2, SignatureResultSet rs) {
        if (o1 == null && o2 == null) {
            return;
        }
        if (o1 != null && o2 == null) {
            rs.addError(new ComparisonError("The checked '" + name + "'" + o2 + "' is null while '" + o1 + "' is not null."));
            return;
        }
        if (o1 == null && o2 != null) {
            rs.addError(new ComparisonError("The '" + name + "'" + o1 + "' is null while the checked value '" + o2
                    + "' is not null."));
            return;
        }

        boolean isArrayO1 = o1.getClass().isArray();
        boolean isArrayO2 = o2.getClass().isArray();

        if (isArrayO1 && !isArrayO2) {
            rs.addError(new ComparisonError("The '" + name + "'" + o1 + "' is an array but not the object '" + o2 + "'."));
        }

        if (isArrayO2 && !isArrayO1) {
            rs.addError(new ComparisonError("The '" + name + "'" + o2 + "' is an array but not the object '" + o1 + "'."));
        }

        if (isArrayO1 && isArrayO2) {
            Object[] arrO1 = (Object[]) o1;
            Object[] arrO2 = (Object[]) o2;

            if (!Arrays.equals(arrO1, arrO2)) {
                rs.addError(new ComparisonError("The value array for '" + name + "' : '" + Arrays.asList(arrO1) + "' and '"
                        + Arrays.asList(arrO2) + "' are not the same"));
            }

        } else {

            // assure equals
            if (!o1.toString().equals(o2.toString())) {
                rs.addError(new ComparisonError("The value '" + name + "' of '" + o1 + "' and '" + o2 + "' are not the same"));
            }
        }

    }

    public static <T> void compareList(String name, List<T> lst1, List<T> lst2, SignatureResultSet rs) {
        if (lst1 == null || lst2 == null) {
            throw new IllegalArgumentException("Lists shouldn't be null for '" + name + "'.");
        }

        // Size
        int referenceSize = lst1.size();
        int analyzedSite = lst2.size();

        // compare lst1 items to lst2 items
        for (T element : lst1) {
            if (!lst2.contains(element)) {
                rs.addError(new ComparisonError(name + " : Reference element '" + element + "' is not present in analyzed list '" + lst2 + "'."));
            }
        }

        // compare lst2 items to lst1 items
        for (T element : lst2) {
            if (!lst1.contains(element)) {
                rs.addError(new ComparisonError(name + " : Analyzed element '" + element + "' is not present in reference list '" + lst1 + "'."));
            }
        }

        if (referenceSize != analyzedSite) {
            rs.addError(new ComparisonError("Invalid list size for name '" + name + "'."));
        }



    }

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