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

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

package com.exigen.ie.constrainer.impl;
import java.util.Collection;
import java.util.HashSet;

import com.exigen.ie.constrainer.Constrainer;
import com.exigen.ie.constrainer.EventOfInterest;
import com.exigen.ie.constrainer.Failure;
import com.exigen.ie.constrainer.Observer;
import com.exigen.ie.constrainer.Subject;
import com.exigen.ie.constrainer.Undo;
import com.exigen.ie.constrainer.UndoImpl;
import com.exigen.ie.constrainer.Undoable;
import com.exigen.ie.tools.FastVector;
import com.exigen.ie.tools.Reusable;
import com.exigen.ie.tools.ReusableFactory;

/**
 * A generic implementation of the Subject interface.
 */
public abstract class SubjectImpl extends UndoableOnceImpl implements Subject
{
  protected FastVector	  _observers;
  protected boolean       _in_process;
  protected int           _publisher_mask;

  public SubjectImpl(Constrainer   constrainer, String name)
  {
    super(constrainer,name);
    if (constrainer.showVariableNames())
      _name = name;

    _observers = new FastVector(); //10,5);

    _in_process = false;
  }

  public SubjectImpl(Constrainer   constrainer)
  {
    this(constrainer,"");
  }

  public void attachObserver(Observer observer)
  {
//    Debug.on(); Debug.print(this + " Attach: " + observer); Debug.off();
    _observers.addElement(observer);
    publisherMask(_publisher_mask | observer.subscriberMask());
    constrainer().addUndo(UndoAttachObserver.getUndo(this,observer));
  }

  public void forcedAttachObserver(Observer observer)
  {
//    Debug.on(); Debug.print(this + " AttachForced: " + observer); Debug.off();
    _observers.addElement(observer);
  }

  public void detachObserver(Observer observer)
  {

//    Debug.on(); Debug.print(this + " Detach: " + observer); Debug.off();
    _observers.removeElement(observer);
    constrainer().addUndo(UndoDetachObserver.getUndo(this,observer));
  }

  public void forcedDetachObserver(Observer observer)
  {
//    Debug.on(); Debug.print(this + " DetachForced: " + observer); Debug.off();
    _observers.removeElement(observer);
  }

  public void addToPropagationQueue()
  {
    if (!_in_process)
    {
      constrainer().addToPropagationQueue(this);
      _in_process = true;
    }
  }

  public void inProcess(boolean flag)
  {
    _in_process = flag;
  }

  public boolean inProcess()
  {
    return _in_process;
  }

  public abstract void propagate() throws Failure;

  final public void notifyObservers(EventOfInterest interest) throws Failure
  {
//    Debug.on(); Debug.print("* "+interest); Debug.off();
//   FastVector observers = (FastVector)_observers.clone();
    FastVector observers = _observers;
    _constrainer.incrementNumberOfNotifications();
    int size = observers.size();
    for(int i=0; i < size ; ++i)
    {
      Observer observer = (Observer)observers.elementAt(i);
      if (observer.interestedIn(interest))
      {
//        Debug.on(); Debug.print("Observer "+i+": "+observer);Debug.off();
        observer.update(this,interest);
      }
    }
    interest.free();
  }

  public FastVector observers()
  {
    return _observers;
  }

  public void trace()
  {
    class ObserverTraceAll extends Observer
    {
      public void update(Subject var, EventOfInterest interest)
        throws Failure
      {
        System.out.println("Trace "+interest+": "+var);
      }

      public int subscriberMask()
      {
        return EventOfInterest.ALL;
      }

      public Object master()
      {
        return null;
      }

    } //~ ObserverTraceAll

    attachObserver(new ObserverTraceAll());
  }

  public void trace(int event_type)
  {
    class ObserverTrace extends Observer
    {
      private int _event_type;

      ObserverTrace(int event_type)
      {
        _event_type = event_type;
      }

      public void update(Subject var, EventOfInterest interest)
        throws Failure
      {
        System.out.println("Trace "+interest+": "+var);
      }

      /*
      public boolean interestedIn(EventOfInterest event)
      {
        switch(_event_type)
        {
          case EventOfInterest.MAX: return event.isMaxEvent();
          case EventOfInterest.MIN: return event.isMinEvent();
          case EventOfInterest.VALUE: return event.isValueEvent();
          case EventOfInterest.REMOVE: return event.isRemoveEvent();
        }
        return  true;
      }
      */
      public int subscriberMask()
      {
        return _event_type;
      }

      public Object master()
      {
        return null;
      }

    } //~ ObserverTrace

    attachObserver(new ObserverTrace(event_type));
  }

  public void publish(int mask)
  {
    publisherMask(_publisher_mask | mask);
  }

  public int publisherMask()
  {
    return _publisher_mask;
  }

  public void onMaskChange()
  {
  }

  public void reattachObserver(Observer observer)
  {
    publisherMask(_publisher_mask | observer.subscriberMask());
  }

  public void publisherMask(int mask)
  {

    if (mask != _publisher_mask)
    {
//      System.out.println("Pub Mask: " + mask + " for: " + this + " old:" + _publisher_mask);
      _publisher_mask = mask;
      onMaskChange();
      addUndo();
    }
  }


  public Collection allDependents()
  {
    HashSet dependendts = new HashSet();

    for (int i = 0; i < _observers.size(); ++i)
    {
      Observer obs = (Observer) _observers.elementAt(i);
      Object master = obs.master();

      if (master == null)
        continue;

      if (dependendts.contains(master))
        continue;

      dependendts.add(master);

      if (master instanceof Subject)
        dependendts.addAll(((Subject) master).allDependents());

    }

    return dependendts;
  }


  public void forcePublisherMask(int mask)
  {
    _publisher_mask = mask;
  }

  public Undo createUndo()
  {
    return UndoSubject.getUndo();
  }

  /**
   * Undo Class for Subject.
   */
  public static class UndoSubject extends UndoImpl
  {

    static ReusableFactory _factory = new ReusableFactory()
    {
        protected Reusable createNewElement()
        {
          return new UndoSubject();
        }

    };

    static UndoSubject getUndo()
    {
      return (UndoSubject) _factory.getElement();
    }

    private int 	  _event_mask;

    public void undoable(Undoable u)
    {
      super.undoable(u);
      Subject subject = (Subject) u;
      _event_mask = subject.publisherMask();
    }

    public void undo()
    {
        Subject subject = (Subject) undoable();
        subject.forcePublisherMask(_event_mask);
        super.undo();
    }

    /**
     * Returns a String representation of this object.
     * @return a String representation of this object.
     */
    public String toString()
    {
      return "UndoSubject "+undoable()+": mask="+_event_mask;
    }

  } // ~UndoSubject

  /**
   * Undo Class for attached Observers.
   */
  static final class UndoAttachObserver extends UndoImpl
  {
    static ReusableFactory _factory = new ReusableFactory()
    {
        protected Reusable createNewElement()
        {
          return new UndoAttachObserver();
        }

    };

    static UndoAttachObserver getUndo(Subject subject, Observer observer)
    {
      UndoAttachObserver undo = (UndoAttachObserver) _factory.getElement();
      undo.undoable(subject);
      undo._observer = observer;
      return undo;
    }

    Observer _observer;

    public void undo()
    {
      Subject subject = (Subject)undoable();
      subject.forcedDetachObserver(_observer);
    }

    /**
     * Returns a String representation of this object.
     * @return a String representation of this object.
     */
    public String toString()
    {
      return "UndoAttachObserver "+_observer;
    }

  } // ~UndoAttachObserver

  /**
   * Undo Class for detach Observers.
   */
  static final class UndoDetachObserver extends UndoImpl
  {

    static ReusableFactory _factory = new ReusableFactory()
    {
        protected Reusable createNewElement()
        {
          return new UndoDetachObserver();
        }

    };

    static UndoDetachObserver getUndo(Subject subject, Observer observer)
    {
      UndoDetachObserver undo = (UndoDetachObserver) _factory.getElement();
      undo.undoable(subject);
      undo._observer = observer;
      return undo;
    }

    private Observer _observer;

    public void undo()
    {
      Subject subject = (Subject)undoable();
      subject.forcedAttachObserver(_observer);
    }

    /**
     * Returns a String representation of this object.
     * @return a String representation of this object.
     */
    public String toString()
    {
      return "UndoDetachObserver "+_observer;
    }

  } // ~UndoDetachObserver

} // ~SubjectImpl




© 2015 - 2024 Weber Informatics LLC | Privacy Policy