blob: 7249fb6091d954088bfcc1ffd9fca913d42d0d62 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004-2008 Andras Schmidt, Andras Balogh, Istvan Rath and Daniel Varro
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andras Schmidt, Andras Balogh, Istvan Rath - initial API and implementation
*******************************************************************************/
package org.eclipse.viatra2.core.simple;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.eclipse.viatra2.core.ICoreNotificationListener;
import org.eclipse.viatra2.core.IModelElement;
import org.eclipse.viatra2.core.IModelManager;
import org.eclipse.viatra2.core.IModelMerger;
import org.eclipse.viatra2.core.IModelSpace;
import org.eclipse.viatra2.core.INotificationManager;
import org.eclipse.viatra2.core.ITransactionManager;
import org.eclipse.viatra2.core.IUndoManager;
import org.eclipse.viatra2.core.simple.tempdata.TemporaryDataFactory;
import org.eclipse.viatra2.errors.VPMCoreException;
import org.eclipse.viatra2.errors.VPMRuntimeException;
import org.eclipse.viatra2.framework.IFramework;
import org.eclipse.viatra2.framework.properties.VPMProperties;
import org.eclipse.viatra2.logger.Logger;
/**
*
* This interface specifies the container of core functions. Implementations
* have to discover and load model manager, merger, notfification, undo and
* transaction support classes.
*
* ModelSpace interface is the common container of the Viatra core functions.
*
* @author Andras Schmidt
*
* Modification on 2006.08.07 by Istvan Rath: - removed reference to
* SimpleUndoManager; undo management moved into the transaction manager
*
*/
public class SimpleModelSpace implements IModelSpace {
/**
* Factory class for cached data storage
*/
protected TemporaryDataFactory<Set<IModelElement>> tempFactory = new TemporaryDataFactory<Set<IModelElement>>();
protected Logger logger;
// protected PatternMatcher patternMatcher;
protected IModelManager mManager;
protected INotificationManager nManager;
// protected SimpleUndoManager uManager;
protected ITransactionManager tManager;
// protected Set _entities, _functions, _relations;
protected Map<Long, SimpleModelElement> entities, relations;
protected Set<SimpleEntity> entitiesSet;
protected Set<SimpleRelation> relationsSet;
protected SimpleEntity rootEntity;
// / ******* ancestors
public static final boolean isAncestorAware = false;
public static final String ancestorContainerName = "vpm";
public static final String ancestorEntityName = "entity";
public static final String ancestorEntityFQN = ancestorContainerName + "."
+ ancestorEntityName;
public static final String ancestorRelationName = "relation";
public static final String ancestorRelationFQN = ancestorEntityFQN + "."
+ ancestorRelationName;
protected SimpleEntity ancestorContainer;
protected SimpleEntity ancestorEntity;
protected SimpleRelation ancestorRelation;
// ********
protected UniqueNameProvider uniqueNameProvider;
protected IDProvider idProvider;
/**
* Counter that counts all updates of the model. The counter is used to
* check cached (dependent) data whether it is valid or not.
*/
protected int numberOfChanges = 0;
// / XXX parallelVIATRA
// protected Lock __lock=new ReentrantLock();
protected ReadWriteLock lock = new ReentrantReadWriteLock();
public class NullRLock implements Lock {
public void lock() {
StackTraceElement e = Thread.currentThread().getStackTrace()[2];
String trace = e.getClassName() + "::" + e.getMethodName();
System.out.println("READ_LOCK [" + trace + "]");
}
public void lockInterruptibly() throws InterruptedException {
}
public Condition newCondition() {
return null;
}
public boolean tryLock() {
return true;
}
public boolean tryLock(long time, TimeUnit unit)
throws InterruptedException {
return true;
}
public void unlock() {
StackTraceElement e = Thread.currentThread().getStackTrace()[2];
String trace = e.getClassName() + "::" + e.getMethodName();
System.out.println("READ UNLOCK [" + trace + "]");
}
}
public class NullWLock implements Lock {
public void lock() {
StackTraceElement e = Thread.currentThread().getStackTrace()[2];
String trace = e.getClassName() + "::" + e.getMethodName();
System.out.println("WRITE_LOCK [" + trace + "]");
}
public void lockInterruptibly() throws InterruptedException {
}
public Condition newCondition() {
return null;
}
public boolean tryLock() {
return true;
}
public boolean tryLock(long time, TimeUnit unit)
throws InterruptedException {
return true;
}
public void unlock() {
StackTraceElement e = Thread.currentThread().getStackTrace()[2];
String trace = e.getClassName() + "::" + e.getMethodName();
System.out.println("WRITE UNLOCK [" + trace + "]");
}
}
protected ReadWriteLock _lock = new ReadWriteLock() {
NullRLock rLock = new NullRLock();
NullWLock wLock = new NullWLock();
public Lock readLock() {
return rLock;
}
public Lock writeLock() {
return wLock;
}
};
// protected String getSyncObject=new String("sync object");
// TODO
protected long newId() {
return idProvider.newID();
}
String uniqueName(String s) {
return uniqueNameProvider.uniqueName(s);
}
String uniqueName() {
return uniqueNameProvider.uniqueName();
}
IFramework framework;
public void init(IFramework fw) throws VPMRuntimeException {
this.framework = fw;
init(fw.getLogger(), fw.getProperties());
}
/**
* Initializes the modelspace.
*
* @param p
* - the collection of runtime properties
* @throws VPMRuntimeException
*/
public void init(Logger log, VPMProperties props)
throws VPMRuntimeException {
logger = log;
uniqueNameProvider = new UniqueNameProvider();
idProvider = new IDProvider(logger);
entities = new TreeMap<Long, SimpleModelElement>();
entitiesSet = new TreeSet<SimpleEntity>();
relations = new TreeMap<Long, SimpleModelElement>();
relationsSet = new TreeSet<SimpleRelation>();
rootEntity = new SimpleEntity(newId(), this);
rootEntity.name = "root";
// entities.put(rootEntity.getLongID(), rootEntity);
// entitiesSet.add(rootEntity);
initManagers();
}
/**
* @throws VPMRuntimeException
*/
protected void initManagers() throws VPMRuntimeException {
mManager = new SimpleModelManager();
nManager = new SimpleNotificationManager();
tManager = new SimpleTransactionManager();
((SimpleModelManager) mManager).init(logger, this);
((SimpleNotificationManager) nManager).init(logger, this);
((SimpleTransactionManager) tManager).init(logger, this);
if (isAncestorAware) {
try {
ancestorContainer = (SimpleEntity) mManager
.newEntity(ancestorContainerName);
ancestorEntity = (SimpleEntity) mManager.newEntity(
ancestorEntityName, ancestorContainer);
ancestorRelation = (SimpleRelation) mManager.newRelation(
ancestorRelationName, ancestorEntity, ancestorEntity);
mManager.setIsAnyFrom(ancestorRelation, true);
mManager.setIsAnyTo(ancestorRelation, true);
} catch (VPMCoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// nManager.addAllListener(uManager);
nManager.addAllListener((ICoreNotificationListener) tManager);
}
/**
* Returns the model merger associated with this modelspace
*
* @return the model merger
*/
public IModelMerger getModelMerger() {
// TODO
return null;
}
/**
* Returns the model manager asociated with this modelspace.
*
* @return the model manager
*/
public IModelManager getModelManager() {
return mManager;
}
/**
* Returns the notification manager associated with this modelspace, or null
* if notification is not supported.
*
* @return notification manager
*/
public INotificationManager getNotificationManager() {
return nManager;
}
/**
* Returns the transaction manager associated with this modelspace, or null
* if transactions are not supported.
*
* @return transaction manager.
*/
public ITransactionManager getTransactionManager() {
return tManager;
}
/**
* Returns the undo manager associated with this modelspace, or null if undo
* is not supported.
*
* @return undo manager.
*/
public IUndoManager getUndoManager() {
// return uManager;
logger.debug("SimpleModelSpace::getUndoManager called");
return null;
}
/**
* Checks whether transactions are supported
*
* @return true if transactions are supported, else false.
*/
public boolean isTransactionAware() {
// TODO
return false;
}
/**
* Checks whether notifications are supported
*
* @return true if notifications are supported, else false.
*/
public boolean isNotificationAware() {
// TODO
return false;
}
/**
* Checks whether undo is supported
*
* @return true if undo is supported, else false.
*/
public boolean isUndoAware() {
return true;
}
/**
* Clones (doubles) the whole modelspace
*
* @return cloned modelspace
*/
public IModelSpace cloneModelSpace() {
// TODO
return null;
}
public String statistics() {
return statistics(0);
}
public String statistics(long memUsedBefore) {
StringBuffer ret = new StringBuffer();
int numSups = 0;
int numSubs = 0;
int numTypes = 0;
int numInsts = 0;
Iterator<SimpleModelElement> it = entities.values().iterator();
while (it.hasNext()) {
SimpleModelElement me = it.next();
numSubs += me.subtypes.size();
numSups += me.supertype.size();
numTypes += me.type.size();
numInsts += me.instances.size();
}
it = relations.values().iterator();
while (it.hasNext()) {
SimpleModelElement me = it.next();
numSubs += me.subtypes.size();
numSups += me.supertype.size();
numTypes += me.type.size();
numInsts += me.instances.size();
}
ret.append("Number uf supertypes:" + numSups + "\n");
ret.append("Number uf subtypes:" + numSubs + "\n");
ret.append("Number uf instance:" + numInsts + "\n");
ret.append("Number uf types:" + numTypes + "\n");
int nEnts = getModelManager().getEntities().size();
int nRels = getModelManager().getRelations().size();
ret.append("nr of entities:" + nEnts + "\n");
ret.append("nr of rels :" + nRels + "\n");
int sum = nRels + nEnts;
ret.append("nr of sum :" + sum + "\n");
ret.append("average num of types:" + (float) numTypes / sum + "\n");
ret.append("average num of supertypes:" + (float) numSups / sum + "\n");
System.gc();
ret.append("memory per element:" + ((memUsed() - memUsedBefore) / sum));
return ret.toString();
}
private static long memUsed() {
Runtime r = Runtime.getRuntime();
long free = r.freeMemory();
long total = r.totalMemory();
return total - free;
}
/**
* Method only for test: deletes all String info in modelspace (name and
* value fields) Then we see what amount of memory they occupied.
*
*/
public void deleteStrings() {
Iterator<SimpleModelElement> it = entities.values().iterator();
while (it.hasNext()) {
SimpleModelElement me = it.next();
SimpleEntity mee = (SimpleEntity) me;
me.name = null;
mee.value = null;
}
it = relations.values().iterator();
while (it.hasNext()) {
SimpleModelElement me = it.next();
me.name = null;
}
}
/**
* @return
*/
public int discardAllTemp() {
return tempFactory.discardAll();
}
public Collection<IModelElement> getAncestorElements() {
if (isAncestorAware) {
TreeSet<IModelElement> ret = new TreeSet<IModelElement>();
if (ancestorContainer != null)
ret.add(ancestorContainer);
if (ancestorEntity != null)
ret.add(ancestorEntity);
if (ancestorRelation != null)
ret.add(ancestorRelation);
return ret;
} else {
return Collections.emptySet();
}
}
public IFramework getFramework() {
return framework;
}
}