Subversion Repositories SmartDukaan

Rev

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

/**
 * 
 */
package in.shop2020.metamodel.util;

import in.shop2020.metamodel.definitions.BulletDefinition;
import in.shop2020.metamodel.definitions.CMPBucketDefinition;
import in.shop2020.metamodel.definitions.CMPRuleDefinition;
import in.shop2020.metamodel.definitions.CMPSlideRuleDefinition;
import in.shop2020.metamodel.definitions.Catalog;
import in.shop2020.metamodel.definitions.Category;
import in.shop2020.metamodel.definitions.CategoryFacetDefinition;
import in.shop2020.metamodel.definitions.CategorySlideDefinition;
import in.shop2020.metamodel.definitions.CompositeDefinition; 
import in.shop2020.metamodel.definitions.CompositePartDefinition;
import in.shop2020.metamodel.definitions.DatatypeDefinition;
import in.shop2020.metamodel.definitions.DefinitionsContainer;
import in.shop2020.metamodel.definitions.EditorialImportance;
import in.shop2020.metamodel.definitions.EnumDefinition;
import in.shop2020.metamodel.definitions.EnumValue;
import in.shop2020.metamodel.definitions.FacetDefinition;
import in.shop2020.metamodel.definitions.FacetRuleDefinition;
import in.shop2020.metamodel.definitions.FeatureDefinition;
import in.shop2020.metamodel.definitions.RuleDefinition;
import in.shop2020.metamodel.definitions.SlideDefinition;
import in.shop2020.metamodel.definitions.SlideFeatureDefinition;
import in.shop2020.metamodel.definitions.Unit;
import in.shop2020.metamodel.jaxb.comparison.CMPBucketDefinitionType;
import in.shop2020.metamodel.jaxb.comparison.CMPDefinitionType;
import in.shop2020.metamodel.jaxb.comparison.CMPRuleDefinitionType;
import in.shop2020.metamodel.jaxb.comparison.CMPSlideRuleDefinitionType;
import in.shop2020.metamodel.jaxb.core.BulletDefinitionType;
import in.shop2020.metamodel.jaxb.core.CategorySlideDefinitionType;
import in.shop2020.metamodel.jaxb.core.CategorySlideSequenceType;
import in.shop2020.metamodel.jaxb.core.CategoryType;
import in.shop2020.metamodel.jaxb.core.CompositeDefinitionType;
import in.shop2020.metamodel.jaxb.core.CompositePartDefinitionType;
import in.shop2020.metamodel.jaxb.core.DatatypeDefinitionType;
import in.shop2020.metamodel.jaxb.core.DefinitionType;
import in.shop2020.metamodel.jaxb.core.EditorialImportanceType;
import in.shop2020.metamodel.jaxb.core.EnumDefinitionType;
import in.shop2020.metamodel.jaxb.core.EnumValueType;
import in.shop2020.metamodel.jaxb.core.FeatureDefinitionType;
import in.shop2020.metamodel.jaxb.core.SlideDefinitionType;
import in.shop2020.metamodel.jaxb.core.SlideFeatureDefinitionType;
import in.shop2020.metamodel.jaxb.core.UnitType;
import in.shop2020.metamodel.jaxb.facets.CategoryFacetDefinitionType;
import in.shop2020.metamodel.jaxb.facets.FacetDefinitionType;
import in.shop2020.metamodel.jaxb.facets.FacetRuleDefinitionType;
import in.shop2020.metamodel.jaxb.facets.IRDefinitionType;
import in.shop2020.metamodel.jaxb.facets.RuleDefinitionType;
import in.shop2020.util.DBUtils;
import in.shop2020.util.Utils;

import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Unmarshaller;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;

/**
 * Command line utility that imports model properties defined in XML
 * 
 * MM - Meta-Model Tool
 * 
 * It can be used to do following things
 * 
 * - Import
 *       - Datatype definitions
 *       - Feature definitions
 *       - Slide definitions
 *       - Categories
 *   - Facet Definition
 *   - Category Facet Definition
 *   - IR Data Rules
 *   - IR Meta-data Rules
 *   - Comparison Rules
 *   - Comparison Definitions
 *   - Comparison Buckets
 *   - Normalization Rules
 *   - Category Slide Sequence
 * 
 * - Show
 *       - Datatype definitions
 *       - Feature definitions
 *       - Slide definitions
 *       - Categories
 *   - Facet Definition
 *   - Category Facet Definition
 *   - IR Data Rules
 *   - IR Meta-data Rules
 *   - Comparison Rules
 *   - Comparison Definitions
 *   - Comparison Buckets
 *   - Normalization Rules
 *   - Category Slide Sequence
 * 
 * - Show all definition objects that define a category 
 * 
 * 
 * @author naveen
 *
 */
public class MM {
        
        /**
         * 
         */
        private String definitionSetName;
        
        /**
         * 
         */
        private String srcFile;
        
        /**
         * 
         */
        private String dbFile;
        
        /**
         * Usage: MM [show|import|showcategory] [units|datatypedefinitions|
         * featuredefinitions|slidedefinitions|categories|facetdefinitions|
         * categoryfacetdefinitions|irdatarules|irmetadatarules|comparisonrules|
         * comparisondefinitions|comparisonbuckets|normalizationrules|
         * categoryslidesequence] {Category ID}
         * 
         * @param args
         */
        public static void main(String[] args) throws Exception {
                String[] definitionSetNames = new String[] {"units", 
                                "datatypedefinitions", "featuredefinitions", "slidedefinitions", 
                                "categories", "facetdefinitions", "categoryfacetdefinitions", 
                                "irdatarules", "irmetadatarules", "comparisonrules", 
                                "comparisondefinitions", "comparisonbuckets", 
                                "normalizationrules", "categoryslidesequence"};
                
                String[] commands = new String[] {"show", "import", "showcategory"};

                String usage = "Usage: MM ["+ StringUtils.join(commands, "|") +"] ["+ 
                        StringUtils.join(definitionSetNames, "|") + "] {Category ID}";
                
                if(args.length < 2) {
                        System.out.println(usage);
                        System.exit(-1);
                }
                Utils.info("MM "+ args[0] + " " + args[1]);
                
                String inputCommand = args[0];
                
                if(!ArrayUtils.contains(commands, inputCommand)) {
                        System.out.println(usage);
                        System.exit(-1);
                }
                
                if(inputCommand.equals("show") || inputCommand.endsWith("import")) {
                        String inputDefinitionSet = args[1];
                        if(!ArrayUtils.contains(definitionSetNames, inputDefinitionSet)) {
                                System.out.println(usage);
                                System.exit(-1);
                        }
                        
                        MM mm = new MM(inputDefinitionSet);
                        if(inputCommand.equals("import")) {
                                mm.importDefinitionSet();
                        }
                        else if(inputCommand.equals("show")) {
                                mm.showDefinitionSet();
                        }
                }
                
                if(inputCommand.equals("showcategory")) {
                        String categoryID = args[1];
                        long catID = 0;
                        try {
                                catID = Long.parseLong(categoryID);
                        } 
                        catch (NumberFormatException nfe) {
                                System.out.println("Invalid category ID");
                                System.exit(-1);
                        }
                        
                        MM mm = new MM();
                        mm.showCategory(catID);
                }
        }
        
        /**
         * 
         */
        public MM() {
        }
        
        /**
         * 
         * @param definitionSet
         */
        public MM(String definitionSetName) {
                this.definitionSetName = definitionSetName;
                this.srcFile = Utils.DEFINITIONS_SRC_PATH + this.definitionSetName + 
                        ".xml";
                
                this.dbFile = Utils.CONTENT_DB_PATH + "definitions" + File.separator + this.definitionSetName + ".ser";
        }
        
        /**
         * 
         * @param categoryID
         * @throws Exception 
         */
        public void showCategory(long categoryID) throws Exception {
                DefinitionsContainer defs = 
                        Catalog.getInstance().getDefinitionsContainer();
                
                ExpandedCategory expCategory = defs.getExpandedCategory(categoryID);
                
                Utils.info(expCategory);
        }
        
        /**
         * 
         */
        @SuppressWarnings("unchecked")
        public void importDefinitionSet() throws Exception {
                String type = "core";
                if(this.definitionSetName.equals("facetdefinitions") || 
                                this.definitionSetName.equals("categoryfacetdefinitions") ||
                                this.definitionSetName.equals("irdatarules") || 
                                                this.definitionSetName.equals("irmetadatarules") ||
                                                this.definitionSetName.equals("normalizationrules")) {
                        type = "facets";
                }
                else if(this.definitionSetName.equals("comparisonrules") || 
                                this.definitionSetName.equals("comparisondefinitions") ||
                                this.definitionSetName.equals("comparisonbuckets")) {
                        type = "comparison";
                }
                
                Object oDefType = this.unmarshallSrcFile(this.srcFile, type);
                DefinitionType defType = null;
                IRDefinitionType irDefType = null;
                CMPDefinitionType cmpDefType = null;
                
                if(type.equals("core")) {
                        defType = (DefinitionType)oDefType;
                } 
                else if (type.equals("facets")) {
                        irDefType = (IRDefinitionType)oDefType;
                }
                else if (type.equals("comparison")) {
                        cmpDefType = (CMPDefinitionType)oDefType;
                }
                
                Object objectToStore = null;
                
                // CORE
                
                // Units
                if(this.definitionSetName.equals("units")) {
                        Map unitsMap = this.convertUnits(defType);
                        objectToStore = unitsMap;
                }
                
                // Categories
                else if(this.definitionSetName.equals("categories")) {
                        Map<Long, Category> categoriesMap = new HashMap<Long, Category>();
                        Category root = this.convertCategories(defType, categoriesMap);
                        //Utils.info(categoriesMap);
                        //Utils.info(root);
                        //System.exit(0);
                        
                        // Tree
                        String categoryTreeDBFile = Utils.CONTENT_DB_PATH + "definitions" + File.separator + 
                                "categorytree.ser";
                        
                        if(root != null) {
                                DBUtils.store(root, categoryTreeDBFile);
                        }
                        
                        // Map
                        objectToStore = categoriesMap;
                }
                
                // Datatype Definitions
                else if(this.definitionSetName.equals("datatypedefinitions")) {
                        Map<Long, DatatypeDefinition> datatypeDefsMap = 
                                this.convertDatatypeDefinition(defType);
                        
                        // Store enum value id to value map separately
                        String enumValueDBFile = Utils.CONTENT_DB_PATH + "definitions" + File.separator  + "enumvalues" + 
                                ".ser";
                        
                        // RE-VISIT - May not be optimal
                        Map<Long, EnumValue> enumValuesMap = new TreeMap<Long, EnumValue>();
                        for(Long datatypeDefID : datatypeDefsMap.keySet()) {
                                DatatypeDefinition datatypeDef = 
                                        datatypeDefsMap.get(datatypeDefID);
                                
                                if(datatypeDef instanceof EnumDefinition) {
                                        List<EnumValue> enumValues = 
                                                ((EnumDefinition) datatypeDef).getEnumValues();
                                        
                                        for(EnumValue enumValue : enumValues) {
                                                enumValuesMap.put(new Long(enumValue.getID()), 
                                                                enumValue);
                                        }
                                }
                        }
                        Utils.info("enumValuesMap=" + enumValuesMap);
                        DBUtils.store(enumValuesMap, enumValueDBFile);
                        
                        objectToStore = datatypeDefsMap;
                }
                
                // Feature Definitions
                else if(this.definitionSetName.equals("featuredefinitions")) {
                        Map featureDefsMap = this.convertFeatureDefinitions(defType);

                        objectToStore = featureDefsMap;
                }
                
                // Slide Definitions
                else if(this.definitionSetName.equals("slidedefinitions")) {
                        Map slideDefsMap = this.convertSlideDefinitions(defType);

                        objectToStore = slideDefsMap;
                }
                
                // Category slide sequence
                else if(this.definitionSetName.equals("categoryslidesequence")) {
                        Map categorySlideSequenceMap = this.convertCategorySlideSequence(
                                        defType);
                        
                        objectToStore = categorySlideSequenceMap;
                }
                
                // FACETS
                
                // Facet Definitions
                else if(this.definitionSetName.equals("facetdefinitions")) {
                        Map facetDefsMap = this.convertFacetDefinitions(irDefType);

                        objectToStore = facetDefsMap;
                }

                
                // Category Facet Definitions
                else if(this.definitionSetName.equals("categoryfacetdefinitions")) {
                        Map categoryFacetDefsMap = 
                                this.convertCategoryFacetDefinitions(irDefType);

                        objectToStore = categoryFacetDefsMap;
                }
                
                // IR Data Rules
                else if(this.definitionSetName.equals("irdatarules")) {
                        Map irdataRuleDefsMap = 
                                this.convertRuleDefinitions(irDefType);

                        objectToStore = irdataRuleDefsMap;
                }
                
                // IR Meta-Data Rules
                else if(this.definitionSetName.equals("irmetadatarules")) {
                        Map irmetadataRuleDefsMap = 
                                this.convertRuleDefinitions(irDefType);

                        objectToStore = irmetadataRuleDefsMap;
                }
                
                // Comparison Rules
                else if(this.definitionSetName.equals("comparisonrules")) {
                        Map comparisonRuleDefsMap = 
                                this.convertComparisonRuleDefinitions(cmpDefType);

                        objectToStore = comparisonRuleDefsMap;
                }
                
                // Comparison Definitions
                else if(this.definitionSetName.equals("comparisondefinitions")) {
                        Map cmpDefsMap = 
                                this.convertComparisonDefinitions(cmpDefType);

                        objectToStore = cmpDefsMap;
                }
                
                // Comparison Buckets
                else if(this.definitionSetName.equals("comparisonbuckets")) {
                        Map cmpBucketsMap = 
                                this.convertComparisonBuckets(cmpDefType);

                        objectToStore = cmpBucketsMap;
                }
                
                // Normalization rules
                else if(this.definitionSetName.equals("normalizationrules")) {
                        Map normalizationRuleDefsMap = 
                                this.convertNormalizationRuleDefinitions(irDefType);

                        objectToStore = normalizationRuleDefsMap;
                }
                
                if(objectToStore != null) {
                        DBUtils.store(objectToStore, this.dbFile);
                }
        }
        
        /**
         * 
         * @param defType
         * @return
         */
        private Map<Long, List<Long>> convertCategorySlideSequence(
                        DefinitionType defType) {
                Map<Long, List<Long>> catSlideSeq = new HashMap<Long, List<Long>>();
                
                List<CategorySlideSequenceType> jaxbCatSlideSeqs = 
                        defType.getCategorySlideSequence();
                
                for(CategorySlideSequenceType jaxbCatSlideSeq : jaxbCatSlideSeqs) {
                        long catID = jaxbCatSlideSeq.getCategoryID();
                        List<Long> slideDefIDs = jaxbCatSlideSeq.getSlideDefinitionID();
                        
                        Long lCatID = new Long(catID);
                        catSlideSeq.put(lCatID, slideDefIDs);
                }
                
                return catSlideSeq;
        }

        /**
         * 
         * @param irDefType
         * @return
         */
        private Map<Long, RuleDefinition> convertNormalizationRuleDefinitions(
                        IRDefinitionType defType) {
                
                Map<Long, RuleDefinition> idRuleDef = 
                        new TreeMap<Long, RuleDefinition>();
                
                List<RuleDefinitionType> jaxbRuleDefs = defType.getRuleDefinition();
                
                for(RuleDefinitionType jaxbRuleDef : jaxbRuleDefs) {
                        long id = jaxbRuleDef.getID();
                        String script = jaxbRuleDef.getScript();
                        
                        RuleDefinition ruleDef = new RuleDefinition(id, script);
                        ruleDef.setDescription(jaxbRuleDef.getDescription());
                        
                        idRuleDef.put(new Long(id), ruleDef);
                }
                
                Utils.info("idRuleDef=" + idRuleDef);
                
                return idRuleDef;
        }

        /**
         * 
         */
        public void showDefinitionSet() throws Exception {
                Object obj = DBUtils.read(this.dbFile);
                Utils.info(obj.toString());
                
                if(this.definitionSetName.equals("categories")) {
                        String categoryTreeDBFile = Utils.CONTENT_DB_PATH + "definitions" + File.separator + 
                                "categorytree" + ".ser";
                        
                        Category root = (Category)DBUtils.read(categoryTreeDBFile);
                        Utils.info(root.toString());
                        //Utils.info("root.getChildrenCategory().size: " + 
                        //              root.getChildrenCategory().size());
                }
        }
        
        /**
         * 
         * @param defType
         * @return
         */
        private Map<Long, RuleDefinition> convertRuleDefinitions(
                        IRDefinitionType defType) {
                Map<Long, RuleDefinition> idRuleDef = 
                        new TreeMap<Long, RuleDefinition>();
                
                List<RuleDefinitionType> jaxbRuleDefs = defType.getRuleDefinition();
                
                for(RuleDefinitionType jaxbRuleDef : jaxbRuleDefs) {
                        long id = jaxbRuleDef.getID();
                        String script = jaxbRuleDef.getScript();
                        
                        RuleDefinition ruleDef = new RuleDefinition(id, script);
                        ruleDef.setDescription(jaxbRuleDef.getDescription());
                        
                        idRuleDef.put(new Long(id), ruleDef);
                }
                
                Utils.info("idRuleDef=" + idRuleDef);
                return idRuleDef;
        }
        
        /**
         * 
         * @param defType
         * @return Map<Long, CMPRuleDefinition>
         */
        private Map<Long, CMPRuleDefinition> convertComparisonRuleDefinitions(
                        CMPDefinitionType defType) {
                Map<Long, CMPRuleDefinition> idRuleDef = 
                        new TreeMap<Long, CMPRuleDefinition>();
                
                List<CMPRuleDefinitionType> jaxbRuleDefs = 
                        defType.getCMPRuleDefinition();
                
                for(CMPRuleDefinitionType jaxbRuleDef : jaxbRuleDefs) {
                        long id = jaxbRuleDef.getID();
                        String script = jaxbRuleDef.getScript();
                        
                        CMPRuleDefinition ruleDef = new CMPRuleDefinition(id, script);
                        ruleDef.setDescription(jaxbRuleDef.getDescription());
                        
                        idRuleDef.put(new Long(id), ruleDef);
                }
                
                Utils.info("idRuleDef=" + idRuleDef);
                return idRuleDef;
        }
        
        /**
         * 
         * @param defType
         * @return Map<Long, CMPSlideRuleDefinition> 
         */
        private Map<Long, CMPSlideRuleDefinition> convertComparisonDefinitions(
                        CMPDefinitionType defType) {
                
                Map<Long, CMPSlideRuleDefinition> slideRuleDefs = 
                        new TreeMap<Long, CMPSlideRuleDefinition>();
                
                List<CMPSlideRuleDefinitionType> jaxbDefs = 
                        defType.getCMPSlideRuleDefinition();
                
                for(CMPSlideRuleDefinitionType jaxbDef : jaxbDefs) {
                        long ruleDefID = jaxbDef.getRuleDefinitionID();
                        long slideDefID = jaxbDef.getSlideDefinitionID();
                        
                        CMPSlideRuleDefinition slideRuleDef = 
                                new CMPSlideRuleDefinition(slideDefID, ruleDefID);
                        
                        slideRuleDef.setDescription(jaxbDef.getDescription());
                        
                        slideRuleDefs.put(new Long(slideDefID), slideRuleDef);
                }
                
                Utils.info("slideRuleDefs=" + slideRuleDefs);
                return slideRuleDefs;
        }
        
        /**
         * 
         * @param defType
         * @return
         */
        private Map<Long, List<CMPBucketDefinition>> convertComparisonBuckets(
                        CMPDefinitionType defType) {
                
                Map<Long, List<CMPBucketDefinition>> cmpBuckets = 
                        new HashMap<Long, List<CMPBucketDefinition>>();
                
                List<CMPBucketDefinitionType> jaxbBuckets = 
                        defType.getCMPBucketDefinition();
                
                for(CMPBucketDefinitionType jaxbBucket : jaxbBuckets) {
                        String name = jaxbBucket.getName();
                        long categoryID = jaxbBucket.getCategoryID();
                        
                        CMPBucketDefinition bucketDef = 
                                new CMPBucketDefinition(name, categoryID);
                        
                        bucketDef.setDescription(jaxbBucket.getDescription());
                        bucketDef.setDefaultWeight(
                                        jaxbBucket.getDefaultWeight().intValue());
                        bucketDef.setSlideDefinitionIDs(jaxbBucket.getSlideDefinitionID());
                        
                        List<CMPBucketDefinition> categoryBuckets = 
                                cmpBuckets.get(new Long(categoryID));
                        
                        if(categoryBuckets == null) {
                                categoryBuckets = new ArrayList<CMPBucketDefinition>();
                                cmpBuckets.put(new Long(categoryID), categoryBuckets);
                        }
                        
                        categoryBuckets.add(bucketDef);
                }
                Utils.info("cmpBuckets=" + cmpBuckets);
                
                return cmpBuckets;
        }
        
        /**
         * 
         * @param defType
         * @return
         */
        private Map<Long, FacetDefinition> convertFacetDefinitions(
                        IRDefinitionType defType) {
                List<FacetDefinitionType> jaxbFacetDefs = defType.getFacetDefinition();
                
                Map<Long, FacetDefinition> idFacetDefs = 
                        new TreeMap<Long, FacetDefinition>();
                
                for(FacetDefinitionType jaxbFacetDef : jaxbFacetDefs) {
                        long id = jaxbFacetDef.getID();
                        String target = jaxbFacetDef.getTarget();

                        FacetDefinition facetDef = new FacetDefinition(id, target);
                        
                        if(jaxbFacetDef.getFeatureDefinitionID() != null) {
                                long featureDefID = jaxbFacetDef.getFeatureDefinitionID();
                                facetDef.setFeatureDefinitionID(featureDefID);
                        }
                        
                        if(jaxbFacetDef.getSlideDefinitionID() != null) {
                                long slideDefID = jaxbFacetDef.getSlideDefinitionID();
                                facetDef.setSlideDefinitionID(slideDefID);
                        }
                        
                        long irMetaDataRuleID = jaxbFacetDef.getIRMetaDataRuleID();
                        facetDef.setIrMetaDataRuleID(irMetaDataRuleID);
                        
                        facetDef.setDescription(jaxbFacetDef.getDescription());
                        
                        idFacetDefs.put(new Long(id), facetDef);
                }
                Utils.info("idFacetDefs=" + idFacetDefs);
                return idFacetDefs;
        }
        
        /**
         * 
         * @param defType
         * @return
         * @throws Exception 
         */
        private Map<Long, CategoryFacetDefinition> convertCategoryFacetDefinitions(
                        IRDefinitionType defType) throws Exception {
                List<CategoryFacetDefinitionType> jaxbCategoryFacetDefs = 
                        defType.getCategoryFacetDefinition();
                
                Map<Long, CategoryFacetDefinition> idCategoryFacetDefs = 
                        new TreeMap<Long, CategoryFacetDefinition>();
                
                for(CategoryFacetDefinitionType jaxbCategoryFacetDef : 
                        jaxbCategoryFacetDefs) {
                        long categoryID = jaxbCategoryFacetDef.getCategoryID();
                        
                        CategoryFacetDefinition categoryFacetDef = 
                                new CategoryFacetDefinition(categoryID);
                        
                        List<FacetRuleDefinitionType> jaxbFacetRuleDefs = 
                                        jaxbCategoryFacetDef.getFacetRuleDefinition();
                        
                        for(FacetRuleDefinitionType jaxbFacetRuleDef : jaxbFacetRuleDefs) {
                                
                                FacetRuleDefinition facetRuleDef = 
                                        this.convertFacetRuleDefinition(jaxbFacetRuleDef);
                                
                                categoryFacetDef.addFacetRuleDefinition(facetRuleDef);
                        }
                        
                        idCategoryFacetDefs.put(new Long(categoryID), categoryFacetDef);
                }
                
                // Append parent's facets 
                // Go only one level for now
                // Categories need to be imported first
                DefinitionsContainer defs = 
                        Catalog.getInstance().getDefinitionsContainer();
                
                for(Long categoryID : idCategoryFacetDefs.keySet()) {
                        Category category = defs.getCategory(categoryID.longValue());
                        Category parentCategory = category.getParentCategory();
                        
                        if(parentCategory != null) {
                                long parentCategoryID = parentCategory.getID();
                                
                                CategoryFacetDefinition parentCategoryFacetDef = 
                                        idCategoryFacetDefs.get(new Long(parentCategoryID));
                                
                                if(parentCategoryFacetDef != null) {
                                        List<FacetRuleDefinition> parentsFacetRuleDefs = 
                                                parentCategoryFacetDef.getFacetRuleDefinitions();
                                        
                                        if(parentsFacetRuleDefs != null) {
                                                CategoryFacetDefinition categoryFacetDef = 
                                                        idCategoryFacetDefs.get(categoryID);
                                                
                                                categoryFacetDef.appendFacetRuleDefinitions(
                                                                parentsFacetRuleDefs);
                                        }
                                }
                        }
                }
                
                Utils.info("idCategoryFacetDefs=" + idCategoryFacetDefs);
                return idCategoryFacetDefs;
        }
        
        /**
         * 
         * @param jaxbFacetRuleDef
         * @return
         */
        private FacetRuleDefinition convertFacetRuleDefinition(
                        FacetRuleDefinitionType jaxbFacetRuleDef) {
                long facetDefID = jaxbFacetRuleDef.getFacetDefinitionID();
                long irDataRuleID = jaxbFacetRuleDef.getIRDataRuleID();
                
                FacetRuleDefinition facetRuleDef = new FacetRuleDefinition(facetDefID, 
                                irDataRuleID);
                
                facetRuleDef.setDescription(jaxbFacetRuleDef.getDescription());
                
                if(jaxbFacetRuleDef.getFeatureDefinitionID() != null) {
                        facetRuleDef.setFeatureDefinitionID(
                                        jaxbFacetRuleDef.getFeatureDefinitionID().longValue());
                }
                
                if(jaxbFacetRuleDef.getSlideDefinitionID() != null) {
                        facetRuleDef.setSlideDefinitionID(
                                        jaxbFacetRuleDef.getSlideDefinitionID().longValue());
                }
                
                return facetRuleDef;
        }

        /**
         * 
         * @return Map
         */
        private Map<Long, SlideDefinition> convertSlideDefinitions(
                        DefinitionType defType) {
                
                Map<Long, SlideDefinition> defs = 
                        new HashMap<Long, SlideDefinition>();
                
                List<SlideDefinitionType> jaxbDefs = defType.getSlideDefinition();
                Iterator<SlideDefinitionType> itjaxbDefs = jaxbDefs.iterator();
                
                // Slide definitions
                while(itjaxbDefs.hasNext()) {
                        SlideDefinitionType jaxbDef = itjaxbDefs.next();
                        
                        Utils.info("Slide label=" + jaxbDef.getLabel());
                        SlideDefinition def = new SlideDefinition(jaxbDef.getID(),
                                        jaxbDef.getLabel());
                        def.setDescription(jaxbDef.getDescription());
                        
                        // Children Slides
                        Utils.info("jaxbDef.getChildSlideID=" + jaxbDef.getChildSlideID());
                        def.setChildrenSlideDefinitionIDs(jaxbDef.getChildSlideID());
                        
                        // Slide Feature Definition
                        List<SlideFeatureDefinitionType> jaxbSlideFeatureDefs = 
                                jaxbDef.getSlideFeatureDefinition();
                        
                        if(jaxbSlideFeatureDefs != null) {
                                def.setSlideFeatureDefinitions((
                                                this.convertSlideFeatureDefinitions(
                                                                jaxbSlideFeatureDefs)));
                        }
                        Utils.info("def=" + def);
                        
                        defs.put(new Long(jaxbDef.getID()), def);
                }
                        
                return defs;
        }
        
        /**
         * 
         * @param jaxbDefs
         * @return List<SlideFeatureDefinition>
         */
        private List<SlideFeatureDefinition> convertSlideFeatureDefinitions(
                        List<SlideFeatureDefinitionType> jaxbDefs) {
                
                List<SlideFeatureDefinition> defs = 
                        new ArrayList<SlideFeatureDefinition>();
                
                Iterator<SlideFeatureDefinitionType> itjaxbDefs = jaxbDefs.iterator();
                
                // Slide-feature definitions
                while(itjaxbDefs.hasNext()) {
                        SlideFeatureDefinitionType jaxbDef = itjaxbDefs.next();
                        SlideFeatureDefinition def = new SlideFeatureDefinition(
                                        jaxbDef.getFeatureDefinitionID());
                        
                        def.setEditorialImportance(this.convertEditorialImportance(
                                        jaxbDef.getEditorialImportance()));
                        
                        def.setDescription(jaxbDef.getDescription());
                        
                        defs.add(def);
                }
                
                return defs;
        }
        
        /**
         * 
         * @param defType
         * @return
         */
        private Map<Long, FeatureDefinition> convertFeatureDefinitions(
                        DefinitionType defType) {
                
                Map<Long, FeatureDefinition> defs = 
                        new HashMap<Long, FeatureDefinition>();
                
                List<FeatureDefinitionType> jaxbDefs = defType.getFeatureDefinition();
                Iterator<FeatureDefinitionType> itjaxbDefs = jaxbDefs.iterator();
                
                // Feature definitions
                while(itjaxbDefs.hasNext()) {
                        FeatureDefinitionType jaxbDef = itjaxbDefs.next();
                        
                        //Utils.info("Feature label=" + jaxbDef.getLabel());
                        FeatureDefinition def = new FeatureDefinition(jaxbDef.getID(),
                                        jaxbDef.getLabel());
                        def.setAllowsBlank(jaxbDef.isCanbeBlank());
                        def.setDescription(jaxbDef.getDescription());
                        
                        // Bullet Definition
                        BulletDefinitionType jaxbBulletDef = jaxbDef.getBulletDefinition();
                        if(jaxbBulletDef != null) {
                                def.setBulletDefinition(this.convertBulletDefinition(
                                                jaxbBulletDef));
                        }
                        
                        Long normRuleDefID = jaxbDef.getNormalizationRuleDefinitionID();
                        if(normRuleDefID != null) {
                                def.setNormalizationRuleDefinitionID(normRuleDefID.longValue());
                        }
                        Utils.info("def=" + def);
                        
                        defs.put(new Long(jaxbDef.getID()), def);
                }
                        
                return defs;
        }

        /**
         * 
         * @param jaxbDef BulletDefinitionType
         * @return BulletDefinition
         */
        private BulletDefinition convertBulletDefinition(
                        BulletDefinitionType jaxbDef) {
                
                BulletDefinition def = new BulletDefinition(
                                jaxbDef.getDatatypeDefinitionID());
                
                List<Long> unitIDs = jaxbDef.getUnitID();
                if(unitIDs != null && !unitIDs.isEmpty()) {
                        def.setUnitIDs(unitIDs);
                }
                Utils.info("jaxbDef.isIsMultivalue=" + jaxbDef.isIsMultivalue());
                
                def.setMultivalue(jaxbDef.isIsMultivalue());
                def.setLearned(jaxbDef.isIsLearned());
                def.setDescription(jaxbDef.getDescription());
                
                return def;
        }

        /**
         * 
         * @param defType
         * @return
         */
        private Map<Long, DatatypeDefinition> convertDatatypeDefinition(
                        DefinitionType defType) {
                
                Map<Long, DatatypeDefinition> defs = 
                        new HashMap<Long, DatatypeDefinition>();
                
                List<DatatypeDefinitionType> jaxbDefs = defType.getDatatypeDefinition();
                Iterator<DatatypeDefinitionType> it = jaxbDefs.iterator();
                
                while(it.hasNext()) {
                        DatatypeDefinitionType jaxbDef = it.next();
                        
                        DatatypeDefinition def = null;
                        CompositeDefinitionType compositeDefType = 
                                jaxbDef.getCompositeDefinition();

                        EnumDefinitionType enumDefType = 
                                jaxbDef.getEnumDefinition();
                        
                        // Composite data type
                        if(compositeDefType != null) {
                                CompositeDefinition compDef = new CompositeDefinition(
                                                jaxbDef.getID(), jaxbDef.getName(), 
                                                compositeDefType.getSeparator());
                                
                                List<CompositePartDefinitionType> jaxbPartDefs = 
                                        compositeDefType.getCompositePartDefinition();
                                
                                Iterator<CompositePartDefinitionType> itPartDefs = 
                                        jaxbPartDefs.iterator();
                                
                                // Collect parts
                                while(itPartDefs.hasNext()) {
                                        CompositePartDefinitionType jaxbPartDef = itPartDefs.next();
                                        CompositePartDefinition partDef = 
                                                this.convertCompositePartDefinition(jaxbPartDef);
                                        
                                        compDef.addCompositePartDefinition(partDef);
                                }
                                
                                def = compDef;
                        }
                        
                        // Enumerated values
                        else if(enumDefType != null) {
                                EnumDefinition enumDef = new EnumDefinition(jaxbDef.getID(), 
                                                jaxbDef.getName());
                                
                                List<EnumValueType> jaxbEnumValues = 
                                        enumDefType.getEnumValue();
                                        
                                Iterator<EnumValueType> itEnumValues = 
                                        jaxbEnumValues.iterator();
                                
                                // Collect individual value
                                while(itEnumValues.hasNext()) {
                                        EnumValueType jaxbEnumValue = itEnumValues.next();
                                        EnumValue enumValue = 
                                                this.convertEnumValueDefinition(jaxbEnumValue);
                                        
                                        enumDef.addEnumValue(enumValue);
                                }
                                
                                def = enumDef;
                        }
                        
                        // Primitive
                        else {
                                def = new DatatypeDefinition(jaxbDef.getID(), 
                                                jaxbDef.getName());
                        }
                        
                        def.setDescription(jaxbDef.getDescription());
                        Utils.info("def=" + def);
                        
                        defs.put(new Long(jaxbDef.getID()), def);
                }
                
                return defs;
        }

        /**
         * 
         * @param jaxbEnumValue
         * @return EnumValue
         */
        private EnumValue convertEnumValueDefinition(EnumValueType jaxbEnumValue) {
                
                EnumValue enumValue = new EnumValue(jaxbEnumValue.getID(), 
                                jaxbEnumValue.getValue());

                return enumValue;
        }
        /**
         * 
         * @param jaxbPartDef
         * @return CompositePartDefinition
         */
        private CompositePartDefinition convertCompositePartDefinition(
                        CompositePartDefinitionType jaxbPartDef) {
                
                CompositePartDefinition partDef = new CompositePartDefinition(
                                jaxbPartDef.getLabel(), jaxbPartDef.getDatatypeDefinitionID(), 
                                jaxbPartDef.getUnitID());
                
                partDef.setDescription(jaxbPartDef.getDescription());
                
                return partDef;
        }

        /**
         * 
         * @param defType
         * @param catMap
         * @return
         */
        private Category convertCategories(DefinitionType defType, 
                        Map<Long, Category> catMap) {
                
                List<CategoryType> jaxbCats = defType.getCategory();
                Iterator<CategoryType> it = jaxbCats.iterator();
                
                // Get root category
                CategoryType jaxbCat = it.next();
                if(jaxbCat == null) {
                        Utils.info("Invalid file: " + this.srcFile);
                        return null;
                }
                
                Category root = this.convertCategoryType(jaxbCat, null, catMap);
                Utils.info("catMap.get(10002)=" + catMap.get(new Long(10002)));
                
                return root;
        }
        
        /**
         * 
         * @param jaxbCat
         * @param parentCat
         * @param catMap
         * @return
         */
        @SuppressWarnings("unchecked")
        private Category convertCategoryType(CategoryType jaxbCat, 
                        Category parentCat, Map<Long, Category> catMap) {
                
                Category cat = new Category(jaxbCat.getID());
                cat.setLabel(jaxbCat.getName());
                cat.setDescription(jaxbCat.getDescription());
                if(parentCat != null) {
                        cat.setParentCategory(parentCat);
                        
                        // Copy parent's category-slide definitions
                        ArrayList<CategorySlideDefinition> parentCSDef = 
                                (ArrayList<CategorySlideDefinition>) 
                                parentCat.getCategorySlideDefintions();
                        
                        if(parentCSDef != null) {
                                cat.setCategorySlideDefintions(
                                        (List<CategorySlideDefinition>) parentCSDef.clone());
                        }
                }
                
                // Category Slide Definition
                List<CategorySlideDefinitionType> jaxbDefs = 
                        jaxbCat.getCategorySlideDefinition();
                
                Iterator<CategorySlideDefinitionType> it = jaxbDefs.iterator();
                while(it.hasNext()) {
                        CategorySlideDefinitionType jaxbDef = it.next();
                        CategorySlideDefinition catSlideDef 
                        = this.convertCategorySlideDefinitionType(jaxbCat.getID(), jaxbDef);
                        
                        cat.addCategorySlideDefintion(catSlideDef);
                }
                
                // Children
                List<CategoryType> jaxbChildren = jaxbCat.getChildCategory();
                //Utils.info("jaxbChildren.size: " + jaxbChildren.size());
                
                Iterator<CategoryType> itChildren = jaxbChildren.iterator();
                while(itChildren.hasNext()) {
                        CategoryType jaxbChildCat = itChildren.next();
                        Category childCat = this.convertCategoryType(jaxbChildCat, cat, 
                                        catMap);
                        cat.addChild(childCat);
                }
                //Utils.info("Parent cat: " + cat);
                // DEBUG ONLY
                Utils.info("####### Cat ID: " + cat.getID());
                if(cat.getCategorySlideDefintions() != null) {
                        for(CategorySlideDefinition csd : cat.getCategorySlideDefintions()){
                                Utils.info("####### SlideDefintionID=" + 
                                                csd.getSlideDefintionID());
                        }
                }
                
                catMap.put(new Long(jaxbCat.getID()), cat);
                return cat;
        }
        
        /**
         * 
         * @param categoryID
         * @param jaxbDef
         * @return
         */
        private CategorySlideDefinition convertCategorySlideDefinitionType(
                        long categoryID, CategorySlideDefinitionType jaxbDef) {
                
                CategorySlideDefinition catSlideDef = new CategorySlideDefinition(
                                jaxbDef.getSlideDefinitionID());
                
                catSlideDef.setDescription(jaxbDef.getDescription());
                
                EditorialImportanceType jaxbEdImp = jaxbDef.getEditorialImportance();
                EditorialImportance edImp = this.convertEditorialImportance(jaxbEdImp);
                catSlideDef.setEditorialImportance(edImp);
                
                return catSlideDef;
        }
        
        /**
         * 
         * @return Map
         */
        private Map<Long, Unit> convertUnits(DefinitionType defType) {
                
                Map<Long, Unit> allUnits = new HashMap<Long, Unit>();
                List<UnitType> jaxbUnits = defType.getUnit();
                Iterator<UnitType> it = jaxbUnits.iterator();
                
                while(it.hasNext()) {
                        UnitType jaxbUnit = it.next();
                        
                        Unit unit = new Unit(jaxbUnit.getID());
                        unit.setDescription(jaxbUnit.getDescription());
                        unit.setFullForm(jaxbUnit.getFullform());
                        unit.setShortForm(jaxbUnit.getShortform());
                        Utils.info("unit=" + unit);
                        
                        allUnits.put(new Long(jaxbUnit.getID()), unit);
                }
                
                return allUnits;
        }

        /**
         * 
         * @param srcFile
         * @return
         * @throws Exception
         */
        private Object unmarshallSrcFile(String srcFile, String type) 
                throws Exception {
                
        JAXBContext jc = JAXBContext.newInstance("in.shop2020.metamodel.jaxb." +
                        type);
        
        // create an Unmarshaller
        Unmarshaller u = jc.createUnmarshaller();
        
        JAXBElement<?> element = (JAXBElement<?>)u.unmarshal(
                        new FileInputStream(srcFile));
        
        return element.getValue();
        }
        
        /**
         * 
         * @param jaxbEdImp
         * @return EditorialImportance
         */
        private EditorialImportance convertEditorialImportance(
                        EditorialImportanceType jaxbEdImp) {
                
                String strEdImp = jaxbEdImp.value();
                EditorialImportance edImp = null;
                
                if(strEdImp.equals("Mandatory"))
                        edImp = EditorialImportance.MANDATORY;
                else if(strEdImp.equals("Optional"))
                        edImp = EditorialImportance.OPTIONAL;
                else 
                        edImp = EditorialImportance.RECOMMENDED;
                
                return edImp;
        }
}