/// <summary> 
		/// Given a collection of entity instances that used to
		/// belong to the collection, and a collection of instances
		/// that currently belong, return a collection of orphans
		/// </summary>
		protected static ICollection GetOrphans(ICollection oldElements, ICollection currentElements, string entityName,
		                                        ISessionImplementor session)
		{
			// short-circuit(s)
			if (currentElements.Count == 0)
			{
				// no new elements, the old list contains only Orphans
				return oldElements;
			}
			if (oldElements.Count == 0)
			{
				// no old elements, so no Orphans neither
				return oldElements;
			}

			IType idType = session.Factory.GetEntityPersister(entityName).IdentifierType;

			// create the collection holding the orphans
			List<object> res = new List<object>();

			// collect EntityIdentifier(s) of the *current* elements - add them into a HashSet for fast access
			HashedSet<TypedValue> currentIds = new HashedSet<TypedValue>();
			foreach (object current in currentElements)
			{
				if (current != null && ForeignKeys.IsNotTransient(entityName, current, null, session))
				{
					object currentId = ForeignKeys.GetEntityIdentifierIfNotUnsaved(entityName, current, session);
					currentIds.Add(new TypedValue(idType, currentId, session.EntityMode));
				}
			}

			// iterate over the *old* list
			foreach (object old in oldElements)
			{
				object oldId = ForeignKeys.GetEntityIdentifierIfNotUnsaved(entityName, old, session);
				if (!currentIds.Contains(new TypedValue(idType, oldId, session.EntityMode)))
				{
					res.Add(old);
				}
			}

			return res;
		}
		public IRStatistics Evaluate(RecommenderBuilder recommenderBuilder,
		                             DataModel dataModel,
		                             int at,
		                             double relevanceThreshold,
		                             double evaluationPercentage) 
		{

			if (recommenderBuilder == null) {
				throw new ArgumentNullException("recommenderBuilder is null");
			}
			if (dataModel == null) {
				throw new ArgumentNullException("dataModel is null");
			}
			if (at < 1) {
				throw new ArgumentException("at must be at least 1");
			}
			if (double.IsNaN(evaluationPercentage) || evaluationPercentage <= 0.0 || evaluationPercentage > 1.0) 
			{
				throw new ArgumentException("Invalid evaluationPercentage: " + evaluationPercentage);
			}
			if (double.IsNaN(relevanceThreshold)) {
				throw new ArgumentException("Invalid relevanceThreshold: " + evaluationPercentage);
			}

			RunningAverage precision = new FullRunningAverage();
			RunningAverage recall = new FullRunningAverage();
			foreach (User user in dataModel.GetUsers()) 
			{
				Object id = user.ID;
				if (random.NextDouble() < evaluationPercentage) 
				{
					ICollection<Item> relevantItems = new HashedSet<Item>(/* at */);
                    Preference[] prefs = user.GetPreferencesAsArray();

					foreach (Preference pref in prefs) 
					{
						if (pref.Value >= relevanceThreshold) 
                        {
							relevantItems.Add(pref.Item);
						}
					}
					int numRelevantItems = relevantItems.Count;
					if (numRelevantItems > 0) 
                    {
						ICollection<User> trainingUsers = new List<User>(dataModel.GetNumUsers());
						foreach (User user2 in dataModel.GetUsers()) 
                        {
							if (id.Equals(user2.ID)) 
							{
								ICollection<Preference> trainingPrefs = new List<Preference>();
                                prefs = user2.GetPreferencesAsArray();
								foreach (Preference pref in prefs) 
								{
									if (!relevantItems.Contains(pref.Item)) 
									{
										trainingPrefs.Add(pref);
									}
								}
								if (trainingPrefs.Count > 0) 
								{
									User trainingUser = new GenericUser<String>(id.ToString(), trainingPrefs);
									trainingUsers.Add(trainingUser);
								}
							} 
                            else 
                            {
								trainingUsers.Add(user2);
							}

						}
						DataModel trainingModel = new GenericDataModel(trainingUsers);
						Recommender recommender = recommenderBuilder.BuildRecommender(trainingModel);

						try 
						{
							trainingModel.GetUser(id);
						} 
                        catch (NoSuchElementException) 
                        {
							continue; // Oops we excluded all prefs for the user -- just move on
						}
						
						int intersectionSize = 0;
						foreach (RecommendedItem recommendedItem in recommender.Recommend(id, at)) 
						{
							if (relevantItems.Contains(recommendedItem.Item)) 
							{
								intersectionSize++;
							}
						}
						precision.AddDatum((double) intersectionSize / (double) at);
						recall.AddDatum((double) intersectionSize / (double) numRelevantItems);					
					}
				}
			}

			return new IRStatisticsImpl(precision.Average, recall.Average);
		}
		private IDictionary<string, string[]> BindPropertyResults(string alias, HbmReturnDiscriminator discriminatorSchema,
			HbmReturnProperty[] returnProperties, PersistentClass pc)
		{
			Dictionary<string, string[]> propertyresults = new Dictionary<string, string[]>();
			// maybe a concrete SQLpropertyresult type, but Map is exactly what is required at the moment

			if (discriminatorSchema != null)
			{
				propertyresults["class"] = GetResultColumns(discriminatorSchema).ToArray();
			}

			List<HbmReturnProperty> properties = new List<HbmReturnProperty>();
			List<string> propertyNames = new List<string>();

			foreach (HbmReturnProperty returnPropertySchema in returnProperties ?? new HbmReturnProperty[0])
			{
				string name = returnPropertySchema.name;
				if (pc == null || name.IndexOf('.') == -1)
				{
					//if dotted and not load-collection nor return-join
					//regular property
					properties.Add(returnPropertySchema);
					propertyNames.Add(name);
				}
				else
				{
					// Reorder properties
					// 1. get the parent property
					// 2. list all the properties following the expected one in the parent property
					// 3. calculate the lowest index and insert the property

					int dotIndex = name.LastIndexOf('.');
					string reducedName = name.Substring(0, dotIndex);
					IValue value = pc.GetRecursiveProperty(reducedName).Value;
					IEnumerable<Mapping.Property> parentPropIter;
					if (value is Component)
					{
						Component comp = (Component) value;
						parentPropIter = comp.PropertyIterator;
					}
					else if (value is ToOne)
					{
						ToOne toOne = (ToOne) value;
						PersistentClass referencedPc = mappings.GetClass(toOne.ReferencedEntityName);
						if (toOne.ReferencedPropertyName != null)
							try
							{
								parentPropIter =
									((Component) referencedPc.GetRecursiveProperty(toOne.ReferencedPropertyName).Value).PropertyIterator;
							}
							catch (InvalidCastException e)
							{
								throw new MappingException("dotted notation reference neither a component nor a many/one to one", e);
							}
						else
							try
							{
								parentPropIter = ((Component) referencedPc.IdentifierProperty.Value).PropertyIterator;
							}
							catch (InvalidCastException e)
							{
								throw new MappingException("dotted notation reference neither a component nor a many/one to one", e);
							}
					}
					else
						throw new MappingException("dotted notation reference neither a component nor a many/one to one");
					bool hasFollowers = false;
					List<string> followers = new List<string>();
					foreach (Mapping.Property prop in parentPropIter)
					{
						string currentPropertyName = prop.Name;
						string currentName = reducedName + '.' + currentPropertyName;
						if (hasFollowers)
							followers.Add(currentName);
						if (name.Equals(currentName))
							hasFollowers = true;
					}

					int index = propertyNames.Count;
					int followersSize = followers.Count;
					for (int loop = 0; loop < followersSize; loop++)
					{
						string follower = followers[loop];
						int currentIndex = GetIndexOfFirstMatchingProperty(propertyNames, follower);
						index = currentIndex != -1 && currentIndex < index ? currentIndex : index;
					}
					propertyNames.Insert(index, name);
					properties.Insert(index, returnPropertySchema);
				}
			}

			ISet<string> uniqueReturnProperty = new HashedSet<string>();
			foreach (HbmReturnProperty returnPropertySchema in properties)
			{
				string name = returnPropertySchema.name;
				if ("class".Equals(name))
					throw new MappingException(
						"class is not a valid property name to use in a <return-property>, use <return-discriminator> instead"
						);
				//TODO: validate existing of property with the chosen name. (secondpass )
				List<string> allResultColumns = GetResultColumns(returnPropertySchema);

				if (allResultColumns.Count == 0)
					throw new MappingException(
						"return-property for alias " + alias +
							" must specify at least one column or return-column name"
						);
				if (uniqueReturnProperty.Contains(name))
					throw new MappingException(
						"duplicate return-property for property " + name +
							" on alias " + alias
						);
				uniqueReturnProperty.Add(name);

				// the issue here is that for <return-join/> representing an entity collection,
				// the collection element values (the property values of the associated entity)
				// are represented as 'element.{propertyname}'.  Thus the StringHelper.root()
				// here puts everything under 'element' (which additionally has significant
				// meaning).  Probably what we need to do is to something like this instead:
				//      String root = StringHelper.root( name );
				//      String key = root; // by default
				//      if ( !root.equals( name ) ) {
				//	        // we had a dot
				//          if ( !root.equals( alias ) {
				//              // the root does not apply to the specific alias
				//              if ( "elements".equals( root ) {
				//                  // we specifically have a <return-join/> representing an entity collection
				//                  // and this <return-property/> is one of that entity's properties
				//                  key = name;
				//              }
				//          }
				//      }
				// but I am not clear enough on the intended purpose of this code block, especially
				// in relation to the "Reorder properties" code block above... 
				//			String key = StringHelper.root( name );
				string key = name;
				string[] intermediateResults;
				if (!propertyresults.TryGetValue(key,out intermediateResults))
					propertyresults[key] = allResultColumns.ToArray();
				else
					ArrayHelper.AddAll(intermediateResults, allResultColumns); // TODO: intermediateResults not used after this
			}

			Dictionary<string, string[]> newPropertyResults = new Dictionary<string, string[]>();

			foreach (KeyValuePair<string, string[]> entry in propertyresults)
			{
				newPropertyResults[entry.Key] = entry.Value;
			}
			return newPropertyResults.Count == 0 ? (IDictionary<string, string[]>)new CollectionHelper.EmptyMapClass<string, string[]>() : newPropertyResults;
		}
Beispiel #4
0
 /// <summary>
 /// Compute depths for all dirEdges via breadth-first traversal of nodes in graph.
 /// </summary>
 /// <param name="startEdge">Edge to start processing with.</param>
 // <FIX> MD - use iteration & queue rather than recursion, for speed and robustness
 private void ComputeDepths(DirectedEdge startEdge)
 {
     ISet nodesVisited = new HashedSet();
     Queue nodeQueue = new Queue();
     Node startNode = startEdge.Node;
     nodeQueue.Enqueue(startNode);
     nodesVisited.Add(startNode);
     startEdge.Visited = true;
     while (nodeQueue.Count != 0)
     {
         Node n = (Node) nodeQueue.Dequeue();
         nodesVisited.Add(n);
         // compute depths around node, starting at this edge since it has depths assigned
         ComputeNodeDepth(n);
         // add all adjacent nodes to process queue, unless the node has been visited already
         IEnumerator i = ((DirectedEdgeStar)n.Edges).GetEnumerator();
         while (i.MoveNext())
         {
             DirectedEdge de = (DirectedEdge) i.Current;
             DirectedEdge sym = de.Sym;
             if (sym.IsVisited) continue;
             Node adjNode = sym.Node;
             if (!(nodesVisited.Contains(adjNode)))
             {
                 nodeQueue.Enqueue(adjNode);
                 nodesVisited.Add(adjNode);
             }
         }
     }
 }