Package org.haystack

Source Code of org.haystack.HDict$MapImpl

//
// Copyright (c) 2011, Brian Frank
// Licensed under the Academic Free License version 3.0
//
// History:
//   07 Jun 2011  Brian Frank  My birthday!
//
package org.haystack;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.haystack.tagval.HBool;
import org.haystack.tagval.HMarker;
import org.haystack.tagval.HNum;
import org.haystack.tagval.HRef;
import org.haystack.tagval.HStr;
import org.haystack.tagval.HVal;

/**
* HDict is an immutable map of name/HVal pairs. Use HDictBuilder
* to construct a HDict instance.
*
* @see <a href='http://project-haystack.org/doc/TagModel#tags'>Project Haystack</a>
*/
public abstract class HDict {

    //////////////////////////////////////////////////////////////////////////
    // Constructor
    //////////////////////////////////////////////////////////////////////////

    /** Singleton for empty set of tags. */
    public static final HDict EMPTY = new MapImpl(new HashMap<String, HVal>());

    //////////////////////////////////////////////////////////////////////////
    // Access
    //////////////////////////////////////////////////////////////////////////

    /** Return if size is zero */
    public final boolean isEmpty() {
        return size() == 0;
    }

    /** Return number of tag name/value pairs */
    public abstract int size();

    /** Return if the given tag is present */
    public final boolean has(String name) {
        return get(name, false) != null;
    }

    /** Return if the given tag is not present */
    public final boolean missing(String name) {
        return get(name, false) == null;
    }

    /** Convenience for "get(name, true)" */
    public final HVal get(String name) {
        return get(name, true);
    }

    /**
     * Get a tag by name. If not found and checked if false then
     * return null, otherwise throw UnknownNameException
     */
    public abstract HVal get(String name, boolean checked);

    /** Create Map.Entry iteratator to walk each name/tag pair */
    public abstract Iterator<Entry<String, HVal>> iterator();

    /** Get the "id" tag as HRef. */
    public HRef id() {
        return getRef("id");
    }

    /**
     * Get display string for this entity:
     * - dis tag
     * - id tag
     */
    public String dis() {
        HVal v;
        v = get("dis", false);
        if (v instanceof HStr)
            return ((HStr) v).val;
        v = get("id", false);
        if (v != null)
            return v.toString();
        return "????";
    }

    //////////////////////////////////////////////////////////////////////////
    // Get Conveniences
    //////////////////////////////////////////////////////////////////////////

    /** Get tag as HBool or raise UnknownNameException or ClassCastException. */
    public final boolean getBool(String name) {
        return ((HBool) get(name)).val;
    }

    /** Get tag as HStr or raise UnknownNameException or ClassCastException. */
    public final String getStr(String name) {
        return ((HStr) get(name)).val;
    }

    /** Get tag as HRef or raise UnknownNameException or ClassCastException. */
    public final HRef getRef(String name) {
        return (HRef) get(name);
    }

    /** Get tag as HNum or raise UnknownNameException or ClassCastException. */
    public final int getInt(String name) {
        return (int) ((HNum) get(name)).val;
    }

    /** Get tag as HNum or raise UnknownNameException or ClassCastException. */
    public final double getDouble(String name) {
        return ((HNum) get(name)).val;
    }

    //////////////////////////////////////////////////////////////////////////
    // Identity
    //////////////////////////////////////////////////////////////////////////

    /** String format is always "toZinc" */
    @Override
    public final String toString() {
        return toZinc();
    }

    /** Hash code is based on tags */
    @Override
    public final int hashCode() {
        if (hashCode == 0) {
            int x = 33;
            for (Iterator<Entry<String, HVal>> it = iterator(); it.hasNext();) {
                Entry<String, HVal> entry = it.next();
                Object key = entry.getKey();
                Object val = entry.getValue();
                x ^= (key.hashCode() << 7) ^ val.hashCode();
            }
            hashCode = x;
        }
        return hashCode;
    }

    private int hashCode;

    /** Equality is tags */
    @Override
    public final boolean equals(Object that) {
        if (!(that instanceof HDict))
            return false;
        HDict x = (HDict) that;
        if (size() != x.size())
            return false;
        for (Iterator<Entry<String, HVal>> it = iterator(); it.hasNext();) {
            Entry<String, HVal> entry = it.next();
            String key = entry.getKey();
            Object val = entry.getValue();
            if (!val.equals(x.get(key, false)))
                return false;
        }
        return true;
    }

    //////////////////////////////////////////////////////////////////////////
    // Encoding
    //////////////////////////////////////////////////////////////////////////

    /** Encode value to zinc format */
    public final String toZinc() {
        StringBuffer s = new StringBuffer();
        boolean first = true;
        for (Iterator<Entry<String, HVal>> it = iterator(); it.hasNext();) {
            Entry<String, HVal> e = it.next();
            String name = e.getKey();
            HVal val = e.getValue();
            if (first)
                first = false;
            else
                s.append(' ');
            s.append(name);
            if (val != HMarker.VAL) {
                s.append(':').append(val.toZinc());
            }
        }
        return s.toString();
    }

    //////////////////////////////////////////////////////////////////////////
    // MapImpl
    //////////////////////////////////////////////////////////////////////////

    static class MapImpl extends HDict {
        MapImpl(Map<String, HVal> map) {
            this.map = map;
        }

        @Override
        public int size() {
            return map.size();
        }

        @Override
        public HVal get(String name, boolean checked) {
            HVal val = map.get(name);
            if (val != null)
                return val;
            if (!checked)
                return null;
            throw new UnknownNameException(name);
        }

        @Override
        public Iterator<Entry<String, HVal>> iterator() {
            return map.entrySet().iterator();
        }

        private final Map<String, HVal> map;
    }

    //////////////////////////////////////////////////////////////////////////
    // MapEntry
    //////////////////////////////////////////////////////////////////////////

    /** Create Map.Entry for given name/value tag pair */
    static Entry<String, HVal> toEntry(String key, HVal val) {
        return new MapEntry(key, val);
    }

    static class MapEntry implements Entry<String, HVal> {
        MapEntry(String key, HVal val) {
            this.key = key;
            this.val = val;
        }

        @Override
        public String getKey() {
            return key;
        }

        @Override
        public HVal getValue() {
            return val;
        }

        @Override
        public HVal setValue(HVal v) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean equals(Object o) {
            Entry<String, HVal> e1 = this;
            @SuppressWarnings("unchecked")
            Entry<String, HVal> e2 = (Entry<String, HVal>) o;
            return (e1.getKey() == null ? e2.getKey() == null : e1.getKey().equals(e2.getKey()))
                    && (e1.getValue() == null ? e2.getValue() == null : e1.getValue().equals(e2.getValue()));
        }

        private final String key;
        private final HVal val;
    }

}
TOP

Related Classes of org.haystack.HDict$MapImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.