org.rifidi.designer.library.retail.shelf.Shelf.java Source code

Java tutorial

Introduction

Here is the source code for org.rifidi.designer.library.retail.shelf.Shelf.java

Source

/*
 *  Clothing.java
 *
 *  Project:      RiFidi Designer - A Virtualization tool for 3D RFID environments
 *  http://www.rifidi.org
 *  http://rifidi.sourceforge.net
 *  Copyright:       Pramari LLC and the Rifidi Project
 *  License:      Lesser GNU Public License (LGPL)
 *  http://www.opensource.org/licenses/lgpl-license.html
 */
package org.rifidi.designer.library.retail.shelf;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EmptyStackException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Stack;
import java.util.concurrent.Callable;

import javax.xml.bind.annotation.XmlIDREF;
import javax.xml.bind.annotation.XmlTransient;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.core.databinding.observable.list.IListChangeListener;
import org.eclipse.core.databinding.observable.list.WritableList;
import org.rifidi.designer.entities.Entity;
import org.rifidi.designer.entities.VisualEntity;
import org.rifidi.designer.entities.annotations.Property;
import org.rifidi.designer.entities.databinding.IEntityObservable;
import org.rifidi.designer.entities.interfaces.IContainer;
import org.rifidi.designer.entities.interfaces.IProducer;
import org.rifidi.designer.entities.internal.RifidiTagWithParent;
import org.rifidi.designer.library.retail.clothing.Clothing;
import org.rifidi.designer.library.retail.retailbox.RetailBox;
import org.rifidi.designer.services.core.entities.EntitiesService;
import org.rifidi.services.annotations.Inject;
import org.rifidi.services.tags.IRifidiTagService;
import org.rifidi.services.tags.exceptions.RifidiTagNotAvailableException;
import org.rifidi.services.tags.model.IRifidiTagContainer;
import org.rifidi.tags.impl.RifidiTag;

import com.jme.bounding.BoundingBox;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.scene.Node;
import com.jme.scene.SharedNode;
import com.jme.scene.Spatial.CullHint;
import com.jme.scene.shape.Box;
import com.jme.util.export.binary.BinaryImporter;

/**
 * FIXME: Class comment.
 * 
 * @author Jochen Mader - jochen@pramari.com - Apr 3, 2008
 * 
 */
public class Shelf extends VisualEntity implements IContainer, IEntityObservable, IRifidiTagContainer,
        PropertyChangeListener, IProducer<RetailBox> {
    /** Logger for this class. */
    private static Log logger = LogFactory.getLog(Shelf.class);
    /** Capacity of the container. */
    private int capacity = 9;
    /** Number of currently stored items. */
    private int itemCount = 0;
    /** Model for shared meshes */
    @XmlTransient
    private static Node model = null;
    /** Box model. */
    @XmlTransient
    private static Node boxmodel = null;
    /** Set containing all available tags. */
    @XmlIDREF
    private List<RifidiTag> tags;
    @XmlTransient
    private Stack<RifidiTag> tagStack;
    /** List of wrapper objects that bind tags and container together. */
    @XmlTransient
    private WritableList wrappers;
    /** Reference to the tag service. */
    @XmlTransient
    private IRifidiTagService tagService;
    /** Reference to the entities service. */
    @XmlTransient
    private EntitiesService entitiesService;
    /** Container for entities inside the holder. */
    @XmlIDREF
    private List<VisualEntity> products;

    /**
     * Constructor.
     */
    public Shelf() {
        super();
        setName("Shelf");
        tags = new ArrayList<RifidiTag>();
        wrappers = new WritableList();
        tagStack = new Stack<RifidiTag>();
        products = new ArrayList<VisualEntity>();
    }

    /*
     * (non-Javadoc)
     * 
     * @seeorg.rifidi.designer.entities.interfaces.IEntityObservable#
     * addListChangeListener
     * (org.eclipse.core.databinding.observable.list.IListChangeListener)
     */
    @Override
    public void addListChangeListener(IListChangeListener changeListener) {
        wrappers.addListChangeListener(changeListener);
    }

    /*
     * (non-Javadoc)
     * 
     * @seeorg.rifidi.designer.entities.interfaces.IEntityObservable#
     * removeListChangeListener
     * (org.eclipse.core.databinding.observable.list.IListChangeListener)
     */
    @Override
    public void removeListChangeListener(IListChangeListener changeListener) {
        wrappers.removeListChangeListener(changeListener);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.rifidi.designer.entities.Entity#destroy()
     */
    @Override
    public void destroy() {
        List<Entity> del = new ArrayList<Entity>();
        del.addAll(products);
        entitiesService.deleteEntities(del);
        for (RifidiTag tag : tags) {
            tagService.releaseRifidiTag(tag, this);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.rifidi.designer.entities.Entity#init()
     */
    @Override
    public void init() {
        prepare();
        Node mainNode = new Node();
        mainNode.setModelBound(new BoundingBox());
        Node node = new Node("maingeometry");
        node.setModelBound(new BoundingBox());
        mainNode.attachChild(node);

        model.setLocalTranslation(new Vector3f(0, 3.7f, 0));
        model.setLocalScale(5.0f);
        model.setLocalRotation(new Quaternion(new float[] { (float) Math.toRadians(270), 0, 0 }));
        node.attachChild(model);
        setNode(mainNode);
        getNode().updateGeometricState(0f, true);
        getNode().updateModelBound();

        Node _node = new Node("hiliter");
        Box box = new Box("hiliter", ((BoundingBox) getNode().getWorldBound()).getCenter().clone()
                .subtractLocal(getNode().getLocalTranslation()).add(new Vector3f(0, 2, 0)), 4f, 4f, 1f);
        box.setModelBound(new BoundingBox());
        box.updateModelBound();
        _node.attachChild(box);
        _node.setModelBound(new BoundingBox());
        _node.updateModelBound();
        _node.setCullHint(CullHint.Always);
        getNode().attachChild(_node);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.rifidi.designer.entities.Entity#loaded()
     */
    @Override
    public void loaded() {
        prepare();
        for (RifidiTag tag : getTags()) {
            RifidiTagWithParent r = new RifidiTagWithParent();
            r.parent = this;
            r.tag = tag;
            wrappers.add(r);
        }
        List<RifidiTag> stackTags = new ArrayList<RifidiTag>(tags);
        for (VisualEntity prod : products) {
            stackTags.remove(((Clothing) prod).getRifidiTag());
        }
        tagStack.addAll(stackTags);
    }

    private void prepare() {
        try {
            URI modelpath = getClass().getClassLoader()
                    .getResource("org/rifidi/designer/library/retail/shelf/shelf.jme").toURI();
            model = (Node) BinaryImporter.getInstance().load(modelpath.toURL());
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        try {
            URI modelpath = getClass().getClassLoader()
                    .getResource("org/rifidi/designer/library/retail/retailbox/box.jme").toURI();
            boxmodel = (Node) BinaryImporter.getInstance().load(modelpath.toURL());
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.rifidi.designer.entities.interfaces.IContainer#addVisualEntity
     * (org.rifidi.designer.entities.VisualEntity)
     */
    @Override
    public void addVisualEntity(final VisualEntity visualEntity) {
        if (accepts(visualEntity) && !isFull() && products.contains(visualEntity)) {
            List<Entity> del = new ArrayList<Entity>();
            del.add(visualEntity);
            entitiesService.deleteEntities(del);
            addBox();
            tagStack.push(((RetailBox) visualEntity).getRifidiTag());
            return;
        }
        throw new RuntimeException("Stupid!! Wrong type or full: " + accepts(visualEntity) + " " + isFull());
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.rifidi.designer.entities.interfaces.IContainer#getVisualEntity
     * ()
     */
    @Override
    public VisualEntity getVisualEntity() {
        try {
            removeBox();
            RifidiTag tag = tagStack.pop();
            RetailBox box = new RetailBox();
            box.setRifidiTag(tag);
            box.setName(box.getName() + " " + tag);
            box.setProducer(this);
            box.setStartTranslation(getNode().getLocalTranslation().clone());
            entitiesService.addEntity(box, null, null);
            products.add(box);
            return box;
        } catch (EmptyStackException e) {
            return null;
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.rifidi.designer.entities.interfaces.IContainer#getVisualEntity
     * (org.rifidi.designer.entities.VisualEntity)
     */
    @Override
    public VisualEntity getVisualEntity(VisualEntity visualEntity) {
        logger.debug("direct selection not supported");
        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.rifidi.designer.entities.interfaces.IContainer#getVisualEntitySet ()
     */
    @Override
    public List<VisualEntity> getVisualEntityList() {
        return Collections.unmodifiableList(products);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.rifidi.designer.entities.interfaces.IContainer#isFull()
     */
    @Override
    public boolean isFull() {
        return capacity <= itemCount;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.rifidi.designer.entities.interfaces.IContainer#accepts(org
     * .rifidi.designer.entities.VisualEntity)
     */
    @Override
    public boolean accepts(VisualEntity visualEntity) {
        return visualEntity instanceof RetailBox;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.rifidi.designer.entities.VisualEntity#setLOD(int)
     */
    @Override
    public void setLOD(int lod) {
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.rifidi.designer.entities.VisualEntity#getBoundingNode()
     */
    @Override
    public Node getBoundingNode() {
        return (Node) getNode().getChild("hiliter");
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.rifidi.services.tags.model.IRifidiTagContainer#addTags(java.util.
     * Collection)
     */
    @Override
    public void addTags(Collection<RifidiTag> tags) {
        for (RifidiTag tag : tags) {
            if (this.tags.size() < capacity) {
                try {
                    tagService.takeRifidiTag(tag, this);
                    tag.addPropertyChangeListener(this);
                    RifidiTagWithParent r = new RifidiTagWithParent();
                    r.parent = this;
                    r.tag = tag;
                    addBox();
                    wrappers.add(r);
                    this.tags.add(tag);
                    tagStack.push(tag);
                } catch (RifidiTagNotAvailableException e) {
                    logger.error("Tag not available: " + e);
                }
            }
        }
    }

    private void addBox() {
        update(new Callable<Object>() {

            /*
             * (non-Javadoc)
             * 
             * @see java.util.concurrent.Callable#call()
             */
            @Override
            public Object call() throws Exception {
                // TODO: Possible race condition
                itemCount++;
                Node box = new Node("box " + itemCount);
                SharedNode shared = new SharedNode(boxmodel);
                box.attachChild(shared);
                box.getLocalTranslation().addLocal(calcPos(itemCount));
                box.setLocalScale(0.5f);
                getNode().attachChild(box);
                box.updateRenderState();
                return null;
            }

        });
    }

    private Vector3f calcPos(int count) {
        Vector3f ret = new Vector3f();
        int pos = (count - 1) % 3;
        int pos2 = (int) Math.floor((count - 1) / 3);
        ret.x = (float) (-1.9 + (1.9 * pos));
        ret.y = (float) (1 + (pos2 * 2.5f));
        ret.z = 0;
        return ret;
    }

    private void removeBox() {
        update(new Callable<Object>() {

            /*
             * (non-Javadoc)
             * 
             * @see java.util.concurrent.Callable#call()
             */
            @Override
            public Object call() throws Exception {
                getNode().getChild("box " + itemCount).removeFromParent();
                itemCount--;
                return null;
            }

        });
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.rifidi.services.tags.model.IRifidiTagContainer#removeTags(java.util
     * .Collection)
     */
    @Override
    public void removeTags(Collection<RifidiTag> tags) {
        // only remove tags that are currently available.
        if (this.tagStack.containsAll(tags)) {
            tagStack.removeAll(tags);
            this.tags.removeAll(tags);
            Set<RifidiTagWithParent> rem = new HashSet<RifidiTagWithParent>();
            for (Object wrapper : wrappers) {
                if (tags.contains(((RifidiTagWithParent) wrapper).tag)) {
                    ((RifidiTagWithParent) wrapper).tag.removePropertyChangeListener(this);
                    rem.add((RifidiTagWithParent) wrapper);
                }
            }
            wrappers.removeAll(rem);
            tagService.releaseRifidiTags(tags, this);
        }
    }

    /**
     * @return the wrappers
     */
    public WritableList getWrappers() {
        return this.wrappers;
    }

    /**
     * Get a string representation of the tags this producer owns.
     * 
     * @return
     */
    public String getTagList() {
        StringBuffer buf = new StringBuffer();
        for (RifidiTag tag : tags) {
            buf.append(tag + "\n");
        }
        return buf.toString();
    }

    @Property(displayName = "Tags", description = "tags assigned to this rack", readonly = true, unit = "")
    public void setTagList(String tagList) {

    }

    /*
     * (non-Javadoc)
     * 
     * @seejava.beans.PropertyChangeListener#propertyChange(java.beans.
     * PropertyChangeEvent)
     */
    @Override
    public void propertyChange(PropertyChangeEvent arg0) {

    }

    /*
     * (non-Javadoc)
     * 
     * @see org.rifidi.services.tags.model.IRifidiTagContainer#getTags()
     */
    @Override
    public Collection<RifidiTag> getTags() {
        return tags;
    }

    /**
     * @param tagService
     *            the tagService to set
     */
    @Inject
    public void setTagService(IRifidiTagService tagService) {
        this.tagService = tagService;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.rifidi.designer.entities.interfaces.IProducer#getProducts()
     */
    @Override
    public List<RetailBox> getProducts() {
        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.rifidi.designer.entities.interfaces.IProducer#productDestroied(org
     * .rifidi.designer.entities.interfaces.IProduct)
     */
    @Override
    public void productDestroied(RetailBox product) {
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.rifidi.designer.entities.interfaces.IProducer#setProducts(java.util
     * .List)
     */
    @Override
    public void setProducts(List<RetailBox> entities) {
    }

    /**
     * @param entitiesService
     *            the entitiesService to set
     */
    @Inject
    public void setEntitiesService(EntitiesService entitiesService) {
        this.entitiesService = entitiesService;
    }

}