/// <summary> /// Property value constructor /// </summary> /// <param name="def"></param> /// <param name="val"></param> public PropVal(PropDef def, object val) { this.def = def; this.val = val; }
private IEnumerable SearchReferenceProperty(VersionHistory type, string uri, NameVal[] patterns, SearchKind kind, DateTime timestamp, NameVal prop, bool compound, PropDef def, ArrayList refs) { refs.Add(def); NameVal[] restOfPatterns = compound ? patterns : SubArray(patterns); object val = prop.val; switch (prop.name) { case Symbols.Timestamp: if (val is Range) { Range range = (Range)val; if (range.from is DateTime) { Key fromKey = new Key((DateTime)range.from, range.fromInclusive); Key tillKey = new Key((DateTime)range.till, range.tillInclusive); return new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.timeIndex.GetEnumerator(fromKey, tillKey), kind, timestamp)); } } else if (val is DateTime) { Key key = new Key((DateTime)val); return new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.timeIndex.GetEnumerator(key, key), kind, timestamp)); } return new object[0]; // empty selection case Symbols.Rectangle: if (val is NameVal[]) { NameVal[] coord = (NameVal[])val; if (coord.Length == 4) { RectangleR2 r = new RectangleR2((double)coord[0].val, (double)coord[1].val, (double)coord[2].val, (double)coord[3].val); return new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.spatialIndex.Overlaps(r).GetEnumerator(), kind, timestamp)); } } break; case Symbols.Point: if (val is NameVal[]) { NameVal[] coord = (NameVal[])val; if (coord.Length == 2) { double x = (double)coord[0].val; double y = (double)coord[1].val; RectangleR2 r = new RectangleR2(x, y, x, y); return new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.spatialIndex.Overlaps(r).GetEnumerator(), kind, timestamp)); } } break; case Symbols.Keyword: if (val is string) { ArrayList keywords = new ArrayList(); foreach (string keyword in ((string)val).ToLower().Split(keywordSeparators)) { if (keyword.Length > 0 && !keywordStopList.ContainsKey(keyword)) { keywords.Add(keyword); } } IEnumerator[] occurences = new IEnumerator[keywords.Count]; for (int i = 0; i < occurences.Length; i++) { Key key = new Key((string)keywords[i]); occurences[i] = root.inverseIndex.GetEnumerator(key, key); } return new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), db.Merge(occurences), kind, timestamp)); } break; } def = (PropDef)root.propDefIndex[prop.name]; if (def == null) { return new object[0]; // empty selection } if (val is Range) { Range range = (Range)val; if (range.from is double) { 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, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.numPropIndex.GetEnumerator(fromKey, tillKey), kind, timestamp)); } else if (range.from is DateTime) { 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, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.timePropIndex.GetEnumerator(fromKey, tillKey), kind, timestamp)); } 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, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.strPropIndex.GetEnumerator(fromKey, tillKey), kind, timestamp)); } } if (val is string) { string str = (string)prop.val; int wc = str.IndexOf('*'); if (wc < 0) { Key key = new Key(new object[]{def, str}); return new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.strPropIndex.GetEnumerator(key, key), kind, timestamp)); } 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 + Char.MaxValue}, false); return new SearchResult(root, type, uri, wc == str.Length-1 ? restOfPatterns : patterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.strPropIndex.GetEnumerator(fromKey, tillKey), kind, timestamp)); } } else if (val is double) { Key key = new Key(new object[]{def, val}); return new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.numPropIndex.GetEnumerator(key, key), kind, timestamp)); } else if (val is DateTime) { Key key = new Key(new object[]{def, (DateTime)val}); return new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.timePropIndex.GetEnumerator(key, key), kind, timestamp)); } else if (val is NameVal) { return SearchReferenceProperty(type, uri, patterns, kind, timestamp, (NameVal)val, compound, def, refs); } else if (val is NameVal[]) { NameVal[] props = (NameVal[])val; if (props.Length > 0) { return SearchReferenceProperty(type, uri, patterns, kind, timestamp, props[0], true, def, refs); } } return null; }
public ReferenceIterator(DatabaseRoot root, PropDef[] defs, IEnumerator iterator, SearchKind kind, DateTime timestamp) { this.root = root; this.defs = defs; this.kind = kind; this.timestamp = timestamp; iterators = new IEnumerator[defs.Length+1]; iterators[iterators.Length-1] = iterator; Reset(); }
private Thing CreateObject(Thing type, VersionHistory vh, NameVal[] props) { Thing thing = new Thing(); thing.vh = vh; thing.type = type; thing.timestamp = DateTime.Now; thing.props = new PropVal[props.Length]; for (int i = 0; i < props.Length; i++) { NameVal prop = props[i]; PropDef def = (PropDef)root.propDefIndex[prop.name]; if (def == null) { def = new PropDef(); def.name = prop.name; root.propDefIndex.Put(def); } object val = prop.val; PropVal pv = new PropVal(def, val); Key key = new Key(new object[]{def, val}); if (val is string) { root.strPropIndex.Put(key, thing); foreach (string keyword in ((string)val).ToLower().Split(keywordSeparators)) { if (keyword.Length > 0 && !keywordStopList.ContainsKey(keyword)) { root.inverseIndex.Put(keyword, thing); } } } else if (val is double) { root.numPropIndex.Put(key, thing); } else if (val is DateTime) { root.timePropIndex.Put(key, thing); } else if (val is VersionHistory || val == null) { root.refPropIndex.Put(key, thing); if (prop.name == Symbols.Rectangle) { PropVal[] coord = ((VersionHistory)val).Latest.props; RectangleR2 r = new RectangleR2((double)coord[0].val, (double)coord[1].val, (double)coord[2].val, (double)coord[3].val); root.spatialIndex.Put(r, thing); } else if (prop.name == Symbols.Point) { PropVal[] coord = ((VersionHistory)val).Latest.props; double x = (double)coord[0].val; double y = (double)coord[1].val; RectangleR2 r = new RectangleR2(x, y, x, y); root.spatialIndex.Put(r, thing); } } else { throw new InvalidOperationException("Invalid propery value type " + prop.val.GetType()); } thing.props[i] = pv; } thing.Modify(); vh.versions.Add(thing); root.timeIndex.Put(thing); root.latest.Add(thing); return thing; }
private IEnumerable SearchReferenceProperty(VersionHistory type, string uri, NameVal[] patterns, SearchKind kind, DateTime timestamp, NameVal prop, bool compound, PropDef def, ArrayList refs) { refs.Add(def); NameVal[] restOfPatterns = compound ? patterns : SubArray(patterns); object val = prop.val; switch (prop.name) { case Symbols.Timestamp: if (val is Range) { Range range = (Range)val; if (range.from is DateTime) { Key fromKey = new Key((DateTime)range.from, range.fromInclusive); Key tillKey = new Key((DateTime)range.till, range.tillInclusive); return(new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.timeIndex.GetEnumerator(fromKey, tillKey), kind, timestamp))); } } else if (val is DateTime) { Key key = new Key((DateTime)val); return(new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.timeIndex.GetEnumerator(key, key), kind, timestamp))); } return(new object[0]); // empty selection case Symbols.Rectangle: if (val is NameVal[]) { NameVal[] coord = (NameVal[])val; if (coord.Length == 4) { RectangleR2 r = new RectangleR2((double)coord[0].val, (double)coord[1].val, (double)coord[2].val, (double)coord[3].val); return(new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.spatialIndex.Overlaps(r).GetEnumerator(), kind, timestamp))); } } break; case Symbols.Point: if (val is NameVal[]) { NameVal[] coord = (NameVal[])val; if (coord.Length == 2) { double x = (double)coord[0].val; double y = (double)coord[1].val; RectangleR2 r = new RectangleR2(x, y, x, y); return(new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.spatialIndex.Overlaps(r).GetEnumerator(), kind, timestamp))); } } break; case Symbols.Keyword: if (val is string) { ArrayList keywords = new ArrayList(); foreach (string keyword in ((string)val).ToLower().Split(keywordSeparators)) { if (keyword.Length > 0 && !keywordStopList.ContainsKey(keyword)) { keywords.Add(keyword); } } IEnumerator[] occurences = new IEnumerator[keywords.Count]; for (int i = 0; i < occurences.Length; i++) { Key key = new Key((string)keywords[i]); occurences[i] = root.inverseIndex.GetEnumerator(key, key); } return(new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), db.Merge(occurences), kind, timestamp))); } break; } def = (PropDef)root.propDefIndex[prop.name]; if (def == null) { return(new object[0]); // empty selection } if (val is Range) { Range range = (Range)val; if (range.from is double) { 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, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.numPropIndex.GetEnumerator(fromKey, tillKey), kind, timestamp))); } else if (range.from is DateTime) { 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, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.timePropIndex.GetEnumerator(fromKey, tillKey), kind, timestamp))); } 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, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.strPropIndex.GetEnumerator(fromKey, tillKey), kind, timestamp))); } } if (val is string) { string str = (string)prop.val; int wc = str.IndexOf('*'); if (wc < 0) { Key key = new Key(new object[] { def, str }); return(new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.strPropIndex.GetEnumerator(key, key), kind, timestamp))); } 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 + Char.MaxValue }, false); return(new SearchResult(root, type, uri, wc == str.Length - 1 ? restOfPatterns : patterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.strPropIndex.GetEnumerator(fromKey, tillKey), kind, timestamp))); } } else if (val is double) { Key key = new Key(new object[] { def, val }); return(new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.numPropIndex.GetEnumerator(key, key), kind, timestamp))); } else if (val is DateTime) { Key key = new Key(new object[] { def, (DateTime)val }); return(new SearchResult(root, type, uri, restOfPatterns, kind, timestamp, new ReferenceIterator(root, (PropDef[])refs.ToArray(typeof(PropDef)), root.timePropIndex.GetEnumerator(key, key), kind, timestamp))); } else if (val is NameVal) { return(SearchReferenceProperty(type, uri, patterns, kind, timestamp, (NameVal)val, compound, def, refs)); } else if (val is NameVal[]) { NameVal[] props = (NameVal[])val; if (props.Length > 0) { return(SearchReferenceProperty(type, uri, patterns, kind, timestamp, props[0], true, def, refs)); } } return(null); }
/// <summary>Get iterator through object matching specified search parameters</summary> /// <param name="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> /// <param name="uri">Object URI pattern. It may be null, in this case URI is not inspected.</param> /// <param name="patterns">array of name:value pairs specifying search condition for object properties</param> /// <param name="kind">search kind used to select inspected versions</param> /// <param name="timestamp">timestamp used to select versions, if kind is SearchKind.LatestVersion /// or SearchKind.AllVersions this parameter is ignored</param> /// <returns>Enumerator through object meet search criteria.</returns> public IEnumerable Search(string type, string uri, NameVal[] patterns, SearchKind kind, DateTime timestamp) { VersionHistory typeVh = null; root.SharedLock(); try { if (type != null) { typeVh = GetObject(type); if (typeVh == null) { return(new object[0]); // empty selection } } if (uri != null) { int wc = uri.IndexOf('*'); if (wc < 0) { return(new SearchResult(root, typeVh, null, patterns, kind, timestamp, root.prefixUriIndex.GetEnumerator(uri, uri))); } else if (wc > 0) { String prefix = uri.Substring(0, wc); return(new SearchResult(root, typeVh, uri, patterns, kind, timestamp, root.prefixUriIndex.GetEnumerator(prefix))); } else if ((wc = uri.LastIndexOf('*')) < uri.Length - 1) { String suffix = ReverseString(uri.Substring(wc + 1, uri.Length - wc - 1)); return(new SearchResult(root, typeVh, uri, patterns, kind, timestamp, root.suffixUriIndex.GetEnumerator(suffix))); } } if (patterns.Length > 0) { NameVal prop = patterns[0]; object val = prop.val; NameVal[] restOfPatterns = SubArray(patterns); switch (prop.name) { case Symbols.Timestamp: if (val is Range) { Range range = (Range)val; if (range.from is DateTime) { Key fromKey = new Key((DateTime)range.from, range.fromInclusive); Key tillKey = new Key((DateTime)range.till, range.tillInclusive); return(new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp, root.timeIndex.GetEnumerator(fromKey, tillKey))); } } else if (val is DateTime) { Key key = new Key((DateTime)val); return(new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp, root.timeIndex.GetEnumerator(key, key))); } return(new object[0]); // empty selection case Symbols.Rectangle: if (val is NameVal[]) { NameVal[] coord = (NameVal[])val; if (coord.Length == 4) { RectangleR2 r = new RectangleR2((double)coord[0].val, (double)coord[1].val, (double)coord[2].val, (double)coord[3].val); return(new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp, root.spatialIndex.Overlaps(r).GetEnumerator())); } } break; case Symbols.Point: if (val is NameVal[]) { NameVal[] coord = (NameVal[])val; if (coord.Length == 2) { double x = (double)coord[0].val; double y = (double)coord[1].val; RectangleR2 r = new RectangleR2(x, y, x, y); return(new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp, root.spatialIndex.Overlaps(r).GetEnumerator())); } } break; case Symbols.Keyword: if (val is string) { ArrayList keywords = new ArrayList(); foreach (string keyword in ((string)val).ToLower().Split(keywordSeparators)) { if (keyword.Length > 0 && !keywordStopList.ContainsKey(keyword)) { keywords.Add(keyword); } } IEnumerator[] occurences = new IEnumerator[keywords.Count]; for (int i = 0; i < occurences.Length; i++) { Key key = new Key((string)keywords[i]); occurences[i] = root.inverseIndex.GetEnumerator(key, key); } return(new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp, db.Merge(occurences))); } break; } PropDef def = (PropDef)root.propDefIndex[prop.name]; if (def == null) { return(new object[0]); // empty selection } if (val is Range) { Range range = (Range)val; if (range.from is double) { 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.GetEnumerator(fromKey, tillKey))); } else if (range.from is DateTime) { 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.GetEnumerator(fromKey, tillKey))); } 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.GetEnumerator(fromKey, tillKey))); } } else if (val is 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.GetEnumerator(key, key))); } 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 + Char.MaxValue }, false); return(new SearchResult(root, typeVh, uri, wc == str.Length - 1 ? restOfPatterns : patterns, kind, timestamp, root.strPropIndex.GetEnumerator(fromKey, tillKey))); } } else if (val is double) { Key key = new Key(new object[] { def, val }); return(new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp, root.numPropIndex.GetEnumerator(key, key))); } else if (val is DateTime) { Key key = new Key(new object[] { def, val }); return(new SearchResult(root, typeVh, uri, restOfPatterns, kind, timestamp, root.timePropIndex.GetEnumerator(key, key))); } else if (val is NameVal) { IEnumerable iterator = SearchReferenceProperty(typeVh, uri, patterns, kind, timestamp, (NameVal)val, false, def, new ArrayList()); if (iterator != null) { return(iterator); } } else if (val is NameVal[]) { NameVal[] props = (NameVal[])val; if (props.Length > 0) { IEnumerable 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.GetEnumerator())); } return(new SearchResult(root, typeVh, uri, patterns, kind, timestamp, root.timeIndex.GetEnumerator())); } finally { root.Unlock(); } }
private Thing CreateObject(Thing type, VersionHistory vh, NameVal[] props) { Thing thing = new Thing(); thing.vh = vh; thing.type = type; thing.timestamp = DateTime.Now; thing.props = new PropVal[props.Length]; for (int i = 0; i < props.Length; i++) { NameVal prop = props[i]; PropDef def = (PropDef)root.propDefIndex[prop.name]; if (def == null) { def = new PropDef(); def.name = prop.name; root.propDefIndex.Put(def); } object val = prop.val; PropVal pv = new PropVal(def, val); Key key = new Key(new object[] { def, val }); if (val is string) { root.strPropIndex.Put(key, thing); foreach (string keyword in ((string)val).ToLower().Split(keywordSeparators)) { if (keyword.Length > 0 && !keywordStopList.ContainsKey(keyword)) { root.inverseIndex.Put(keyword, thing); } } } else if (val is double) { root.numPropIndex.Put(key, thing); } else if (val is DateTime) { root.timePropIndex.Put(key, thing); } else if (val is VersionHistory || val == null) { root.refPropIndex.Put(key, thing); if (prop.name == Symbols.Rectangle) { PropVal[] coord = ((VersionHistory)val).Latest.props; RectangleR2 r = new RectangleR2((double)coord[0].val, (double)coord[1].val, (double)coord[2].val, (double)coord[3].val); root.spatialIndex.Put(r, thing); } else if (prop.name == Symbols.Point) { PropVal[] coord = ((VersionHistory)val).Latest.props; double x = (double)coord[0].val; double y = (double)coord[1].val; RectangleR2 r = new RectangleR2(x, y, x, y); root.spatialIndex.Put(r, thing); } } else { throw new InvalidOperationException("Invalid propery value type " + prop.val.GetType()); } thing.props[i] = pv; } thing.Modify(); vh.versions.Add(thing); root.timeIndex.Put(thing); root.latest.Add(thing); return(thing); }