package org.nthx.pat;
import org.apache.log4j.Logger;
import org.prevayler.Command;
import org.prevayler.PrevalentSystem;
import org.prevayler.implementation.SnapshotPrevayler;
import java.io.IOException;
import java.io.Serializable;
public class Pat
{
private transient static Pat INSTANCE;
private transient static Logger log = Logger.getLogger("pat");
private transient static boolean NO_COMMANDS_MODE =
Boolean.valueOf(System.getProperty("pat.no-commands", "false")).booleanValue();
private transient PrevalentSystem patRoot; private transient SnapshotPrevayler snapshotPrevayler;
private transient IdentityMapMixin temporaryIdentityMap;
private transient boolean freshRoot = true;
transient static boolean finishedCreatingRoot = false;
private Pat()
{
temporaryIdentityMap = new IdentityMapMixin();
if (isInNoCommandsMode())
{
String warning =
" ****************************** " +
" * PAT is in NO-COMMANDS-MODE * " +
" ****************************** ";
System.out.println(warning);
log.warn(warning);
}
}
boolean isFreshRoot() { return freshRoot; }
public IdentityMap getRootAsIdentityMap()
{
if (null != patRoot)
{
if (null != temporaryIdentityMap && finishedCreatingRoot)
throw new IllegalStateException("Temporary IM should be null");
return (IdentityMap)patRoot;
}
else
{
return temporaryIdentityMap;
}
}
public static Pat getInstance()
{
if (null == INSTANCE)
INSTANCE = new Pat();
return INSTANCE;
}
public static void unload()
{
log.warn("Unloading PAT instance: " + INSTANCE);
INSTANCE = null;
finishedCreatingRoot = false;
}
Serializable executeCommand(Command command)
throws Throwable
{
return snapshotPrevayler.executeCommand(command);
}
public void updateRoot(PrevalentSystem systemFromSnapshot,
PrevalentSystem newlyCreatedSystem)
{
if (systemFromSnapshot == newlyCreatedSystem)
throw new IllegalStateException("Should differ!");
if (null == systemFromSnapshot)
{
freshRoot = true;
patRoot = newlyCreatedSystem;
getRootAsIdentityMap().setMap(temporaryIdentityMap.getMap());
getRootAsIdentityMap().setUniqueOID(temporaryIdentityMap.getUniqueOID());
temporaryIdentityMap = null;
getRootAsIdentityMap().putObject((Identifiable)patRoot);
}
else
{
freshRoot = false;
patRoot = systemFromSnapshot;
temporaryIdentityMap = null;
((IdentityMap)newlyCreatedSystem).setMap(null);
((IdentityMap)newlyCreatedSystem).setUniqueOID(-999L);
newlyCreatedSystem = null;
}
}
void setSnapshotPrevayler(SnapshotPrevayler snapshotPrevayler)
{
this.snapshotPrevayler = snapshotPrevayler;
if (patRoot != snapshotPrevayler.system())
throw new IllegalStateException("These two objects should be the same...");
}
void takeSnapshot()
{
try
{
snapshotPrevayler.takeSnapshot();
} catch (IOException e)
{
log.error("Why?", e);
}
}
void finishedCreatingRoot()
{
finishedCreatingRoot = true;
printMemoryStatistics();
}
public boolean afterRootConstructor()
{
return finishedCreatingRoot;
}
public boolean beforeRootConstructor()
{
return !afterRootConstructor();
}
boolean isInNoCommandsMode()
{
return NO_COMMANDS_MODE;
}
private void printMemoryStatistics()
{
String percentage = "" + (float)getRootAsIdentityMap().getSize()*100 / Integer.MAX_VALUE;
if (percentage.length() > 4 && percentage.charAt(2) == '.')
percentage = percentage.substring(0, 4);
else
percentage = "0.00";
log.debug("Objects in IdentityMap: "
+ getRootAsIdentityMap().getSize()
+ " Usage of the map: "
+ percentage + "%");
log.debug("------------------- * * * -----------------------");
}
}