package agg.attribute.view.impl;
import java.lang.ref.WeakReference;
import java.util.Hashtable;
import java.util.Vector;
import agg.attribute.AttrEvent;
import agg.attribute.AttrObserver;
import agg.attribute.AttrTuple;
import agg.attribute.AttrType;
import agg.attribute.impl.AttrTupleManager;
import agg.attribute.impl.DeclTuple;
import agg.attribute.impl.DeclMember;
import agg.attribute.impl.TupleObject;
import agg.attribute.view.AttrViewEvent;
import agg.attribute.view.AttrViewObserver;
import agg.attribute.view.AttrViewSetting;
/**
* @author $Author: olga $
* @version $Id: OpenViewSetting.java,v 1.12 2010/09/23 08:15:32 olga Exp $
*/
public class OpenViewSetting extends ViewSetting implements AttrObserver {
/** Table of tuple formats for (type) tuples. */
protected Hashtable<DeclTuple, TupleFormat> formatTab;
protected MaskedViewSetting maskedView;
protected int lastOpenDeletedSlot0 = -1;
protected int lastOpenDeletedSlot1 = -1;
protected int lastMaskedDeletedSlot0 = -1;
protected int lastMaskedDeletedSlot1 = -1;
static final long serialVersionUID = 4242537253046200014L;
public OpenViewSetting(AttrTupleManager m) {
super(m);
this.maskedView = new MaskedViewSetting(this);
this.formatTab = new Hashtable<DeclTuple, TupleFormat>(50);
}
/** Getting the tuple format for a (type) tuple, raw style. */
protected TupleFormat rawGetFormat(AttrTuple attr) {
DeclTuple type = ((TupleObject) attr).getTupleType();
TupleFormat format = this.formatTab.get(type);
return format;
}
/** Getting the tuple format for a (type) tuple, raw style. */
protected TupleFormat rawAddFormatFor(AttrTuple attr) {
DeclTuple type = ((TupleObject) attr).getTupleType();
TupleFormat format = new TupleFormat(type.getNumberOfEntries());
this.formatTab.put(type, format);
return format;
}
/**
* Getting the tuple format for a (type) tuple. Format tuples are created
* lazily "on demand". It means that when there is no format for the
* specified AttrTuple yet, it is created and returned.
*/
protected TupleFormat getFormat(AttrTuple attr) {
TupleFormat format = rawGetFormat(attr);
if (format == null) {
format = rawAddFormatFor(attr);
}
return format;
}
/** Removing the format for a (type) tuple. */
public synchronized void removeFormat(AttrType type) {
DeclTuple typ = ((TupleObject) type).getTupleType();
this.formatTab.remove(typ);
}
// protected ViewSetting getSharingView(){ return maskedView; }
protected boolean hasObserversForTuple(AttrTuple attr) {
Vector<WeakReference<AttrViewObserver>> observers1 = getObserversForTuple(attr);
Vector<WeakReference<AttrViewObserver>> observers2 = this.maskedView.getObserversForTuple(attr);
if ((observers1 == null || observers1.isEmpty())
&& (observers2 == null || observers2.isEmpty())) {
return false;
}
return true;
}
//
// Public methods
//
/**
* Called by addObserver(), from MaskedViewSetting as well as from this
* class.
*/
public void ensureBeingAttrObserver(AttrTuple attr) {
// System.out.println("OpenViewSetting.ensureBeingAttrObserver vor
// getFormat...");
if (attr == null)
return;
DeclTuple type = ((TupleObject) attr).getTupleType();
if (!hasObserversForTuple(attr)) {
type.addObserver(this);
attr.addObserver(this);
getFormat(attr);
}
}
/**
* Called by removeObserver(), from MaskedViewSetting as well as from this
* class.
*/
public void stopObservingIfNeedless(AttrTuple attr) {
// DeclTuple type = ((TupleObject) attr).getTupleType();
if (!hasObserversForTuple(attr)) {
attr.removeObserver(this);
// To do:
// type.removeObserver( this )
// if we're not observating any instances of 'type' anymore.
// Not urgent.
}
}
//
// AttrViewSetting interface implementation
//
public AttrViewSetting getOpenView() {
return this;
}
public AttrViewSetting getMaskedView() {
return this.maskedView;
}
public void addObserver(AttrViewObserver o, AttrTuple attr) {
if (attr == null)
return;
ensureBeingAttrObserver(attr);
addObserverForTuple(o, attr);
}
public void removeObserver(AttrViewObserver o, AttrTuple attr) {
// System.out.println("OpenViewSetting.removeObserver ...");
removeObserverForTuple(o, attr);
// If 'attr' has no more view observers, there's no point observing it.
stopObservingIfNeedless(attr);
}
public boolean hasObserver(AttrTuple attr) {
Vector<WeakReference<AttrViewObserver>> observers = getObserversForTuple(attr);
return (observers == null || observers.isEmpty())?false:true;
}
public int convertIndexToSlot(AttrTuple attr, int index) {
TupleFormat f = getFormat(attr);
return f.getTotalSlotForIndex(index);
}
public int convertSlotToIndex(AttrTuple attr, int slot) {
TupleFormat f = getFormat(attr);
return f.getIndexAtTotalSlot(slot);
}
public int getSize(AttrTuple attr) {
return attr.getNumberOfEntries();
}
public boolean isVisible(AttrTuple attr, int slot) {
TupleFormat f = getFormat(attr);
return f.isVisible(slot);
}
public void setVisibleAt(AttrTuple attr, boolean b, int slot) {
TupleFormat f = getFormat(attr);
synchronized (f) {
f.setVisible(b, slot);
((DeclMember) (((TupleObject) attr).getTupleType())
.getMemberAt(slot)).setVisible(b);
fireAttrChanged(((TupleObject) attr).getTupleType(),
AttrViewEvent.MEMBER_VISIBILITY, slot, slot);
this.maskedView.fireAttrChanged(((TupleObject) attr).getTupleType(),
AttrEvent.GENERAL_CHANGE, 0, 0);
}
}
public void setAllVisible(AttrTuple attr, boolean b) {
TupleFormat f = getFormat(attr);
synchronized (f) {
for (int i = 0; i < attr.getNumberOfEntries(); i++) {
f.setVisible(b, i);
((DeclMember) (((TupleObject) attr).getTupleType())
.getMemberAt(i)).setVisible(b);
}
fireAttrChanged(((TupleObject) attr).getTupleType(),
AttrEvent.GENERAL_CHANGE, 0, 0);
this.maskedView.fireAttrChanged(((TupleObject) attr).getTupleType(),
AttrEvent.GENERAL_CHANGE, 0, 0);
}
}
public void setVisible(AttrTuple attr) {
TupleFormat f = getFormat(attr);
synchronized (f) {
for (int i = 0; i < attr.getNumberOfEntries(); i++) {
boolean b = ((DeclMember) (((TupleObject) attr).getTupleType())
.getMemberAt(i)).isVisible();
f.setVisible(b, i);
}
fireAttrChanged(((TupleObject) attr).getTupleType(),
AttrEvent.GENERAL_CHANGE, 0, 0);
this.maskedView.fireAttrChanged(((TupleObject) attr).getTupleType(),
AttrEvent.GENERAL_CHANGE, 0, 0);
}
}
public void moveSlotInserting(AttrTuple attr, int srcSlot, int destSlot) {
getFormat(attr).moveSlotInserting(srcSlot, destSlot);
fireAttrChanged(((TupleObject) attr).getTupleType(),
AttrViewEvent.MEMBER_MOVED, srcSlot, destSlot);
if (isVisible(attr, destSlot)) {
this.maskedView.fireAttrChanged(((TupleObject) attr).getTupleType(),
AttrEvent.GENERAL_CHANGE, 0, 0);
}
}
public void resetTuple(AttrTuple attr) {
// Thread.dumpStack();
// System.out.println("OpenViewSetting.resetTuple... "+
// attr.hashCode());
DeclTuple type = ((TupleObject) attr).getTupleType();
removeFormat(type);
// TupleFormat format =
getFormat(type);
// Hashtable t = getIndexOfSameMember(attr); // -olga
// System.out.println("after getFormat: "+type.getSize()+"
// "+type.getNumberOfEntries());
fireAttrChanged(((TupleObject) attr).getTupleType(),
AttrEvent.GENERAL_CHANGE, 0, 0);
this.maskedView.fireAttrChanged(((TupleObject) attr).getTupleType(),
AttrEvent.GENERAL_CHANGE, 0, 0);
}
/*
private Hashtable<DeclMember, Vector<Integer>> getIndexOfSameMember(AttrTuple attr) {
DeclTuple type = ((TupleObject) attr).getTupleType();
Hashtable<DeclMember, Vector<Integer>> t = new Hashtable<DeclMember, Vector<Integer>>();
int length = type.getNumberOfEntries();
for (int i = 0; i < length; i++) {
DeclMember mi = (DeclMember) type.getMemberAt(i);
Vector<Integer> v = new Vector<Integer>(5);
for (int j = 0; j < length; j++) {
DeclMember mj = (DeclMember) type.getMemberAt(j);
if (i < j && mi != null && mj != null) {
if (mi.getHoldingTuple() == mj.getHoldingTuple()) {
if (mi.compareTo(mj)) {
// System.out.println(attr);
// mi.setEnabled(false);
// mi.setVisible(false);
System.out.println(i + " | " + j + ": "
+ mi.getHoldingTuple().hashCode()
+ " == "
+ mj.getHoldingTuple().hashCode());
v.add(new Integer(j));
}
}
}
}
if (!v.isEmpty() && t.get(mi) == null)
t.put(mi, v);
}
return t;
}
*/
public void reorderTuple(AttrTuple attr) {
// System.out.println("OpenViewSetting.reorderTuple..."+
// attr.hashCode());
DeclTuple type = ((TupleObject) attr).getTupleType();
// removeFormat( type );
// multiple inheritance - olga
removeFormat(type);
getFormat(type);
//
fireAttrChanged(((TupleObject) attr).getTupleType(),
AttrEvent.GENERAL_CHANGE, 0, 0);
this.maskedView.fireAttrChanged(((TupleObject) attr).getTupleType(),
AttrEvent.GENERAL_CHANGE, 0, 0);
}
/**
* AttrObserver implementation; Attribute event handling relies on the fact
* that an AttrType always sends its MEMBER_ADDED and MEMBER_DELETED events
* before his AttrInstance.
*/
public void attributeChanged(AttrEvent event) {
// System.out.println(this+ " attributeChanged "+event+")");
AttrTuple attr = event.getSource();
int id = event.getID();
int index0 = event.getIndex0();
int index1 = event.getIndex1();
switch (id) {
case AttrEvent.MEMBER_ADDED:
if (attr instanceof AttrType) { // Only for types
// System.out.println(this+ " attributeChanged "+attr);
TupleFormat form = getFormat(attr);
for (int i = index0; i <= index1; i++) {
form.addMember(i);
}
}
propagateAttrEvent(event);
this.maskedView.propagateAttrEvent(event);
break;
case AttrEvent.MEMBER_DELETED:
if (attr instanceof AttrType) { // Only for types
TupleFormat form = getFormat(attr);
this.lastOpenDeletedSlot0 = convertIndexToSlot(attr, index0);
this.lastOpenDeletedSlot1 = convertIndexToSlot(attr, index1);
this.lastMaskedDeletedSlot0 = this.maskedView.convertIndexToSlot(attr,
index0);
this.lastMaskedDeletedSlot1 = this.maskedView.convertIndexToSlot(attr,
index1);
for (int i = index0; i <= index1; i++) {
form.deleteMember(i);
}
}
/*
* log( "converted slots: ("+lastOpenDeletedSlot0+", "+
* lastOpenDeletedSlot1+"); ("+lastMaskedDeletedSlot0+", "+
* lastMaskedDeletedSlot1+")");
*/
notifyObservers(attr, id, this.lastOpenDeletedSlot0,
this.lastOpenDeletedSlot1);
this.maskedView.notifyObservers(attr, id, this.lastMaskedDeletedSlot0,
this.lastMaskedDeletedSlot1);
break;
default:
propagateAttrEvent(event);
this.maskedView.propagateAttrEvent(event);
} // switch( id )
}
/** AttrObserver implementation */
public boolean isPersistentFor(AttrTuple at) {
return true;
}
}
/*
* $Log: OpenViewSetting.java,v $
* Revision 1.12 2010/09/23 08:15:32 olga
* tuning
*
* Revision 1.11 2010/03/08 15:38:56 olga
* code optimizing
*
* Revision 1.10 2008/04/07 09:36:56 olga
* Code tuning: refactoring + profiling
* Extension: CPA - two new options added
*
* Revision 1.9 2007/11/05 09:18:23 olga
* code tuning
*
* Revision 1.8 2007/11/01 09:58:20 olga
* Code refactoring: generic types- done
*
* Revision 1.7 2007/09/10 13:05:50 olga
* In this update:
* - package xerces2.5.0 is not used anymore;
* - class com.objectspace.jgl.Pair is replaced by the agg own generic class agg.util.Pair;
* - bugs fixed in: usage of PACs in rules; match completion;
* usage of static method calls in attr. conditions
* - graph editing: added some new features
* Revision 1.6 2006/12/13 13:33:05 enrico
* reimplemented code
*
* Revision 1.5 2006/11/01 11:17:30 olga Optimized agg sources of CSP algorithm,
* match usability, graph isomorphic copy, node/edge type multiplicity check for
* injective rule and match
*
* Revision 1.4 2006/08/02 09:00:57 olga Preliminary version 1.5.0 with -
* multiple node type inheritance, - new implemented evolutionary graph layouter
* for graph transformation sequences
*
* Revision 1.3 2006/04/12 14:54:07 olga Restore attr. values of attr. type
* observers after type graph imported.
*
* Revision 1.2 2005/11/03 14:16:03 enrico Implemented method reorderTuple
*
* Revision 1.1 2005/08/25 11:56:58 enrico *** empty log message ***
*
* Revision 1.1 2005/05/30 12:58:04 olga Version with Eclipse
*
* Revision 1.5 2004/11/15 11:24:45 olga Neue Optionen fuer Transformation;
* verbesserter default Graphlayout; Close GraGra mit Abfrage wenn was geaendert
* wurde statt Delete GraGra
*
* Revision 1.4 2003/03/05 18:24:26 komm sorted/optimized import statements
*
* Revision 1.3 2002/10/04 16:36:44 olga Es gibt noch Fehler unter Window
*
* Revision 1.2 2002/09/23 12:24:04 komm added type graph in xt_basis, editor
* and GUI
*
* Revision 1.1.1.1 2002/07/11 12:17:07 olga Imported sources
*
* Revision 1.12 2000/06/05 14:08:21 shultzke Debugausgaben fuer V1.0.0b
* geloescht
*
* Revision 1.11 2000/04/05 12:11:27 shultzke serialVersionUID aus V1.0.0
* generiert
*
* Revision 1.10 1999/10/11 10:47:32 shultzke debugmeldungen geloescht
*
* Revision 1.9 1999/10/11 10:42:55 shultzke kleine Bugfixes
*
* Revision 1.7 1999/10/07 11:50:15 olga *** empty log message ***
*
* Revision 1.6 1999/10/05 08:20:31 shultzke SlotSequences werden zwar
* geloescht, aber gleich wieder erzeugt
*
* Revision 1.5 1999/09/27 16:16:44 olga dispose Methoden hinzugefuegt.
*
* Revision 1.4 1999/09/06 13:39:40 shultzke ChainedObserver auf WeakReferences
* umgestellt, samt serialUID
*/