/*
 * @(#)$RCSfile: TestAttributeMap.java,v $ $Revision: 1.2 $ $Date: 2000/04/24 20:52:58 $
 *
 * (C) Copyright IBM Corp. 1998-1999.  All Rights Reserved.
 *
 * The program is provided "as is" without any warranty express or
 * implied, including the warranty of non-infringement and the implied
 * warranties of merchantibility and fitness for a particular purpose.
 * IBM will not be liable for any damages suffered by you as a result
 * of using the Program. In no event will IBM be liable for any
 * special, indirect or consequential damages or lost profits even if
 * IBM has been advised of the possibility of their occurrence. IBM
 * will not be liable for any third party claims against you.
 */
package com.ibm.test.richtext;

import com.ibm.test.TestFmwk;

import com.ibm.textlayout.attributes.AttributeSet;
import com.ibm.textlayout.attributes.TextAttribute;
import com.ibm.textlayout.attributes.Map;
import com.ibm.textlayout.attributes.AttributeMap;
import java.util.Enumeration;

// Java2 imports
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import java.util.Map.Entry;


public class TestAttributeMap extends TestFmwk  {

    static final String COPYRIGHT =
                "(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";


    // There are JDK 1.1 versions of AttributeMap and AttributeSet.
    // Some of the tests in this class require Java 2 API's.  I have
    // tried to isolate these tests by conditionalizing them on
    // this static variable.  If you are back-porting to 1.1, remove
    // the Java 2 tests ONLY.
    private static final boolean gJDK11 = false;

    public static void main(String[] args) throws Exception {

        new TestAttributeMap().run(args);
    }

    private AttributeSet maps;  // A Set of AttributeMaps
    private AttributeSet sets;  // A Set of Sets

    private static final class TestAttribute extends TextAttribute {

        TestAttribute(String name) {
            super(name);
        }
    }

    private static final TestAttribute[] attributes = {
        new TestAttribute("0"), new TestAttribute("1"), new TestAttribute("2")
    };

    private static final Object[] values = {
        "Hello world", new Float(-42), new Object(), new AttributeMap(new TestAttribute("3"), "HH")
    };

    /**
     * Returns lhs.equals(rhs) - but also checks for symmetry, and
     * consistency with hashCode().
     */
    private boolean equalMaps(AttributeMap lhs, Object rhs) {

        boolean equal = lhs.equals(rhs);
        if (equal != (rhs.equals(lhs))) {
            errln("AttributeMap.equals is not symetric");
        }
        if (equal) {
            if (lhs.hashCode() != rhs.hashCode()) {
                errln("AttributeMaps are equal but hashCodes differ");
            }
        }
        return equal;
    }

    public TestAttributeMap() {

        maps = AttributeSet.EMPTY_SET;
        maps = maps.addElement(AttributeMap.EMPTY_ATTRIBUTE_MAP);
        maps.addElement(new AttributeMap(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUB));
        maps.addElement(new AttributeMap(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUPER));

        for (int i=0; i < attributes.length; i++) {
            for (int j=0; j < values.length; j++) {
                maps = maps.addElement(new AttributeMap(attributes[i], values[j]));
            }
        }

        AttributeMap bigMap = new AttributeMap(new TestAttribute("4"), "value");
        for (int i=0; i < Math.min(attributes.length, values.length); i++) {
            bigMap = bigMap.addAttribute(attributes[i], values[values.length-i-1]);
        }
        maps = maps.addElement(bigMap);

        sets = AttributeSet.EMPTY_SET;

        sets = new AttributeSet(AttributeSet.EMPTY_SET);

        for (int i=0; i < attributes.length; i++) {
            AttributeSet newSet = new AttributeSet(attributes[i]);
            sets = sets.addElement(newSet);
        }

        AttributeSet allAttrs = AttributeSet.EMPTY_SET;
        for (int i=0; i < attributes.length; i++) {
            allAttrs = allAttrs.addElement(attributes[i]);
        }

        sets = sets.addElement(allAttrs);
    }

    /**
     * Run tests on AttributeMap.  If a test fails an exception will propogate out
     * of this method.
     */
    public void test() {

        easyTests();

        Enumeration mapIter = maps.elements();
        while (mapIter.hasMoreElements()) {

            AttributeMap testMap = (AttributeMap) mapIter.nextElement();

            _testModifiers(testMap);
            _testViews(testMap);

            Enumeration unionIter = maps.elements();
            while (unionIter.hasMoreElements()) {
                _testUnionWith(testMap, (AttributeMap) unionIter.nextElement());
            }

            Enumeration setIter = sets.elements();
            while (setIter.hasMoreElements()) {
                AttributeSet testSet = (AttributeSet) setIter.nextElement();
                _testIntersectWith(testMap, testSet);
                _testRemoveAttributes(testMap, testSet);
            }
        }
    }

    /**
     * Invoke modifiers on map.  All should throw
     * UnsupportedOperationException, and leave map unmodified.
     */
    void _testModifiers(AttributeMap map) {

        if (gJDK11) {
            return;
        }
        
        AttributeMap originalMap = new AttributeMap(map);

        try {
            map.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
            errln("Put should throw UnsupportedOperationException.");
        }
        catch(UnsupportedOperationException e) {
        }

        try {
            Object key = TextAttribute.WEIGHT;
            Iterator iter = map.keySet().iterator();
            if (iter.hasNext()) {
                key = iter.next();
            }
            map.remove(key);
            errln("Set should throw UnsupportedOperationException.");
        }
        catch(UnsupportedOperationException e) {
        }

        try {
            map.putAll(map);
            errln("putAll should throw UnsupportedOperationException.");
        }
        catch(UnsupportedOperationException e) {
        }

        try {
            map.clear();
            errln("clear should throw UnsupportedOperationException.");
        }
        catch(UnsupportedOperationException e) {
        }

        if (!originalMap.equals(map)) {
            errln("Modifiers changed map.");
        }
    }

    /**
     * Ensure that map.addAttributes(addMap) is equivalent to calling
     * map.add on all of addMap's entries.
     */
    void _testUnionWith(AttributeMap map, AttributeMap addMap) {

        AttributeMap lhs = map.addAttributes(addMap);

        AttributeMap rhs = map;

        Enumeration iter = addMap.getKeySet().elements();
        while (iter.hasMoreElements()) {
            Object attr = iter.nextElement();
            Object value = addMap.get(attr);
            rhs = rhs.addAttribute(attr, value);
        }

        if (!equalMaps(lhs, rhs)) {
            errln("Maps are not equal.");
        }
    }

    /**
     * Ensure that map.removeAttributes(remove) is equivalent to calling
     * map.removeAttribute on remove's elements.
     */
    void _testRemoveAttributes(AttributeMap map, AttributeSet remove) {

        AttributeMap lhs = map.removeAttributes(remove);

        AttributeMap rhs = map;

        Enumeration iter = remove.elements();
        while (iter.hasMoreElements()) {
            Object attr = iter.nextElement();
            rhs = rhs.removeAttribute(attr);
        }

        if (!equalMaps(lhs, rhs)) {
            errln("Maps are not equal.");
        }
    }

    /**
     * Ensure that map.intersectWith(intersect) is equivalent to
     * map.removeAttributes(map.keySet() - intersect);
     */
    void _testIntersectWith(AttributeMap map, AttributeSet intersect) {

        AttributeMap lhs = map.intersectWith(intersect);

        AttributeSet keySet = map.getKeySet();
        AttributeSet removeSet = keySet.subtract(intersect);
        AttributeMap rhs = map.removeAttributes(removeSet);

        if (!equalMaps(lhs, rhs)) {
            map.intersectWith(intersect);
            logln("intersect: " + intersect);
            logln("keySet: " + keySet);
            logln("removeSet: " + removeSet);
            logln("map: " + map);
            logln("lhs: " + lhs);
            logln("rhs: " + rhs);
            errln("Maps are not equal.");
        }
    }

    /**
     * Ensure that:
     *    map, map.keySet(), and map.entrySet() are the same size;
     *    map.containsKey() is true for every key in keySet();
     *    map.containsValue() is true for every value in values;
     *    every entry key is in keySet, every entry value is in map.values();
     *    map.get() is consistent with entry's key, value;
     *    sum of hashcodes of entries equals map.hashCode().
     */
    void _testViews(AttributeMap map) {

        AttributeSet keySet = map.getKeySet();

        Enumeration keyIter = keySet.elements();
        while (keyIter.hasMoreElements()) {
            if (!map.containsKey(keyIter.nextElement())) {
                errln("keySet contains key not in map");
            }
        }

        if (gJDK11) {
            return;
        }
        
        Collection values = map.values();
        Set entrySet = map.entrySet();

        if (keySet.size() != map.size() || entrySet.size() != map.size()) {
            errln("Set sizes are inconsistent with map size.");
        }

        int hashCode = 0;

        Iterator valueIter = values.iterator();
        while (valueIter.hasNext()) {
            if (!map.containsValue(valueIter.next())) {
                errln("value set contains value not in map");
            }
        }

        Iterator entryIter = entrySet.iterator();
        while (entryIter.hasNext()) {

            Entry entry = (Entry) entryIter.next();

            Object key = entry.getKey();
            if (!keySet.contains(key)) {
                errln("Entry key is not in key set.");
            }

            Object value = map.get(entry.getKey());
            if (!values.contains(value)) {
                errln("Entry value is not in value set.");
            }

            if (map.get(key) != value) {
                errln("map.get did not return entry value.");
            }

            hashCode += entry.hashCode();
        }

        if (hashCode != map.hashCode()) {
            errln("map hashcode is not sum of entry hashcodes.");
        }
    }

    /**
     * Look for correct behavior in obvious cases.
     */
    void easyTests() {

        AttributeMap map = new AttributeMap();
        if (!map.equals(AttributeMap.EMPTY_ATTRIBUTE_MAP)) {
            errln("Default-constructed map is not equal to empty map.");
        }

        map = map.addAttribute(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
        Object otherMap = new AttributeMap(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
        if (!map.equals(otherMap)) {
            errln("Maps are inconsistent after map.add");
        }

        otherMap = map.addAttributes(map);
        if (!equalMaps(map,otherMap)) {
            errln("Maps are inconsistent after addAttributes");
        }

        map = map.addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);

        if (map.size() != 2) {
            errln("Map size is wrong.  map="+map);
        }

        if (equalMaps(map,otherMap)) {
            errln("Maps should not be equal");
        }

        Object posture = new Float(0);
        map = map.addAttribute(TextAttribute.POSTURE, posture);

        if (map.size() != 2) {
            errln("Map size is wrong");
        }

        if (!map.get(TextAttribute.POSTURE).equals(posture)) {
            errln("Map element is wrong");
        }

        map = map.removeAttribute(TextAttribute.UNDERLINE);

        if (map.size() != 1) {
            errln("Map size is wrong");
        }

        if (map.get(TextAttribute.UNDERLINE) != null) {
            errln("Map should not have element");
        }

        // map has POSTURE_REGULAR.  If we addAttributes a map with
        // POSTURE_ITALIC the new map should have POSTURE_ITALIC

        map = map.addAttributes(new AttributeMap(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE));
        if (map.get(TextAttribute.POSTURE) != TextAttribute.POSTURE_OBLIQUE) {
            errln("Map element is wrong");
        }

        _testModifiers(map);
        _testViews(map);

        Enumeration mapIter = maps.elements();
        while (mapIter.hasMoreElements()) {
            AttributeMap testMap = (AttributeMap) mapIter.nextElement();
            Object newValue = new Object();
            AttributeMap newMap = testMap.addAttribute(attributes[0], newValue);
            if (newMap.get(attributes[0]) != newValue) {
                errln("Did not get expected value back.  map=" + map);
            }
        }
    }
}