blob: 57957f6c87e2e5c6f5b457f963bc950aa98a9de4 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 University of Illinois at Urbana-Champaign and others.
* 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:
* UIUC - Initial API and implementation
*******************************************************************************/
package org.eclipse.rephraserengine.core.vpg;
import java.io.IOException;
import java.io.PrintStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.Assert;
import org.eclipse.rephraserengine.core.util.Pair;
import org.eclipse.rephraserengine.core.util.SetOfPairs;
/**
* Decorator for a VPG database that handles lazy edge computations (i.e., edges computed on demand).
*
* @author Jeff Overbey
*
* @param <A> AST type
* @param <T> token type
* @param <R> TokenRef type
*
* @since 3.0
*/
public final class DemandDB<A, T, R extends IVPGNode<T>>
extends VPGDB<A, T, R>
{
private final VPGDB<A, T, R> db;
private SetOfPairs<String, ILazyVPGPopulator> oldFilesPopulated;
private SetOfPairs<String, ILazyVPGPopulator> filesPopulated;
private ILazyVPGPopulator[] lazyPopulators;
private Map<Integer, ILazyVPGPopulator> edgeTypePopulators;
private Map<Integer, ILazyVPGPopulator> annotationTypePopulators;
public DemandDB(VPGDB<A, T, R> diskDatabase)
{
super(diskDatabase);
Assert.isNotNull(diskDatabase);
Assert.isTrue(diskDatabase != this);
this.db = diskDatabase;
this.oldFilesPopulated = null;
this.filesPopulated = new SetOfPairs<String, ILazyVPGPopulator>();
this.edgeTypePopulators = new HashMap<Integer, ILazyVPGPopulator>();
this.annotationTypePopulators = new HashMap<Integer, ILazyVPGPopulator>();
}
void setContentProvider(VPGWriter<A, T, R> contentProvider)
{
this.lazyPopulators = contentProvider.getLazyEdgePopulators();
for (ILazyVPGPopulator populator : lazyPopulators)
{
for (int edgeType : populator.edgeTypesPopulated())
edgeTypePopulators.put(edgeType, populator);
for (int annotationType : populator.annotationTypesPopulated())
annotationTypePopulators.put(annotationType, populator);
}
}
////////////////////////////////////////////////////////////////////////////
// NEW API
////////////////////////////////////////////////////////////////////////////
public boolean lazyComputationEnabled = true;
////////////////////////////////////////////////////////////////////////////
// UTILITY METHODS
////////////////////////////////////////////////////////////////////////////
private void ensureLazyEdgesAndAnnotations(String targetFile)
{
if (!lazyComputationEnabled) return;
runPopulators(getPopulatorsThatHaveNotBeenRunOn(targetFile), targetFile);
}
private List<ILazyVPGPopulator> getPopulatorsThatHaveNotBeenRunOn(String targetFile)
{
List<ILazyVPGPopulator> result = new ArrayList<ILazyVPGPopulator>(lazyPopulators.length);
for (ILazyVPGPopulator populator : lazyPopulators)
if (!filesPopulated.contains(targetFile, populator))
result.add(populator);
return result;
}
private void runPopulators(Collection<ILazyVPGPopulator> populators, String targetFile)
{
if (somePopulatorRequiresDependentFilesToBePopulated(populators))
{
ArrayList<String> files = new ArrayList<String>(Collections.singletonList(targetFile));
for (String filename : sortFilesAccordingToDependencies(files))
{
for (ILazyVPGPopulator populator : populators)
{
// Add the populator to the list BEFORE running it so that
// it can read edges that it has written without causing
// infinite recursion
filesPopulated.add(filename, populator);
populator.populateVPG(filename);
}
}
}
else
{
for (ILazyVPGPopulator populator : populators)
{
filesPopulated.add(targetFile, populator);
populator.populateVPG(targetFile);
}
}
}
private boolean somePopulatorRequiresDependentFilesToBePopulated(Collection<ILazyVPGPopulator> populatorsToRun)
{
for (ILazyVPGPopulator populator : populatorsToRun)
if (populator.dependentFilesMustBePopulated())
return true;
return false;
}
private void ensureLazyEdge(String targetFile, int edgeType)
{
if (!lazyComputationEnabled) return;
if (edgeTypePopulators.containsKey(edgeType))
{
ILazyVPGPopulator populator = edgeTypePopulators.get(edgeType);
if (!filesPopulated.contains(targetFile, populator))
runPopulators(Collections.singleton(populator), targetFile);
}
}
private void ensureLazyAnnotation(String targetFile, int annotationType)
{
if (!lazyComputationEnabled) return;
if (annotationTypePopulators.containsKey(annotationType))
{
ILazyVPGPopulator populator = annotationTypePopulators.get(annotationType);
if (!filesPopulated.contains(targetFile, populator))
runPopulators(Collections.singleton(populator), targetFile);
}
}
////////////////////////////////////////////////////////////////////////////
// VPG DATABASE METHODS
////////////////////////////////////////////////////////////////////////////
@Override public void flush()
{
db.flush();
}
@Override public void close()
{
db.close();
}
@Override public void clearDatabase()
{
filesPopulated.clear();
db.clearDatabase();
}
// HYPOTHETICAL UPDATING ///////////////////////////////////////////////////
@Override public void enterHypotheticalMode() throws IOException
{
oldFilesPopulated = filesPopulated.clone();
db.enterHypotheticalMode();
}
@Override public void leaveHypotheticalMode() throws IOException
{
db.leaveHypotheticalMode();
filesPopulated = oldFilesPopulated;
oldFilesPopulated = null;
}
@Override public boolean isInHypotheticalMode()
{
return oldFilesPopulated != null; // true iff db.isInHypotheticalMode();
}
// FILES ///////////////////////////////////////////////////////////////////
@Override public void updateModificationStamp(String filename)
{
db.updateModificationStamp(filename);
}
@Override public boolean isOutOfDate(String filename)
{
return db.isOutOfDate(filename);
}
@Override public void deleteAllEntriesFor(String filename)
{
filesPopulated.remove(filename);
db.deleteAllEntriesFor(filename);
}
@Override public void deleteAllEdgesAndAnnotationsFor(String filename)
{
filesPopulated.remove(filename);
db.deleteAllEdgesAndAnnotationsFor(filename);
}
@Override public void deleteAllIncomingDependenciesFor(String filename)
{
db.deleteAllIncomingDependenciesFor(filename);
}
@Override public void deleteAllOutgoingDependenciesFor(String filename)
{
db.deleteAllOutgoingDependenciesFor(filename);
}
@Override public Iterable<String> listAllFilenames()
{
return db.listAllFilenames();
}
@Override public Iterable<String> listAllFilenamesWithDependents()
{
return db.listAllFilenamesWithDependents();
}
@Override public Iterable<String> listAllDependentFilenames()
{
return db.listAllDependentFilenames();
}
// DEPENDENCIES ////////////////////////////////////////////////////////////
@Override public void ensure(VPGDependency<A, T, R> dependency)
{
db.ensure(dependency);
}
@Override public void delete(VPGDependency<A, T, R> dependency)
{
db.delete(dependency);
}
@Override public Iterable<String> getOutgoingDependenciesFrom(String filename)
{
return db.getOutgoingDependenciesFrom(filename);
}
@Override public Iterable<String> getIncomingDependenciesTo(String filename)
{
return db.getIncomingDependenciesTo(filename);
}
// EDGES ///////////////////////////////////////////////////////////////////
@Override public void ensure(VPGEdge<A, T, R> edge)
{
db.ensure(edge);
}
@Override public void delete(VPGEdge<A, T, R> edge)
{
db.delete(edge);
}
@Override public Iterable<? extends VPGEdge<A, T, R>> getAllEdgesFor(String filename)
{
ensureLazyEdgesAndAnnotations(filename);
return db.getAllEdgesFor(filename);
}
@Override public Iterable<? extends VPGEdge<A, T, R>> getOutgoingEdgesFrom(R tokenRef, int edgeType)
{
ensureLazyEdge(tokenRef.getFilename(), edgeType);
return db.getOutgoingEdgesFrom(tokenRef, edgeType);
}
@Override public Iterable<? extends VPGEdge<A, T, R>> getIncomingEdgesTo(R tokenRef, int edgeType)
{
ensureLazyEdge(tokenRef.getFilename(), edgeType);
return db.getIncomingEdgesTo(tokenRef, edgeType);
}
// ANNOTATIONS /////////////////////////////////////////////////////////////
@Override public void setAnnotation(R token, int annotationID, Serializable annotation)
{
db.setAnnotation(token, annotationID, annotation);
}
@Override public void deleteAnnotation(R token, int annotationID)
{
db.deleteAnnotation(token, annotationID);
}
@Override public Serializable getAnnotation(R tokenRef, int annotationID)
{
ensureLazyAnnotation(tokenRef.getFilename(), annotationID);
return db.getAnnotation(tokenRef, annotationID);
}
@Override public Iterable<Pair<R, Integer>> getAllAnnotationsFor(String filename)
{
ensureLazyEdgesAndAnnotations(filename);
return db.getAllAnnotationsFor(filename);
}
// UTILITY METHODS /////////////////////////////////////////////////////////
@Override public void printOn(PrintStream out)
{
db.printOn(out);
}
@Override public void printStatisticsOn(PrintStream out)
{
db.printStatisticsOn(out);
}
@Override public void resetStatistics()
{
db.resetStatistics();
}
}