edu.ku.brc.specify.tasks.subpane.wb.wbuploader.UploadField.java Source code

Java tutorial

Introduction

Here is the source code for edu.ku.brc.specify.tasks.subpane.wb.wbuploader.UploadField.java

Source

/* Copyright (C) 2015, University of Kansas Center for Research
 * 
 * Specify Software Project, specify@ku.edu, Biodiversity Institute,
 * 1345 Jayhawk Boulevard, Lawrence, Kansas, 66045, USA
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
package edu.ku.brc.specify.tasks.subpane.wb.wbuploader;

import java.lang.reflect.Method;
import java.text.DecimalFormatSymbols;
import java.util.Comparator;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
import java.util.Vector;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import edu.ku.brc.af.core.AppContextMgr;
import edu.ku.brc.af.core.db.DBFieldInfo;
import edu.ku.brc.af.ui.db.PickListDBAdapterIFace;
import edu.ku.brc.af.ui.db.PickListItemIFace;
import edu.ku.brc.af.ui.forms.formatters.UIFieldFormatterIFace;
import edu.ku.brc.dbsupport.DBConnection;
import edu.ku.brc.specify.config.SpecifyAppContextMgr;
import edu.ku.brc.specify.conversion.BasicSQLUtils;
import edu.ku.brc.specify.datamodel.DataModelObjBase;
import edu.ku.brc.specify.datamodel.Locality;
import edu.ku.brc.specify.datamodel.PrepType;
import edu.ku.brc.specify.dbsupport.RecordTypeCodeBuilder;
import edu.ku.brc.specify.tasks.subpane.wb.schema.Field;
import edu.ku.brc.specify.tasks.subpane.wb.schema.Relationship;
import edu.ku.brc.specify.ui.CatalogNumberUIFieldFormatter;
import edu.ku.brc.specify.ui.db.PickListDBAdapterFactory;
import edu.ku.brc.specify.ui.db.PickListTableAdapter;

/**
 * @author timbo
 * 
 * @code_status Alpha
 * 
 * Describes properties of fields being uploaded as part of a workbench upload.
 */
public class UploadField {
    protected static DecimalFormatSymbols formatSymbols = new DecimalFormatSymbols(Locale.getDefault());

    protected static final Logger log = Logger.getLogger(UploadField.class);
    /**
     * The Field in the database being uploaded to.
     */
    protected Field field;
    /**
     * The current value of the field. (The text contained in the Workbench)
     */
    protected String value;
    /**
     * For UploadFields implementing foreign keys: The relationship the foreign key participates in.
     */
    protected Relationship relationship;
    /**
     * The field's column index in the workbench being uploaded. (-1 when not applicable (as for
     * foreign keys.))
     */
    protected int index;
    /**
     * The caption of the field's column in the workbench. (null when index == -1)
     */
    protected String wbFldName;
    /**
     * The one to many 'order' of the field (e.g. LastName1, lastName2, ... )
     */
    protected Integer sequence = null;
    /**
     * True if the field must contain data
     */
    protected Boolean required = null;

    protected boolean autoAssignForUpload = false;
    /**
     * The methods used to set and get the field's contents in the java object representing the field's
     * Table.
     */
    protected Method setter;
    protected Method getter = null;

    protected Integer precision = null; //BigDecimal fields
    protected Integer scale = null; //BigDecimal
    protected boolean precisionAndScaleDetermined = false; //Big Decimal

    /**
    * @return the precisionAndScaleDetermined
    */
    public boolean isPrecisionAndScaleDetermined() {
        return precisionAndScaleDetermined;
    }

    /**
      * A set of valid values for fields with associated pick lists.
      */
    protected Map<String, PickListItemIFace> validValues = null;

    /**
    * @return the precision
    */
    public Integer getPrecision() {
        if (!isPrecisionAndScaleDetermined()) {
            determinePrecisionAndScale();
        }
        return precision;
    }

    /**
     * @param input
     * @return
     */
    public boolean checkPrecisionAndScale(String input) {
        if (getPrecision() != null) {
            int l = input.length();
            int sepIdx = input.indexOf(formatSymbols.getDecimalSeparator());
            int rightOfDecimal = (sepIdx > -1) ? l - sepIdx - 1 : 0;
            if (sepIdx > -1) {
                l--;
            }
            int leftOfDecimal = l - rightOfDecimal;
            return leftOfDecimal <= precision - scale && rightOfDecimal <= scale;
        }
        return true;
    }

    /**
     * @return the scale
     */
    public Integer getScale() {
        return scale;
    }

    /**
     * 
     */
    public void determinePrecisionAndScale() {
        if (field != null && field.getFieldInfo() != null
                && field.getFieldInfo().getType().equals("java.math.BigDecimal")) {
            String dbName = ((SpecifyAppContextMgr) AppContextMgr.getInstance()).getDatabaseName();
            String tblName = field.getFieldInfo().getTableInfo().getName();
            String fldName = field.getFieldInfo().getName();
            String colType = null;
            Vector<Object[]> rows = BasicSQLUtils.query(DBConnection.getInstance().getConnection(),
                    "SELECT COLUMN_TYPE FROM `information_schema`.`COLUMNS` where TABLE_SCHEMA = '" + dbName
                            + "' and TABLE_NAME = '" + tblName + "' and COLUMN_NAME = '" + fldName + "'");
            if (rows.size() == 1) {
                colType = rows.get(0)[0].toString().toLowerCase().trim();
            }
            if (colType != null && colType.startsWith("decimal")) {
                //"DECIMAL(19,2)"
                String psStr = colType.substring(8).replace(")", "");
                String[] ps = psStr.split(",");
                if (ps.length == 2) {
                    this.precision = Integer.valueOf(ps[0]);
                    this.scale = Integer.valueOf(ps[1]);
                }
            }
        }
        this.precisionAndScaleDetermined = true;
    }

    /**
      * True if field has a read-only picklist
      */
    protected boolean readOnlyValidValues = false;

    /**
     * True if warnings should be made about values not contained in picklist.
     */
    protected boolean picklistWarn = false;

    /**
     * True if associated pick list has been searched for.
     */
    protected boolean validValuesChecked = false;

    /**
     * @return the setter
     */
    public final Method getSetter() {
        return setter;
    }

    /**
     * @param setter the setter to set
     */
    public final void setSetter(Method setter) {
        this.setter = setter;
    }

    /**
     * @return getter
     */
    public final Method getGetter() {
        if (getter != null) {
            return getter;
        }

        if (setter == null) {
            return null;
        }
        Class<?> cls = setter.getDeclaringClass();
        try {
            String name = "get" + setter.getName().substring(3);
            getter = cls.getMethod(name, (Class<?>[]) null);
        } catch (NoSuchMethodException ex) {
            //no getter
        }
        return getter;
    }

    /**
     * @param field
     * @param index
     * @param wbFldName
     * @param relationship
     */
    public UploadField(Field field, int index, String wbFldName, Relationship relationship) {
        this.field = field;
        this.index = index;
        this.wbFldName = wbFldName;
        this.relationship = relationship;
        if (field != null && field.getFieldInfo() != null) {
            UIFieldFormatterIFace fmt = field.getFieldInfo().getFormatter();
            if (fmt != null) {
                this.autoAssignForUpload = field.getFieldInfo().isRequired() && fmt.isIncrementer()
                        && (fmt.isNumeric() || (fmt instanceof CatalogNumberUIFieldFormatter
                                && ((CatalogNumberUIFieldFormatter) fmt).isNumericCatalogNumber()));
            }
        }
    }

    /**
     * @param configFld
     */
    public void copyConfig(UploadField configFld) {
        setAutoAssignForUpload(configFld.isAutoAssignForUpload());
    }

    /**
    * @return the autoAssignForUpload
    */
    public boolean isAutoAssignForUpload() {
        return autoAssignForUpload;
    }

    public boolean isAutoAssignable() {
        return getField().getFieldInfo() != null && getField().getFieldInfo().getFormatter() != null
                && getField().getFieldInfo().getFormatter().isIncrementer();
        //               //&& fld.getField().getFieldInfo().getFormatter().isNumeric();

    }

    /**
     * @param autoAssignForUpload the autoAssignForUpload to set
     */
    public void setAutoAssignForUpload(boolean autoAssignForUpload) {
        this.autoAssignForUpload = autoAssignForUpload;
    }

    @Override
    public String toString() {
        return wbFldName + ", " + String.valueOf(index) + ", " + field.getName();
    }

    /**
     * @return the field
     */
    public Field getField() {
        return field;
    }

    /**
     * @param field the field to set
     */
    public void setField(Field field) {
        this.field = field;
    }

    /**
     * @param val
     * @return true if val is a valid value for this field.
     */
    public boolean validate(final String val) {
        return true;
    }

    /**
     * @return the value; if the field has a picklist lookup the value in the list and
     * return the associated value object.
     */
    public String getValueObject() {
        if (getValidValues() == null) {
            return getValue();
        }
        PickListItemIFace item = validValues.get(value);
        if (item != null) {
            Object valObj = item.getValueObject();
            if (valObj instanceof DataModelObjBase) {
                //this means its a table picklist, but, with current code, all we need is the item 'name'
                return value;
            }
            return valObj.toString();
        }
        if (!StringUtils.isBlank(value)) {
            if (readOnlyValidValues) {
                //this should have already been caught.
                log.error("Invalid value '" + value + "' for field '" + wbFldName + "'");
                return null;
            }
            return value;
        }
        return null;
    }

    /**
     * @return the value
     */
    public String getValue() {
        if (StringUtils.isEmpty(value)) {
            return null;
        }
        return value;
    }

    /**
     * @param value the value to set
     */
    public void setValue(String value) {
        this.value = value;
    }

    /**
     * @return the relationship
     */
    public Relationship getRelationship() {
        return relationship;
    }

    /**
     * @param relationship the relationship to set
     */
    public void setRelationship(Relationship relationship) {
        this.relationship = relationship;
    }

    /**
     * @return the sequence
     */
    public Integer getSequence() {
        return sequence;
    }

    public int getSequenceInt() {
        if (sequence == null) {
            return 0;
        }
        return sequence;
    }

    /**
     * @param sequence the sequence to set
     */
    public void setSequence(Integer sequence) {
        this.sequence = sequence;
    }

    /**
     * @return the index
     */
    public int getIndex() {
        return index;
    }

    /**
     * @param index the index to set
     */
    public void setIndex(int index) {
        this.index = index;
    }

    /**
     * @return the required
     */
    public boolean isRequired() {
        if (required != null) {
            return required;
        }

        if (field != null && field.getFieldInfo() != null) {
            return field.getFieldInfo().isRequired()
                    //force CollectionObject.CatalogNumber to be required
                    //|| (field.getFieldInfo().getTableInfo().getTableId() == 1 && field.getFieldInfo().getName().equalsIgnoreCase("catalogNumber"))
                    //ditto for locality.LocalityName. Its field info no longer says it's required, but hibernate/mysql still requires it.
                    || (field.getFieldInfo().getTableInfo().getTableId() == Locality.getClassTableId()
                            && field.getFieldInfo().getName().equalsIgnoreCase("localityname"));
        }

        return false;
    }

    /**
     * @param required the required to set
     */
    public void setRequired(boolean required) {
        this.required = required;
    }

    /**
     * @return the wbFldName
     */
    public final String getWbFldName() {
        return wbFldName;
    }

    /**
      * @return list valid values for this field's picklist,
     * or null if no picklist is defined for this field.
    */
    public Map<String, PickListItemIFace> getValidValues() {
        if (!validValuesChecked) {
            validValuesChecked = true;
            validValues = buildValidValues();
        }
        return validValues;
    }

    /**
     * @return list valid values for this field's picklist,
     * or null if no picklist is defined for this field.
     */
    protected Map<String, PickListItemIFace> buildValidValues() {
        if (getIndex() != -1 && getField().getFieldInfo() != null) {
            PickListDBAdapterIFace pickList = null;
            if (!StringUtils.isEmpty(getField().getFieldInfo().getPickListName())) {
                pickList = PickListDBAdapterFactory.getInstance()
                        .create(getField().getFieldInfo().getPickListName(), false);
            } else if (RecordTypeCodeBuilder.isTypeCodeField(getField().getFieldInfo())) {
                pickList = RecordTypeCodeBuilder.getTypeCode(getField().getFieldInfo());
            } else {
                pickList = checkForSpecialCasePicklist();
            }
            if (pickList != null) {
                readOnlyValidValues = pickList.isReadOnly() && !(pickList instanceof PickListTableAdapter);
                picklistWarn = !readOnlyValidValues && pickList instanceof PickListTableAdapter;

                //                TreeMap<String, PickListItemIFace> pickListItems = picklistWarn ?
                //                      new TreeMap<String, PickListItemIFace>(new Comparator<String>(){
                //
                //                     /* (non-Javadoc)
                //                      * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
                //                      */
                //                     @Override
                //                     public int compare(String arg0, String arg1) {
                //                        if (arg0 == null && arg1 == null) return 0;
                //                        if (arg0 == null) return 1;
                //                        if (arg1 == null) return -1;
                //                        return arg0.compareToIgnoreCase(arg1);
                //                     }
                //                         
                //                      })
                //                      : new TreeMap<String, PickListItemIFace>();                
                TreeMap<String, PickListItemIFace> pickListItems = new TreeMap<String, PickListItemIFace>(
                        new Comparator<String>() {

                            /*
                             * (non-Javadoc)
                             * 
                             * @see
                             * java.util.Comparator#compare(java.lang.Object,
                             * java.lang.Object)
                             */
                            @Override
                            public int compare(String arg0, String arg1) {
                                if (arg0 == null && arg1 == null)
                                    return 0;
                                if (arg0 == null)
                                    return 1;
                                if (arg1 == null)
                                    return -1;
                                return arg0.compareToIgnoreCase(arg1);
                            }

                        });
                for (PickListItemIFace item : pickList.getList()) {
                    pickListItems.put(item.getTitle(), item);
                }
                return pickListItems;
            }
        }
        return null;
    }

    /**
     * @return picklist for "special cases"
     */
    protected PickListDBAdapterIFace checkForSpecialCasePicklist() {
        PickListDBAdapterIFace result = null;
        DBFieldInfo fldInfo = getField().getFieldInfo();
        if (fldInfo != null) {
            if (fldInfo.getName().equals("name") && fldInfo.getTableInfo().getClassObj().equals(PrepType.class)) {
                PickListDBAdapterIFace pl = PickListDBAdapterFactory.getInstance()
                        .create(fldInfo.getTableInfo().getName(), false);
                if (pl instanceof PickListTableAdapter) {
                    result = pl;
                }
            }
        }
        return result;
    }

    /**
     * @return the readOnlyValidValues
     */
    public boolean isReadOnlyValidValues() {
        return readOnlyValidValues;
    }

    /**
     * @return the picklistWarn
     */
    public boolean isPicklistWarn() {
        return picklistWarn;
    }

}