package data.ooimpl;
import java.util.*;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import java.io.*;
import data.events.*;
import data.*;
import util.*;
public abstract class StockImpl extends StockItemImpl implements Stock,
ListenableStock,
NameContext,
SelfManagingDBESource,
SelfManagingDBEDestination {
protected CatalogImpl m_ciCatalog;
protected DataBasket m_dbCatalogValidator;
protected ListenerHelper m_lhListeners = new ListenerHelper();
private Map m_mpItems = new HashMap();
private Map m_mpTemporaryAddedItems = new HashMap();
private Map m_mpTemporaryRemovedItems = new HashMap();
private Map m_mpEditingItems = new HashMap();
private Map m_mpRefIntegrItems = new HashMap();
private Map m_mpRefIntegrEdit = new HashMap();
private transient Object m_oItemsLock;
protected final Object getItemsLock() {
if (m_oItemsLock == null) {
m_oItemsLock = new Object();
}
return m_oItemsLock;
}
class CatalogItemNameListener implements PropertyChangeListener, SerializableListener {
public void propertyChange (PropertyChangeEvent e) {
if (e.getPropertyName().equals (NAME_PROPERTY)) {
synchronized (getItemsLock()) {
String sOld = (String) e.getOldValue();
String sNew = (String) e.getNewValue();
nameChangeOccurred (sOld, sNew);
}
}
}
protected void nameChangeOccurred (String sOld,
String sNew) {
Object oData = getTemporaryAddedItemsContainer().remove (sOld);
if (oData != null) {
getTemporaryAddedItemsContainer().put (sNew, oData);
}
oData = getItemsContainer().remove (sOld);
if (oData != null) {
getItemsContainer().put (sNew, oData);
}
oData = getTemporaryRemovedItemsContainer().remove (sOld);
if (oData != null) {
getTemporaryRemovedItemsContainer().put (sNew, oData);
}
oData = getRefIntegrItemsContainer().remove (sOld);
if (oData != null) {
getRefIntegrItemsContainer().put (sNew, oData);
}
getRefIntegrEditContainer().put (sNew, getRefIntegrEditContainer().remove (sOld));
}
}
protected CatalogItemNameListener m_cinlCatalogItemNameListener = new CatalogItemNameListener();
protected final CatalogChangeListener m_cclEditListener = new CatalogChangeAdapter() {
public void canEditCatalogItem (CatalogChangeEvent e)
throws VetoException {
synchronized (getItemsLock()) {
String sKey = e.getAffectedItem().getName();
if ((getTemporaryAddedItemsContainer().containsKey (sKey)) ||
(getTemporaryRemovedItemsContainer().containsKey (sKey))) {
throw new VetoException ("Stock \"" + getName() + "\": Having StockItems with key \"" + sKey + "\" in DataBaskets.");
}
}
}
public void editingCatalogItem (CatalogChangeEvent e) {
synchronized (getItemsLock()) {
String sKey = e.getAffectedItem().getName();
getRefIntegrEditContainer().put (sKey, sKey);
((CatalogItemImpl) e.getAffectedItem()).addNameListener (m_cinlCatalogItemNameListener);
}
}
public void rollbackEditCatalogItem (CatalogChangeEvent e) {
synchronized (getItemsLock()) {
String sCurKey = e.getAffectedItem().getName();
String sKey = (String) getRefIntegrEditContainer().remove (sCurKey);
Object oData = getTemporaryAddedItemsContainer().remove (sCurKey);
if (oData != null) {
getTemporaryAddedItemsContainer().put (sKey, oData);
}
oData = getItemsContainer().remove (sCurKey);
if (oData != null) {
getItemsContainer().put (sKey, oData);
}
oData = getTemporaryRemovedItemsContainer().remove (sCurKey);
if (oData != null) {
getTemporaryRemovedItemsContainer().put (sKey, oData);
}
oData = getRefIntegrItemsContainer().remove (sCurKey);
if (oData != null) {
getRefIntegrItemsContainer().put (sKey, oData);
}
((CatalogItemImpl) e.getAffectedItem()).removeNameListener (m_cinlCatalogItemNameListener);
}
}
public void commitEditCatalogItem (CatalogChangeEvent e) {
synchronized (getItemsLock()) {
getRefIntegrEditContainer().remove (e.getAffectedItem().getName());
((CatalogItemImpl) e.getAffectedItem()).removeNameListener (m_cinlCatalogItemNameListener);
}
}
};
private transient java.lang.ref.SoftReference m_srsiEditCreator = null;
private final StockChangeListener m_sclEditingListener = new StockChangeAdapter() {
public void commitEditStockItems (StockChangeEvent e) {
if (e.getAffectedKey() == getName()) {
for (Iterator i = e.getAffectedItems(); i.hasNext();) {
if (i.next() == StockImpl.this) {
((StockImpl) e.getSource()).removeStockChangeListener (this);
return;
}
}
}
}
public void rollbackEditStockItems (StockChangeEvent e) {
if (e.getAffectedKey() == getName()) {
for (Iterator i = e.getAffectedItems(); i.hasNext();) {
if (i.next() == StockImpl.this) {
((StockImpl) e.getSource()).removeStockChangeListener (this);
((StockImpl) m_srsiEditCreator.get()).removeStockChangeListener (m_sclEditCreatorListener);
m_srsiEditCreator = null;
return;
}
}
}
}
};
protected StockChangeListener m_sclEditCreatorListener;
private void writeObject (ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject();
if (m_srsiEditCreator != null) {
oos.writeObject (m_srsiEditCreator.get());
}
else {
oos.writeObject (null);
}
}
private void readObject (ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject();
Object oEditCreator = ois.readObject();
if (oEditCreator != null) {
m_srsiEditCreator = new java.lang.ref.SoftReference (oEditCreator);
}
}
public StockImpl (String sName, CatalogImpl ciRef) {
super (sName);
if (ciRef == null)
throw new NullPointerException ("Catalog must not be null!");
internalSetCatalog (ciRef);
}
protected void internalSetCatalog (CatalogImpl ciRef) {
if (m_ciCatalog != null) {
m_ciCatalog.removeCatalogChangeListener (m_cclEditListener);
}
m_ciCatalog = ciRef;
if (m_ciCatalog != null) {
m_ciCatalog.addCatalogChangeListener (m_cclEditListener);
}
m_dbCatalogValidator = null;
}
protected Map getItemsContainer() {
return m_mpItems;
}
protected Map getTemporaryAddedItemsContainer() {
return m_mpTemporaryAddedItems;
}
protected Map getTemporaryRemovedItemsContainer() {
return m_mpTemporaryRemovedItems;
}
protected Map getEditingItemsContainer() {
return m_mpEditingItems;
}
protected Map getRefIntegrItemsContainer() {
return m_mpRefIntegrItems;
}
protected Map getRefIntegrEditContainer() {
return m_mpRefIntegrEdit;
}
protected void setItemsContainer (Map mp) {
m_mpItems = mp;
}
protected void setTemporaryAddedItemsContainer (Map mp) {
m_mpTemporaryAddedItems = mp;
}
protected void setTemporaryRemovedItemsContainer (Map mp) {
m_mpTemporaryRemovedItems = mp;
}
protected void setEditingItemsContainer (Map mp) {
m_mpEditingItems = mp;
}
protected void setRefIntegrItemsContainer (Map mp) {
m_mpRefIntegrItems = mp;
}
protected void setRefIntegrEditContainer (Map mp) {
m_mpRefIntegrEdit = mp;
}
public void addStock (Stock st, DataBasket db, boolean fRemove) {
if (st.getCatalog (db) != getCatalog (db)) {
throw new CatalogConflictException();
}
Object oLock = ((db == null)?(new Object()):(((DataBasketImpl) db).getDBIMonitor()));
synchronized (oLock) {
synchronized (getItemsLock()) {
Object oLock2 = ((st instanceof StockImpl)?(((StockImpl) st).getItemsLock()):(oLock));
synchronized (oLock2) {
for (Iterator i = st.iterator (db, false); i.hasNext();) {
try {
StockItem si = (StockItem) i.next();
if (fRemove) {
i.remove();
}
else {
si = (StockItem) si.clone();
}
add (si, db);
}
catch (ConcurrentModificationException e) { break; }
catch (UnsupportedOperationException e) {
continue;
}
}
}
}
}
}
public boolean contains (String sKey, DataBasket db) {
return (countItems (sKey, db) > 0);
}
public boolean contains (StockItem si, DataBasket db) {
Object oLock = ((db == null)?(new Object()):(((DataBasketImpl) db).getDBIMonitor()));
synchronized (oLock) {
synchronized (getItemsLock()) {
for (Iterator i = get (si.getName(), db, false); i.hasNext();) {
StockItem si2 = (StockItem) i.next();
if (si.equals (si2)) {
return true;
}
}
return false;
}
}
}
public boolean containsStock (Stock st, DataBasket db) {
Object oLock = ((db == null)?(new Object()):(((DataBasketImpl) db).getDBIMonitor()));
synchronized (oLock) {
synchronized (getItemsLock()) {
Object oLock2 = ((st instanceof StockImpl)?(((StockImpl) st).getItemsLock()):(oLock));
synchronized (oLock2) {
for (Iterator i = st.iterator (db, false); i.hasNext();) {
if (!contains ((StockItem) i.next(), db)) {
return false;
}
}
return true;
}
}
}
}
public Iterator iterator (final DataBasket db, final boolean fForEdit) {
class I implements Iterator {
private StockImpl m_stiOwner;
private Iterator m_iKeys;
private Iterator m_iItems;
public I (StockImpl stiOwner) {
super();
m_stiOwner = stiOwner;
m_iKeys = m_stiOwner.keySet (db).iterator();
}
public boolean hasNext() {
return findNext();
}
public Object next() {
if (!findNext()) {
throw new NoSuchElementException ("No more elements in Stock.");
}
return m_iItems.next();
}
public void remove() {
if (m_iItems == null) {
throw new IllegalStateException();
}
m_iItems.remove();
}
private boolean findNext() {
if (m_iItems == null) {
if (m_iKeys.hasNext()) {
m_iItems = m_stiOwner.get ((String) m_iKeys.next(), db, fForEdit);
}
else {
return false;
}
}
while ((m_iItems.hasNext()) ||
(m_iKeys.hasNext())) {
if (m_iItems.hasNext()) {
return true;
}
m_iItems = m_stiOwner.get ((String) m_iKeys.next(), db, fForEdit);
}
return false;
}
}
return new I (this);
}
public Set keySet (DataBasket db) {
Object oLock = ((db == null)?(new Object()):(((DataBasketImpl) db).getDBIMonitor()));
synchronized (oLock) {
synchronized (getItemsLock()) {
Set stKeys = new TreeSet (getItemsContainer().keySet());
for (Iterator i = getTemporaryAddedItemsContainer().keySet().iterator(); i.hasNext();) {
String sKey = (String) i.next();
if ((!stKeys.contains (sKey)) &&
(countItems (sKey, db) > 0)) {
stKeys.add (sKey);
}
}
return stKeys;
}
}
}
public Value sumStock (DataBasket db, CatalogItemValue civ, Value vInit) {
Object oLock = ((db == null)?(new Object()):(((DataBasketImpl) db).getDBIMonitor()));
synchronized (oLock) {
synchronized (getItemsLock()) {
Set stKeys = keySet (db);
for (Iterator i = stKeys.iterator(); i.hasNext();) {
String sKey = (String) i.next();
try {
vInit.addAccumulating (civ.getValue (getCatalog (db).get (sKey, db, false)).multiply (countItems (sKey, db)));
}
catch (VetoException ex) {}
}
return vInit;
}
}
}
public Value fillStockWithValue (DataBasket db, Value vTarget, StockFromValueCreator sfvc) {
Object oLock = ((db != null)?(((DataBasketImpl) db).getDBIMonitor()):(new Object()));
synchronized (oLock) {
synchronized (getItemsLock()) {
return sfvc.fillStock (this, vTarget, db);
}
}
}
public int size (DataBasket db) {
Object oLock = ((db == null)?(new Object()):(((DataBasketImpl) db).getDBIMonitor()));
synchronized (oLock) {
synchronized (getItemsLock()) {
Set stKeys = new HashSet (getItemsContainer().keySet());
stKeys.addAll (getTemporaryAddedItemsContainer().keySet());
int nCount = 0;
for (Iterator i = stKeys.iterator(); i.hasNext();) {
String sKey = (String) i.next();
nCount += countItems (sKey, db);
}
return nCount;
}
}
}
public Catalog getCatalog (DataBasket db) {
if ((m_dbCatalogValidator == null) ||
(m_dbCatalogValidator == db)) {
return m_ciCatalog;
}
else
throw new DataBasketConflictException ("Cannot access catalog that is currently being edited in another transaction.");
}
public StockItemImpl getShallowClone() {
StockImpl sti = createPeer();
fillShallowClone (sti);
sti.m_srsiEditCreator = new java.lang.ref.SoftReference (this);
addStockChangeListener (sti.m_sclEditCreatorListener);
if (getStock() != null) {
((StockImpl) getStock()).addStockChangeListener (sti.m_sclEditingListener);
}
return sti;
}
protected void fillShallowClone (StockImpl stiClone) {
synchronized (getItemsLock()) {
synchronized (stiClone.getItemsLock()) {
stiClone.setItemsContainer (new HashMap (getItemsContainer()));
stiClone.setTemporaryAddedItemsContainer (new HashMap (getTemporaryAddedItemsContainer()));
stiClone.setTemporaryRemovedItemsContainer (new HashMap (getTemporaryRemovedItemsContainer()));
stiClone.setEditingItemsContainer (new HashMap (getEditingItemsContainer()));
stiClone.setRefIntegrItemsContainer (new HashMap (getRefIntegrItemsContainer()));
stiClone.setRefIntegrEditContainer (new HashMap (getRefIntegrEditContainer()));
}
}
}
public Object clone() {
StockImpl sti = createPeer();
sti.addStock (this, null, false);
return sti;
}
protected abstract StockImpl createPeer();
protected void setStock (StockImpl sti) {
super.setStock (sti);
if (sti != null) {
internalSetCatalog ((CatalogImpl) getAssociatedItem (sti.m_dbCatalogValidator));
}
}
public int compareTo (Object o) {
if (o instanceof Stock) {
return super.compareTo (o);
}
else {
return 1;
}
}
public void checkNameChange (DataBasket db, String sOldName, String sNewName)
throws NameContextException {
throw new NameContextException ("StockItem names cannot be changed when they are part of a Stock.");
}
public void nameHasChanged (DataBasket db, String sOldName, String sNewName) {}
public Object getNCMonitor() {
return new Object();
}
protected void prepareReferentialIntegrity (DataBasket db, DataBasketEntry dbe) {
DataBasketCondition dbc = new DataBasketConditionImpl (CatalogItemImpl.CATALOG_ITEM_MAIN_KEY,
dbe.getSecondaryKey(),
(CatalogImpl) getCatalog (db),
null,
null);
DataBasketEntry dbeRemovedCI = db.get (dbc);
dbc = new DataBasketConditionImpl (CatalogItemImpl.CATALOG_ITEM_MAIN_KEY,
dbe.getSecondaryKey(),
null,
(CatalogImpl) getCatalog (db),
null);
DataBasketEntry dbeAddedCI = db.get (dbc);
if (((dbeRemovedCI == null) ||
(dbeAddedCI == null)) &&
(dbeRemovedCI != dbeAddedCI)) {
if (dbeRemovedCI != null) {
dbeRemovedCI.rollback();
}
else {
dbeAddedCI.commit();
}
}
}
public void addStockChangeListener (StockChangeListener scl) {
m_lhListeners.add (StockChangeListener.class, scl);
}
public void removeStockChangeListener(StockChangeListener scl) {
m_lhListeners.remove (StockChangeListener.class, scl);
}
protected void fireStockItemsAdded (StockChangeEvent e) {
Object[] listeners = m_lhListeners.getListenerList();
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i] == StockChangeListener.class) {
((StockChangeListener) listeners[i+1]).addedStockItems (e);
}
}
}
protected void fireStockItemsAddCommit (StockChangeEvent e) {
Object[] listeners = m_lhListeners.getListenerList();
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i] == StockChangeListener.class) {
((StockChangeListener) listeners[i+1]).commitAddStockItems (e);
}
}
}
protected void fireStockItemsAddRollback (StockChangeEvent e) {
Object[] listeners = m_lhListeners.getListenerList();
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i] == StockChangeListener.class) {
((StockChangeListener) listeners[i+1]).rollbackAddStockItems (e);
}
}
}
protected void fireStockItemsRemoved (StockChangeEvent e) {
Object[] listeners = m_lhListeners.getListenerList();
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i] == StockChangeListener.class) {
((StockChangeListener) listeners[i+1]).removedStockItems (e);
}
}
}
protected void fireStockItemsRemoveCommit (StockChangeEvent e) {
Object[] listeners = m_lhListeners.getListenerList();
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i] == StockChangeListener.class) {
((StockChangeListener) listeners[i+1]).commitRemoveStockItems (e);
}
}
}
protected void fireStockItemsRemoveRollback (StockChangeEvent e) {
Object[] listeners = m_lhListeners.getListenerList();
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i] == StockChangeListener.class) {
((StockChangeListener) listeners[i+1]).rollbackRemoveStockItems (e);
}
}
}
protected void fireCanRemoveStockItems (StockChangeEvent e)
throws VetoException {
Object[] temp = m_lhListeners.getListenerList();
Object[] listeners = new Object[temp.length];
System.arraycopy (temp, 0, listeners, 0, temp.length);
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i] == StockChangeListener.class) {
try {
((StockChangeListener) listeners[i+1]).canRemoveStockItems (e);
}
catch (VetoException ex) {
for (int j = i; j < listeners.length; j += 2) {
if (listeners[j] == CatalogChangeListener.class) {
((StockChangeListener) listeners[j + 1]).noRemoveStockItems (e);
}
}
throw ex;
}
}
}
}
protected void fireCanEditStockItems (StockChangeEvent e)
throws VetoException {
Object[] temp = m_lhListeners.getListenerList();
Object[] listeners = new Object[temp.length];
System.arraycopy (temp, 0, listeners, 0, temp.length);
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i] == StockChangeListener.class) {
try {
((StockChangeListener) listeners[i+1]).canEditStockItems (e);
}
catch (VetoException ex) {
for (int j = i; j < listeners.length; j += 2) {
if (listeners[j] == CatalogChangeListener.class) {
((StockChangeListener) listeners[j + 1]).noRemoveStockItems (e);
}
}
throw ex;
}
}
}
}
protected void fireEditingStockItems (StockChangeEvent e) {
Object[] listeners = m_lhListeners.getListenerList();
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i] == StockChangeListener.class) {
((StockChangeListener) listeners[i+1]).editingStockItems (e);
}
}
}
protected void fireStockItemsEditCommit (StockChangeEvent e) {
Object[] listeners = m_lhListeners.getListenerList();
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i] == StockChangeListener.class) {
((StockChangeListener) listeners[i+1]).commitEditStockItems (e);
}
}
}
protected void fireStockItemsEditRollback (StockChangeEvent e) {
Object[] listeners = m_lhListeners.getListenerList();
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i] == StockChangeListener.class) {
((StockChangeListener) listeners[i+1]).rollbackEditStockItems (e);
}
}
}
void relinkCatalog (DataBasket db, int nAction) {
super.relinkCatalog (db, nAction);
switch (nAction) {
case STARTEDIT_ACTION:
internalSetCatalog ((CatalogImpl) getAssociatedItem (db));
m_dbCatalogValidator = db;
break;
case COMMIT_ACTION:
if (db == m_dbCatalogValidator) {
m_dbCatalogValidator = null;
}
break;
case ROLLBACK_ACTION:
if (db == m_dbCatalogValidator) {
DataBasket dbParent = ((StockImpl) getStock()).m_dbCatalogValidator;
if (dbParent != null) {
Debug.print ("In data.ooimpl.StockImpl.relinkCatalog (db, ROLLBACK_ACTION): parent databasket is not null!", -1);
}
internalSetCatalog ((CatalogImpl) getAssociatedItem (dbParent));
m_dbCatalogValidator = null;
}
break;
}
}
}