/* This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV This program is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program; if not, see http://www.gnu.org/licenses or write to the Free Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 */ package com.servoy.j2db.persistence; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.List; import com.servoy.base.scripting.annotations.ServoyClientSupport; import com.servoy.j2db.documentation.ServoyDocumented; import com.servoy.j2db.query.ColumnType; import com.servoy.j2db.util.Utils; /** * Add some info to a column * * @author jblok */ @ServoyDocumented(category = ServoyDocumented.DESIGNTIME, publicName = "ColumnInfo") @ServoyClientSupport(mc = true, wc = true, sc = true) public class ColumnInfo implements Serializable, ISupportHTMLToolTipText { public static final long serialVersionUID = -6167880772070620512L; //auto_enter_type public static final int NO_AUTO_ENTER = 0; public static final int SYSTEM_VALUE_AUTO_ENTER = 1; public static final int SEQUENCE_AUTO_ENTER = 2; public static final int CUSTOM_VALUE_AUTO_ENTER = 3; public static final int CALCULATION_VALUE_AUTO_ENTER = 4; public static final int LOOKUP_VALUE_AUTO_ENTER = 5; //auto_enter_sub_types to use if auto_enter_type == SYSTEM_VALUE_AUTO_ENTER public static final int NO_SYSTEM_VALUE = 0; public static final int SYSTEM_VALUE_CREATION_DATETIME = 1; public static final int SYSTEM_VALUE_CREATION_USERNAME = 2; public static final int SYSTEM_VALUE_MODIFICATION_DATETIME = 3; public static final int SYSTEM_VALUE_MODIFICATION_USERNAME = 4; public static final int DATABASE_MANAGED = 5; public static final int SYSTEM_VALUE_CREATION_USERUID = 6; public static final int SYSTEM_VALUE_MODIFICATION_USERUID = 7; public static final int SYSTEM_VALUE_CREATION_SERVER_DATETIME = 8; public static final int SYSTEM_VALUE_MODIFICATION_SERVER_DATETIME = 9; //auto_enter_sub_types to use if auto_enter_type == SEQUENCE_AUTO_ENTER public static final int NO_SEQUENCE_SELECTED = -1; public static final int SERVOY_SEQUENCE = 0; public static final int DATABASE_SEQUENCE = 1; public static final int DATABASE_IDENTITY = 2; public static final int UUID_GENERATOR = 3; public static final int[] allDefinedSeqTypes = { NO_SEQUENCE_SELECTED, SERVOY_SEQUENCE, DATABASE_SEQUENCE, DATABASE_IDENTITY, UUID_GENERATOR }; public static final int[] allDefinedSystemValues = { NO_SYSTEM_VALUE, SYSTEM_VALUE_CREATION_DATETIME, SYSTEM_VALUE_CREATION_USERNAME, SYSTEM_VALUE_MODIFICATION_DATETIME, SYSTEM_VALUE_MODIFICATION_USERNAME, DATABASE_MANAGED, SYSTEM_VALUE_CREATION_USERUID, SYSTEM_VALUE_MODIFICATION_USERUID, SYSTEM_VALUE_CREATION_SERVER_DATETIME, SYSTEM_VALUE_MODIFICATION_SERVER_DATETIME }; private String element_template_properties = null; /* * This property is not saved but determined on the fly from the db. */ private String databaseDefaultValue = null; private int columninfo_id; private boolean storedPersistently; private boolean changed; private int autoEnterType = NO_AUTO_ENTER; private int autoEnterSubType = NO_SEQUENCE_SELECTED; private String databaseSequenceName = null; private String preSequenceChars = null; private String postSequenceChars = null; private long nextSequence = 1; private int sequenceStepSize = 1; private String defaultValue = null; private String lookupValue = null; private String titleText = null; private String dataProviderID = null; private String description = null; private String converterProperties = null; private String converterName = null; private String foreignType = null; private String validatorProperties = null; private String validatorName = null; private String defaultFormat = null; private Integer containsMetaData = null; private ColumnType configuredColumnType; // as configured by developer private List<ColumnType> compatibleColumnTypes; // compatible with configured private int flags = 0; public ColumnInfo(int columninfo_id, boolean storedPersistently) { this.columninfo_id = columninfo_id; this.storedPersistently = storedPersistently; if (!storedPersistently) changed = true; } public int getID() { return columninfo_id; } public void setID(int id) { columninfo_id = id; } public boolean isStoredPersistently() { return storedPersistently; } public void setStoredPersistently(boolean storedPersistently) { this.storedPersistently = storedPersistently; } public void flagChanged() { changed = true; } public boolean isChanged() { return changed; } public void flagStored() { changed = false; storedPersistently = true; } /** * Flag that shows if the column is excluded. Excluded columns are ignored by Servoy and are not * visible as data providers. */ public boolean isExcluded() { return hasFlag(Column.EXCLUDED_COLUMN); } public boolean isDBManaged() { return (autoEnterType == SYSTEM_VALUE_AUTO_ENTER && autoEnterSubType == DATABASE_MANAGED); } public boolean isDBSequence() { return (autoEnterType == SEQUENCE_AUTO_ENTER && autoEnterSubType == DATABASE_SEQUENCE); } public void setDatabaseDefaultValue(String value) { databaseDefaultValue = value; } /** * The database default value that is used when autoenter is set to database default. */ public String getDatabaseDefaultValue() { return databaseDefaultValue; } /* * _____________________________________________________________ Property methods */ /** * The type of autoenter configured for the column. Can be one of: none, * system value, sequence, custom value or lookup value. * */ public int getAutoEnterType() { return autoEnterType; } public void setAutoEnterType(int t) { autoEnterType = t; } /** * The subtype of autoenter configured for the column. The available options depend * on the type of autoenter. * * If autoenter is set to system value, then the subtype can be one of: none, creation datetime, * creation username, modification datetime, modification username, database managed, * creation user uid, modification user uid, creation server datetime or modification server datetime. * * If autoenter is set to sequence, then the subtype can be one of: none, Servoy sequence, * database sequence, database identity or universally unique identifier. */ public int getAutoEnterSubType() { return autoEnterSubType; } public void setAutoEnterSubType(int t) { autoEnterSubType = t; } /** * The database sequence name that is used when autoenter is set to sequence and autoenter subtype * is set to database sequence. */ public String getDatabaseSequenceName() { return databaseSequenceName; } public void setDatabaseSequenceName(String databaseSequenceName) { if (databaseSequenceName != null) { databaseSequenceName = databaseSequenceName.trim(); if (databaseSequenceName.length() == 0) { databaseSequenceName = null; } else if (databaseSequenceName.length() > 50) { databaseSequenceName = databaseSequenceName.substring(0, 50); } } this.databaseSequenceName = databaseSequenceName; } public String getPreSequenceChars() { return preSequenceChars; } public void setPreSequenceChars(String s) { preSequenceChars = getNonEmptyValue(s); } public String getPostSequenceChars() { return postSequenceChars; } public void setPostSequenceChars(String s) { postSequenceChars = getNonEmptyValue(s); } /** * this is normally a snapshot of the sequence when running the application, especially when getNextSequence on Repository is called by clients */ public long getNextSequence() { return nextSequence; } public void setNextSequence(long l) { nextSequence = l; } public int getSequenceStepSize() { return sequenceStepSize; } public void setSequenceStepSize(int s) { sequenceStepSize = s; } /** * The value that is used when autoenter is set to custom value. */ public String getDefaultValue() { return defaultValue; } public void setDefaultValue(String s) { defaultValue = getNonEmptyValue(s); } /** * The lookup value that is used when autotype is set to lookup. */ public String getLookupValue() { return lookupValue; } public void setLookupValue(String s) { lookupValue = getNonEmptyValue(s); } /** * The title of the column. */ public String getTitleText() { return titleText; } public void setTitleText(String s) { titleText = getNonEmptyValue(s); } public void setDataProviderID(String dataProviderID) { this.dataProviderID = dataProviderID; } public String getDataProviderID() { return dataProviderID; } /** * The description of the column. */ public String getDescription() { return description; } public void setDescription(String s) { description = getNonEmptyValue(s); } /** * The properties of the converter used for this column. */ public String getConverterProperties() { return converterProperties; } public void setConverterProperties(String s) { converterProperties = getNonEmptyValue(s); } /** * The name of the converter used for this column. */ public String getConverterName() { return converterName; } public void setConverterName(String s) { converterName = getNonEmptyValue(s); } /** * The foreign type of the column. It is used for foreign key columns, to hold the foreign table they point to. */ public String getForeignType() { return foreignType; } public void setForeignType(String s) { foreignType = getNonEmptyValue(s); } /** * The properties of the validator used for the column. */ public String getValidatorProperties() { return validatorProperties; } public void setValidatorProperties(String s) { validatorProperties = getNonEmptyValue(s); } /** * The name of the validator used for the column. */ public String getValidatorName() { return validatorName; } public void setValidatorName(String s) { validatorName = getNonEmptyValue(s); } /** * The default format of the column. * Currently only strings or numbers are supported. */ public String getDefaultFormat() { return this.defaultFormat; } public void setDefaultFormat(String s) { this.defaultFormat = getNonEmptyValue(s); } /** * @param i */ public static String getSeqDisplayTypeString(int i) { switch (i) { case SERVOY_SEQUENCE : return "servoy seq"; //$NON-NLS-1$ case DATABASE_SEQUENCE : return "db seq"; //$NON-NLS-1$ case DATABASE_IDENTITY : return "db identity"; //$NON-NLS-1$ case UUID_GENERATOR : return "uuid generator"; //$NON-NLS-1$ case NO_SEQUENCE_SELECTED : default : return "none"; //$NON-NLS-1$ } } public static String getAutoEnterTypeString(int i) { switch (i) { case SYSTEM_VALUE_AUTO_ENTER : return "System Value"; //$NON-NLS-1$ case SEQUENCE_AUTO_ENTER : return "Sequence Value"; //$NON-NLS-1$ case CUSTOM_VALUE_AUTO_ENTER : return "Custom Value"; //$NON-NLS-1$ case CALCULATION_VALUE_AUTO_ENTER : return "Calculation Value"; //$NON-NLS-1$ case LOOKUP_VALUE_AUTO_ENTER : return "Related Value"; //$NON-NLS-1$ case NO_AUTO_ENTER : default : return "none"; //$NON-NLS-1$ } } public String getAutoEnterSubTypeString(int mainType, int subType) { if (mainType == SYSTEM_VALUE_AUTO_ENTER) { switch (subType) { case SYSTEM_VALUE_CREATION_DATETIME : return "creation datetime"; //$NON-NLS-1$ case SYSTEM_VALUE_CREATION_USERNAME : return "creation username"; //$NON-NLS-1$ case SYSTEM_VALUE_MODIFICATION_DATETIME : return "modification datetime"; //$NON-NLS-1$ case SYSTEM_VALUE_MODIFICATION_USERNAME : return "modification username"; //$NON-NLS-1$ case DATABASE_MANAGED : return "database managed"; //$NON-NLS-1$ case SYSTEM_VALUE_CREATION_USERUID : return "creation user uid"; //$NON-NLS-1$ case SYSTEM_VALUE_MODIFICATION_USERUID : return "modification user uid"; //$NON-NLS-1$ case SYSTEM_VALUE_CREATION_SERVER_DATETIME : return "creation server datetime"; //$NON-NLS-1$ case SYSTEM_VALUE_MODIFICATION_SERVER_DATETIME : return "modification server datetime"; //$NON-NLS-1$ case NO_SYSTEM_VALUE : default : return "none"; //$NON-NLS-1$ } } else if (mainType == SEQUENCE_AUTO_ENTER) { switch (subType) { case SERVOY_SEQUENCE : return "Servoy sequence"; //$NON-NLS-1$ case DATABASE_SEQUENCE : return "database sequence"; //$NON-NLS-1$ case DATABASE_IDENTITY : return "database identity"; //$NON-NLS-1$ case UUID_GENERATOR : return "universally unique identifier"; //$NON-NLS-1$ case NO_SEQUENCE_SELECTED : default : return "none"; //$NON-NLS-1$ } } else if (mainType == CUSTOM_VALUE_AUTO_ENTER) { return getDefaultValue(); } // else if (mainType == CALCULATION_VALUE_AUTO_ENTER) // { // return getDefaultValueCalculationScript(); // } else if (mainType == LOOKUP_VALUE_AUTO_ENTER) { return getLookupValue(); } return ""; //$NON-NLS-1$ } public String toHTML() { return getTextualPropertyInfo(true); } public String getTextualPropertyInfo(boolean html) { StringBuffer sb = new StringBuffer(); if (html) sb.append("<html>"); //$NON-NLS-1$ if (getAutoEnterType() != NO_AUTO_ENTER) { if (html) sb.append("<B>Auto Enter: </B>"); //$NON-NLS-1$ else sb.append("AE: "); //$NON-NLS-1$ sb.append(getAutoEnterTypeString(autoEnterType)); String sub = getAutoEnterSubTypeString(autoEnterType, autoEnterSubType); if (sub != null && sub.length() > 0) { sb.append(","); //$NON-NLS-1$ sb.append(sub); sb.append(" "); } } if (titleText != null && titleText.length() > 0) { if (html) sb.append("<B>Title: </B>"); //$NON-NLS-1$ else sb.append("T: "); //$NON-NLS-1$ sb.append(titleText); if (html) sb.append("<br>"); //$NON-NLS-1$ else sb.append(",");//$NON-NLS-1$ } if (defaultFormat != null && defaultFormat.length() > 0) { if (html) sb.append("<B>Default Format: </B> "); //$NON-NLS-1$ else sb.append("DF: "); //$NON-NLS-1$ sb.append(defaultFormat); if (html) sb.append("<br>"); //$NON-NLS-1$ else sb.append(",");//$NON-NLS-1$ } if (foreignType != null && foreignType.length() > 0) { if (html) sb.append("<B>Foreign Type: </B> "); //$NON-NLS-1$ else sb.append("FT: "); //$NON-NLS-1$ sb.append(foreignType); if (html) sb.append("<br>"); //$NON-NLS-1$ else sb.append(",");//$NON-NLS-1$ } if (validatorName != null) { if (html) sb.append("<B>Validator: </B>"); //$NON-NLS-1$ else sb.append("V: "); //$NON-NLS-1$ sb.append(validatorName); if (html) sb.append("<br>"); //$NON-NLS-1$ else sb.append(",");//$NON-NLS-1$ } if (converterName != null) { if (html) sb.append("<B>Converter: </B>"); //$NON-NLS-1$ else sb.append("C: "); //$NON-NLS-1$ sb.append(converterName); if (html) sb.append("<br>"); //$NON-NLS-1$ else sb.append(",");//$NON-NLS-1$ } if (html) sb.append("</html>"); //$NON-NLS-1$ if (html && sb.length() == 13) return null; //= empty html return sb.toString(); } public boolean hasSequence() { if (getAutoEnterType() == SEQUENCE_AUTO_ENTER) { if (getAutoEnterSubType() != NO_SEQUENCE_SELECTED) { return true; } } return false; } public boolean hasSystemValue() { if (getAutoEnterType() == SYSTEM_VALUE_AUTO_ENTER) { if (getAutoEnterSubType() != NO_SYSTEM_VALUE) { return true; } } return false; } public int getFlags() { return flags; } /** Should always called via Column */ public void setFlags(int flags) { this.flags = flags; } /** * Set or clear a flag. * * @param flag * @param set */ public void setFlag(int flag, boolean set) { setFlags(set ? (getFlags() | flag) : (getFlags() & ~flag)); } /** * @param flag */ public boolean hasFlag(int flag) { return (flags & flag) != 0; } /** * Returns true if the auto enter type specified has the same semantics as the auto enter type of this column info. * */ public boolean hasSameAutoEnterType(int autoEnterType2, int autoEnterSubType2, String databaseSequenceName2) { if (this.autoEnterType == NO_AUTO_ENTER) { if (autoEnterType2 == SEQUENCE_AUTO_ENTER) { return autoEnterSubType2 == NO_SEQUENCE_SELECTED; } if (autoEnterType2 == SYSTEM_VALUE_AUTO_ENTER) { return autoEnterSubType2 == NO_SYSTEM_VALUE; } return autoEnterSubType2 == NO_AUTO_ENTER; } if (autoEnterType2 == NO_AUTO_ENTER) { if (this.autoEnterType == SEQUENCE_AUTO_ENTER) { return this.autoEnterSubType == NO_SEQUENCE_SELECTED; } if (this.autoEnterType == SYSTEM_VALUE_AUTO_ENTER) { return this.autoEnterSubType == NO_SYSTEM_VALUE; } return this.autoEnterType == NO_AUTO_ENTER; } if (this.autoEnterType == SEQUENCE_AUTO_ENTER && autoEnterType2 == SEQUENCE_AUTO_ENTER && this.autoEnterSubType == DATABASE_SEQUENCE && autoEnterSubType2 == DATABASE_SEQUENCE) { // if the sequence name was changed, the auto enter is different return Utils.stringSafeEquals(this.databaseSequenceName, databaseSequenceName2); } return autoEnterType2 == this.autoEnterType && autoEnterSubType2 == this.autoEnterSubType; } public String getElementTemplateProperties() { return element_template_properties; } public void setElementTemplateProperties(String s) { element_template_properties = getNonEmptyValue(s); } /** * @return the containsMetaData */ public Integer getContainsMetaData() { return containsMetaData; } /** * @param containsMetaData the containsMetaData to set */ public void setContainsMetaData(Integer containsMetaData) { this.containsMetaData = containsMetaData; } /** * Set the column type as configured by developer */ public void setConfiguredColumnType(ColumnType columnType) { this.configuredColumnType = Column.checkColumnType(columnType); } /** * Get the column type as configured by developer. * <p>Note, do not call this method directly, use Column.getConfiguredColumnType() instead so that in case of * old column info (with configured type not set), there will be a fallback to the db column type. * * @see Column#getConfiguredColumnType() */ public ColumnType getConfiguredColumnType() { return configuredColumnType; } /** * @return the compatibleColumnTypes */ public List<ColumnType> getCompatibleColumnTypes() { return compatibleColumnTypes == null ? null : Collections.unmodifiableList(compatibleColumnTypes); } /** * Check if the column type is listed as compatible */ public boolean isCompatibleColumnType(ColumnType columnType) { return columnType != null && (columnType.equals(configuredColumnType) || (compatibleColumnTypes != null && compatibleColumnTypes.contains(columnType))); } /** * @param compatibleColumnTypes the compatibleColumnTypes to set */ public void setCompatibleColumnTypes(List<ColumnType> compatibleColumnTypes) { this.compatibleColumnTypes = compatibleColumnTypes == null ? null : new ArrayList<ColumnType>(compatibleColumnTypes); } /** * @param columnType */ public void addCompatibleColumnType(ColumnType columnType) { if (compatibleColumnTypes == null) { compatibleColumnTypes = new ArrayList<ColumnType>(); } if (!compatibleColumnTypes.contains(columnType)) { compatibleColumnTypes.add(columnType); } } /** * Turns strings with no content (blank spaces are not considered content) into null. Returns other strings unchanged. * * @param s the string. * @return null if there is no content in string, s otherwise. */ private String getNonEmptyValue(String s) { if (s == null || s.trim().length() == 0) return null; else return s; } /** * Copy column info into this column info. * * @param sourceColumnInfo */ public void copyFrom(ColumnInfo sourceColumnInfo) { if (sourceColumnInfo == null) { return; } setValidatorProperties(sourceColumnInfo.getValidatorProperties()); setDefaultValue(sourceColumnInfo.getDefaultValue()); setTitleText(sourceColumnInfo.getTitleText()); setConverterName(sourceColumnInfo.getConverterName()); setConverterProperties(sourceColumnInfo.getConverterProperties()); setForeignType(sourceColumnInfo.getForeignType()); setValidatorName(sourceColumnInfo.getValidatorName()); setDescription(sourceColumnInfo.getDescription()); setDataProviderID(sourceColumnInfo.getDataProviderID()); setContainsMetaData(sourceColumnInfo.getContainsMetaData()); setLookupValue(sourceColumnInfo.getLookupValue()); setFlags(sourceColumnInfo.getFlags()); setSequenceStepSize(sourceColumnInfo.getSequenceStepSize()); setPostSequenceChars(sourceColumnInfo.getPostSequenceChars()); setPreSequenceChars(sourceColumnInfo.getPreSequenceChars()); setAutoEnterType(sourceColumnInfo.getAutoEnterType()); setAutoEnterSubType(sourceColumnInfo.getAutoEnterSubType()); setDatabaseSequenceName(sourceColumnInfo.getDatabaseSequenceName()); setConfiguredColumnType(sourceColumnInfo.getConfiguredColumnType()); setCompatibleColumnTypes(sourceColumnInfo.getCompatibleColumnTypes()); // Flag that the column is changed. flagChanged(); // Don't set the next sequence; it's a new sequence, so you generally want to start at the beginning. } }