Move stored value creation into StoredValues

Methods that compute and store certain values when needed now occur
during StoredValues.<Type>.get() for those stored values. If the
interpreter does not have a value, it will create one using
createValue() and then store it in the interpreter's hash map. By
default, createValue() returns null (which throws an exception in get()).
To use it, override it with code that computes the desired value for a
certain type. StoredValue also now uses Java Object instead of
JavaObjectTerm for its key. Some existing predicates have also been
refactored to not create values on their own.

Change-Id: Ia3d44169f86526c0c16f9580f3d52d04b0b83b2b
This commit is contained in:
Jason Tsay
2011-07-14 13:21:10 -07:00
parent 2b58c2a221
commit c0e1e4e6db
6 changed files with 78 additions and 102 deletions

View File

@@ -14,10 +14,8 @@
package com.google.gerrit.rules;
import com.googlecode.prolog_cafe.lang.JavaObjectTerm;
import com.googlecode.prolog_cafe.lang.Prolog;
import com.googlecode.prolog_cafe.lang.SystemException;
import com.googlecode.prolog_cafe.lang.Term;
/**
* Defines a value cached in a {@link PrologEnvironment}.
@@ -27,43 +25,49 @@ import com.googlecode.prolog_cafe.lang.Term;
public class StoredValue<T> {
/** Construct a new unique key that does not match any other key. */
public static <T> StoredValue<T> create() {
return new StoredValue<T>(new JavaObjectTerm(new Object()));
return new StoredValue<T>();
}
/** Construct a key based on a Java Class object, useful for singletons. */
public static <T> StoredValue<T> create(Class<T> clazz) {
return new StoredValue<T>(new JavaObjectTerm(clazz));
return new StoredValue<T>(clazz);
}
private final Term key;
private final Object key;
/**
* Initialize a stored value key using a Prolog term.
* Initialize a stored value key using any Java Object.
*
* @param key unique identity of the stored value. This will be the hash key
* in the interpreter's hash manager.
* in the Prolog Environments's hash map.
*/
public StoredValue(Term key) {
public StoredValue(Object key) {
this.key = key;
}
/**
* Initializes a stored value key with a new unique key.
*/
public StoredValue() {
key = this;
}
/** Look up the value in the engine, or return null. */
public T getOrNull(Prolog engine) {
return get((PrologEnvironment) engine.control);
}
/** Get the value from the engine, or throw SystemException. */
public T get(Prolog engine) {
T r = getOrNull(engine);
if (r == null) {
String msg;
if (key.isJavaObject() && key.toJava() instanceof Class<?>) {
msg = "No " + ((Class<?>) key.toJava()).getName() + " avaliable";
} else {
msg = key.toString();
T obj = getOrNull(engine);
if (obj == null) {
//unless createValue() is overridden, will return null
obj = createValue(engine);
if (obj == null) {
throw new SystemException("No " + key + " available");
}
throw new SystemException(msg);
set(engine, obj);
}
return r;
return obj;
}
public void set(Prolog engine, T obj) {
@@ -79,4 +83,9 @@ public class StoredValue<T> {
public void set(PrologEnvironment env, T obj) {
env.set(this, obj);
}
/** Creates a value to store, returns null by default. */
protected T createValue(Prolog engine) {
return null;
}
}

View File

@@ -16,20 +16,64 @@ package com.google.gerrit.rules;
import static com.google.gerrit.rules.StoredValue.create;
import com.google.gerrit.reviewdb.AccountDiffPreference.Whitespace;
import com.google.gerrit.reviewdb.Change;
import com.google.gerrit.reviewdb.PatchSet;
import com.google.gerrit.reviewdb.PatchSetInfo;
import com.google.gerrit.reviewdb.Project;
import com.google.gerrit.reviewdb.ReviewDb;
import com.google.gerrit.server.patch.PatchList;
import com.google.gerrit.server.patch.PatchListCache;
import com.google.gerrit.server.patch.PatchListKey;
import com.google.gerrit.server.patch.PatchSetInfoFactory;
import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
import com.google.gerrit.server.project.ChangeControl;
import com.googlecode.prolog_cafe.lang.Prolog;
import com.googlecode.prolog_cafe.lang.SystemException;
import org.eclipse.jgit.lib.ObjectId;
public final class StoredValues {
public static final StoredValue<ReviewDb> REVIEW_DB = create(ReviewDb.class);
public static final StoredValue<Change> CHANGE = create(Change.class);
public static final StoredValue<PatchSet.Id> PATCH_SET_ID = create(PatchSet.Id.class);
public static final StoredValue<ChangeControl> CHANGE_CONTROL = create(ChangeControl.class);
public static final StoredValue<PatchSetInfo> PATCH_SET_INFO = create(PatchSetInfo.class);
public static final StoredValue<PatchList> PATCH_LIST = create(PatchList.class);
public static final StoredValue<PatchSetInfo> PATCH_SET_INFO = new StoredValue<PatchSetInfo>() {
@Override
public PatchSetInfo createValue(Prolog engine) {
PatchSet.Id patchSetId = StoredValues.PATCH_SET_ID.get(engine);
PrologEnvironment env = (PrologEnvironment) engine.control;
PatchSetInfoFactory patchInfoFactory =
env.getInjector().getInstance(PatchSetInfoFactory.class);
try {
return patchInfoFactory.get(patchSetId);
} catch (PatchSetInfoNotAvailableException e) {
throw new SystemException(e.getMessage());
}
}
};
public static final StoredValue<PatchList> PATCH_LIST = new StoredValue<PatchList>() {
@Override
public PatchList createValue(Prolog engine) {
PrologEnvironment env = (PrologEnvironment) engine.control;
PatchSetInfo psInfo = StoredValues.PATCH_SET_INFO.get(engine);
PatchListCache plCache = env.getInjector().getInstance(PatchListCache.class);
Change change = StoredValues.CHANGE.get(engine);
Project.NameKey projectKey = change.getProject();
ObjectId a = null;
ObjectId b = ObjectId.fromString(psInfo.getRevId());
Whitespace ws = Whitespace.IGNORE_NONE;
PatchListKey plKey = new PatchListKey(projectKey, a, b, ws);
PatchList patchList = plCache.get(plKey);
if (patchList == null) {
throw new SystemException("Cannot create " + plKey);
}
return patchList;
}
};
private StoredValues() {
}

View File

@@ -82,19 +82,4 @@ abstract class AbstractCommitUserIdentityPredicate extends Predicate.P3 {
}
return cont;
}
protected PatchSetInfo getPatchSetInfo(Prolog engine)
throws PatchSetInfoNotAvailableException {
PrologEnvironment env = (PrologEnvironment) engine.control;
PatchSetInfo psInfo = env.get(StoredValues.PATCH_SET_INFO);
if (psInfo == null) {
PatchSet.Id patchSetId = env.get(StoredValues.PATCH_SET_ID);
PatchSetInfoFactory patchInfoFactory =
env.getInjector().getInstance(PatchSetInfoFactory.class);
psInfo = patchInfoFactory.get(patchSetId);
env.set(StoredValues.PATCH_SET_INFO, psInfo);
}
return psInfo;
}
}

View File

@@ -16,9 +16,8 @@ package gerrit;
import com.google.gerrit.reviewdb.PatchSetInfo;
import com.google.gerrit.reviewdb.UserIdentity;
import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
import com.google.gerrit.rules.StoredValues;
import com.googlecode.prolog_cafe.lang.JavaException;
import com.googlecode.prolog_cafe.lang.Operation;
import com.googlecode.prolog_cafe.lang.Prolog;
import com.googlecode.prolog_cafe.lang.PrologException;
@@ -33,12 +32,7 @@ public class PRED_commit_author_3 extends AbstractCommitUserIdentityPredicate {
@Override
public Operation exec(Prolog engine) throws PrologException {
PatchSetInfo psInfo;
try {
psInfo = getPatchSetInfo(engine);
} catch (PatchSetInfoNotAvailableException err) {
throw new JavaException(this, 1, err);
}
PatchSetInfo psInfo = StoredValues.PATCH_SET_INFO.get(engine);
UserIdentity author = psInfo.getAuthor();
return exec(engine, author);
}

View File

@@ -16,9 +16,8 @@ package gerrit;
import com.google.gerrit.reviewdb.PatchSetInfo;
import com.google.gerrit.reviewdb.UserIdentity;
import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
import com.google.gerrit.rules.StoredValues;
import com.googlecode.prolog_cafe.lang.JavaException;
import com.googlecode.prolog_cafe.lang.Operation;
import com.googlecode.prolog_cafe.lang.Prolog;
import com.googlecode.prolog_cafe.lang.PrologException;
@@ -33,12 +32,7 @@ public class PRED_commit_committer_3 extends AbstractCommitUserIdentityPredicate
@Override
public Operation exec(Prolog engine) throws PrologException {
PatchSetInfo psInfo;
try {
psInfo = getPatchSetInfo(engine);
} catch (PatchSetInfoNotAvailableException err) {
throw new JavaException(this, 1, err);
}
PatchSetInfo psInfo = StoredValues.PATCH_SET_INFO.get(engine);
UserIdentity committer = psInfo.getCommitter();
return exec(engine, committer);
}

View File

@@ -14,23 +14,13 @@
package gerrit;
import com.google.gerrit.reviewdb.AccountDiffPreference.Whitespace;
import com.google.gerrit.reviewdb.Change;
import com.google.gerrit.reviewdb.Patch;
import com.google.gerrit.reviewdb.PatchSet;
import com.google.gerrit.reviewdb.PatchSetInfo;
import com.google.gerrit.reviewdb.Project;
import com.google.gerrit.rules.PrologEnvironment;
import com.google.gerrit.rules.StoredValues;
import com.google.gerrit.server.patch.PatchList;
import com.google.gerrit.server.patch.PatchListCache;
import com.google.gerrit.server.patch.PatchListEntry;
import com.google.gerrit.server.patch.PatchListKey;
import com.google.gerrit.server.patch.PatchSetInfoFactory;
import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
import com.googlecode.prolog_cafe.lang.IllegalTypeException;
import com.googlecode.prolog_cafe.lang.JavaException;
import com.googlecode.prolog_cafe.lang.JavaObjectTerm;
import com.googlecode.prolog_cafe.lang.Operation;
import com.googlecode.prolog_cafe.lang.PInstantiationException;
@@ -40,8 +30,6 @@ import com.googlecode.prolog_cafe.lang.PrologException;
import com.googlecode.prolog_cafe.lang.SymbolTerm;
import com.googlecode.prolog_cafe.lang.Term;
import org.eclipse.jgit.lib.ObjectId;
import java.util.Iterator;
import java.util.regex.Pattern;
@@ -92,15 +80,8 @@ public class PRED_commit_delta_4 extends Predicate.P4 {
engine.areg3 = arg3;
engine.areg4 = arg4;
PrologEnvironment env = (PrologEnvironment) engine.control;
PatchSetInfo psInfo;
try {
psInfo = getPatchSetInfo(env);
} catch (PatchSetInfoNotAvailableException err) {
throw new JavaException(this, 1, err);
}
PatchList pl = getPatchList(env, psInfo);
PatchSetInfo psInfo = StoredValues.PATCH_SET_INFO.get(engine);
PatchList pl = StoredValues.PATCH_LIST.get(engine);
Iterator<PatchListEntry> iter = pl.getPatches().iterator();
engine.areg5 = new JavaObjectTerm(iter);
@@ -188,35 +169,4 @@ public class PRED_commit_delta_4 extends Predicate.P4 {
}
throw new IllegalArgumentException("ChangeType not recognized");
}
protected PatchSetInfo getPatchSetInfo(PrologEnvironment env)
throws PatchSetInfoNotAvailableException {
PatchSetInfo psInfo = env.get(StoredValues.PATCH_SET_INFO);
if (psInfo == null) {
PatchSet.Id patchSetId = env.get(StoredValues.PATCH_SET_ID);
PatchSetInfoFactory patchInfoFactory =
env.getInjector().getInstance(PatchSetInfoFactory.class);
psInfo = patchInfoFactory.get(patchSetId);
env.set(StoredValues.PATCH_SET_INFO, psInfo);
}
return psInfo;
}
protected PatchList getPatchList(PrologEnvironment env, PatchSetInfo psInfo) {
PatchList patchList = env.get(StoredValues.PATCH_LIST);
if (patchList == null) {
PatchListCache plCache = env.getInjector().getInstance(PatchListCache.class);
Change change = env.get(StoredValues.CHANGE);
Project.NameKey projectKey = change.getProject();
ObjectId a = null;
ObjectId b = ObjectId.fromString(psInfo.getRevId());
Whitespace ws = Whitespace.IGNORE_NONE;
PatchListKey plKey = new PatchListKey(projectKey, a, b, ws);
patchList = plCache.get(plKey);
env.set(StoredValues.PATCH_LIST, patchList);
}
return patchList;
}
}