| /******************************************************************************* |
| * 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; |
| } |
| } |