📄 versionedstorage.java
字号:
package org.garret.rdf;
import java.util.*;
import org.garret.perst.*;
/**
* Main class
**/
public class VersionedStorage
{
Storage db;
DatabaseRoot root;
private static final Iterator EmptyIterator = (new HashSet()).iterator();
/**
* List of separator characters used to split string into keywords
**/
public static char[] keywordSeparators = {' ', ','};
/**
* List of most commonly used words which should be ignored andnot included in inverse index
*/
public static HashSet keywordStopList = new HashSet();
static {
keywordStopList.add("the");
keywordStopList.add("at");
keywordStopList.add("of");
keywordStopList.add("a");
keywordStopList.add("to");
keywordStopList.add("at");
keywordStopList.add("and");
keywordStopList.add("or");
keywordStopList.add("i");
}
/**
* Open database
* @param filePath path to the database file
*/
public void open(String filePath) {
db = StorageFactory.getInstance().createStorage();
db.open(filePath);
root = (DatabaseRoot)db.getRoot();
if (root == null) {
root = new DatabaseRoot();
root.prefixUriIndex = db.createIndex(String.class, true);
root.suffixUriIndex = db.createIndex(String.class, true);
root.strPropIndex = db.createIndex(new Class[]{PropDef.class, String.class}, false);
root.numPropIndex = db.createIndex(new Class[]{PropDef.class, Double.class}, false);
root.refPropIndex = db.createIndex(new Class[]{PropDef.class, VersionHistory.class}, false);
root.timePropIndex = db.createIndex(new Class[]{PropDef.class, Date.class}, false);
root.propDefIndex = db.createFieldIndex(PropDef.class, "name", true);
root.timeIndex = db.createFieldIndex(Thing.class, "timestamp", false);
root.inverseIndex = db.createIndex(String.class, false);
root.spatialIndex = db.createSpatialIndexR2();
root.latest = db.createSet();
createMetaType();
db.setRoot(root);
}
}
/**
* Get verion history by URI
* @param uri object URI
* @return version history or null if no such object is found
*/
public VersionHistory getObject(String uri) {
return (VersionHistory)root.prefixUriIndex.get(uri);
}
/**
* Get latest verion of object with specified URI
* @param uri object URI
* @return latest version of object or null if no such object is found
*/
public Thing getLatestVersion(String uri) {
VersionHistory vh = (VersionHistory)root.prefixUriIndex.get(uri);
return (vh != null) ? vh.getLatest() : null;
}
/**
* Get verion history by URI and timestamp
* @param uri object URI
* @param kind search kind, should be object SearchKind.LatestVersion, SearchKind.LatestBefore or
* SearchKind.OldestAfter
* @param timestamp timestamp used to locate version
* @return version of the object or null if no such version is found
*/
public Thing getVersion(String uri, SearchKind kind, Date timestamp) {
VersionHistory vh = (VersionHistory)root.prefixUriIndex.get(uri);
if (vh != null) {
return vh.getVersion(kind, timestamp);
}
return null;
}
/**
* Create bew object. If version history with this URI is not exists, it is created first.
* Then new object version is created and appended to this version history.
*
* @param uri object URI
* @param type URI of object type
* @param props object properties
* @return created object version
*/
public Thing createObject(String uri, String type, NameVal[] props) {
VersionHistory vh = (VersionHistory)root.prefixUriIndex.get(uri);
if (vh == null) {
VersionHistory typeVh = null;
typeVh = getObject(type);
if (typeVh == null) {
typeVh = createVersionHistory(type, root.metatype);
createObject(root.metatype.getLatest(), typeVh, new NameVal[0]);
}
vh = createVersionHistory(uri, typeVh);
} else {
root.latest.remove(vh.getLatest());
}
return createObject(vh.type.getLatest(), vh, props);
}
/**
* Get iterator through object matching specified search parameters
* @param type String representing type of the object (direct or indirect - IsInstanceOf
* method will be used to check if object belongs to the specified type). It may be null,
* in this case type criteria is skipped.
* @param uri Object URI pattern. It may be null, in this case URI is not inspected.
* @param patterns array of name:value pairs specifying search condition for object properties
* @param kind search kind used to select inspected versions
* @param timestamp timestamp used to select versions, if kind is SearchKind.LatestVersion
* or SearchKind.AllVersions this parameter is ignored
* @return Enumerator through object meet search criteria.
*/
public Iterator search(String type, String uri, NameVal[] patterns, SearchKind kind, Date timestamp) {
VersionHistory typeVh = null;
root.sharedLock();
try {
if (type != null) {
typeVh = getObject(type);
if (typeVh == null) {
return EmptyIterator;
}
}
if (uri != null) {
int wc = uri.indexOf('*');
if (wc < 0) {
Key key = new Key(uri);
return new SearchResult(root, typeVh, null, patterns, kind, timestamp, root.prefixUriIndex.iterator(key, key, Index.ASCENT_ORDER));
} else if (wc > 0) {
String prefix = uri.substring(0, wc);
return new SearchResult(root, typeVh, uri, patterns, kind, timestamp, root.prefixUriIndex.prefixIterator(prefix));
} else if ((wc = uri.lastIndexOf('*')) < uri.length()-1) {
String suffix = reverseString(uri.substring(wc+1, uri.length()));
return new SearchResult(root, typeVh, uri, patterns, kind, timestamp, root.suffixUriIndex.prefixIterator(suffix));
}
}
if (patterns.length > 0) {
NameVal prop = patterns[0];
Object val = prop.val;
NameVal[] restOfPatterns = subArray(patterns);
if (Symbols.Timestamp.equals(prop.name)) {
if (val instanceof Range) {
Range range = (Range)val;
if (range.from instanceof Date) {
Key fromKey = new Key((Date)range.from, range.fromInclusive);
Key tillKey = new Key((Date)range.till, range.tillInclusive);
return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp,
root.timeIndex.iterator(fromKey, tillKey, Index.ASCENT_ORDER));
}
} else if (val instanceof Date) {
Key key = new Key((Date)val);
return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp,
root.timeIndex.iterator(key, key, Index.ASCENT_ORDER));
}
return EmptyIterator;
} else if (Symbols.Rectangle.equals(prop.name)) {
if (val instanceof NameVal[]) {
NameVal[] coord = (NameVal[])val;
if (coord.length == 4) {
RectangleR2 r = new RectangleR2(((Number)coord[0].val).doubleValue(),
((Number)coord[1].val).doubleValue(),
((Number)coord[2].val).doubleValue(),
((Number)coord[3].val).doubleValue());
return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp,
root.spatialIndex.iterator(r));
}
}
} else if (Symbols.Point.equals(prop.name)) {
if (val instanceof NameVal[]) {
NameVal[] coord = (NameVal[])val;
if (coord.length == 2) {
double x = ((Number)coord[0].val).doubleValue();
double y = ((Number)coord[1].val).doubleValue();
RectangleR2 r = new RectangleR2(x, y, x, y);
return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp,
root.spatialIndex.iterator(r));
}
}
} else if (Symbols.Keyword.equals(prop.name)) {
if (val instanceof String) {
ArrayList keywords = getKeywords((String)val);
Iterator[] occurences = new Iterator[keywords.size()];
for (int i = 0; i < occurences.length; i++) {
Key key = new Key((String)keywords.get(i));
occurences[i] = root.inverseIndex.iterator(key, key, Index.ASCENT_ORDER);
}
return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp, db.merge(occurences));
}
}
PropDef def = (PropDef)root.propDefIndex.get(prop.name);
if (def == null) {
return EmptyIterator;
}
if (val instanceof Range) {
Range range = (Range)val;
if (range.from instanceof Number) {
Key fromKey = new Key(new Object[]{def, range.from}, range.fromInclusive);
Key tillKey = new Key(new Object[]{def, range.till}, range.tillInclusive);
return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp,
root.numPropIndex.iterator(fromKey, tillKey, Index.ASCENT_ORDER));
} else if (range.from instanceof Date) {
Key fromKey = new Key(new Object[]{def, range.from}, range.fromInclusive);
Key tillKey = new Key(new Object[]{def, range.till}, range.tillInclusive);
return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp,
root.timePropIndex.iterator(fromKey, tillKey, Index.ASCENT_ORDER));
} else {
Key fromKey = new Key(new Object[]{def, range.from}, range.fromInclusive);
Key tillKey = new Key(new Object[]{def, range.till}, range.tillInclusive);
return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp,
root.strPropIndex.iterator(fromKey, tillKey, Index.ASCENT_ORDER));
}
} else if (val instanceof String) {
String str = (String)val;
int wc = str.indexOf('*');
if (wc < 0) {
Key key = new Key(new Object[]{def, str});
return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp,
root.strPropIndex.iterator(key, key, Index.ASCENT_ORDER));
} else if (wc > 0) {
String prefix = str.substring(0, wc);
Key fromKey = new Key(new Object[]{def, prefix});
Key tillKey = new Key(new Object[]{def, prefix + Character.MAX_VALUE}, false);
return new SearchResult(root, typeVh, uri, wc == str.length()-1 ? restOfPatterns : patterns, kind, timestamp,
root.strPropIndex.iterator(fromKey, tillKey, Index.ASCENT_ORDER));
}
} else if (val instanceof Number) {
Key key = new Key(new Object[]{def, val});
return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp,
root.numPropIndex.iterator(key, key, Index.ASCENT_ORDER));
} else if (val instanceof Date) {
Key key = new Key(new Object[]{def, val});
return new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp,
root.timePropIndex.iterator(key, key, Index.ASCENT_ORDER));
} else if (val instanceof NameVal) {
Iterator iterator = searchReferenceProperty(typeVh, uri, patterns, kind, timestamp, (NameVal)val, false, def, new ArrayList());
if (iterator != null) {
return iterator;
}
} else if (val instanceof NameVal[]) {
NameVal[] props = (NameVal[])val;
if (props.length > 0) {
Iterator iterator = searchReferenceProperty(typeVh, uri, patterns, kind, timestamp, props[0], props.length > 1, def, new ArrayList());
if (iterator != null) {
return iterator;
}
}
}
}
if (kind == SearchKind.LatestVersion) {
return new SearchResult(root, typeVh, uri, patterns, kind, timestamp, root.latest.iterator());
}
return new SearchResult(root, typeVh, uri, patterns, kind, timestamp, root.timeIndex.iterator());
} finally {
root.unlock();
}
}
class ReferenceIterator implements Iterator {
PropDef[] defs;
Iterator[] iterators;
int pos;
Thing currThing;
SearchKind kind;
Date timestamp;
DatabaseRoot root;
HashSet visited;
public ReferenceIterator(DatabaseRoot root, PropDef[] defs, Iterator iterator, SearchKind kind, Date timestamp) {
this.root = root;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -