/**
   * Constructs the property widget
   *
   * @param beanJobBuilder the transformer job builder for the table lookup
   * @param inputColumnsProperty the property represeting the columns to use for settig up
   *     conditional lookup (InputColumn[])
   * @param mappedColumnsProperty the property representing the mapped columns in the datastore
   *     (String[])
   */
  public MultipleMappedColumnsPropertyWidget(
      AbstractBeanJobBuilder<?, ?, ?> beanJobBuilder,
      ConfiguredPropertyDescriptor inputColumnsProperty,
      ConfiguredPropertyDescriptor mappedColumnsProperty) {
    super(beanJobBuilder, inputColumnsProperty);
    _mappedColumnComboBoxes = new WeakHashMap<InputColumn<?>, SourceColumnComboBox>();
    _mappedColumnsProperty = mappedColumnsProperty;

    _tableRef = new MutableRef<Table>();
    _mappedColumnNamesPropertyWidget = createMappedColumnNamesPropertyWidget();
    _sourceColumnUpdating = false;

    final InputColumn<?>[] currentValue = getCurrentValue();
    final String[] currentMappedColumnsValue =
        (String[]) beanJobBuilder.getConfiguredProperty(mappedColumnsProperty);
    if (currentValue != null && currentMappedColumnsValue != null) {
      // first create combo's, then set value (so combo is ready before it
      // is requested)

      _mappedColumnNamesPropertyWidget.setValue(currentMappedColumnsValue);
      final int minLength = Math.min(currentValue.length, currentMappedColumnsValue.length);
      for (int i = 0; i < minLength; i++) {
        final InputColumn<?> inputColumn = currentValue[i];
        final String mappedColumnName = currentMappedColumnsValue[i];
        createComboBox(inputColumn, new MutableColumn(mappedColumnName));
      }

      setValue(currentValue);
    }
  }
 public PropertyWidget<?> create(String propertyName) {
   BeanDescriptor<?> descriptor = _beanJobBuilder.getDescriptor();
   ConfiguredPropertyDescriptor propertyDescriptor =
       descriptor.getConfiguredProperty(propertyName);
   if (propertyDescriptor == null) {
     throw new IllegalArgumentException("No such property: " + propertyName);
   }
   return create(propertyDescriptor);
 }
  /** Invoked whenever a configured property within this widget factory is changed. */
  public void onConfigurationChanged() {
    final Collection<PropertyWidget<?>> widgets = getWidgets();

    for (PropertyWidget<?> widget : widgets) {
      @SuppressWarnings("unchecked")
      final PropertyWidget<Object> objectWidget = (PropertyWidget<Object>) widget;
      final ConfiguredPropertyDescriptor propertyDescriptor = objectWidget.getPropertyDescriptor();
      final Object value = _beanJobBuilder.getConfiguredProperty(propertyDescriptor);
      objectWidget.onValueTouched(value);
    }
  }
 /**
  * Registers a widget in this factory in rare cases when the factory is not used to actually
  * instantiate the widget, but it is still needed to register the widget for compliancy with eg.
  * the onConfigurationChanged() behaviour.
  *
  * @param propertyDescriptor
  * @param widget
  */
 public void registerWidget(
     ConfiguredPropertyDescriptor propertyDescriptor, PropertyWidget<?> widget) {
   if (widget == null) {
     _widgets.remove(propertyDescriptor);
   } else {
     _widgets.put(propertyDescriptor, widget);
     @SuppressWarnings("unchecked")
     PropertyWidget<Object> objectWidget = (PropertyWidget<Object>) widget;
     Object value = _beanJobBuilder.getConfiguredProperty(objectWidget.getPropertyDescriptor());
     objectWidget.initialize(value);
   }
 }
  @Inject
  protected PropertyWidgetFactory(
      AbstractBeanJobBuilder<?, ?, ?> beanJobBuilder, InjectorBuilder injectorBuilder) {
    _beanJobBuilder = beanJobBuilder;
    _injectorBuilder = injectorBuilder;
    _propertyWidgetMappings =
        new IdentityHashMap<ConfiguredPropertyDescriptor, PropertyWidgetMapping>();

    Set<ConfiguredPropertyDescriptor> mappedProperties =
        beanJobBuilder.getDescriptor().getConfiguredPropertiesByAnnotation(MappedProperty.class);
    for (ConfiguredPropertyDescriptor mappedProperty : mappedProperties) {
      MappedProperty annotation = mappedProperty.getAnnotation(MappedProperty.class);
      String mappedToName = annotation.value();
      ConfiguredPropertyDescriptor mappedToProperty =
          beanJobBuilder.getDescriptor().getConfiguredProperty(mappedToName);

      PropertyWidgetMapping propertyWidgetMapping =
          buildMappedPropertyWidget(mappedProperty, mappedToProperty);

      _propertyWidgetMappings.put(mappedProperty, propertyWidgetMapping);
      _propertyWidgetMappings.put(mappedToProperty, propertyWidgetMapping);
    }
  }
  /**
   * Creates (and registers) a widget that fits the specified configured property.
   *
   * @param propertyDescriptor
   * @return
   */
  public PropertyWidget<?> create(ConfiguredPropertyDescriptor propertyDescriptor) {
    final PropertyWidget<?> result;

    // first check if there is a mapping created for this property
    // descriptor
    PropertyWidget<?> propertyWidget = getMappedPropertyWidget(propertyDescriptor);
    if (propertyWidget != null) {
      result = propertyWidget;
    } else {
      // check for fitting property widgets by type
      final Class<?> type = propertyDescriptor.getBaseType();

      final Class<? extends PropertyWidget<?>> widgetClass;
      if (propertyDescriptor.isArray()) {
        if (propertyDescriptor.isInputColumn()) {
          widgetClass = MultipleInputColumnsPropertyWidget.class;
        } else if (ReflectionUtils.isString(type)) {
          widgetClass = MultipleStringPropertyWidget.class;
        } else if (type == Dictionary.class) {
          widgetClass = MultipleDictionariesPropertyWidget.class;
        } else if (type == SynonymCatalog.class) {
          widgetClass = MultipleSynonymCatalogsPropertyWidget.class;
        } else if (type == StringPattern.class) {
          widgetClass = MultipleStringPatternPropertyWidget.class;
        } else if (type.isEnum()) {
          widgetClass = MultipleEnumPropertyWidget.class;
        } else if (type == Class.class) {
          widgetClass = MultipleClassesPropertyWidget.class;
        } else if (type == char.class) {
          widgetClass = MultipleCharPropertyWidget.class;
        } else if (ReflectionUtils.isNumber(type)) {
          widgetClass = MultipleNumberPropertyWidget.class;
        } else {
          // not yet implemented
          widgetClass = DummyPropertyWidget.class;
        }
      } else {

        if (propertyDescriptor.isInputColumn()) {
          if (_beanJobBuilder.getDescriptor().getConfiguredPropertiesForInput().size() == 1) {
            // if there is only a single input column property, it
            // will
            // be displayed using radiobuttons.
            widgetClass = SingleInputColumnRadioButtonPropertyWidget.class;
          } else {
            // if there are multiple input column properties, they
            // will
            // be displayed using combo boxes.
            widgetClass = SingleInputColumnComboBoxPropertyWidget.class;
          }
        } else if (ReflectionUtils.isCharacter(type)) {
          widgetClass = SingleCharacterPropertyWidget.class;
        } else if (ReflectionUtils.isString(type)) {
          widgetClass = SingleStringPropertyWidget.class;
        } else if (ReflectionUtils.isBoolean(type)) {
          widgetClass = SingleBooleanPropertyWidget.class;
        } else if (ReflectionUtils.isNumber(type)) {
          widgetClass = SingleNumberPropertyWidget.class;
        } else if (ReflectionUtils.isDate(type)) {
          widgetClass = SingleDatePropertyWidget.class;
        } else if (type == Dictionary.class) {
          widgetClass = SingleDictionaryPropertyWidget.class;
        } else if (type == SynonymCatalog.class) {
          widgetClass = SingleSynonymCatalogPropertyWidget.class;
        } else if (type == StringPattern.class) {
          widgetClass = SingleStringPatternPropertyWidget.class;
        } else if (type.isEnum()) {
          widgetClass = SingleEnumPropertyWidget.class;
        } else if (ReflectionUtils.is(type, Resource.class)) {
          widgetClass = SingleResourcePropertyWidget.class;
        } else if (type == File.class) {
          widgetClass = SingleFilePropertyWidget.class;
        } else if (type == Pattern.class) {
          widgetClass = SinglePatternPropertyWidget.class;
        } else if (ReflectionUtils.is(type, Datastore.class)) {
          widgetClass = SingleDatastorePropertyWidget.class;
        } else if (type == Class.class) {
          widgetClass = SingleClassPropertyWidget.class;
        } else {
          // not yet implemented
          widgetClass = DummyPropertyWidget.class;
        }
      }

      final Injector injector = getInjectorForPropertyWidgets(propertyDescriptor);
      result = injector.getInstance(widgetClass);
    }

    registerWidget(propertyDescriptor, result);
    return result;
  }