All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.exigen.ie.constrainer.impl.IntExpArrayElement Maven / Gradle / Ivy

package com.exigen.ie.constrainer.impl;

import java.util.LinkedList;
import java.util.ListIterator;

import com.exigen.ie.constrainer.Constrainer;
import com.exigen.ie.constrainer.EventOfInterest;
import com.exigen.ie.constrainer.Failure;
import com.exigen.ie.constrainer.IntExp;
import com.exigen.ie.constrainer.IntExpArray;
import com.exigen.ie.constrainer.IntVar;
import com.exigen.ie.constrainer.Observer;
import com.exigen.ie.constrainer.Subject;

/**
 * Title: Integer expression array element with index specified by
 * integer expression.
 * Description: class
 * Copyright: (c) 2002
 * Company: Exigen Group 2002
 * @author Sergey Vanskov
 * @version 1.0
 */

public class IntExpArrayElement extends IntExpImpl {
  private LinkedList  _elements;
  private IntExp      _index;
  private Observer    _index_observer;
  private IntVar      _result;

  public IntExpArrayElement (IntExpArray array, IntExp index) throws Failure {
    super (index.constrainer ());

    if(constrainer ().showInternalNames ()) {
      name (array.name () + "[" + index.name () + "]");
    }
    _index = index;
    _index.setMin (0);
    _index.setMax (array.size () - 1);
    _elements = new LinkedList ();

    int                     min = index.min ();
    int                     max = index.max ();
    IntExp                  element;
    ArrayElementObserver observer;

    for (int i = min; i <= max; i ++) {
      element = array.get (i);
      observer = new ArrayElementObserver (element);
      element.attachObserver (observer);
      _elements.add (
        new ArrayElementAndObserver (
          element,
          i,
          observer
        )
      );
    }

    _index_observer = new IndexObserver (_elements, _index);
    _index.attachObserver (_index_observer);

    int trace = 0;
    _result = constrainer().addIntVarTraceInternal(
      calc_min (),
      calc_max (),
      array.name () + "[" + index.name () + "](internal)",
      IntVar.DOMAIN_PLAIN,
      trace
    );
  }

  public void setMin (int min) throws Failure {
    _result.setMin (min);
    if (_elements.size () == 1) {
      ((IntExp) _elements.getFirst ()).setMin (min);
    }
  }
  public void setMax (int max) throws Failure {
    _result.setMax (max);
    if (_elements.size () == 1) {
      ((IntExp) _elements.getFirst ()).setMax (max);
    }
  }
  public int min () {
    return _result.min ();
  }
  public int max () {
    return _result.max ();
  }
  public int calc_min () {
    if (_elements.size () == 1) {
      return ((IntExp) ((ArrayElementAndObserver) _elements.getFirst ())._exp).min ();
    }
    ListIterator iterator = _elements.listIterator ();
    int l_min = Constrainer.INT_MAX;
    int e_min;

    while (iterator.hasNext ()) {
      e_min = ((IntExp) ((ArrayElementAndObserver) iterator.next ())._exp).min ();
      if (e_min < l_min) {
        l_min = e_min;
      }
    }
    return l_min;
  }
  public int calc_max () {
    if (_elements.size () == 1) {
      return ((IntExp) ((ArrayElementAndObserver) _elements.getFirst ())._exp).max ();
    }
    ListIterator iterator = _elements.listIterator ();
    int l_max = Constrainer.INT_MIN;
    int e_max;

    while (iterator.hasNext ()) {
      e_max = ((IntExp) ((ArrayElementAndObserver)iterator.next ())._exp).max ();
      if (e_max > l_max) {
        l_max = e_max;
      }
    }
    return l_max;
  }
  private class ArrayElementAndObserver {
    public ArrayElementAndObserver (IntExp exp, int index, Observer observer) {
      _index = index;
      _exp = exp;
      _observer = observer;
    }
    public int      _index;
    public IntExp   _exp;
    public Observer _observer;
  }
  private class ArrayElementObserver extends Observer {
    private IntExp  _exp;

    public ArrayElementObserver (IntExp exp) {
      _exp = exp;
    }
    public void update (Subject subject, EventOfInterest event) throws Failure {
      IntEvent  i_event = (IntEvent) event;

      if (i_event.min () > _result.min ()) {
        _result.setMin (calc_min ());
      }
      if (i_event.max () < _result.max ()) {
        _result.setMax (calc_max ());
      }
    }
    public Object master () {
      return IntExpArrayElement.this;
    }
    public int subscriberMask() {
      return MIN | MAX | VALUE | REMOVE;
    }
  }
  private class IndexObserver extends Observer {
    IntExp      _index;
    LinkedList  _elements;

    public IndexObserver (LinkedList elements, IntExp index) {
      _elements = elements;
      _index = index;
    }
    private void updateMinMax () throws Failure {
      _result.setMin (calc_min ());
      _result.setMax (calc_max ());
    }
    public void update (Subject subject, EventOfInterest event) throws Failure {
      IntEvent  i_event = (IntEvent) event;
      switch (event.type ()) {
        case MIN:
          {
            int                     min = i_event.min ();
            ArrayElementAndObserver element_and_observer;

            while (!_elements.isEmpty ()) {
              element_and_observer = (ArrayElementAndObserver) _elements.getFirst ();
              if (element_and_observer._index < min) {
                element_and_observer._exp.detachObserver (element_and_observer._observer);
                _elements.removeFirst ();
              } else {
                break;
              }
            }
            updateMinMax ();
          }
          break;
        case MAX:
          {
            int                     max = i_event.max ();
            ArrayElementAndObserver element_and_observer;

            while (!_elements.isEmpty ()) {
              element_and_observer = (ArrayElementAndObserver) _elements.getLast ();
              if (element_and_observer._index > max) {
                element_and_observer._exp.detachObserver (element_and_observer._observer);
                _elements.removeLast ();
              } else {
                break;
              }
            }
            updateMinMax ();
          }
          break;
        case VALUE:
        case MINMAX:
          {
            int                     min = i_event.min ();
            ArrayElementAndObserver element_and_observer;

            while (!_elements.isEmpty ()) {
              element_and_observer = (ArrayElementAndObserver) _elements.getFirst ();
              if (element_and_observer._index < min) {
                element_and_observer._exp.detachObserver (element_and_observer._observer);
                _elements.removeFirst ();
              } else {
                break;
              }
            }

            int                     max = i_event.max ();

            while (!_elements.isEmpty ()) {
              element_and_observer = (ArrayElementAndObserver) _elements.getLast ();
              if (element_and_observer._index > max) {
                element_and_observer._exp.detachObserver (element_and_observer._observer);
                _elements.removeLast ();
              } else {
                break;
              }
            }

            updateMinMax ();
          }
          break;
        case REMOVE:
          {
            for (int i = 0; i < i_event.numberOfRemoves (); i++ ) {
              int                     rem = i_event.removed (i);
              ArrayElementAndObserver element_and_observer;
              ListIterator            iterator = _elements.listIterator ();
              while (iterator.hasNext ()) {
                element_and_observer = (ArrayElementAndObserver) iterator.next ();
                if (element_and_observer._index == rem) {
                  element_and_observer._exp.detachObserver (element_and_observer._observer);
                  _elements.remove (element_and_observer);
                  break;
                }
              }
            }
            updateMinMax ();
          }
          break;
      }
      if (_elements.size () == 1) {
        ArrayElementAndObserver element_and_observer;
        element_and_observer = (ArrayElementAndObserver) _elements.getFirst ();
        element_and_observer._exp.setMin (_result.min ());
        element_and_observer._exp.setMax (_result.max ());
      }
    }
    public Object master () {
      return IntExpArrayElement.this;
    }
    public int subscriberMask() {
      return MIN | MAX | VALUE | REMOVE;
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy