Package DisplayProject.binding

Source Code of DisplayProject.binding.ListElementValueModelConverter

/*
Copyright (c) 2003-2008 ITerative Consulting Pty Ltd. All Rights Reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted
provided that the following conditions are met:

o Redistributions of source code must retain the above copyright notice, this list of conditions and
the following disclaimer.
 
o 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.
   
o This jcTOOL Helper Class software, whether in binary or source form may not be used within,
or to derive, any other product without the specific prior written permission of the copyright holder

 
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "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.


*/
package DisplayProject.binding;

import java.util.List;

import org.apache.log4j.Logger;

import DisplayProject.binding.value.AbstractConverter;
import DisplayProject.binding.value.ValueHolder;
import DisplayProject.binding.value.ValueModel;
import Framework.Array_Of_ListElement;
import Framework.CloneHelper;
import Framework.DataValue;
import Framework.IntegerData;
import Framework.IntegerNullable;
import Framework.ListElement;
import Framework.TextData;
import Framework.TextNullable;
import Framework.UsageException;

/**
* Converts between list elements used in lists which are generic holders
* containing both an integer value and a text value where either one can
* be bound to a bean property.
*/
@SuppressWarnings("serial")
public class ListElementValueModelConverter extends AbstractConverter implements TypeAwareValueModel {
    private ValueModel elementsValueModel;
    private Class<?> subjectType;
    private String failedToFindTextInList; // CraigM:11/08/2008.
    private Integer failedToFindNumberInList; // CraigM:11/08/2008.
    private boolean isFillInField; // CraigM:10/12/2008.
    private boolean forceValidValue;  // TF:18/07/2009:Force a valid element to be mapped.
    private static Logger _log = Logger.getLogger(ListElementValueModelConverter.class);

    public ListElementValueModelConverter(ValueModel subject, ValueModel elements, Class<?> subjectType) {
        super(subject);
        this.elementsValueModel = elements;
        this.subjectType = subjectType;
        this.isFillInField = false;
    }

    public ListElementValueModelConverter(ValueModel subject, List<ListElement> elements, Class<?> subjectType) {
        this(subject, new ValueHolder(elements), subjectType);
    }
   
    public void setIsFillInField() {
      this.isFillInField = true;
    }

    /**
     * @param str
     * @return the index for the passed in str.
     * CraigM:11/08/2008.
     */
    @SuppressWarnings("unchecked")
  private int getIndexInElementList(String str) {
      if (str == null) return -1;
      List<ListElement> elements = (List<ListElement>)elementsValueModel.getValue();
     
      for (int i = 0; i < elements.size(); i++) {
        if (str.equals(elements.get(i).getTextValue().toString())) {
          return i;
        }
      }
      return -1;
    }
   
    /**
     * @param integer
     * @return the index for the passed in integer.
     * CraigM:11/08/2008.
     */
    @SuppressWarnings("unchecked")
  private int getIndexInElementList(Integer integer) {
      if (integer == null) return -1;
      List<ListElement> elements = (List<ListElement>)elementsValueModel.getValue();
     
      for (int i = 0; i < elements.size(); i++) {
        // CraigM:19/11/2008 - Added null check.  JIRA: DET-51.
        if (elements.get(i) != null && integer.equals(elements.get(i).getIntegerValue())) {
          return i;
        }
      }
      return -1;
    }
   
    @SuppressWarnings("unchecked")
  private boolean isEmptyList() {
      List<ListElement> elements = (List<ListElement>)elementsValueModel.getValue();
      return elements == null || elements.size() == 0;
    }
   
    public Object convertFromSubject(Object subjectValue) {
      return convertFromSubject(subjectValue, true);
    }
   
    /**
     * Return the current value of this model. This differs from getValue() in that it does not have side-effects, such
     * as setting flags to indicate that an item has been selected
     * @return
     */
    public Object getCurrentValue() {
      return convertFromSubject(subject.getValue(), false);
    }
    @SuppressWarnings("unchecked")
  private Object convertFromSubject(Object subjectValue, boolean pAllowValueToBeForced)
    {
//        System.out.println("convertFromSubject(" + subjectValue + ") subjectType [" + subjectType.getName() + "]");
      // TF:10/7/07: Changed this to better handle integer datas
        if (subjectValue == null) {
            //return null;
         
          // TF:28/07/2009:This seemed like such a good idea at the time... This code was introduced to solve a problem where
          // a drop list mapped to an attribute of an object is set to an invalid value via code, eg "myObj.myDroplist = """.
          // Forte would set this value to be the first element in the drop list, java wasn't. This code corrected this. However,
          // it appears to have introduced an undesirable side effect -- when using the keyboard to change the value in the drop
          // list, we fire a property change event with oldvalue = null, newvalue = some_value. The AbstractConverter then calls
          // convertFromSubject on the old value, then on the new value. So we will be called with null as the parameter via the
          // convertFromSubject(oldValue) call. This will then set the value to be the first element in the list, overriding the
          // setting of the value we were doing in the first place!
//          if (forceValidValue && this.elementsValueModel.getValue() instanceof Array_Of_ListElement) {
//            List<ListElement> list = (List<ListElement>)this.elementsValueModel.getValue();
//            if (list != null && list.size() > 0) {
//              // Map a dummy return to the first element in the list
//              ListElement value = list.get(0);
//              this.setValue(value);
//              return value;
//            }
//          }
          return null;
        }

        else if (subjectValue instanceof DataValue && ((DataValue)subjectValue).isNull()) {
            return null;
        }
       
        // CraigM:11/08/2008 - Reset the failed conversion variables.
        failedToFindTextInList = null;
        failedToFindNumberInList = null;

        // TF:18/07/2009:Set a value if we need to force this control to have a valid value, eg a drop list.
        boolean forceValue = !this.isEmptyList() && this.forceValidValue && pAllowValueToBeForced;
       
        // Look for the item in the list
        if (subjectValue instanceof TextData || subjectValue instanceof String) {
          int index = this.getIndexInElementList(subjectValue.toString());
          // TF:18/07/2009:Check to see if we need to force the value
          if (index == -1 && forceValue) {
            index = 0;
          }
          if (index != -1) {
            return ((List<ListElement>)elementsValueModel.getValue()).get(index);
          }
        }
        else if (subjectValue instanceof Number) {
          int index = this.getIndexInElementList(((Number)subjectValue).intValue());
          // TF:18/07/2009:Check to see if we need to force the value
          if (index == -1 && forceValue) {
            index = 0;
          }
          if (index != -1) {
            return ((List<ListElement>)elementsValueModel.getValue()).get(index);
          }
        }
        else if (subjectValue instanceof IntegerData) {
          if (!((IntegerData)subjectValue).isNull()) {
            int index = this.getIndexInElementList(((IntegerData)subjectValue).asScalarInteger());
              // TF:18/07/2009:DET-127:Check to see if we need to force the value
              if (index == -1 && forceValue) {
                if (((IntegerData)subjectValue).isNullable()) {
                  return null;
                }
                index = 0;
              }
            if (index != -1) {
                return ((List<ListElement>)elementsValueModel.getValue()).get(index);
            }
          }
        }

        // TF:20/11/2009:Wrappered this in a conditional clause
        if (pAllowValueToBeForced) {
          // CraigM:11/08/2008 - Store the failed value (to be used later in a setElements call)
          if (subjectValue instanceof TextData || subjectValue instanceof String) {
               failedToFindTextInList = subjectValue.toString();
          }
          else if (subjectValue instanceof Number) {
               failedToFindNumberInList = ((Number)subjectValue).intValue();
          }
          else if (subjectValue instanceof IntegerData) {
            if (!((IntegerData)subjectValue).isNull()) {
              failedToFindNumberInList = ((IntegerData)subjectValue).asScalarInteger();
            }
          }
        }
       
        if (subjectValue instanceof Number) {
            return null;
        }
        // TF:10/7/07: If we're passed a nullable type and it's not able to be set in the list, it really should be null
        else if (subjectValue instanceof DataValue && ((DataValue)subjectValue).isNullable()) {
         
          // CraigM:10/12/2008 - Don't null our value if we are a FillInField
          if (this.isFillInField == false) {
            // ((DataValue)subjectValue).setIsNull(true);
            return null;
          }
        }
        return subjectValue;
    }

    public void setValue(Object newValue)
    {
//        System.out.println("setValue(" + newValue + ") subjectType [" + subjectType.getName() + "]");
        if (newValue instanceof String) {
            // This can be the case in an editable droplist, in which case it can only be mapped to a string or TextData
            if (TextData.class.isAssignableFrom(subjectType)) {
                TextData newObject;
                try {
                    // Map the string back to the underlying type for proper mapping
                    newObject = (TextData) subjectType.newInstance();
                    newObject.setValue((String)newValue);
                    subject.setValue(newObject);
                } catch (Exception e) {
                    throw new UsageException("Could not instantiate an instance of " + subjectType.getName(), e);
                }
            }
            else if (String.class.equals(subjectType)) {
                subject.setValue(newValue.toString());
            }
        }
        else if (newValue instanceof ListElement) {
            ListElement element = (ListElement) newValue;

            if (Integer.class.equals(subjectType) || Integer.TYPE.equals(subjectType)) {
                subject.setValue(new Integer(element.getIntegerValue()));
            }
            else if (IntegerData.class.equals(subjectType)) {
                subject.setValue(new IntegerData(element.getIntegerValue()));
            }
            else if (IntegerNullable.class.equals(subjectType)) {
                subject.setValue(new IntegerNullable(element.getIntegerValue()));
            }
            else if (IntegerData.class.isAssignableFrom(subjectType)) {
                try {
                    IntegerData anIntData = (IntegerData)subjectType.newInstance();
                    anIntData.setValue(element.getIntegerValue());
                    subject.setValue(anIntData);
                }
                catch (Exception e) {
                    // No default constructor
                    _log.debug("Could not instantiate class " + subjectType.getName(), e);
                }
            }
            else if (TextData.class.equals(subjectType)) {
                // TF:27/8/07:We need to clone the return value, otherwise we'll be returning the actual textdata mapped to the listelement
                // and any changes on this list element will erroneously affect the underlying list
                subject.setValue(CloneHelper.clone(element.getTextValue(), false));
            }
            else if (TextNullable.class.equals(subjectType)) {
        subject.setValue(new TextNullable(element.getTextValue()));
      }
            else if (TextData.class.isAssignableFrom(subjectType)) {
                try {
                    TextData aTextData = (TextData)subjectType.newInstance();
                    aTextData.setValue(element.getTextValue());
                    subject.setValue(aTextData);
                }
                catch (Exception e) {
                    // No default constructor
                    _log.debug("Could not instantiate class " + subjectType.getName(), e);
                }
            }
            else if (String.class.equals(subjectType)) {
                subject.setValue(element.toString());
            }
            else {
              // CraigM:11/12/2008 - We can always set the object value as a last resort
              subject.setValue(element.getObjectValue());
            }
        }

        // Handle nulls - Can happen when mapped to a IntegerNullable radio list. CraigM 11/10/2007
        else if (newValue == null) {
            if (IntegerNullable.class.equals(subjectType)) {
                subject.setValue(new IntegerNullable((Integer)null));
            }
            else if (TextNullable.class.equals(subjectType)) {
                subject.setValue(new TextNullable((String)null));
            }
        }
    }
   
    /**
     * If the convertFromSubject call failed to find the item in the list, we store the item.  Call this method to recheck the failed item.
     * This is useful if we set the item value before setting the list items.
     *
     * @return the index into the list of items that we tried to set earlier.  -1 if not found or no previous failed set.
     *
     * CraigM:11/08/2008.
     */
    public int getFailedSetIndex() {
      if (this.failedToFindTextInList != null) {
        return this.getIndexInElementList(this.failedToFindTextInList);
      }
      else if (this.failedToFindNumberInList != null) {
        return this.getIndexInElementList(this.failedToFindNumberInList);
      }
      return -1;
    }

    public void setElements(Array_Of_ListElement<ListElement> pList) {
        this.elementsValueModel.setValue(pList);
    }

    public Class<?> getSubjectType() {
        return subjectType;
    }

  public Class<?> getValueType() {
    return getSubjectType();
  }

  public void setForceValidValue(boolean mustForceValidValue) {
    this.forceValidValue = mustForceValidValue;
  }
}
TOP

Related Classes of DisplayProject.binding.ListElementValueModelConverter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.