Java tutorial
/* 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.datamodel; import static edu.ku.brc.helpers.XMLHelper.addAttr; import static edu.ku.brc.helpers.XMLHelper.getAttr; import java.lang.reflect.Method; import java.util.HashSet; import java.util.Set; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.Transient; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.dom4j.Element; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; import edu.ku.brc.af.core.db.DBFieldInfo; import edu.ku.brc.af.core.db.DBTableIdMgr; import edu.ku.brc.af.core.db.DBTableInfo; import edu.ku.brc.specify.tasks.subpane.wb.wbuploader.UploadTable; import edu.ku.brc.ui.UIRegistry; /** * @author rod * * @code_status Alpha * * Oct 17, 2007 * */ @Entity @org.hibernate.annotations.Entity(dynamicInsert = true, dynamicUpdate = true) @org.hibernate.annotations.Proxy(lazy = false) @Table(name = "spqueryfield") public class SpQueryField extends DataModelObjBase implements Comparable<SpQueryField>, Cloneable { protected static final Logger log = Logger.getLogger(SpQueryField.class); public static final Byte SORT_NONE = 0; public static final Byte SORT_ASC = 1; public static final Byte SORT_DESC = 2; public enum SortType { NONE(0), ASC(1), DESC(2); SortType(final int ord) { this.ord = (byte) ord; } private byte ord; public byte getOrdinal() { return ord; } public void set(final byte ord) { this.ord = ord; } public static String getString(final byte ord) { String[] names = { "None", "Ascending", "Descending" }; return names[ord]; } public static SortType valueOf(Byte ord) { return SortType.valueOf(ord.toString()); } } public enum OperatorType { LIKE(0), EQUALS(1), GREATERTHAN(2), LESSTHAN(3), GREATERTHANEQUALS(4), LESSTHANEQUALS(5), TRUE(6), FALSE( 7), DONTCARE(8), BETWEEN(9), IN(10), CONTAINS(11), EMPTY(12), TRUEORNULL(13), FALSEORNULL(14); OperatorType(final int ord) { this.ord = (byte) ord; } private byte ord; private static final String[] names = { "Like", "=", ">", "<", ">=", "<=", UIRegistry.getResourceString("true"), UIRegistry.getResourceString("false"), " ", UIRegistry.getResourceString("QB_BETWEEN"), UIRegistry.getResourceString("QB_IN"), UIRegistry.getResourceString("QB_CONTAINS"), UIRegistry.getResourceString("QB_EMPTY"), UIRegistry.getResourceString("QB_TRUEORNULL"), UIRegistry.getResourceString("QB_FALSEORNULL") }; private static final String[] qlOps = { "Like", "=", ">", "<", ">=", "<=", "true", "false", " ", "BETWEEN", "IN", "CONTAINS", "EMPTY", "TRUEORNULL", "FALSEORNULL" }; public byte getOrdinal() { return ord; } public void set(final byte ord) { this.ord = ord; } public static String getString(final byte ord) { return names[ord]; } public static OperatorType valueOf(Byte ord) { return OperatorType.valueOf(ord.toString()); } /*public static byte getOrdForName(final String name) { for (byte o = 0; o < names.length; o++) { if (names[o].equals(name)) { return o; } } return -1; }*/ /** * @param ord * @return */ public static String getOp(byte ord) { return qlOps[ord]; } /** * @param op * @return */ public static byte getOrdForOp(final String op) { for (byte o = 0; o < qlOps.length; o++) { if (qlOps[o].equals(op)) { return o; } } return -1; } @Override public String toString() { return names[ord]; } } protected Integer spQueryFieldId; protected Short position; protected String fieldName; protected Boolean isNot; protected Boolean isDisplay; protected Boolean isPrompt; //whether or not criteria for this field is requested when it's query is run //outside the querybuilder context. protected Boolean isRelFld; //true if this field represents a relationship //(the data object or objects on the 'other' side of the relationship) protected Boolean alwaysFilter; //true if criteria for this field should be applied in all situations, i.e. even //when query content is provided by a list of ids. protected Boolean allowNulls; //true if 'or is null' should be appended to the condition for the field //This allows, for example, a Determination.Current is true condition //to be applied without removing specimens that don't have any determinations. protected String stringId; //unique name for the field within it's query protected Byte operStart; protected Byte operEnd; protected String startValue; protected String endValue; protected Byte sortType; protected String tableList; protected Set<SpExportSchemaItemMapping> mappings; //This a set to provide support the theoretical capability to //map a single field to more than one concept, which, I think, //is supported by TAPIR. /** * The tableId of the table that contains the database field represented by this object. */ protected Integer contextTableIdent; /** * Unique column name among query's other fields. */ protected String columnAlias; /** * The name of the formatter to use for formatted or aggregated fields. * (if null then default formatter is used) */ protected String formatName; protected SpQuery query; /** * */ public SpQueryField() { // no op } /** * @param spQueryItemId the spQueryItemId to set */ public void setSpQueryFieldId(Integer spQueryFieldId) { this.spQueryFieldId = spQueryFieldId; } /** * @param position the position to set */ public void setPosition(Short position) { this.position = position; } /** * @param fieldName the fieldName to set */ public void setFieldName(String fieldName) { this.fieldName = fieldName; } /** * @param stringId the stringId to set */ public void setStringId(String stringId) { this.stringId = stringId; } /** * @param formatName the formatName to set */ public void setFormatName(String formatName) { this.formatName = formatName; } /** * @param isNot the isNot to set */ public void setIsNot(Boolean isNot) { this.isNot = isNot; } /** * @param isDisplay the isDisplay to set */ public void setIsDisplay(Boolean isDisplay) { this.isDisplay = isDisplay; } /** * @param isPrompt the isPrompt to set */ public void setIsPrompt(Boolean isPrompt) { this.isPrompt = isPrompt; } /** * @param alwaysFilter the alwaysFilter to set */ public void setAlwaysFilter(Boolean alwaysFilter) { this.alwaysFilter = alwaysFilter; } /** * @param allowNulls the allowNulls to set */ public void setAllowNulls(Boolean allowNulls) { this.allowNulls = allowNulls; } /** * @param isRelFld the isRelFld to set */ public void setIsRelFld(Boolean isRelFld) { this.isRelFld = isRelFld; } /** * @param operStart the operStart to set */ public void setOperStart(Byte operStart) { this.operStart = operStart; } /** * @param operEnd the operEnd to set */ public void setOperEnd(Byte operEnd) { this.operEnd = operEnd; } /** * @param startValue the startValue to set */ public void setStartValue(String startValue) { this.startValue = startValue; } /** * @param endValue the endValue to set */ public void setEndValue(String endValue) { this.endValue = endValue; } /** * @param sortType the sortType to set */ public void setSortType(Byte sortType) { this.sortType = sortType; } /** * @param table the table to set */ public void setQuery(SpQuery query) { this.query = query; } /** * @param tableList the tableList to set */ public void setTableList(String tableList) { this.tableList = tableList; } /** * @return the spQueryItemId */ @Id @GeneratedValue @Column(name = "SpQueryFieldID", unique = false, nullable = false, insertable = true, updatable = true) public Integer getSpQueryFieldId() { return spQueryFieldId; } /** * @return the position */ @Column(name = "Position", unique = false, nullable = false, insertable = true, updatable = true) public Short getPosition() { return position; } /** * @return the fieldName */ @Column(name = "FieldName", unique = false, nullable = false, insertable = true, updatable = true, length = 32) public String getFieldName() { return fieldName; } /** * @return the stringId */ @Column(name = "StringId", unique = false, nullable = false, insertable = true, updatable = true, length = 500) public String getStringId() { return stringId; } /** * @return the formatName */ @Column(name = "FormatName", unique = false, nullable = true, insertable = true, updatable = true, length = 64) public String getFormatName() { return formatName; } /** * @return the isNot */ @Column(name = "IsNot", unique = false, nullable = false, insertable = true, updatable = true) public Boolean getIsNot() { return isNot; } /** * @return the isDisplay */ @Column(name = "IsDisplay", unique = false, nullable = false, insertable = true, updatable = true) public Boolean getIsDisplay() { return isDisplay; } /** * @return the isPrompt */ @Column(name = "IsPrompt", unique = false, nullable = true, insertable = true, updatable = true) public Boolean getIsPrompt() { return isPrompt; } /** * @return the isRelFld */ @Column(name = "IsRelFld", unique = false, nullable = true, insertable = true, updatable = true) public Boolean getIsRelFld() { return isRelFld; } /** * @return the alwasyFilter */ @Column(name = "AlwaysFilter", unique = false, nullable = true, insertable = true, updatable = true) public Boolean getAlwaysFilter() { return alwaysFilter; } /** * @return the allowNulls */ @Column(name = "AllowNulls", unique = false, nullable = true, insertable = true, updatable = true) public Boolean getAllowNulls() { return allowNulls; } /** * @return the operStart */ @Column(name = "OperStart", unique = false, nullable = false, insertable = true, updatable = true) public Byte getOperStart() { return operStart; } /** * @return the operEnd */ @Column(name = "OperEnd", unique = false, nullable = true, insertable = true, updatable = true) public Byte getOperEnd() { return operEnd; } /** * @return the startValue */ @Column(name = "StartValue", unique = false, nullable = false, insertable = true, updatable = true, length = 255) public String getStartValue() { return startValue; } /** * @return the endValue */ @Column(name = "EndValue", unique = false, nullable = true, insertable = true, updatable = true, length = 255) public String getEndValue() { return endValue; } /** * @return the sortType */ @Column(name = "SortType", unique = false, nullable = false, insertable = true, updatable = true) public Byte getSortType() { return sortType; } /** * @return the table */ @ManyToOne(cascade = {}, fetch = FetchType.LAZY) @JoinColumn(name = "SpQueryID", unique = false, nullable = true, insertable = true, updatable = true) public SpQuery getQuery() { return query; } /** * @return the fields */ @OneToMany(fetch = FetchType.EAGER, mappedBy = "queryField") @Cascade({ CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.LOCK }) public Set<SpExportSchemaItemMapping> getMappings() { return mappings; } /** * @return the tableList */ @Column(name = "TableList", unique = false, nullable = false, insertable = true, updatable = true, length = 500) public String getTableList() { return tableList; } /** * @param mapping the mapping to set * * Sets mapping to be the single mapping for this SpQueryField. */ public void setMapping(SpExportSchemaItemMapping mapping) { // for (SpExportSchemaItemMapping currentMapping : mappings) // { // currentMapping.setExportSchemaMapping(null); // } mappings.clear(); if (mapping != null) { mappings.add(mapping); } } /** * @return the first mapping. */ @Transient public SpExportSchemaItemMapping getMapping() { if (mappings.size() > 0) { if (mappings.size() > 1) { log.warn("getMappig() was called for object with more than one mapping."); } return mappings.iterator().next(); } return null; } /* (non-Javadoc) * @see edu.ku.brc.specify.datamodel.DataModelObjBase#initialize() */ @Override public void initialize() { super.init(); spQueryFieldId = null; position = null; fieldName = null; isNot = null; isDisplay = null; isPrompt = null; alwaysFilter = null; allowNulls = null; isRelFld = null; operStart = null; operEnd = null; startValue = null; endValue = null; sortType = null; query = null; tableList = null; stringId = null; formatName = null; columnAlias = null; contextTableIdent = null; mappings = new HashSet<SpExportSchemaItemMapping>(); } @Transient public OperatorType getStartOperator() { return OperatorType.valueOf(operStart); } @Transient public OperatorType getEndOperator() { return OperatorType.valueOf(operEnd); } @Transient public SortType getSort() { return SortType.valueOf(sortType); } public void setStartOper(OperatorType oper) { operStart = oper.getOrdinal(); } public void setEndOper(OperatorType oper) { operEnd = oper.getOrdinal(); } public void setSort(SortType sortType) { this.sortType = sortType.getOrdinal(); } public void setMappings(Set<SpExportSchemaItemMapping> mappings) { this.mappings = mappings; } //------------------------------------------------------------------------- //-- DataModelObjBase //------------------------------------------------------------------------- /* (non-Javadoc) * @see edu.ku.brc.specify.datamodel.DataModelObjBase#getDataClass() */ @Override @Transient public Class<?> getDataClass() { return SpQueryField.class; } /* (non-Javadoc) * @see edu.ku.brc.specify.datamodel.DataModelObjBase#getId() */ @Override @Transient public Integer getId() { return spQueryFieldId; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.FormDataObjIFace#getTableId() */ @Override @Transient public int getTableId() { return getClassTableId(); } /* (non-Javadoc) * @see edu.ku.brc.specify.datamodel.DataModelObjBase#isChangeNotifier() */ @Transient @Override public boolean isChangeNotifier() { return false; } /** * @return the Table ID for the class. */ public static int getClassTableId() { return 518; } public int compareTo(SpQueryField o) { return position != null && o != null && o.position != null ? position.compareTo(o.position) : 0; } /** * @return the contextTableId */ @Column(name = "ContextTableIdent", unique = false, nullable = true, insertable = true, updatable = true) public Integer getContextTableIdent() { return contextTableIdent; } /** * @param contextTableId the contextTableId to set */ public void setContextTableIdent(Integer contextTableIdent) { this.contextTableIdent = contextTableIdent; } /** * @return the columnAlias */ @Column(name = "ColumnAlias", unique = false, nullable = true, insertable = true, updatable = true, length = 64) public String getColumnAlias() { return columnAlias; } /** * @return the columnAlias with the field's current title substituted for it's name. */ @Transient public String getColumnAliasTitle() { if (columnAlias == null) { columnAlias = fieldName; } DBTableInfo tbl = DBTableIdMgr.getInstance().getInfoById(contextTableIdent); if (tbl != null) { DBFieldInfo fld = tbl.getFieldByName(fieldName); if (fld != null) { int nameIdx = columnAlias.lastIndexOf(fld.getName()); if (nameIdx >= 0) { int nameEndIdx = nameIdx + fld.getName().length(); return columnAlias.substring(0, nameIdx) + fld.getTitle() + columnAlias.substring(nameEndIdx); } } } log.error("Returning unprocessed columnAlias because FieldInfo was not found: " + columnAlias); return columnAlias; } /** * @param columnAlias the columnAlias to set */ public void setColumnAlias(String columnAlias) { this.columnAlias = columnAlias; } /** * @param columnAliasTitle * * Substitutes the field's name for it's title in columnAliasTitle and sets columnAlias. */ public void setColumnAliasTitle(String columnAliasTitle, boolean doNotReportError) { DBTableInfo tbl = DBTableIdMgr.getInstance().getInfoById(contextTableIdent); if (tbl != null) { DBFieldInfo fld = tbl.getFieldByName(fieldName); if (fld != null) { int nameIdx = columnAliasTitle.lastIndexOf(fld.getTitle()); //XXX - if the title for a field is changed while a query is open //columnAliasTitle might contain the fld's old title??? if (nameIdx >= 0) { int nameEndIdx = nameIdx + fld.getTitle().length(); setColumnAlias(columnAliasTitle.substring(0, nameIdx) + fld.getName() + columnAliasTitle.substring(nameEndIdx)); return; } } } if (!doNotReportError) { log.error("Setting unprocessed alias because FieldInfo was not found: " + columnAliasTitle); } setColumnAlias(columnAliasTitle); } /* (non-Javadoc) * @see edu.ku.brc.specify.datamodel.DataModelObjBase#clone() */ @Override public Object clone() throws CloneNotSupportedException { SpQueryField field = (SpQueryField) super.clone(); return field; } /** * @param sb */ public void toXML(final StringBuilder sb) { sb.append("<field "); addAttr(sb, "position", position); addAttr(sb, "fieldName", fieldName); addAttr(sb, "isNot", isNot); addAttr(sb, "isDisplay", isDisplay); addAttr(sb, "isPrompt", isPrompt); addAttr(sb, "isRelFld", isRelFld); addAttr(sb, "alwaysFilter", alwaysFilter); addAttr(sb, "stringId", stringId); addAttr(sb, "operStart", operStart); addAttr(sb, "operEnd", operEnd); addAttr(sb, "startValue", startValue); addAttr(sb, "endValue", endValue); addAttr(sb, "sortType", sortType); addAttr(sb, "tableList", tableList); addAttr(sb, "contextTableIdent", contextTableIdent); addAttr(sb, "columnAlias", columnAlias); addAttr(sb, "formatName", formatName); sb.append(" />\n"); } /** * @param tblInfo * @param fieldToSetName * @param fieldToSet * @param value * * Sets value modifying it if necessary to make it valid. Only check currently is on string lengths. */ protected void setValue(DBTableInfo tblInfo, String fieldToSetName, Object value) { try { DBFieldInfo fldInfo = tblInfo.getFieldByName(fieldToSetName); String fieldSetterName = "set" + UploadTable.capitalize(fieldToSetName); Method fieldSetter = SpQueryField.class.getMethod(fieldSetterName, fldInfo.getDataClass()); if (fldInfo.getDataClass().equals(String.class) && value != null) { String strVal = (String) value; if (strVal.length() > fldInfo.getLength()) { fieldSetter.invoke(this, ((String) value).substring(0, fldInfo.getLength())); return; } } fieldSetter.invoke(this, value); } catch (Exception ex) { edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount(); edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(SpQueryField.class, ex); ex.printStackTrace(); } } public void fromXML(Element element) { DBTableInfo tblInfo = DBTableIdMgr.getInstance().getInfoById(getTableId()); setValue(tblInfo, "position", getAttr(element, "position", (short) 0)); setValue(tblInfo, "fieldName", getAttr(element, "fieldName", null)); setValue(tblInfo, "isNot", getAttr(element, "isNot", false)); setValue(tblInfo, "isDisplay", getAttr(element, "isDisplay", false)); setValue(tblInfo, "isPrompt", getAttr(element, "isPrompt", false)); setValue(tblInfo, "isRelFld", getAttr(element, "isRelFld", false)); setValue(tblInfo, "alwaysFilter", getAttr(element, "alwaysFilter", false)); //XXX there is a problem with TreeLevels stringId properties. //Currently, the level 'names' are used in the stringId and there are potential problems with i18n. //If the rankIds are used then there may be problems with 'custom' levels //For the taxon and geography tress, problems will be minimal to nonexistent //if the Specify6 Standard levels are used. //For Storage and other trees without standards there are likely to be many //issues with imports/exports setValue(tblInfo, "stringId", getAttr(element, "stringId", null)); setValue(tblInfo, "operStart", getAttr(element, "operStart", (byte) 0)); setValue(tblInfo, "operEnd", getAttr(element, "operEnd", (byte) 0)); if (operEnd.byteValue() == 0) { operEnd = null; } setValue(tblInfo, "startValue", getAttr(element, "startValue", null)); setValue(tblInfo, "endValue", getAttr(element, "endValue", null)); setValue(tblInfo, "sortType", getAttr(element, "sortType", (byte) 0)); setValue(tblInfo, "tableList", getAttr(element, "tableList", null)); setValue(tblInfo, "contextTableIdent", getAttr(element, "contextTableIdent", 0)); setValue(tblInfo, "columnAlias", getAttr(element, "columnAlias", null)); setValue(tblInfo, "formatName", getAttr(element, "formatName", null)); if (formatName != null && "".equals(formatName.trim())) { formatName = null; } } /** * @param obj1 * @param obj2 * @return */ protected boolean eq(final Object obj1, final Object obj2) { if (obj1 == null && obj2 == null) { return true; } if (obj1 == null || obj2 == null) { return false; } return obj1.equals(obj2); } /** * @param val * @return */ protected String nullIfBlank(String val) { if (StringUtils.isEmpty(val)) { return null; } return val; } /** * @param val * @return */ protected Number nullIfZero(Number val) { if (val != null && val.equals(0)) { return null; } return val; } /** * @param obj * @return true if this and obj represent the same database field with the same relationship to the * root query table, parameters. and options. */ public boolean isEquivalent(Object obj) { if (obj instanceof SpQueryField) { SpQueryField f = (SpQueryField) obj; return fieldName.equals(f.fieldName) && isNot.equals(f.isNot) && isDisplay.equals(f.isDisplay) && isPrompt.equals(f.isPrompt) && alwaysFilter.equals(f.alwaysFilter) && eq(nullIfZero(operStart), nullIfZero(f.operStart)) && eq(nullIfZero(operEnd), nullIfZero(f.operEnd)) && eq(nullIfBlank(startValue), nullIfBlank(f.startValue)) && eq(nullIfBlank(endValue), nullIfBlank(f.endValue)) && eq(nullIfZero(sortType), nullIfZero(f.sortType)) && eq(nullIfBlank(tableList), nullIfBlank(f.tableList)) && eq(nullIfZero(contextTableIdent), nullIfZero(f.contextTableIdent)) && eq(nullIfBlank(columnAlias), nullIfBlank(f.columnAlias)); } return false; } }