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

com.exigen.ie.constrainer.impl.IntExpCardIntExp 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.IntArrayCards;
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: Cardinality of Integer Expression in Integer Expression Array
 * Description: class
 * Copyright: 2002
 * Company: Exigen Group, Inc.
 * @author Sergej Vanskov
 * @version 1.0
 */

public class IntExpCardIntExp extends IntExpImpl {
  private IntVar                    _result;
  private IntExp                    _exp;
  private LinkedList                _cards;
  private IntExpCardIntExpObserver  _exp_observer;

  public IntExpCardIntExp (IntExpArray array, IntExp exp) throws Failure {
    super (exp.constrainer ());
    if(constrainer ().showInternalNames ()) {
      name ("C{" + array.name() + "/" + exp.name() + "}");
    }

    _exp = exp;

    _cards = new LinkedList ();

    int                           min = _exp.min ();
    int                           max = _exp.max ();
    IntExpCard                    card;
    IntArrayCards                 cards = array.cards ();
    IntExpCardCardinalityObserver observer;

    for (int i = min; i <= max; i++) {
      if (_exp.contains (i)) {
        card = cards.cardAt (i);
        observer = new IntExpCardCardinalityObserver (card);
        card.attachObserver (observer);
        _cards.add (new IntExpAndObserver (card, observer));
      }
    }

    _exp_observer = new IntExpCardIntExpObserver (_cards, _exp);
    _exp.attachObserver (_exp_observer);

    int trace = 0;
    _result = constrainer ().addIntVarTraceInternal(
      calc_min (),
      calc_max (),
      "IX{" + array.name () + "/" + exp.name () + "}",
      IntVar.DOMAIN_PLAIN,
      trace
    );
  }
  public void setMin (int min) throws com.exigen.ie.constrainer.Failure {
    _result.setMin (min);

    if (_cards.size () == 1) {
      ((IntExpCard)_cards.get (0)).setMin (min);
    }
  }
  public void setMax (int max) throws com.exigen.ie.constrainer.Failure {
    _result.setMax (max);

    if (_cards.size () == 1) {
      ((IntExpCard)_cards.get (0)).setMax (max);
    }
  }
  public int min () {
    return _result.min ();
  }
  public int max () {
    return _result.max ();
  }
  public int calc_min () {
    if (_cards.size () == 1) {
      return ((IntExpCard) ((IntExpAndObserver) _cards.getFirst ())._exp).min ();
    }
    ListIterator iterator = _cards.listIterator ();
    int l_min = Constrainer.INT_MAX;
    int e_min;

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

    while (iterator.hasNext ()) {
      e_max = ((IntExpCard) ((IntExpAndObserver)iterator.next ())._exp).max ();
      if (e_max > l_max) {
        l_max = e_max;
      }
    }
    return l_max;
  }
  private class IntExpAndObserver {
    public IntExpAndObserver (IntExp exp, Observer observer) {
      _exp = exp;
      _observer = observer;
    }
    public IntExp   _exp;
    public Observer _observer;
  }

  private class IntExpCardIntExpObserver extends Observer {
    IntExp      _exp;
    LinkedList  _cards;

    public IntExpCardIntExpObserver (LinkedList cards, IntExp exp) {
      _cards = cards;
      _exp = exp;
    }
    public 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 ();
            IntExpAndObserver exp_and_observer;

            while (!_cards.isEmpty ()) {
              exp_and_observer = (IntExpAndObserver) _cards.getFirst ();
              if (((IntExpCard)exp_and_observer._exp).get_cardinality_value() < min) {
                exp_and_observer._exp.detachObserver (exp_and_observer._observer);
                _cards.removeFirst ();
              } else {
                break;
              }
            }
            updateMinMax ();
          }
          break;
        case MAX:
          {
            int max = i_event.max ();
            IntExpAndObserver exp_and_observer;

            while (!_cards.isEmpty ()) {
              exp_and_observer = (IntExpAndObserver) _cards.getLast ();
              if (((IntExpCard)exp_and_observer._exp).get_cardinality_value() > max) {
                exp_and_observer._exp.detachObserver (exp_and_observer._observer);
                _cards.removeLast ();
              } else {
                break;
              }
            }
            updateMinMax ();
          }
          break;
        case VALUE:
        case MINMAX:
          {
            int min = i_event.min ();
            IntExpAndObserver exp_and_observer;

            while (!_cards.isEmpty ()) {
              exp_and_observer = (IntExpAndObserver) _cards.getFirst ();
              if (((IntExpCard)exp_and_observer._exp).get_cardinality_value() < min) {
                exp_and_observer._exp.detachObserver (exp_and_observer._observer);
                _cards.removeFirst ();
              } else {
                break;
              }
            }

            int max = i_event.max ();

            while (!_cards.isEmpty ()) {
              exp_and_observer = (IntExpAndObserver) _cards.getLast ();
              if (((IntExpCard)exp_and_observer._exp).get_cardinality_value() > max) {
                exp_and_observer._exp.detachObserver (exp_and_observer._observer);
                _cards.removeLast ();
              } else {
                break;
              }
            }

            updateMinMax ();
          }
          break;
        case REMOVE:
          {
            for (int i = 0; i < i_event.numberOfRemoves (); i++ ) {
              int               rem = i_event.removed (i);
              IntExpAndObserver exp_and_observer;
              ListIterator      iterator = _cards.listIterator ();
              while (iterator.hasNext ()) {
                exp_and_observer = (IntExpAndObserver) iterator.next ();
                if ( ((IntExpCard)exp_and_observer._exp).get_cardinality_value () == rem) {
                  exp_and_observer._exp.detachObserver (exp_and_observer._observer);
                  _cards.remove (exp_and_observer);
                  break;
                }
              }
            }
            updateMinMax ();
          }
          break;
      }
    }
    public Object master () {
      return IntExpCardIntExp.this;
    }
    public int subscriberMask() {
      return MIN | MAX | VALUE | REMOVE;
    }
  }

  private class IntExpCardCardinalityObserver extends Observer {
    private IntExpCard  _exp;

    public IntExpCardCardinalityObserver (IntExpCard 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 IntExpCardIntExp.this;
    }
    public int subscriberMask() {
      return MIN | MAX | VALUE | REMOVE;
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy