001: /*
002: * This file is part of JGAP.
003: *
004: * JGAP offers a dual license model containing the LGPL as well as the MPL.
005: *
006: * For licensing information please see the file license.txt included with JGAP
007: * or have a look at the top of class org.jgap.Chromosome which representatively
008: * includes the JGAP license policy applicable for any file delivered with JGAP.
009: */
010: package org.jgap.impl;
011:
012: import org.jgap.*;
013:
014: /**
015: * Base class for all Genes based on numbers.
016: *
017: * @author Klaus Meffert
018: * @since 1.1 (most code moved and adapted from IntegerGene)
019: */
020: public abstract class NumberGene extends BaseGene {
021: /** String containing the CVS revision. Read out via reflection!*/
022: private static final String CVS_REVISION = "$Revision: 1.23 $";
023:
024: /**
025: * References the internal value (allele) of this Gene
026: * E.g., for DoubleGene this is of type Double
027: */
028: private Object m_value;
029:
030: public NumberGene(Configuration a_config)
031: throws InvalidConfigurationException {
032: super (a_config);
033: }
034:
035: /**
036: * Compares this NumberGene with the specified object (which must also
037: * be a NumberGene) for order, which is determined by the number value of
038: * this Gene compared to the one provided for comparison.
039: *
040: * @param a_other the NumberGene to be compared to this NumberGene
041: * @return a negative integer, zero, or a positive integer as this object
042: * is less than, equal to, or greater than the object provided for comparison
043: *
044: * @throws ClassCastException if the specified object's type prevents it
045: * from being compared to this NumberGene
046: *
047: * @author Klaus Meffert
048: * @since 1.1
049: */
050: public int compareTo(final Object a_other) {
051: NumberGene otherGene = (NumberGene) a_other;
052: // First, if the other gene (or its value) is null, then this is
053: // the greater allele. Otherwise, just use the overridden compareToNative
054: // method to perform the comparison.
055: // ----------------------------------------------------------------------
056: if (otherGene == null) {
057: return 1;
058: } else if (otherGene.m_value == null) {
059: // Check if type corresponds (because we could have a type not inherited
060: // from NumberGene).
061: // ---------------------------------------------------------------------
062: if (!otherGene.getClass().equals(getClass())) {
063: throw new ClassCastException(
064: "Comparison not possible: different types!");
065: }
066: // If our value is also null, then we're the same. Otherwise,
067: // this is the greater gene.
068: // ----------------------------------------------------------
069: if (m_value == null) {
070: if (isCompareApplicationData()) {
071: return compareApplicationData(getApplicationData(),
072: otherGene.getApplicationData());
073: } else {
074: return 0;
075: }
076: } else {
077: return 1;
078: }
079: } else {
080: try {
081: if (!otherGene.getClass().equals(getClass())) {
082: throw new ClassCastException(
083: "Comparison not possible: different types!");
084: }
085: if (m_value == null) {
086: return -1;
087: }
088: int res = compareToNative(m_value, otherGene.m_value);
089: if (res == 0) {
090: if (isCompareApplicationData()) {
091: return compareApplicationData(
092: getApplicationData(), otherGene
093: .getApplicationData());
094: } else {
095: return 0;
096: }
097: } else {
098: return res;
099: }
100: } catch (ClassCastException e) {
101: throw e;
102: }
103: }
104: }
105:
106: /**
107: * Compares to objects by first casting them into their expected type
108: * (e.g. Integer for IntegerGene) and then calling the compareTo-method
109: * of the casted type.
110: *
111: * @param a_o1 first object to be compared, always is not null
112: * @param a_o2 second object to be compared, always is not null
113: * @return a negative integer, zero, or a positive integer as this object
114: * is less than, equal to, or greater than the object provided for comparison
115: *
116: * @author Klaus Meffert
117: * @since 1.1
118: */
119: protected abstract int compareToNative(Object a_o1, Object a_o2);
120:
121: /**
122: * Sets the value (allele) of this Gene to the new given value. This class
123: * expects the value to be an instance of current type (e.g. Integer).
124: * If the value is above or below the upper or lower bounds, it will be
125: * mappped to within the allowable range.
126: *
127: * @param a_newValue the new value of this Gene instance
128: *
129: * @author Klaus Meffert
130: * @since 1.1
131: */
132: public void setAllele(final Object a_newValue) {
133: if (getConstraintChecker() != null) {
134: if (!getConstraintChecker().verify(this , a_newValue, null,
135: -1)) {
136: return;
137: }
138: }
139: m_value = a_newValue;
140: // If the value isn't between the upper and lower bounds of this
141: // Gene, map it to a value within those bounds.
142: // -------------------------------------------------------------
143: mapValueToWithinBounds();
144: }
145:
146: /**
147: * Maps the value of this NumberGene to within the bounds specified by
148: * the m_upperBounds and m_lowerBounds instance variables. The value's
149: * relative position within the integer range will be preserved within the
150: * bounds range (in other words, if the value is about halfway between the
151: * integer max and min, then the resulting value will be about halfway
152: * between the upper bounds and lower bounds). If the value is null or
153: * is already within the bounds, it will be left unchanged.
154: *
155: * @author Klaus Meffert
156: * @since 1.1
157: */
158: protected abstract void mapValueToWithinBounds();
159:
160: protected Object getInternalValue() {
161: return m_value;
162: }
163: }
|