private RatingResult predictUserRating(DBObject reviewObject) {
		if (reviewObject == null)
			return null;
		if (!reviewObject.containsField(CollectionReview.KEY_USER_ID)
				|| !reviewObject
						.containsField(CollectionReview.KEY_BUSINESS_ID)
				|| !reviewObject.containsField(CollectionReview.KEY_STARS)) {
			return null;
		}
		RatingResult ratingResult = new RatingResult();
		/* user id of the (original) user */
		ratingResult.userId = (String) reviewObject
				.get(CollectionReview.KEY_USER_ID);
		/* business id of the (original) business */
		ratingResult.businessId = (String) reviewObject
				.get(CollectionReview.KEY_BUSINESS_ID);
		/*
		 * actual stars rating of the (original) review. The rest of the logic
		 * tries to use collaborative filtering to predict this values and then
		 * compares the prediction vs. the actual.
		 */
		ratingResult.stars = (Integer) reviewObject
				.get(CollectionReview.KEY_STARS);
		/* collect all reviews of the (original) user */
		HashMap<String, DBObject> reviewArray = findUserReviews(reviewObject);
		System.out.println("Try to predict user " + ratingResult.userId
				+ " for business " + ratingResult.businessId);
		/* search for all reviews for the same business */
		DBCollection reviewCollection = db.getCollection(COLLECTION_REVIEW);
		BasicDBObject filter = new BasicDBObject();
		filter.put(CollectionReview.KEY_BUSINESS_ID, ratingResult.businessId);
		DBCursor cursorReview2 = reviewCollection.find(filter);
		/*
		 * comparableRatingArray contains the reviews by other users of the
		 * (original) business
		 */
		ArrayList<ComparableRating> comparableRatingArray = new ArrayList<ComparableRating>();
		DBCollection userCollection = db.getCollection(COLLECTION_USER);
		ensureCollectionUserIndex(userCollection);
		int totalRatingCount = 0;
		int totalRatingStars = 0;
		/* for each review of the (original) business */
		while (cursorReview2.hasNext()) {
			DBObject reviewObject2 = cursorReview2.next();
			String userId2 = (String) reviewObject2
					.get(CollectionReview.KEY_USER_ID);
			/* make sure to skip the review by the (original) business */
			if (!userId2.equals(ratingResult.userId)) {
				totalRatingCount++;
				totalRatingStars += (Integer) reviewObject2
						.get(CollectionReview.KEY_STARS);
				/* collect all reviews of this other user */
				HashMap<String, DBObject> reviewArray2 = findUserReviews(reviewObject2);
				/*
				 * compute similarity between this other user and the (original)
				 * user
				 */
				SimilarityCoefficient coefficient = computeSimilarityCoefficient(
						reviewArray, reviewArray2, ratingResult.businessId);
				/* sometimes similarity cannot be computed so we need to check */
				if (isCoefficientUsable(coefficient)) {
					coefficient.sameGenderProbability = calculateSameGenderProbability(
							userCollection, ratingResult.userId, userId2);
					DBObject businessReview = reviewArray2
							.get(ratingResult.businessId);
					ComparableRating comparableRating = new ComparableRating();
					comparableRating.originalUserId = ratingResult.userId;
					comparableRating.userId = (String) businessReview
							.get(CollectionReview.KEY_USER_ID);
					comparableRating.stars = (Integer) businessReview
							.get(CollectionReview.KEY_STARS);
					comparableRating.coefficient = coefficient;
					/*
					 * add an entry containing the other users' actual stars
					 * rating and the similarity of the other user vs. the
					 * (original) user
					 */
					comparableRatingArray.add(comparableRating);
					System.out.println(comparableRating);
				} // if
			} // if
		} // while
		cursorReview2.close();
		/*
		 * total number of reviews of the same business by other users where
		 * similarity can be computed
		 */
		ratingResult.totalUserCount = comparableRatingArray.size();
		/* only use a subset of all other users' reviews */
		ratingResult.actualUserCount = limitComparableRating(comparableRatingArray);
		/* generate the prediction using the subset */
		ratingResult.predictedStars = computeComparableRating(
				comparableRatingArray, ratingResult.actualUserCount);
		System.out.println(ratingResult);
		if (ratingResult.predictedStars == null) {
			System.out.println("Insufficient data to predict rating");
		} else {
			double error = ratingResult.predictedStars - ratingResult.stars;
			System.out.println("error=" + error + " predictedStars="
					+ ratingResult.predictedStars + " actualStars="
					+ ratingResult.stars);
		} // else
		/* naive average rating of the (original) business by all other users */
		ratingResult.averageRatingStars = (double) totalRatingStars
				/ (double) totalRatingCount;
		double arsError = ratingResult.averageRatingStars - ratingResult.stars;
		System.out.println("averageRatingStars.error="
				+ Double.toString(arsError) + " averageRatingStars="
				+ Double.toString(ratingResult.averageRatingStars)
				+ " actualStars=" + ratingResult.stars);
		return ratingResult;
	} // predictUserRating