org.newcashel.meta.model.NCClass.java Source code

Java tutorial

Introduction

Here is the source code for org.newcashel.meta.model.NCClass.java

Source

/*
 * Licensed to NewCashel under one or more contributor
 * license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright
 * ownership. NewCashel licenses this file to you under
 * the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.newcashel.meta.model;

import java.io.Serializable;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
//import org.newcashel.service.ElasticQuery;
import org.newcashel.meta.util.POIUtil;
import org.newcashel.meta.util.UTIL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.annotation.JsonIgnore;

public class NCClass implements Serializable {

    private static final int CLASSNAME_OFFSET = 0;
    private static final int SUPERCLASS_NAME_OFFSET = 1;
    private static final int PARENTCLASS_OFFSET = 2;
    private static final int PRIMARYKEY_OFFSET = 3;
    private static final int PERCOLATE_OFFSET = 4;
    private static final int GROUP_CONSTRAIN_OFFSET = 5;
    private static final int ATTRIBUTE_OFFSET = 6;
    private static final int TYPE_OFFSET = 7;
    private static final int VERSION_OFFSET = 8;
    private static final int LABEL_OFFSET = 9;
    private static final int INDEXNAME_OFFSET = 10;
    private static final int STORE_OFFSET = 11;
    private static final int INDEX_OFFSET = 12;
    private static final int INCLUDEINALL_OFFSET = 13;
    private static final int PRECISIONSTEP_OFFSET = 14;
    private static final int DATEFORMAT_OFFSET = 15;
    private static final int FIELDDATAFORMAT_OFFSET = 16;
    private static final int DOCVALUES_OFFSET = 17;
    private static final int BOOST_OFFSET = 18;
    private static final int NULLVALUE_OFFSET = 19;
    private static final int TERMVECTOR_OFFSET = 20;
    private static final int ANALYZER_OFFSET = 21;
    private static final int INDEX_ANALYZER_OFFSET = 22;
    private static final int SEARCH_ANALYZER_OFFSET = 23;
    private static final int IGNOREABOVE_OFFSET = 24;
    private static final int POSITIONGAP_OFFSET = 25;
    private static final int IGNOREMALFORMED_OFFSET = 26;
    private static final int COERCENUMBER_OFFSET = 27;
    private static final int BINARYCOMPRESS_OFFSET = 28;
    private static final int COMPRESSTHRESHOLD_OFFSET = 29;
    private static final int JAVA_CLASS_OFFSET = 30;

    //private static final long serialVersionUID = -6881574265686003184L;
    private static final Logger logger = LoggerFactory.getLogger(NCClass.class);

    private static HashMap<String, NCClass> classes = new HashMap<String, NCClass>();

    // used to access the sub class when serializing JSON (key is the field collection name)
    private static HashMap<String, String> subTypes = new HashMap<String, String>();

    private HashMap<String, Attribute> attributes = new HashMap<String, Attribute>();

    // key is the label (must be unique per class), return attribute
    private HashMap<String, Attribute> labels = new HashMap<String, Attribute>();

    //private ArrayList<String> indexes = new ArrayList<String>(2);
    private ElasticAlias assignedIndexAlias; // assigned at runtime based on MetaBook config (mode, version)

    private String className;
    private String classParent;

    @JsonIgnore()
    private NCClass superClass;

    private String superClassName;
    private String javaClassName;
    private String primaryKey;
    private boolean percolate; // if true, ES add/update will follow up on perq triggers
    private boolean groupConstrain; // if true, user's assigned groups will be used to constrain search results

    public NCClass() {
    }

    public static HashMap<String, NCClass> getNCClasses() {
        return classes;
    };

    public static NCClass getNCClass(String key) {
        return classes.get(key);
    }

    public static NCClass getSubClass(String key) {
        String className = subTypes.get(key);
        return getNCClass(className);
    }

    public NCClass getSuperClass() {
        if (superClass == null) {
            if (superClassName == null)
                return null; // no super class
            this.superClass = getNCClass(getSuperClassName());
            if (superClass == null) {
                logger.debug("no super class for " + getClassName());
            }
        }
        return superClass;
    }

    public Attribute getAttribute(String key) {
        Attribute atb = attributes.get(key);
        if (atb != null)
            return atb;
        NCClass superCls = getSuperClass();
        if (superCls != null)
            return superCls.attributes.get(key);
        return null;
    }

    public String getAggregationTag(String atbStr) throws Exception {
        Attribute atb = getAttribute(atbStr);
        if (atb == null) {
            throw new Exception("invalid atb, cannot create aggregation tag " + atbStr);
        }
        return getClassName() + "_" + atbStr;
    }

    public HashMap<String, Attribute> getSuperAttributes() {
        NCClass superClass = getSuperClass();
        if (superClass != null)
            return superClass.getAttributes();
        return null;
    }

    public HashMap<String, Attribute> getAttributes() {
        return attributes;
    }

    public Attribute getAttributeByLabel(String key) {
        return labels.get(key);
    }

    public static String getElasticMeta(String className) throws Exception {
        NCClass ncCls = getNCClass(className);
        if (ncCls == null) {
            throw new Exception("Attempt to build an Elastic Type without any definition for " + className);
        }
        return null;
    }

    public static void load(HSSFWorkbook wb, LaunchParms launchParm) throws Exception {

        // load the sheet
        Sheet sheet = wb.getSheet("ClassAttributes");
        if (sheet == null) {
            throw new Exception("The ClassAttributes sheet was not found in the MetaBook, terminate load process");
        }

        //String[] fieldNames = POIUtil.getFirstRowVals(sheet);

        Class cls = Class.forName("org.newcashel.meta.model.NCClass");
        Class[] parmString = new Class[1];

        Row row = null;

        try {

            for (int i = 1; i <= sheet.getLastRowNum(); i++) {
                // skip blank rows between class attributes
                row = sheet.getRow(i);

                if (row != null && (POIUtil.getCellValue(row, ATTRIBUTE_OFFSET) == null
                        || POIUtil.getCellValue(row, TYPE_OFFSET).length() < 1))
                    continue;

                // get the size of the cell, the length will be the number of atbs in the class
                // determine if the next Cell to the left is a separate Cell or part of a CellRangeAddress
                Cell cell = row.getCell(0, Row.RETURN_BLANK_AS_NULL);
                if (cell == null) {
                    continue;
                }

                CellRangeAddress cra = getCellRangeAddress(sheet, row.getRowNum(), 0);
                if (cra == null) {
                    return;
                }

                // instantiate the NCClass instance
                NCClass ncClass = new NCClass();
                ncClass.setClassName(POIUtil.getCellValue(row, CLASSNAME_OFFSET));
                //logger.info("loading NCClass " + ncClass.getClassName());

                ncClass.setSuperClassName(POIUtil.getCellValue(row, SUPERCLASS_NAME_OFFSET));
                ncClass.setClassParent(POIUtil.getCellValue(row, PARENTCLASS_OFFSET));
                ncClass.setPrimaryKey(POIUtil.getCellValue(row, PRIMARYKEY_OFFSET));
                ncClass.setPercolate(new Boolean(POIUtil.getCellValue(row, PERCOLATE_OFFSET)));
                ncClass.setGroupConstrain(new Boolean(POIUtil.getCellValue(row, GROUP_CONSTRAIN_OFFSET)));

                // not throwing java class errors, may not be significant to load context

                // TODO, if NO_VERIFY_JAVA_CLASS is true, skip validation
                // TODO, if NO_VERF true and blank 

                String javaClassName = POIUtil.getCellValue(row, JAVA_CLASS_OFFSET);
                if (javaClassName.endsWith("Person.class")) {
                    System.out.println("OKK");
                }
                Class<?> javaCls = null;
                if (javaClassName != null && javaClassName.length() > 0) {
                    ncClass.setJavaClassName(javaClassName);
                    try {
                        javaCls = Class.forName(javaClassName);
                    } catch (Exception e) {
                        logger.error("Java class specified but cannot be loaded for " + ncClass.getClassName()
                                + ", " + javaClassName);
                    }
                } else {
                    logger.info("no java class specified for class " + ncClass.getClassName());
                }

                classes.put(ncClass.getClassName(), ncClass);
                logger.info("Adding class " + ncClass.getClassName());

                // loop for all the rows in the cell range
                for (i = cra.getFirstRow(); i <= cra.getLastRow(); i++) {
                    row = sheet.getRow(i);
                    if (row == null) {
                        return; // range iteration complete
                    }
                    cell = row.getCell(ATTRIBUTE_OFFSET, Row.RETURN_BLANK_AS_NULL);
                    if (cell == null)
                        continue;

                    String atbName = POIUtil.getCellValue(row, ATTRIBUTE_OFFSET);
                    String version = POIUtil.getCellValue(row, VERSION_OFFSET);

                    // if  no version id and the atb has not been set, then set it
                    // if a version and it matches the build version, set/overwrite the value 
                    Attribute atb = null;

                    // if version id is set and matches the launchParm setting, use it else skip 
                    // a non-versioned atb may be encountered first, reuse it if received a versioned one
                    if (version != null && version.length() > 0) {
                        if (!(launchParm.getVersion().equals(version))) {
                            continue;
                        }
                        logger.debug("add version specific atb " + ncClass.getClassName() + ", " + atbName + ", "
                                + version);
                        // if a default version has already been established, use it else create one
                        atb = ncClass.getAttribute(atbName);
                        if (atb == null) {
                            atb = new Attribute();
                        }
                    } else { // no version, use existing if already set to the current version
                        atb = ncClass.getAttribute(atbName);
                        if (atb == null) {
                            atb = new Attribute();
                        } else
                            continue; // already established a version specific atb, ignore non-versioned entry
                    }

                    // create the Attributes and add to the class instance
                    // TODO, verify not null on these required values, user may override Excel edits
                    atb.setName(POIUtil.getCellValue(row, ATTRIBUTE_OFFSET));
                    atb.setType(POIUtil.getCellValue(row, TYPE_OFFSET));
                    atb.setLabel(POIUtil.getCellValue(row, LABEL_OFFSET));
                    atb.setIndexName(POIUtil.getPopulatedCellValue(row, INDEXNAME_OFFSET));

                    //logger.info("added NCClass atb " + ncClass.getClassName() + ", " + atb.getName());

                    // defaults to false
                    atb.setStore(UTIL.convertBoolean(POIUtil.getCellValue(row, STORE_OFFSET)));
                    /*
                    String storeVal = POIUtil.getPopulatedCellValue(row, STORE_OFFSET);
                    if (storeVal != null) {
                       atb.setStore(new Boolean(storeVal));
                    }
                    */

                    // analyzed is default value, will tokenize field
                    String indexVal = POIUtil.getPopulatedCellValue(row, INDEX_OFFSET);
                    if (indexVal != null) {
                        atb.setIndex(indexVal);
                    }

                    // default is true, don't set unless value is not
                    String includeInAll = POIUtil.getPopulatedCellValue(row, INCLUDEINALL_OFFSET);
                    if (includeInAll != null && includeInAll.equalsIgnoreCase("no")) {
                        atb.setIncludeInAll(false);
                    }

                    // default varies, based on the numeric type
                    // TODO, verify numeric field
                    String precision = POIUtil.getPopulatedCellValue(row, PRECISIONSTEP_OFFSET);
                    if (precision != null) {
                        atb.setPrecision(new Integer(precision));
                    }

                    String dateFormat = POIUtil.getPopulatedCellValue(row, DATEFORMAT_OFFSET);
                    if (dateFormat != null) {
                        atb.setDateFormat(dateFormat);
                    }

                    String fieldDataFormat = POIUtil.getPopulatedCellValue(row, FIELDDATAFORMAT_OFFSET);
                    if (fieldDataFormat != null) {
                        atb.setFieldDataFormat(fieldDataFormat);
                    }

                    atb.setDocValues(UTIL.convertBoolean(POIUtil.getCellValue(row, DOCVALUES_OFFSET)));

                    String boost = POIUtil.getPopulatedCellValue(row, BOOST_OFFSET);
                    if (boost != null) {
                        atb.setBoost(new Double(boost));
                    }

                    // defaults to not adding the field to the JSON string
                    String nullVal = POIUtil.getPopulatedCellValue(row, NULLVALUE_OFFSET);
                    if (nullVal != null) {
                        atb.setNullValue(nullVal);
                    }

                    String termVector = POIUtil.getPopulatedCellValue(row, TERMVECTOR_OFFSET);
                    if (termVector != null) {
                        atb.setTermVector(termVector);
                    }

                    String analyzer = POIUtil.getPopulatedCellValue(row, ANALYZER_OFFSET);
                    if (analyzer != null) {
                        atb.setAnalyzer(analyzer);
                    }

                    String indexAnalyzer = POIUtil.getPopulatedCellValue(row, INDEX_ANALYZER_OFFSET);
                    if (indexAnalyzer != null) {
                        atb.setIndexAnalyzer(indexAnalyzer);
                    }

                    String searchAnalyzer = POIUtil.getPopulatedCellValue(row, SEARCH_ANALYZER_OFFSET);
                    if (searchAnalyzer != null) {
                        atb.setSearchAnalyzer(searchAnalyzer);
                    }

                    atb.setIgnoreAbove(UTIL.convertAnyNumberToInt(POIUtil.getCellValue(row, IGNOREABOVE_OFFSET)));
                    atb.setPositionOffset(
                            UTIL.convertAnyNumberToInt(POIUtil.getCellValue(row, POSITIONGAP_OFFSET)));
                    atb.setIgnoreMalformed(UTIL.convertBoolean(POIUtil.getCellValue(row, IGNOREMALFORMED_OFFSET)));
                    atb.setCoerceNumber(UTIL.convertBoolean(POIUtil.getCellValue(row, COERCENUMBER_OFFSET)));
                    atb.setBinaryCompress(UTIL.convertBoolean(POIUtil.getCellValue(row, BINARYCOMPRESS_OFFSET)));
                    atb.setCompressThreshold(
                            UTIL.convertAnyNumberToInt(POIUtil.getCellValue(row, COMPRESSTHRESHOLD_OFFSET)));

                    // TODO, all all the others

                    //atb.setStore(UTIL.convertBoolean(POIUtil.getCellValue(row, STORE_OFFSET)));

                    if (atb.getType().equalsIgnoreCase("SubType")) {
                        subTypes.put(atb.getName(), atb.getLabel());
                    } else {
                        // save the attribute
                        ncClass.attributes.put(atb.getName(), atb);
                        ncClass.labels.put(atb.getLabel(), atb);

                        // if java class, verify the field accessibility
                        if (javaCls != null) {
                            Field field = null;
                            Class<?> current = javaCls;
                            while (!(current.getName().equals("java.lang.Object"))) {
                                try {
                                    field = current.getDeclaredField(atb.getName());
                                    atb.setField(field);
                                    //atb.setField(current.getDeclaredField(atb.getName()));
                                    break;
                                } catch (Exception e) {
                                    //System.out.println("java reflection warning, class/field not found, checking super class " + cls.getName() + ", " + atb.getName());
                                    current = current.getSuperclass();
                                    continue;
                                }
                            }

                            if (field != null) {
                                field.setAccessible(true);
                            }
                        }
                    }
                }
                i--; // continue the loop on the prior row
            }
        } catch (Exception e) {
            String msg = "exception in NCClass load " + e.toString();
            logger.error(msg);
            throw new Exception(msg);
        }
    }

    private static CellRangeAddress getCellRangeAddress(Sheet sheet, int row, int col) {
        for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
            CellRangeAddress cellRange = sheet.getMergedRegion(i);
            if (cellRange.isInRange(row, col))
                return cellRange;
        }
        return null;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public String getClassParent() {
        return classParent;
    }

    public void setClassParent(String classParent) {
        this.classParent = classParent;
    }

    public String getJavaClassName() {
        return javaClassName;
    }

    public void setJavaClassName(String javaClassName) {
        this.javaClassName = javaClassName;
    }

    // UTIL strips and trims the primary key string  
    // prop names that comprise the  primary key are returned 
    // TODO, strip and reassemble the key string in the set function
    public String[] getPrimaryKeys() throws Exception {
        if (primaryKey == null)
            return null;
        //String[] keys = UTIL.convertStringToList(primaryKey, ",");
        String[] keys = UTIL.convertCSVStringToList(primaryKey, false);
        return keys;
    }

    public static String getPrimaryKeyValue(String[] keys, Inst inst) throws Exception {
        try {
            StringWriter sw = new StringWriter();
            for (int i = 0; i < keys.length; i++) {
                Object value = PropertyUtils.getProperty(inst, keys[i]);
                if (value == null) {
                    return null; // primary key part may not be available, ES will assign id
                }
                sw.write(value.toString());
                if ((i + 1) < keys.length) {
                    sw.write("_");
                }
            }
            sw.flush();
            return sw.toString();

        } catch (Exception e) {
            String msg = "primary key build failed on this class: " + inst.getType();
            logger.error(msg);
            throw new Exception(msg);
        }
    }

    // note, this returns a csv string
    public String getPrimaryKey() {
        return primaryKey;
    }

    public void setPrimaryKey(String primaryKey) {
        this.primaryKey = primaryKey;
    }

    public HashMap<String, String> getSubTypes() {
        return subTypes;
    }

    public void setAttributes(HashMap<String, Attribute> attributes) {
        this.attributes = attributes;
    }

    public String getSuperClassName() {
        return superClassName;
    }

    public void setSuperClassName(String superClassName) {
        this.superClassName = superClassName;
    }

    public boolean isPercolate() {
        return percolate;
    }

    public void setPercolate(boolean percolate) {
        this.percolate = percolate;
    }

    public boolean isGroupConstrain() {
        return groupConstrain;
    }

    public void setGroupConstrain(boolean groupConstrain) {
        this.groupConstrain = groupConstrain;
    }

    public ElasticAlias getAssignedIndexAlias() {
        return assignedIndexAlias;
    }

    // called by ElasticMetaManager at startup, a given Type is assigned to one and one only alias
    public void setAssignedIndexAlias(ElasticAlias assignedIndex) {
        this.assignedIndexAlias = assignedIndex;
    }

    /*
    public String getQualifiedAtbName(String atbStr) {
       StringWriter sw = new StringWriter();
       sw.write(getClassPrefix());
       sw.write(".");
       sw.write(atbStr);
       return sw.toString();
    }
    */

    /*
    public void setIndexes(ArrayList<String> indexes) {this.indexes = indexes;}
    public void setIndexes(String indexList) {
       String[] s = indexList.split(",");
       for (int i = 0; i < s.length; i++) {
     indexes.add(s[i].toLowerCase());
       }
    }
    */
}