/* * Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Business Objects nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * DatabaseField.java * Creation date (Oct 5, 2004). * By: Richard Webster */ package org.openquark.util.datadictionary; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.openquark.util.ObjectUtils; /** * A database field. * It is possible for a database field to have child fields (details). * @author Richard Webster */ public class DatabaseField extends DatabaseItem implements Field { /** The data type of the field. */ private final ValueType dataType; /** The field type */ private final FieldType fieldType; /** The default aggregation type for the field (sum, min, max, etc...). */ private final AggregationType defaultAggregationType; /** Indicates whether the underlying definition for the field includes an aggregation function. */ private final boolean isPreaggregated; /** * DatabaseField constructor. * @param uniqueName the unique name of the field * @param name the name of the database field * @param dataType the data type of the database field * @param fieldType the type of the field * @param defaultAggregationType the default way in which values of this field should be aggregated * @param isPreaggregated whether the underlying definition for the field includes an aggregation function * @param children children of this database field */ public DatabaseField(String uniqueName, String name, ValueType dataType, FieldType fieldType, AggregationType defaultAggregationType, boolean isPreaggregated, List <DatabaseItem> children) { super(uniqueName, name, children); this.dataType = dataType; this.fieldType = fieldType; this.defaultAggregationType = defaultAggregationType; this.isPreaggregated = isPreaggregated; } /** * DatabaseField constructor. * @param uniqueName the unique name of the field * @param name the name of the database field * @param dataType the data type of the database field * @param fieldType the type of the field * @param defaultAggregationType the default way in which values of this field should be aggregated * @param isPreaggregated whether the underlying definition for the field includes an aggregation function */ public DatabaseField(String uniqueName, String name, ValueType dataType, FieldType fieldType, AggregationType defaultAggregationType, boolean isPreaggregated) { this(uniqueName, name, dataType, fieldType, defaultAggregationType, isPreaggregated, Collections.<DatabaseItem>emptyList()); } /** * DatabaseField constructor. * @param uniqueName the unique name of the field * @param name the name of the database field * @param dataType the data type of the database field * @param fieldType the type of the field * @param defaultAggregationType the default way in which values of this field should be aggregated */ public DatabaseField(String uniqueName, String name, ValueType dataType, FieldType fieldType, AggregationType defaultAggregationType) { this(uniqueName, name, dataType, fieldType, defaultAggregationType, false, Collections.<DatabaseItem>emptyList()); } /** * DatabaseField constructor. * @param name the name of the database field * @param dataType the data type of the database field * @param fieldType the type of the field */ public DatabaseField(String name, ValueType dataType, FieldType fieldType) { this(name, name, dataType, fieldType, bestAggregationType(dataType)); } /** * DatabaseField constructor. * @param uniqueName * @param name the name of the database field * @param dataType the data type of the database field * @param fieldType the type of the field */ public DatabaseField(String uniqueName, String name, ValueType dataType, FieldType fieldType) { this(uniqueName, name, dataType, fieldType, bestAggregationType(dataType)); } /** * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int hc = super.hashCode(); hc *= dataType.hashCode(); hc *= fieldType.hashCode(); hc *= defaultAggregationType.hashCode(); hc *= isPreaggregated ? Boolean.TRUE.hashCode() : Boolean.FALSE.hashCode(); return hc; } /** * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (obj == null || !(obj.getClass().equals(DatabaseField.class))) { return false; } DatabaseField other = (DatabaseField) obj; return super.equals(obj) && ObjectUtils.equals(dataType, other.dataType) && ObjectUtils.equals(fieldType, other.fieldType) && ObjectUtils.equals(defaultAggregationType, other.defaultAggregationType) && isPreaggregated == other.isPreaggregated; } /** * @param dataType * @return Returns the best aggregation type for this data type. */ private static AggregationType bestAggregationType(ValueType dataType) { if (dataType.equals(ValueType.intType) || dataType.equals(ValueType.doubleType)) { return AggregationType.SUM; } else { return AggregationType.COUNT; } } /** * Returns the data type of this database field. * @return the data type of this field */ public ValueType getDataType() { return dataType; } /** * Returns the field type of this database field. * @return FieldType */ public FieldType getFieldType() { return fieldType; } /** * @return Returns the default aggregation type for the field (sum, min, max, etc...). */ public AggregationType getDefaultAggregationType() { return defaultAggregationType; } /** * @return Returns whether the underlying definition for the field includes an aggregation function. */ public boolean isPreaggregated() { return isPreaggregated; } /** * @see org.openquark.util.datadictionary.DatabaseItem#filterItem(org.openquark.util.datadictionary.DatabaseFieldFilter) */ @Override public DatabaseItem filterItem(DatabaseFieldFilter fieldFilter) { // Handle the case where there is no filter. if (fieldFilter == null) { return this; } // Check whether this field should be rejected. if (!fieldFilter.acceptField(this)) { return null; } // Filter any child fields as well. List<DatabaseItem> filteredChildren = new ArrayList<DatabaseItem>(); boolean childrenFiltered = false; for (final DatabaseItem childItem : getChildren()) { DatabaseItem filteredItem = childItem.filterItem(fieldFilter); // Keep track of whether any child item was modified. // Note that the objects should be compared by identity, not equivalence. if (filteredItem != childItem) { childrenFiltered = true; } if (filteredItem != null) { filteredChildren.add(filteredItem); } } return childrenFiltered ? new DatabaseField(getUniqueName(), getName(), dataType, fieldType, defaultAggregationType, isPreaggregated, filteredChildren) : this; } /** * A helper function to combine 2 field filters (either of which can be null). * @param f1 a field filter * @param f2 another field filter * @return a combined filter */ public static DatabaseFieldFilter combineFilters(final DatabaseFieldFilter f1, final DatabaseFieldFilter f2) { if (f1 == null) { return f2; } if (f2 == null) { return f1; } return new DatabaseFieldFilter() { public boolean acceptField(DatabaseField field) { return f1.acceptField(field) && f2.acceptField(field); } }; } /** * Fields returned from the CAL data dictionary can not expose a SQL expression. The SQL * expression is internal to the data dictionary and intentionally not exposed to the client * code which shouldn't care about such details. * @see org.openquark.util.datadictionary.Field#getExpression() */ public String getExpression() { return getName(); } /** * @see org.openquark.util.datadictionary.Field#getQualifierName() */ public String getQualifierName() { return ""; } /** * @see org.openquark.util.datadictionary.Field#getOwnerName() */ public String getOwnerName() { return ""; } /** * @see org.openquark.util.datadictionary.Field#getTableName() */ public String getTableName() { return ""; } /** * @return The field name. This name will be a valid field name coming from the table * specified in getTableName(). */ public String getFieldName() { return getName(); } /** * Fields returned from the CAL data dictionary do not know they're table name. This makes sense * since the field may not be a field in the sense of a data foundation table/field, but could * be a more abstract object like a calculation or Universe object. * @see org.openquark.util.datadictionary.Field#getQualifiedTableName() */ public String getQualifiedTableName() { return null; } }