/// /// Copyright © 2003-2008 JetBrains s.r.o. /// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder). /// using System; using JetBrains.Omea.Database; using JetBrains.Omea.OpenAPI; using JetBrains.Omea.Containers; using System.Text; namespace JetBrains.Omea.ResourceStore { internal enum PredicateMatch { Match, None, Add, Del }; /** * The base interface for a resource list predicate. */ public abstract class ResourceListPredicate { internal abstract IntArrayList GetMatchingResources( out bool sortedById ); /// /// Returns a reference to the sorted list of the resource IDs matching the predicate. /// The object returned in syncObject must be locked while working with the list. /// /// The object for synchronizing access to the list, or null /// if synchronization is not required. /// The sorted list of resource IDs matching the predicate. internal virtual IntArrayList GetSortedMatchingResourcesRef( out object syncObject ) { bool sortedById; IntArrayList result = GetMatchingResources( out sortedById ); if ( !sortedById ) { result.Sort(); } syncObject = null; return result; } internal abstract PredicateMatch MatchResource( IResource res, IPropertyChangeSet cs ); internal abstract int GetSelectionCost(); internal virtual ResourceListPredicate Optimize( bool isLive ) { ResourceListPredicate predicate = MyPalStorage.Storage.GetCachedPredicate( this ); if ( predicate != null ) { return predicate; } return this; } /** * If all elements matching the predicate are known to be of the same type, * returns the ID of that type. If not, returns -1. */ internal virtual int GetKnownType() { return -1; } /** * Checks if the predicate is (or contains in a union) the type predicate with the * specified type ID. */ internal virtual bool HasTypePredicate( int typeId ) { return false; } internal virtual bool HasAnyTypePredicate() { return false; } internal void GetMatchCounts( IResource res, IPropertyChangeSet cs, ref int oldMatch, ref int newMatch ) { PredicateMatch match = MatchResource( res, cs ); if ( match == PredicateMatch.Add || match == PredicateMatch.Match ) newMatch++; if ( match == PredicateMatch.Del || match == PredicateMatch.Match ) oldMatch++; } internal PredicateMatch MatchFromCounts( int oldMatch, int newMatch ) { if ( newMatch > 0 && oldMatch > 0 ) return PredicateMatch.Match; if ( newMatch > 0 ) return PredicateMatch.Add; if ( oldMatch > 0 ) return PredicateMatch.Del; return PredicateMatch.None; } protected IntArrayList GetResourcesFromResultSet( IResultSet rs, int column ) { try { return DoGetResourcesFromResultSet( rs, column ); } finally { rs.Dispose(); } } protected IntArrayList DoGetResourcesFromResultSet( IResultSet rs, int column ) { IntArrayList result = new IntArrayList(); using( SafeRecordValueEnumerator enumerator = new SafeRecordValueEnumerator( rs, "PredicateResourceList.DoGetResourcesFromResultSet" ) ) { while( enumerator.MoveNext() ) { result.Add( enumerator.GetCurrentIntValue( column ) ); } } return result; } } /** * The predicate which is implemented as a plain list of resource IDs. */ public class PlainListPredicate: ResourceListPredicate { private IntArrayList _resources; public PlainListPredicate( IntArrayList resources ) { _resources = resources; } internal int Count { get { return _resources.Count; } } public void Add( int resourceId ) { _resources.Add( resourceId ); } public void AddRange( IntArrayList list ) { _resources.AddRange( list ); } internal override IntArrayList GetMatchingResources( out bool sortedById ) { sortedById = false; return (IntArrayList) _resources.Clone(); } internal override PredicateMatch MatchResource( IResource res, IPropertyChangeSet cs ) { return ( _resources.IndexOf( res.Id ) >= 0 ) ? PredicateMatch.Match : PredicateMatch.None; } internal override int GetSelectionCost() { return 0; } public override string ToString() { StringBuilder builder = new StringBuilder( "List(" ); if ( _resources.Count > 0 ) { builder.Append( _resources [0] ); for( int i=1; i<_resources.Count; i++ ) { builder.Append( ',' ); builder.Append( _resources [i] ); } } builder.Append( ")" ); return builder.ToString(); } public override bool Equals( object obj ) { if ( Object.ReferenceEquals( this, obj ) ) return true; PlainListPredicate rhs = obj as PlainListPredicate; if ( rhs == null ) return false; if ( _resources.Count != rhs._resources.Count ) return false; for( int i=0; i<_resources.Count; i++ ) { if ( rhs._resources.IndexOf( _resources [i] ) < 0 ) return false; } return true; } public override int GetHashCode() { int hc = 0; for( int i=0; i<_resources.Count; i++ ) { hc ^= _resources [i] << (i % 32); } return hc; } } }