package Express.services;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.Serializable;
import DisplayProject.binding.beans.ExtendedPropertyChangeSupport;
import DisplayProject.binding.beans.Observable;
import Framework.Array_Of_DataValue;
import Framework.BooleanData;
import Framework.BooleanNullable;
import Framework.Constants;
import Framework.DataValue;
import Framework.DateTimeData;
import Framework.IntervalData;
import Framework.NumericData;
import Framework.RuntimeProperties;
import Framework.TextData;
/**
* The BusinessKey class defines a key. The BusinessKey class is used as the type for the InstanceKey attribute of a BusinessClass object, which defines the unique key for the class.
* <p>
* @author ITerative Consulting
* @since 26-Feb-2008
*/
@RuntimeProperties(isDistributed=false, isAnchored=false, isShared=false, isTransactional=false)
@SuppressWarnings("serial")
public class BusinessKey
implements Serializable, Observable
{
// ---------
// Constants
// ---------
public static final int CMP_EQ = 1;
public static final int CMP_GT = 32;
public static final int CMP_LONGER = 4;
public static final int CMP_LT = 64;
public static final int CMP_NE = 16;
public static final int CMP_NULL = 8;
public static final int CMP_SHORTER = 2;
// ----------
// Attributes
// ----------
public PropertyChangeSupport qq_Listeners = new ExtendedPropertyChangeSupport(this, true);
private Array_Of_DataValue<DataValue> values;
// ------------
// Constructors
// ------------
public BusinessKey() {
// Explicitly call the superclass constructor to prevent the implicit call
super();
this.setValues(new Array_Of_DataValue<DataValue>());
}
// ----------------------
// Accessors and Mutators
// ----------------------
public void setValues(Array_Of_DataValue<DataValue> values) {
Array_Of_DataValue<DataValue> oldValue = this.values;
this.values = values;
this.qq_Listeners.firePropertyChange("values", oldValue, this.values);
}
public Array_Of_DataValue<DataValue> getValues() {
return this.values;
}
// -------
// Methods
// -------
public void addPropertyChangeListener(String property, PropertyChangeListener listener) {
qq_Listeners.addPropertyChangeListener(property, listener);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
qq_Listeners.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(String property, PropertyChangeListener listener) {
qq_Listeners.removePropertyChangeListener(property, listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
qq_Listeners.removePropertyChangeListener(listener);
}
/**
* asTextData<p>
* AsTextData<br>
* The AsTextData method concatenates all the values in the Values array<br>
* and returns it as a text string. The values are separated by periods.<br>
* <p>
* @return TextData
*/
public TextData asTextData() {
TextData keyValue = new TextData();
if (this.getValues() == null) {
keyValue.concat("<NIL>");
}
else {
keyValue.concat("[");
if (this.getValues() != null) {
for (DataValue v : this.getValues()) {
keyValue.concat(v);
keyValue.concat(".");
}
}
//
// Lop off the last period.
//
if (keyValue.getActualSize() > 1) {
keyValue.cutRange(keyValue.getActualSize()-1);
}
keyValue.concat("]");
}
return keyValue;
}
/**
* compare<p>
* Compare<br>
* The Compare method compares the elements in the Values arrays with the<br>
* corresponding elements in the Values array of the source parameter. If<br>
* two elements have the same data type and are subclasses of TextData,<br>
* NumericData, DateTimeData, or IntervalData, then an ordered comparison<br>
* is performed, and equal, less than, or greater than can be returned.<br>
* If the data types are not the same or for other subclasses of DataValue<br>
* only an equality check is made.<br>
* <p>
* Implementation Note: The managers depend on the numerical ordering of<br>
* CMP_EQ < CMP_SHORTER < everything else. So don't change it.<br>
* <p>
* source<br>
* The BusinessKey against which to compare.<br>
* <p>
* Returns<br>
* CMP_EQ The keys are equal in value.<br>
* CMP_SHORTER All the elements in our key are equal, but we have<br>
* fewer than the source. We're shorter.<br>
* CMP_LONGER All the elements in our key are equal, but we have<br>
* more than the source. We're longer.<br>
* CMP_NULL No comparison could be made. Elements in either<br>
* key are null or NIL.<br>
* CMP_NE The keys cannot be ordered and they are not equal.<br>
* CMP_GT The first value that differed was greater than<br>
* the source.<br>
* CMP_LT The first value that differed was less than the<br>
* source.<br>
* <p>
* @param source Type: BusinessKey
* @return int
*/
public int compare(BusinessKey source) {
BooleanNullable result = null;
DataValue srcItem = null;
int srcItemIndex = 0;
if (source == null || this.getValues() == null) {
return BusinessKey.CMP_NULL;
}
//
// Iterate through each DataValues item in the Values array and compare
// it against the corresponding element in source's Values array.
//
if (this.getValues() != null) {
for (DataValue item : this.getValues()) {
srcItemIndex = srcItemIndex+1;
if (item == null) {
return BusinessKey.CMP_NULL;
//
// If source runs out of items then we must be greater
//
}
else if (srcItemIndex > source.getValues().size()) {
return BusinessKey.CMP_LONGER;
}
else {
srcItem = source.getValues().get(srcItemIndex-1);
if (srcItem == null) {
return BusinessKey.CMP_NULL;
}
}
//
// Numeric things might not be of the same class but they can all compare
// against each other so check this case first
//
if (item instanceof NumericData && srcItem instanceof NumericData) {
result = ((NumericData)item).isEqual((NumericData)srcItem);
if (result.getIsNull()) {
return BusinessKey.CMP_NULL;
}
else if (!(result.getValue())) {
result = ((NumericData)item).isGreaterThan((NumericData)srcItem);
if ((result).getValue()) {
return BusinessKey.CMP_GT;
}
return BusinessKey.CMP_LT;
}
}
else {
//
// Everthing else can only compare if it is of the same data type.
// We and the data type with 0x7F to mask off the nullable bit.
//
int myType = item.dataType()&127;
int srcType = srcItem.dataType()&127;
if (myType != srcType) {
result = item.getTextValue().isEqual(srcItem.getTextValue());
if (result.getIsNull()) {
return BusinessKey.CMP_NULL;
}
else if (!(result.getValue())) {
return BusinessKey.CMP_NE;
}
}
else {
switch (myType) {
case Constants.DV_DT_TEXT: {
result = ((TextData)item).isEqual((TextData)srcItem);
if (result.getIsNull()) {
return BusinessKey.CMP_NULL;
}
else if (!(result.getValue())) {
result = ((TextData)item).isGreaterThan((TextData)srcItem);
if ((result).getValue()) {
return BusinessKey.CMP_GT;
}
return BusinessKey.CMP_LT;
}
break;
}
case Constants.DV_DT_DATETIME: {
result = ((DateTimeData)item).isEqual((DateTimeData)srcItem);
if (result.getIsNull()) {
return BusinessKey.CMP_NULL;
}
else if (!(result.getValue())) {
result = ((DateTimeData)item).isGreaterThan((DateTimeData)srcItem);
if ((result).getValue()) {
return BusinessKey.CMP_GT;
}
return BusinessKey.CMP_LT;
}
break;
}
case Constants.DV_DT_INTERVAL: {
result = ((IntervalData)item).isEqual((IntervalData)srcItem);
if (result.getIsNull()) {
return BusinessKey.CMP_NULL;
}
else if (!(result.getValue())) {
result = ((IntervalData)item).isGreaterThan((IntervalData)srcItem);
if ((result).getValue()) {
return BusinessKey.CMP_GT;
}
return BusinessKey.CMP_LT;
}
break;
}
case Constants.DV_DT_BOOLEAN: {
result = ((BooleanData)item).isEqual((BooleanData)srcItem);
if (result.getIsNull()) {
return BusinessKey.CMP_NULL;
}
else if (!(result.getValue())) {
return BusinessKey.CMP_NE;
}
break;
}
default: {
result = item.getTextValue().isEqual(srcItem.getTextValue());
if (result.getIsNull()) {
return BusinessKey.CMP_NULL;
}
else if (!(result.getValue())) {
return BusinessKey.CMP_NE;
}
break;
}
}
}
}
// We'd like to do:
//
// result = Item.Compare(source.Values[srcValIndex]);
//
// if (result <> CMP_EQ) then
// return result;
// end if;
}
}
//
// If all of our items compared equal but we have fewer then we must be less
//
if (this.getValues().size() < source.getValues().size()) {
return BusinessKey.CMP_SHORTER;
}
//
// Same number of items, all compared equal, OK I guess we really are equal
//
return BusinessKey.CMP_EQ;
}
} // end class BusinessKey
// c Pass 2 Conversion Time: 734 milliseconds