Subversion Repositories SmartDukaan

Rev

Rev 250 | Blame | Last modification | View Log | RSS feed

package in.shop2020.creation.controllers;

import in.shop2020.creation.util.ContentValidator;
import in.shop2020.creation.util.CreationUtils;
import in.shop2020.metamodel.core.Bullet;
import in.shop2020.metamodel.core.CompositeDataObject;
import in.shop2020.metamodel.core.Entity;
import in.shop2020.metamodel.core.EnumDataObject;
import in.shop2020.metamodel.core.Feature;
import in.shop2020.metamodel.core.FreeformContent;
import in.shop2020.metamodel.core.PrimitiveDataObject;
import in.shop2020.metamodel.core.Slide;
import in.shop2020.metamodel.definitions.Catalog;
import in.shop2020.metamodel.definitions.Category;
import in.shop2020.metamodel.definitions.CompositeDefinition;
import in.shop2020.metamodel.definitions.CompositePartDefinition;
import in.shop2020.metamodel.definitions.DefinitionsContainer;
import in.shop2020.metamodel.definitions.EditorialImportance;
import in.shop2020.metamodel.definitions.EntityContainer;
import in.shop2020.metamodel.definitions.FeatureDefinition;
import in.shop2020.metamodel.definitions.SlideDefinition;
import in.shop2020.metamodel.definitions.SlideFeatureDefinition;
import in.shop2020.metamodel.util.ExpandedBullet;
import in.shop2020.metamodel.util.ExpandedBulletDefinition;
import in.shop2020.metamodel.util.ExpandedEntity;
import in.shop2020.metamodel.util.ExpandedFeature;
import in.shop2020.metamodel.util.ExpandedFeatureDefinition;
import in.shop2020.metamodel.util.ExpandedSlide;
import in.shop2020.metamodel.util.ExpandedSlideDefinition;
import in.shop2020.metamodel.util.SequenceGenerator;
import in.shop2020.util.Utils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import org.apache.struts2.interceptor.ParameterAware;
import org.apache.struts2.rest.DefaultHttpHeaders;
import org.apache.struts2.rest.HttpHeaders;

import com.opensymphony.xwork2.ValidationAwareSupport;

@Results({
    @Result(name="success", type="redirectAction", 
                params = {"actionName" , "entity"}),
    @Result(name="redirect", location="${url}", type="redirect")
})

public class EntityController extends ValidationAwareSupport 
        implements ParameterAware {
        
        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        /**
         * 
         */
        private static Log log = LogFactory.getLog(EntityController.class);
        
        /**
         * 
         */
        private String id;
        
        private ExpandedEntity expEntity;
        
        private Entity entity;
        
        private Collection<Entity> entities;

        private Map<String, String[]> reqparams;
        
        private EntityContainer ents;
        
        private DefinitionsContainer defs;
        
        private long firstSlideDefID;
        
        private ExpandedSlideDefinition expSlideDef;

        private ExpandedSlide expSlide;
        
        private String redirectURL;
        
        private Exception exception;
        
        private String errorString;
        
        private long newCurrentSlideDefinitionID;
        
        private long newNextSlideDefinitionID;
        
        private long newPrevSlideDefinitionID;

        private Map<Long, List<Long>> catSlides;

    // GET /entity/1
    public String show() {
        log.info("EntityController.show");
        
        try {
                long entityID = Long.parseLong(this.getId());
                log.info("entityID:" + entityID);
                
                        this.expEntity = this.getExpandedEntity(entityID);
                        
                        return "show";
                } catch (Exception e) {
                        log.error(CreationUtils.getStackTrace(e));
                        this.setErrorString(CreationUtils.getStackTrace(e));
                        return "fatal";
                }
    }
        
    // GET /entity
    public HttpHeaders index() {
        log.info("EntityController.index");
        
        EntityContainer ents = new EntityContainer();
        
        try {
                        this.entities = ents.getEntities().values();
                } catch (Exception e) {
                        log.error(CreationUtils.getStackTrace(e));
                        this.setErrorString(CreationUtils.getStackTrace(e));
                        return new DefaultHttpHeaders("fatal");
                }
        
        return new DefaultHttpHeaders("index").disableCaching();
    }

    // GET /entity
    public String create() {
        log.info("EntityController.create");
        
                SequenceGenerator sg;
                try {
                        sg = SequenceGenerator.getInstance();
                        long entityID = sg.getNextSequence(SequenceGenerator.ENTITY);

                        String categoryID = this.reqparams.get("category")[0];
                        Entity entity = new Entity(entityID, Long.parseLong(categoryID));

                        entity.setBrand(this.reqparams.get("brand")[0]);
                        entity.setModelName(this.reqparams.get("modelname")[0]);
                        entity.setModelNumber(this.reqparams.get("modelnumber")[0]);
                        
                        this.addEntity(entity);
                        
                this.setId(new Long(entityID).toString());
                } catch (Exception e) {
                        log.error(CreationUtils.getStackTrace(e));
                        this.setErrorString(CreationUtils.getStackTrace(e));
                        return "fatal";
                }
                
                this.redirectURL = "entity/" + this.getId() + "/edit";
        
                return "redirect";
    }
    
    // GET /entity/1/edit
    public String edit() {
        log.info("EntityController.edit");
        
        long entityID = Long.parseLong(this.getId());
        log.info("entityID:" + entityID);
        
        DefinitionsContainer defs = this.getDefinitionsContainer();
        
        try {
                        this.expEntity = this.getExpandedEntity(entityID);
                        //log.info("this.expEntity:" + this.expEntity);

                        String[] inputSlideDefIDs = this.reqparams.get("slideDefID");
                        long inputSlideDefID = 0L;
                        if(inputSlideDefIDs != null && inputSlideDefIDs.length > 0) {
                                try {
                                        inputSlideDefID = Long.parseLong(inputSlideDefIDs[0]);
                                } catch (NumberFormatException nfe) {}
                        }
                        long categoryID = this.getEntity(entityID).getCategoryID();
                        
                        log.info("Entity ID:" + entityID + "   CategoryID " + categoryID );
                        //Changed to make correct order of borrowed slides 
                        List<Long> slideDefIDs = CreationUtils.getSlideSequence(entityID, categoryID);
                        
                        log.info("slideDefIDs:" + slideDefIDs);
                        
                        // Edit the entity from a specific slide
                        if(slideDefIDs != null && inputSlideDefID != 0L) {
                                
                                // -2 : Not set
                                // -1 : Not found
                                int currentIndex = slideDefIDs.indexOf(
                                                new Long(inputSlideDefID));
                                
                                int nextIndex = -2;
                                if(currentIndex != slideDefIDs.size()) {
                                        nextIndex = currentIndex + 1;
                                }
                                
                                int prevIndex = -2;
                                if(currentIndex != 0) {
                                        prevIndex = currentIndex - 1;
                                }
                                
                                this.setNewCurrentSlideDefinitionID(
                                                slideDefIDs.get(currentIndex).longValue());
                                
                                if(nextIndex != -2) {
                                        this.setNewNextSlideDefinitionID(
                                                        slideDefIDs.get(nextIndex).longValue());
                                }
                                
                                if(prevIndex != -2) {
                                        this.setNewPrevSlideDefinitionID(
                                                        slideDefIDs.get(prevIndex).longValue());
                                }

                                // Current Slide Definition
                                this.expSlideDef = defs.getExpandedSlideDefinition(
                                                inputSlideDefID);
                                
                                // Current Slide Instance
                                this.expSlide = this.expEntity.getExpandedSlide(
                                                inputSlideDefID);
                                
                                return "editSlide";
                        }
                } catch (Exception e) {
                        log.error(CreationUtils.getStackTrace(e));
                        this.setErrorString(CreationUtils.getStackTrace(e));
                        return "fatal";
                }
                
        return "edit";
    }
    
    /**
     * 
     * @return
     */
    public String getUrl() {
        return this.redirectURL;
    }
    
    /**
     * 
     * @return
     */
    // GET /entity/new
    public String editNew() {
        log.info("EntityController.editNew");

        return "editNew";
    }
    
    /**
     * 
     * @return
     */
    // GET /entity/1
    public String update() {
        log.info("EntityController.update");

        long entityID = Long.parseLong(this.getId());
        log.info("entityID:" + entityID);
        
        DefinitionsContainer defs = this.getDefinitionsContainer();
        
        try {
                        this.expEntity = this.getExpandedEntity(entityID);
                        //log.info("this.expEntity:" + this.expEntity);

                        // Save and Go to slides selection page
                        if (this.reqparams.containsKey("slides")) {
                                log.info("Slides");
                                
                                Entity entity = this.expEntity.getEntity();

                                String categoryID = this.reqparams.get("category")[0];
                                
                                entity.setCategoryID(Long.parseLong(categoryID));
                                entity.setBrand(this.reqparams.get("brand")[0]);
                                entity.setModelName(this.reqparams.get("modelname")[0]);
                                entity.setModelNumber(this.reqparams.get("modelnumber")[0]);
                                
                                this.updateEntity(entity);
                                
                                this.redirectURL = "/slides/" + this.getId() + "/edit";
                                return "redirect";
                        }
                        
                        long currentSlideDefID = 0L;
                        long nextSlideDefID = 0L;
                        long prevSlideDefID = 0L;
                        long gotoSlideDefID = 0L;
                        
                        String[] currentslideDefIDStrings = 
                                this.reqparams.get("currentslideDefID");
                        
                        String[] nextslideDefIDStrings = 
                                this.reqparams.get("nextslideDefID");
                        
                        String[] prevslideDefIDStrings = 
                                this.reqparams.get("prevslideDefID");
                        
                        String[] gotoslideDefIDStrings = 
                                this.reqparams.get("gotoslideDefID");
                        log.info("gotoslideDefIDStrings:" + 
                                        Arrays.toString(gotoslideDefIDStrings));
                        
                        // Current Slide ID
                        if(currentslideDefIDStrings != null && 
                                        currentslideDefIDStrings.length > 0) {
                                try {
                                        currentSlideDefID = Long.parseLong(
                                                        currentslideDefIDStrings[0]);
                                }
                                catch (NumberFormatException nfe) {}
                        }
                        
                        // Next Slide ID
                        if(nextslideDefIDStrings != null && 
                                        nextslideDefIDStrings.length > 0) {
                                try {
                                        nextSlideDefID = Long.parseLong(nextslideDefIDStrings[0]);
                                }
                                catch (NumberFormatException nfe) {}
                        }
                        
                        // Prev Slide ID
                        if(prevslideDefIDStrings != null && 
                                        prevslideDefIDStrings.length > 0) {
                                try {
                                        prevSlideDefID = Long.parseLong(prevslideDefIDStrings[0]);
                                }
                                catch (NumberFormatException nfe) {}
                        }
                        
                        // Go to Slide ID
                        if(gotoslideDefIDStrings != null && 
                                        gotoslideDefIDStrings.length > 0) {
                                try {
                                        gotoSlideDefID = Long.parseLong(gotoslideDefIDStrings[0]);
                                }
                                catch (NumberFormatException nfe) {}
                        }
                        
                        log.info("currentSlideDefID:" + currentSlideDefID);
                        log.info("nextSlideDefID:" + nextSlideDefID);
                        log.info("prevSlideDefID:" + prevSlideDefID);
                        log.info("gotoSlideDefID:" + gotoSlideDefID);
                        
                        
                        // Save on basic info page
                        if (this.reqparams.containsKey("save") && currentSlideDefID == 0L) {
                                log.info("Save");
                                
                                Entity entity = this.expEntity.getEntity();

                                String categoryID = this.reqparams.get("category")[0];
                                
                                entity.setCategoryID(Long.parseLong(categoryID));
                                entity.setBrand(this.reqparams.get("brand")[0]);
                                entity.setModelName(this.reqparams.get("modelname")[0]);
                                entity.setModelNumber(this.reqparams.get("modelnumber")[0]);
                                
                                this.updateEntity(entity);
                                
                                return "success";
                        }
                        
                        List<Long> slideIDs = this.getSlideSequence(entityID);
                        log.info("slideIDs:"+slideIDs);
                        if(slideIDs == null) {
                                this.setErrorString("Slides need to be picked first!");
                                return "fatal";
                        }
                        
                        boolean skip = false;
                        if(this.reqparams.containsKey("skipprev") || 
                                        this.reqparams.containsKey("skipnext")) {
                                skip = true;
                        }
                        
                        boolean next = this.reqparams.containsKey("skipnext") || 
                                this.reqparams.containsKey("next");

                        boolean prev = this.reqparams.containsKey("skipprev") || 
                                this.reqparams.containsKey("prev");

                        boolean go = this.reqparams.containsKey("goto");
                                
                        // Save or Next or Prev or Go - When editing a slide
                        int currentSlideIndex = 0;
                        currentSlideIndex = slideIDs.indexOf(new Long(currentSlideDefID));
                        log.info("currentSlideIndex:" + currentSlideIndex);

                        if(!skip && currentSlideDefID != 0L) {
                                Entity entity = this.expEntity.getEntity();
                                
                                // Create new instance and override existing
                                Slide currentSlide = this.createSlide(currentSlideDefID);
                                
                                entity.addSlide(currentSlide);
                                long categoryID = this.getEntity().getCategoryID();
                                List<Long> orderedSlideIDs = 
                                        CreationUtils.getSlideSequence(entityID, categoryID);
                                
                                if(orderedSlideIDs != null) {
                                        entity.reorderSlides(orderedSlideIDs);
                                }
                                
                                // Store
                                this.updateEntity(entity);
                                //log.info("entity:" + entity);
                        }
                        
                        // Skip will delete current slide from entity
                        else if(skip && currentSlideDefID != 0L) {
                                Entity entity = this.expEntity.getEntity();
                                entity.removeSlide(currentSlideDefID);
                                long categoryID = this.getEntity().getCategoryID();
                                List<Long> orderedSlideIDs = 
                                        CreationUtils.getSlideSequence(entityID, categoryID);
                                
                                if(orderedSlideIDs != null) {
                                        entity.reorderSlides(orderedSlideIDs);
                                }
                                
                                // Store
                                this.updateEntity(entity);
                                //log.info("entity:" + entity);
                        }
                        
                        boolean showAnotherSlide = false;
                        
                        // -2 : Not set
                        // -1 : Not found
                        int newCurrentIndex = -2;  
                        int newNextIndex = -2;
                        int newPrevIndex = -2;
                                
                        // Next
                        if(next && nextSlideDefID != 0L) {
                                log.info("Next");
                                
                                // Decide on next slide ID
                                int nextSlideIndex = slideIDs.indexOf(new Long(nextSlideDefID));
                                log.info("nextSlideIndex:"+nextSlideIndex);
                                
                                // New Current
                                if (nextSlideIndex == -1) {
                                        this.setErrorString("Invalid Next slide ID " + 
                                                        nextSlideDefID);
                                        return "fatal";
                                }
                                
                                newCurrentIndex = nextSlideIndex;
                                
                                // New Next
                                if (newCurrentIndex != slideIDs.size()-1) {
                                        newNextIndex = newCurrentIndex + 1;
                                }
                                
                                // New Prev.
                                if(currentSlideDefID != 0L) {
                                        newPrevIndex = currentSlideIndex;
                                }
                                
                                showAnotherSlide = true;
                        }
                        
                        // Prev
                        if(prev && prevSlideDefID != 0L) {
                                log.info("Prev");
                                
                                // Decide on prev slide ID
                                int prevSlideIndex = slideIDs.indexOf(new Long(prevSlideDefID));
                                log.info("prevSlideIndex:" + prevSlideIndex);
                                
                                if (prevSlideIndex == -1) {
                                        this.setErrorString("Invalid Prev slide ID " + 
                                                        prevSlideDefID);
                                        return "fatal";
                                }
                                
                                // New Next
                                if(currentSlideDefID != 0L) {
                                        newNextIndex = currentSlideIndex;
                                }

                                // New Current
                                newCurrentIndex = prevSlideIndex;
                                
                                // New Prev.
                                if (newCurrentIndex != 0) {
                                        newPrevIndex = newCurrentIndex - 1;
                                }
                                
                                showAnotherSlide = true;
                        }
                        
                        // Go to
                        if(go && gotoSlideDefID != 0) {
                                log.info("Goto");
                                int gotoSlideIndex = slideIDs.indexOf(new Long(gotoSlideDefID));
                                log.info("gotoSlideIndex:" + gotoSlideIndex);
                                
                                if (gotoSlideIndex == -1) {
                                        this.setErrorString("Invalid Go to slide ID " + 
                                                        gotoSlideDefID);
                                        return "fatal";
                                }
                                                                
                                // New Next
                                if(gotoSlideIndex != slideIDs.size()-1) {
                                        newNextIndex = gotoSlideIndex + 1;
                                }

                                // New Current
                                newCurrentIndex = gotoSlideIndex;
                                
                                // New Prev.
                                if (gotoSlideIndex != 0) {
                                        newPrevIndex = gotoSlideIndex - 1;
                                }
                                
                                showAnotherSlide = true;
                        }
                        
                        if(showAnotherSlide) {
                                log.info("newCurrentIndex:" + newCurrentIndex);
                                log.info("newNextIndex:" + newNextIndex);
                                log.info("newPrevIndex:" + newPrevIndex);

                                if(newCurrentIndex != -2) {
                                        this.setNewCurrentSlideDefinitionID(
                                                        slideIDs.get(newCurrentIndex).longValue());
                                }
                                
                                if(newNextIndex != -2) {
                                        this.setNewNextSlideDefinitionID(
                                                        slideIDs.get(newNextIndex).longValue());
                                }
                                
                                if(newPrevIndex != -2) {
                                        this.setNewPrevSlideDefinitionID(
                                                        slideIDs.get(newPrevIndex).longValue());
                                }

                                long newCurrentSlideDefID = 
                                        this.getNewCurrentSlideDefinitionID();
                                log.info("newCurrentSlideDefID:" + newCurrentSlideDefID);
                                
                                // Current Slide Definition
                                this.expSlideDef = defs.getExpandedSlideDefinition(
                                                newCurrentSlideDefID);
                                
                                // Current Slide Instance
                                this.expSlide = this.expEntity.getExpandedSlide(
                                                newCurrentSlideDefID);
                                
                                log.info("this.expSlide is null: " + (this.expSlide == null));
                                
                                return "editSlide";
                        }
                }
        catch (Exception e) {
                        log.error(CreationUtils.getStackTrace(e));
                        this.setErrorString(CreationUtils.getStackTrace(e));
                        return "fatal";
        }
        
        return "success";
    }
        
    /**
     * 
     * @param entityID
     * @return
     * @throws Exception 
     */
    public long getBorrowedCategoryID(long slideDefID) throws Exception {
        long entityID = Long.parseLong(this.getId());
        Entity entity = this.getEntity(entityID);
        Long entityCatID = new Long(entity.getCategoryID());
        
        Map<Long, List<Long>> catSlides = this.getRawSlideSequence(entityID);
        
        Long lSlideDefID = new Long(slideDefID);
        if(catSlides != null) {
                for(Long catID : catSlides.keySet()) {
                        List<Long> slideDefIDs = catSlides.get(catID);
                        if(slideDefIDs.contains(lSlideDefID) && 
                                        !catID.equals(entityCatID)) {
                                return catID.longValue();
                        }
                }
        }
        
        return 0L;
    }

        /**
     * 
     * @param entityID
     * @return
     * @throws Exception 
     */
    private List<Long> getSlideSequence(long entityID) throws Exception {
        this.catSlides = this.getRawSlideSequence(entityID);
        return CreationUtils.getSlideSequence(this.catSlides);
        }
    
    /**
     * 
     * @param entityID
     * @return
     * @throws Exception
     */
        private Map<Long, List<Long>> getRawSlideSequence(long entityID) 
                throws Exception {
                if(this.catSlides == null) {
                        this.catSlides = CreationUtils.getRawSlideSequence(entityID);
                }
                
                return this.catSlides;
        }


        /**
     * 
     * @param slideDefID
     * @return
     * @throws Exception
     */
    private Slide createSlide(long slideDefID) throws Exception {
                Slide slide = new Slide(slideDefID);
                
                long borrowedCategoryID = this.getBorrowedCategoryID(slideDefID);
                log.info("borrowedCategoryID:" + borrowedCategoryID);
                
                if(borrowedCategoryID != 0L) {
                        slide.setBorrowedCategoryID(borrowedCategoryID);
                }
                
                // Slide free-form content
                FreeformContent slideFFC = this.getFreeformContent(
                                "slide_" + slideDefID);
                
                log.info("slideFFC:" + slideFFC);
                
                slide.setFreeformContent(slideFFC);
                //log.info("currentSlide:" + currentSlide);
                
                // Collect Feature bullets
                List<Feature> features = this.createFeatures(slide);
                log.info("features:" + features);
                
                slide.setFeatures(features);
                
                // Collect children slides
                SlideDefinition slideDef = 
                        this.getDefinitionsContainer().getSlideDefinition(slideDefID);

                List<Long> childrenSlideIDs = slideDef.getChildrenSlideDefinitionIDs();
                if(childrenSlideIDs != null) {
                        List<Slide> childrenSlides = new ArrayList<Slide>();
                        for (Long childSlideID : childrenSlideIDs) {
                                Slide childSlide = this.createSlide(childSlideID.longValue());
                                if(childSlide != null) {
                                        childrenSlides.add(childSlide);
                                }
                        }
                        
                        slide.setChildrenSlides(childrenSlides);
                }
                
                return slide;
    }

    /**
     * 
     * @param slide
     * @return
     * @throws Exception
     */
    private List<Feature> createFeatures(Slide slide) throws Exception {
                
                long slideDefID = slide.getSlideDefinitionID();
                SlideDefinition slideDef = defs.getSlideDefinition(slideDefID);
                
                List<SlideFeatureDefinition> slideFeatureDefs = 
                        slideDef.getSlideFeatureDefinitions();
                
                DefinitionsContainer defs = this.getDefinitionsContainer();
                
                List<Feature> features = new ArrayList<Feature>();      
                for(SlideFeatureDefinition slideFeatureDef : slideFeatureDefs) {
                        long featureDefinitionID = slideFeatureDef.getFeatureDefintionID();
                        log.info("featureDefinitionID:" + featureDefinitionID);
                        
                        // Ignore skipped featured
                        String[] skipvalue = 
                                this.reqparams.get(featureDefinitionID + "_skip");
                        log.info("skipvalue:" + Arrays.toString(skipvalue));
                        
                        if(skipvalue != null && skipvalue.length > 0 && 
                                        skipvalue[0].equals("on")) {
                                continue;
                        }
                        
                        String featureDefIDString = 
                                new Long(featureDefinitionID).toString();
                        
                        Feature feature = new Feature(featureDefinitionID);

                        FeatureDefinition featureDef = defs.getFeatureDefinition(
                                        featureDefinitionID);
                        log.info("featureDef:" + featureDef);
                        
                        ExpandedFeatureDefinition expFeatureDef = 
                                new ExpandedFeatureDefinition(featureDef);
                        
                        ExpandedBulletDefinition expBulletDef = 
                                expFeatureDef.getExpandedBulletDefinition();
                        
                        boolean isBlank = false;
                        
                        // Check if feature has no bullets
                        // Composite
                        if(expBulletDef.isComposite()) {
                                CompositeDefinition compositeDef = (CompositeDefinition)
                                        expBulletDef.getDatatypeDefinition(); 
                                
                                List<CompositePartDefinition> compositeParts = 
                                        compositeDef.getCompositePartDefinitions();
                                
                                boolean allPartsBlank = true;
                                for(int j=0;j<compositeParts.size();j++) {
                                        String[] partValues = this.reqparams.get(
                                                        featureDefIDString + "_" + (j + 1));

                                        if(partValues != null && partValues.length > 0) {
                                                allPartsBlank = false;
                                        }
                                }
                                
                                isBlank = allPartsBlank;
                        }
                        
                        // Enumerated and Primitive
                        else {
                                String[] bulletValues = this.reqparams.get(featureDefIDString);
                                if(bulletValues == null || bulletValues.length == 0) {
                                        isBlank = true;
                                }
                        }

                        // Has no bullets
                        if(isBlank) {

                                // Mandatory 
                                if(slideFeatureDef.getEditorialImportance() == 
                                        EditorialImportance.MANDATORY) {                
                                        features.add(feature);
                                }
                                
                                continue;
                        }
                        
                        // Bullets
                        List<Bullet> bullets = new ArrayList<Bullet>();
                        
                        // Collect unit
                        String[] unitIDs = this.reqparams.get(featureDefIDString + "_unit");
                        long unitID = 0L;
                        if(unitIDs != null && unitIDs.length > 0) {
                                unitID = Long.parseLong(unitIDs[0]);
                        }
                        
                        // Composite
                        if(expBulletDef.isComposite()) {
                                log.info("Composite");
                                
                                CompositeDataObject compositeDataObject = 
                                        new CompositeDataObject();
                                
                                CompositeDefinition compositeDef = 
                                        (CompositeDefinition)expBulletDef.getDatatypeDefinition(); 
                                
                                List<CompositePartDefinition> compositeParts = 
                                        compositeDef.getCompositePartDefinitions();
                                
                                for(int j=0;j<compositeParts.size();j++) {
                                        String[] partValues = this.reqparams.get(
                                                        featureDefIDString + "_" + (j + 1));
                                        
                                        if(partValues != null && partValues.length > 0) {
                                                compositeDataObject.addPrimitiveDataObject(
                                                        new PrimitiveDataObject(partValues[0]));
                                        }
                                }
                                
                                Bullet bullet = new Bullet(compositeDataObject);
                                
                                if(unitID != 0L) {
                                        bullet.setUnitID(unitID);
                                }
                                
                                bullets.add(bullet);
                        }
                        
                        // Enumerated
                        else if(expBulletDef.isEnumerated()) {
                                log.info("Enumerated");
                                
                                String[] bulletValues = this.reqparams.get(featureDefIDString);
                                log.info("bulletValues:" + Arrays.toString(bulletValues));

                                
                                for(int i=0;i<bulletValues.length;i++) {
                                        EnumDataObject enumDataObject = 
                                                new EnumDataObject(Long.parseLong(bulletValues[i]));
                                        
                                        Bullet bullet = new Bullet(enumDataObject);
                                        
                                        if(unitID != 0L) {
                                                bullet.setUnitID(unitID);
                                        }
                                        
                                        bullets.add(bullet);
                                }
                        }
                        
                        // Primitive
                        else {
                                log.info("Primitive");
                                
                                String[] bulletValues = this.reqparams.get(featureDefIDString);
                                log.info("bulletValues:" + Arrays.toString(bulletValues));
                                
                                for(int i=0;i<bulletValues.length;i++) {
                                        Bullet bullet = new Bullet(
                                                        new PrimitiveDataObject(bulletValues[i]));
                                        
                                        if(unitID != 0L) {
                                                bullet.setUnitID(unitID);
                                        }
                                        
                                        bullets.add(bullet);
                                }
                        }
                        
                        feature.setBullets(bullets);
                        
                        // FFC
                        FreeformContent featureFFC = 
                                this.getFreeformContent(featureDefIDString);
                        
                        feature.setFreeformContent(featureFFC);
                        
                        features.add(feature);
                }
                
                return features;
        }

    // DELETE /entity/1000001
    /**
     * 
     */
    public String destroy() {
        log.info("#### EntityController.destroy ####");
        
        long entityID = Long.parseLong(this.getId());
        log.info("entityID:" + entityID);
        
                // Store
                try {
                Entity entity = this.getEntity(entityID);
                EntityContainer ents = this.getEntityContainer();
                
                Map<Long, Entity> entities = ents.getEntities();
                Map<Long, List<Entity>> entitiesbycat = 
                        ents.getEntitiesbyCategory();
                
                entities.remove(new Long(entityID));
                
                List<Entity> catentities = 
                        entitiesbycat.get(new Long(entity.getCategoryID()));
                
                Entity entitytodelete = null;
                for(Entity catentity : catentities) {
                        if(catentity.getID() == entityID) {
                                entitytodelete = catentity;
                                break;
                        }
                }
                
                if(entitytodelete != null) {
                        catentities.remove(entitytodelete);
                }
                
                CreationUtils.deleteFromIncomplete(entity);
                
                CreationUtils.deleteEntity(entityID);
                
                CreationUtils.rewriteRepository(entities, entitiesbycat);
                } catch (Exception e) {
                        log.error(CreationUtils.getStackTrace(e));
                        this.setErrorString(CreationUtils.getStackTrace(e));
                        return "fatal";
                }
                
        addActionMessage("Entity deleted successfully");
        return "success";
    }
        /**
     * 
     * @param ID
     * @return
     */
    private FreeformContent getFreeformContent(String ID) {
                FreeformContent ffc = new FreeformContent();
                String[] ffts = this.reqparams.get(ID + "_fft");
                if(ffts != null) {
                        ffc.setFreeformTexts(Arrays.asList(ffts));
                }
                
                String[] imgRefs = this.reqparams.get(ID + "_image_references");
                if(imgRefs != null) {
                        ffc.setMedia("image", Arrays.asList(imgRefs));
                }
                
                String[] youtubeRefs = 
                        this.reqparams.get(ID + "_youtube_references");
                if(youtubeRefs != null) {
                        ffc.setMedia("youtube", Arrays.asList(youtubeRefs));
                }
                
                log.info("ffc:" + ffc);
                return ffc;
        }
    
    
    /**
     * 
     * @param slideDefinitionID
     * @return
     */
        public ExpandedSlide getChildSlide(long slideDefinitionID) {
                if(this.expSlide == null) {
                        return null;
                }
                
                return this.getChildSlide(this.expSlide, slideDefinitionID);
        }
        
        
    /**
     * 
     * @param expSlide
     * @param slideDefinitionID
     * @return
     */
        public ExpandedSlide getChildSlide(ExpandedSlide expSlide, 
                        long slideDefinitionID) {
                
                List<ExpandedSlide> childrenSlides = 
                        expSlide.getExpandedChildrenSlides();
                
                ExpandedSlide resultSlide = null;
                
                if(childrenSlides != null) {
                        for(ExpandedSlide childSlide : childrenSlides) {
                                if(childSlide.getSlideDefinitionID() == slideDefinitionID) {
                                        return childSlide;
                                }
                                
                                resultSlide = this.getChildSlide(childSlide, slideDefinitionID);
                                if(resultSlide == null) {
                                        continue;
                                }
                                else {
                                        break;
                                }
                        }
                }
                
                return resultSlide;
        }

        /**
         * @return the entities
         */
        public Collection<Entity> getEntities() {
                return entities;
        }

        /**
         * 
         * @return
         */
        public List<Entity> getIncompleteEntities() {
                try {
                        return CreationUtils.getIncomplete();
                } catch (Exception e) {
                        log.error(CreationUtils.getStackTrace(e));
                        this.setErrorString(CreationUtils.getStackTrace(e));
                        return null;
                }
        }
        
    /**
         * @return the entities
         */
        public ExpandedEntity getEntity() {
                return expEntity;
        }

    /**
         * @return the current slide to edit
         */
        public ExpandedSlideDefinition getExpandedSlideDefinition() {
                return expSlideDef;
        }

        /**
         * 
         * @param slideDefID
         * @return
         */
        public ExpandedSlideDefinition getExpandedSlideDefinition(long slideDefID) {
                DefinitionsContainer defs = this.getDefinitionsContainer();
                
                try {
                        return defs.getExpandedSlideDefinition(slideDefID);
                } catch (Exception e) {
                        return null;
                }
        }
        
        /**
     * 
     * @param id
     */
    public void setId(String id) {
        this.id = id;
    }
    
    /**
     * 
     */
    public String getId() {
        return this.id;
    }

        /**
         * @return the firstSlideID
         */
        public long getFirstSlideDefID() {
                return firstSlideDefID;
        }

        @Override
        public void setParameters(Map<String, String[]> reqmap) {
                log.info("setParameters:" + reqmap);
                
                this.reqparams = reqmap;
        }

        public Map<String, String> getCategories() throws Exception {
                DefinitionsContainer defs = this.getDefinitionsContainer();
                Map<String, String> cats = new HashMap<String, String>();

                List<Category> children = defs.getChildrenCategories(10001L);
                for(Category child : children) {
                        cats.put(new Long(child.getID()).toString(), child.getLabel());
                }
                
                return cats;
        }
        
        /**
         * 
         * @return
         * @throws Exception
         */
        public String getBrandString() throws Exception {
                List<String> brands = this.getBrands();
                return "\"" + StringUtils.join(brands, "\", \"") + "\"";
        }

        /**
         * 
         * @return
         * @throws Exception
         */
        public List<String> getBrands() throws Exception {
                EntityContainer ents = this.getEntityContainer();
                List<String> brands = new ArrayList<String>();
                
                List<ExpandedBullet> expBullets;

                expBullets = ents.getLearnedBullets(
                                Utils.BRAND_FEATURE_DEFINITION_ID);
                
                for(ExpandedBullet expBullet : expBullets) {
                        brands.add(expBullet.getValue());
                }

                return brands;
        }

        /**
         * 
         * @return
         */
    protected EntityContainer getEntityContainer() {
        if(this.ents == null) {
                this.ents = Catalog.getInstance().getEntityContainer();
        }
        
            return this.ents;
    }
    
    /**
     * 
     * @return
     */
    protected DefinitionsContainer getDefinitionsContainer() {
        if(this.defs == null) {
                this.defs = Catalog.getInstance().getDefinitionsContainer();
        }
        
            return this.defs;
    }

    /**
     * 
     * @param entity
     * @throws Exception
     */
        private void addEntity(Entity entity) throws Exception {
                log.info("#### EntityController.addEntity ####");
                EntityContainer entContainer = this.getEntityContainer();

                entContainer.addEntity(entity);
                
                CreationUtils.storeEntity(entity);
                
                ContentValidator validator = new ContentValidator();
                if(!validator.validate(entity)) {
                        CreationUtils.addToIncomplete(entity);
                }
                // Add to repository only if validations succeed
                else {
                        CreationUtils.deleteFromIncomplete(entity);
                        
                        this.updateRepository();
                }
        }

    /**
     * 
     * @param entity
     * @throws Exception
     */
        private void updateEntity(Entity entity) throws Exception {             
                log.info("#### EntityController.updateEntity ####");
                EntityContainer entContainer = this.getEntityContainer();
                
                ContentValidator validator = new ContentValidator();
                if(!validator.validate(entity)) {
                        CreationUtils.addToIncomplete(entity);
                        
                        // Delete from repository if incomplete
                        entContainer.deleteEntity(entity);
                }
                else {
                        CreationUtils.deleteFromIncomplete(entity);
                        
                        entContainer.updateEntity(entity);
                }
                
                CreationUtils.storeEntity(entity);
                
                this.updateRepository();
        }

        /**
         * 
         * @throws Exception
         */
        private void updateRepository() throws Exception {      
                EntityContainer entContainer = this.getEntityContainer();
                
                Map<Long, Entity> entities = entContainer.getEntities();
                log.info("entities.size():" + entities.size());
                
                Map<Long, List<Entity>> entitiesByCategory = 
                        entContainer.getEntitiesbyCategory();
                log.info("entitiesByCategory.size():" + entitiesByCategory.size());
                
                CreationUtils.rewriteRepository(entities, entitiesByCategory);
        }
        
        /**
         * @param exception the exception to set
         */
        public void setException(Exception exception) {
                this.exception = exception;
        }

        /**
         * @return the exception
         */
        public Exception getException() {
                return exception;
        }

        /**
         * @param errorString the exceptionString to set
         */
        public void setErrorString(String errorString) {
                this.errorString = errorString;
        }

        /**
         * @return the exceptionString
         */
        public String getErrorString() {
                return errorString;
        }

        /**
         * @param newCurrentSlideID the newCurrentSlideID to set
         */
        public void setNewCurrentSlideDefinitionID(
                        long newCurrentSlideDefinitionID) {
                this.newCurrentSlideDefinitionID = newCurrentSlideDefinitionID;
        }

        /**
         * @return the newCurrentSlideID
         */
        public long getNewCurrentSlideDefinitionID() {
                return newCurrentSlideDefinitionID;
        }

        /**
         * @param newNextSlideID the newNextSlideID to set
         */
        public void setNewNextSlideDefinitionID(long newNextSlideDefinitionID) {
                this.newNextSlideDefinitionID = newNextSlideDefinitionID;
        }

        /**
         * @return the newNextSlideID
         */
        public long getNewNextSlideDefinitionID() {
                return newNextSlideDefinitionID;
        }

        /**
         * @param expSlide the expSlide to set
         */
        public void setExpandedSlide(ExpandedSlide expSlide) {
                this.expSlide = expSlide;
        }

        /**
         * @return the expSlide
         */
        public ExpandedSlide getExpandedSlide() {
                return expSlide;
        }

        /**
         * @param newPrevSlideDefinitionID the newPrevSlideDefinitionID to set
         */
        public void setNewPrevSlideDefinitionID(long newPrevSlideDefinitionID) {
                this.newPrevSlideDefinitionID = newPrevSlideDefinitionID;
        }

        /**
         * @return the newPrevSlideDefinitionID
         */
        public long getNewPrevSlideDefinitionID() {
                return newPrevSlideDefinitionID;
        }

        /**
         * 
         * @param featureDefinitionID
         * @return
         * @throws Exception
         */
        public String getLearnedValuesString(long featureDefinitionID) 
                        throws Exception {
                List<String> learnedValues = this.getLearnedValues(featureDefinitionID);
                if(learnedValues == null) {
                        return "";
                }
                
                return "\"" + StringUtils.join(learnedValues, "\", \"") + "\"";
        }

        /**
         * 
         * @param featureDefinitionID
         * @return
         * @throws Exception
         */
        public List<String> getLearnedValues(long featureDefinitionID) 
                        throws Exception {
                EntityContainer ents = this.getEntityContainer();
                List<ExpandedBullet> learnedBullets = 
                        ents.getLearnedBullets(featureDefinitionID);
                
                if(learnedBullets == null) {
                        return null;
                }
                
                List<String> learnedValues = new ArrayList<String>();
                for(ExpandedBullet expBullet : learnedBullets) {
                        learnedValues.add(expBullet.getValue());
                }
                
                return learnedValues;
        }

        /**
         * 
         * @param featureDefinitionID
         * @return
         * @throws Exception
         */
        public ExpandedFeature getFeature(long featureDefinitionID) 
                throws Exception {
                EntityContainer ents = this.getEntityContainer();
                
                if(this.expSlide != null) {
                        Feature feature = ents.getFeature(
                                        this.expSlide, featureDefinitionID);
                        
                        if(feature == null) {
                                return null;
                        }
                        return new ExpandedFeature(feature);
                }
                
                return null;
        }
        
        /**
         * 
         * @return
         */
        public String getEditorialImportance() {
                // Now that slides are selected upfront
                return "Mandatory";
                
                /*
                long catID = this.expEntity.getCategoryID();
                long slideDefID = this.getNewCurrentSlideDefinitionID();
                
                try {
                        List<CategorySlideDefinition> catSlideDefs =
                                defs.getCategorySlideDefinitions(catID);
                        for(CategorySlideDefinition catSlideDef : catSlideDefs) {
                                if(catSlideDef.getSlideDefintionID() == slideDefID) {
                                        return catSlideDef.getEditorialImportance().toString();
                                }
                        }
                } catch (Exception e) {
                        log.error(CreationUtils.getStackTrace(e));
        }
                
                return "";
                */
        }
        
        /**
         * 
         * @return
         * @throws Exception 
         * @throws NumberFormatException 
         */
        public List<String> getMediaLabels(String type) {
                try {
                        return CreationUtils.getMediaLabels(Long.parseLong(this.getId()), 
                                        type);
                }
                catch(Exception nfe) {
                        return null;
                }
        }

        /**
         * 
         * @return
         */
        public String getCategoryName(long categoryID) {
                try {
                        return this.getDefinitionsContainer().getCategory(categoryID).
                                getLabel();
                } catch (Exception e) {
                        return null;
                }
        }
        
        /**
         * 
         * @return
         */
        public List<String[]> getSlides() {
                try {
                        long entityID = Long.parseLong(this.getId());
                        long categoryID = this.getEntity().getCategoryID();
                        List<Long> slideDefIDs = CreationUtils.getSlideSequence(entityID, categoryID);
                        
                        List<String[]> slideData = new ArrayList<String[]>();
                        
                        DefinitionsContainer defs = this.getDefinitionsContainer();
                        for(Long slideDefID : slideDefIDs) {
                                SlideDefinition slideDef = defs.getSlideDefinition(slideDefID);
                                String label = slideDef.getLabel();
                                
                                slideData.add(new String[] {slideDefID.toString(), label});
                        }
                        
                        return slideData;
                } catch (Exception e) {
                        log.error(CreationUtils.getStackTrace(e));
                        
                        return null;
                }
        } 
    
    /**
     * 
     * @param entityID
     * @return
     * @throws Exception 
     */
    private ExpandedEntity getExpandedEntity(long entityID) throws Exception {
        if(this.expEntity == null) {
                if(this.entity == null) {
                        this.entity = this.getEntity(entityID);
                }
                
                this.expEntity = new ExpandedEntity(entity);
        }
        
        return this.expEntity;
    }

    /**
     * 
     * @param entityID
     * @return
     * @throws Exception 
     */
    private Entity getEntity(long entityID) throws Exception {
        log.info("#### EntityController.getEntity ####");
                if(this.entity == null) {
                        this.entity = CreationUtils.getEntity(entityID);
                }
                
                return this.entity;
        }
}