RandomSec/main/src/com/google/refine/LookupCacheManager.java

137 lines
5.1 KiB
Java

package com.google.refine;
import com.google.refine.expr.ExpressionUtils;
import com.google.refine.expr.HasFieldsListImpl;
import com.google.refine.expr.WrappedRow;
import com.google.refine.expr.functions.Cross;
import com.google.refine.model.Column;
import com.google.refine.model.Project;
import com.google.refine.model.Row;
import com.google.refine.util.LookupException;
import java.util.*;
/**
* Manage the cache of project's lookups.
*
* @author Lu Liu
*/
public class LookupCacheManager {
protected final Map<String, ProjectLookup> _lookups = new HashMap<>();
/**
* Computes the ProjectLookup based on combination key,
* returns the cached one from the HashMap if already computed.
*
* @param targetProject the project to look up
* @param targetColumn the column of the target project to look up
* @return a {@link ProjectLookup} instance of the lookup result
*/
public ProjectLookup getLookup(long targetProject, String targetColumn) throws LookupException {
String key = targetProject + ";" + targetColumn;
if (!_lookups.containsKey(key)) {
ProjectLookup lookup = new ProjectLookup(targetProject, targetColumn);
computeLookup(lookup);
synchronized (_lookups) {
_lookups.put(key, lookup);
}
}
return _lookups.get(key);
}
public void flushLookupsInvolvingProject(long projectID) {
synchronized (_lookups) {
for (Iterator<Map.Entry<String, ProjectLookup>> it = _lookups.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<String, ProjectLookup> entry = it.next();
ProjectLookup lookup = entry.getValue();
if (lookup.targetProjectID == projectID) {
it.remove();
}
}
}
}
public void flushLookupsInvolvingProjectColumn(long projectID, String columnName) {
synchronized (_lookups) {
for (Iterator<Map.Entry<String, ProjectLookup>> it = _lookups.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<String, ProjectLookup> entry = it.next();
ProjectLookup lookup = entry.getValue();
if (lookup.targetProjectID == projectID && lookup.targetColumnName.equals(columnName)) {
it.remove();
}
}
}
}
protected void computeLookup(ProjectLookup lookup) throws LookupException {
if (lookup.targetProjectID < 0) {
return;
}
Project targetProject = ProjectManager.singleton.getProject(lookup.targetProjectID);
ProjectMetadata targetProjectMetadata = ProjectManager.singleton.getProjectMetadata(lookup.targetProjectID);
if (targetProject == null) {
return;
}
// if this is a lookup on the index column
if (lookup.targetColumnName.equals(Cross.INDEX_COLUMN_NAME)) {
for (int r = 0; r < targetProject.rows.size(); r++) {
lookup.valueToRowIndices.put(String.valueOf(r) , Collections.singletonList(r));
}
return; // return directly
}
Column targetColumn = targetProject.columnModel.getColumnByName(lookup.targetColumnName);
if (targetColumn == null) {
throw new LookupException("Unable to find column " + lookup.targetColumnName + " in project " + targetProjectMetadata.getName());
}
// We can't use for-each here, because we'll need the row index when creating WrappedRow
int count = targetProject.rows.size();
for (int r = 0; r < count; r++) {
Row targetRow = targetProject.rows.get(r);
Object value = targetRow.getCellValue(targetColumn.getCellIndex());
if (ExpressionUtils.isNonBlankData(value)) {
String valueStr = value.toString();
lookup.valueToRowIndices.putIfAbsent(valueStr, new ArrayList<>());
lookup.valueToRowIndices.get(valueStr).add(r);
}
}
}
static public class ProjectLookup {
final public long targetProjectID;
final public String targetColumnName;
final public Map<Object, List<Integer>> valueToRowIndices = new HashMap<>();
ProjectLookup(long targetProjectID, String targetColumnName) {
this.targetProjectID = targetProjectID;
this.targetColumnName = targetColumnName;
}
public HasFieldsListImpl getRows(Object value) {
if (!ExpressionUtils.isNonBlankData(value)) return null;
String valueStr = value.toString();
if (valueToRowIndices.containsKey(valueStr)) {
Project targetProject = ProjectManager.singleton.getProject(targetProjectID);
if (targetProject != null) {
HasFieldsListImpl rows = new HasFieldsListImpl();
for (Integer r : valueToRowIndices.get(valueStr)) {
Row row = targetProject.rows.get(r);
rows.add(new WrappedRow(targetProject, r, row));
}
return rows;
}
}
return null;
}
}
}