ded.model.Entity.java Source code

Java tutorial

Introduction

Here is the source code for ded.model.Entity.java

Source

// Entity.java
// See toplevel license.txt for copyright and license terms.

package ded.model;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashMap;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import util.FlattenInputStream;
import util.Util;
import util.XParse;
import util.awt.AWTJSONUtil;
import util.json.JSONable;

/** An ER entity, represented as a box with a label and text contents. */
public class Entity implements JSONable {
    // ------------ constants -------------
    /** Default shape. */
    public static final EntityShape defaultShape = EntityShape.ES_RECTANGLE;

    /** Default entity fill color.  Assumed when no color is
      * specified in the input file. */
    public static final String defaultFillColor = "Gray";

    /** Default image fill style. */
    public static final ImageFillStyle defaultImageFillStyle = ImageFillStyle.IFS_UPPER_LEFT;

    // ------------ public data ------------
    /** Location of upper-left corner, in pixels. */
    public Point loc;

    /** Size in pixels. */
    public Dimension size;

    /** Shape of the outline (or indication of its absence). */
    public EntityShape shape = defaultShape;

    /** Name of fill color.  For the moment, this must be one of
      * a fixed set, but I plan on making it customizable. */
    public String fillColor = defaultFillColor;

    /** Name/title of the entity. */
    public String name = "";

    /** Attributes as free text with newlines. */
    public String attributes = "";

    /** Additional shape-specific geometry parameters.  May be null. */
    public int[] shapeParams = null;

    /** Shape-specific flags. */
    public EnumSet<ShapeFlag> shapeFlags = ShapeFlag.defaultFlagsForShape(defaultShape);

    /** Name of anchor in an HTML document for a section that describes
      * this entity.  This is only used by a separate Python script,
      * 'insert-ded-image-map' that reads the 'ded' JSON format and
      * writes an HTML image map. */
    public String anchorName = "";

    /** File name of image to draw as the entity background instead of
      * 'fillColor' (which is then not used for most shapes).  When
      * rendered, if relative, the this will be interpreted as relative
      * to the directory where the containing .ded file is.  This is
      * only used if it is not empty. */
    public String imageFileName = "";

    /** When 'imageFileName' is not empty, this specifies how we fill
      * the entity rectangle with it. */
    public ImageFillStyle imageFillStyle = defaultImageFillStyle;

    // ------------ public methods ------------
    public Entity() {
        this.loc = new Point(0, 0);
        this.size = new Dimension(100, 50);
    }

    /** Return the primary bounding rectangle for this entity, used for
      * drawing the selection box and hit testing.  Some shapes might
      * extend a little outside this box visually. */
    public Rectangle getRect() {
        return new Rectangle(this.loc, this.size);
    }

    /** Return the point at the center of the Entity's bounding box. */
    public Point getCenter() {
        return new Point(this.loc.x + this.size.width / 2, this.loc.y + this.size.height / 2);
    }

    /** Set 'fillColor'.  For the moment, that is all. */
    public void setFillColor(String colorName) {
        this.fillColor = colorName;
    }

    /** Set 'shape'.  Adjust 'shapeParams' to match if needed. */
    public void setShape(EntityShape shape) {
        if (this.shape != shape) {
            this.shape = shape;

            if (shape.numParams == 0) {
                this.shapeParams = null;
            } else {
                this.shapeParams = new int[shape.numParams];
                for (int i = 0; i < shape.numParams; i++) {
                    this.shapeParams[i] = 5 + 5 * i;
                }
            }
        }
    }

    /** Get shape param 'i', or 0 if it is not set. */
    public int getShapeParam(int i) {
        if (this.shapeParams != null && this.shapeParams.length > i) {
            return this.shapeParams[i];
        } else {
            return 0;
        }
    }

    /** Set the shape parameters. */
    public void setShapeParams(int p, int q) {
        this.shapeParams = new int[2];
        this.shapeParams[0] = p;
        this.shapeParams[1] = q;
    }

    // ------------ serialization ------------
    @Override
    public JSONObject toJSON() {
        JSONObject o = new JSONObject();
        try {
            o.put("loc", AWTJSONUtil.pointToJSON(this.loc));
            o.put("size", AWTJSONUtil.dimensionToJSON(this.size));

            if (this.shape != defaultShape) {
                o.put("shape", this.shape.name());
            }

            if (!this.name.isEmpty()) {
                o.put("name", this.name);
            }

            if (!this.attributes.isEmpty()) {
                o.put("attributes", this.attributes);
            }

            if (this.shapeParams != null) {
                o.put("shapeParams", new JSONArray(this.shapeParams));
            }

            if (!this.shapeFlags.isEmpty()) {
                o.put("shapeFlags", AWTJSONUtil.enumSetToJSON(this.shapeFlags));
            }

            if (!this.fillColor.equals(defaultFillColor)) {
                o.put("fillColor", this.fillColor);
            }

            if (!this.anchorName.isEmpty()) {
                o.put("anchorName", this.anchorName);
            }

            if (!this.imageFileName.isEmpty()) {
                o.put("imageFileName", this.imageFileName);
            }

            if (this.imageFillStyle != defaultImageFillStyle) {
                o.put("imageFillStyle", this.imageFillStyle.name());
            }
        } catch (JSONException e) {
            assert (false);
        }
        return o;
    }

    public Entity(JSONObject o, int ver) throws JSONException {
        this.loc = AWTJSONUtil.pointFromJSON(o.getJSONObject("loc"));
        this.size = AWTJSONUtil.dimensionFromJSON(o.getJSONObject("size"));

        if (o.has("shape")) {
            this.shape = EntityShape.valueOf(EntityShape.class, o.getString("shape"));
        }

        this.name = o.optString("name", "");
        this.attributes = o.optString("attributes", "");

        JSONArray params = o.optJSONArray("shapeParams");
        if (params != null) {
            this.shapeParams = new int[params.length()];
            for (int i = 0; i < params.length(); i++) {
                this.shapeParams[i] = params.getInt(i);
            }
        }

        JSONArray flags = o.optJSONArray("shapeFlags");
        if (flags != null) {
            this.shapeFlags = AWTJSONUtil.enumSetFromJSON(ShapeFlag.class, flags);
        }

        if (ver >= 5) {
            this.fillColor = o.optString("fillColor", defaultFillColor);
        }

        if (ver >= 12) {
            this.anchorName = o.optString("anchorName", "");
        }

        if (ver >= 7) {
            this.imageFileName = o.optString("imageFileName", "");
        }

        if (ver >= 8 && o.has("imageFillStyle")) {
            this.imageFillStyle = ImageFillStyle.valueOf(ImageFillStyle.class, o.getString("imageFillStyle"));
        }
    }

    /** Return the value to which 'this' is mapped in 'entityToInteger'. */
    public int toJSONRef(HashMap<Entity, Integer> entityToInteger) {
        Integer index = entityToInteger.get(this);
        if (index == null) {
            throw new RuntimeException("internal error: entityToInteger mapping not found");
        }
        return index.intValue();
    }

    /** Return the value to which 'index' is mapped in 'integerToEntity'. */
    public static Entity fromJSONRef(ArrayList<Entity> integerToEntity, long index) throws JSONException {
        if (0 <= index && index < integerToEntity.size()) {
            return integerToEntity.get((int) index);
        } else {
            throw new JSONException("invalid entity ref " + index);
        }
    }

    // -------------- legacy serialization ---------------
    /** Construct an Entity by reading an ER FlattenInputStream. */
    public Entity(FlattenInputStream flat) throws XParse, IOException {
        this.loc = flat.readPoint();
        this.size = flat.readDimension();
        this.name = flat.readString();

        if (flat.version < 2) {
            return;
        }

        this.attributes = flat.readString();

        if (flat.version < 6) {
            return;
        }

        int s = flat.readInt();
        switch (s) {
        case 0:
            this.shape = EntityShape.ES_NO_SHAPE;
            break;
        case 1:
            this.shape = EntityShape.ES_RECTANGLE;
            break;
        case 2:
            this.shape = EntityShape.ES_ELLIPSE;
            break;
        default:
            throw new XParse("unrecognized entity shape code: " + s);
        }
    }

    // ------------- data object boilerplate -------------
    /** Deep clone copy constructor. */
    public Entity(Entity obj) {
        this.loc = new Point(obj.loc);
        this.size = new Dimension(obj.size);
        this.shape = obj.shape;
        this.fillColor = obj.fillColor;
        this.name = obj.name;
        this.attributes = obj.attributes;
        this.shapeParams = Util.copyArray(obj.shapeParams);
        this.shapeFlags = obj.shapeFlags.clone();
        this.anchorName = obj.anchorName;
        this.imageFileName = obj.imageFileName;
        this.imageFillStyle = obj.imageFillStyle;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (this.getClass() == obj.getClass()) {
            Entity e = (Entity) obj;
            return this.loc.equals(e.loc) && this.size.equals(e.size) && this.shape.equals(e.shape)
                    && this.fillColor.equals(e.fillColor) && this.name.equals(e.name)
                    && this.attributes.equals(e.attributes) && Arrays.equals(this.shapeParams, e.shapeParams)
                    && this.shapeFlags.equals(e.shapeFlags) && this.anchorName.equals(e.anchorName)
                    && this.imageFileName.equals(e.imageFileName) && this.imageFillStyle.equals(e.imageFillStyle);
        }
        return false;
    }

    @Override
    public int hashCode() {
        int h = 1;
        h = h * 31 + this.loc.hashCode();
        h = h * 31 + this.size.hashCode();
        h = h * 31 + this.shape.hashCode();
        h = h * 31 + this.fillColor.hashCode();
        h = h * 31 + this.name.hashCode();
        h = h * 31 + this.attributes.hashCode();
        h = h * 31 + Arrays.hashCode(this.shapeParams);
        h = h * 31 + this.shapeFlags.hashCode();
        h = h * 31 + this.anchorName.hashCode();
        h = h * 31 + this.imageFileName.hashCode();
        h = h * 31 + this.imageFillStyle.hashCode();
        return h;
    }

    @Override
    public String toString() {
        return toJSON().toString();
    }
}

// EOF