Package com.springone.myrestaurants.domain

Source Code of com.springone.myrestaurants.domain.TopRatedRestaurantFinder$CalculateRatingPredicate$AggregatedRecommendation

package com.springone.myrestaurants.domain;

import org.neo4j.graphdb.*;
import org.neo4j.graphdb.traversal.TraversalDescription;
import org.neo4j.graphdb.traversal.Traverser;
import org.neo4j.helpers.Predicate;
import org.neo4j.kernel.Traversal;
import org.neo4j.kernel.impl.traversal.TraversalDescriptionImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.data.graph.neo4j.support.GraphDatabaseContext;

import java.util.*;

/**
* @author Michael Hunger
* @since 02.10.2010
*/
@Configurable
public class TopRatedRestaurantFinder {

    @Autowired
    GraphDatabaseContext graphDatabaseContext;

    private static final int MAXIMUM_DEPTH = 5;
    public Collection<RatedRestaurant> getTopNRatedRestaurants(final UserAccount user, final int n) {
        final CalculateRatingPredicate calculateRatingPredicate = new CalculateRatingPredicate();
        final Node userNode=user.getPersistentState();
        final TraversalDescription traversalDescription = new TraversalDescriptionImpl()
                .order(Traversal.postorderBreadthFirst())
                .prune(Traversal.pruneAfterDepth(MAXIMUM_DEPTH))
                .filter(calculateRatingPredicate)
                .relationships(DynamicRelationshipType.withName("friends"));
        final Traverser traverser = traversalDescription.traverse(userNode);
        final Iterator<Node> it = traverser.nodes().iterator();
        while (it.hasNext()) {
            it.next();
        }
        return calculateRatingPredicate.getRecommendedRestaurants(n);
    }

    private class CalculateRatingPredicate implements Predicate<Path> {
        class AggregatedRecommendation implements Comparable<AggregatedRecommendation> {
            private Node restaurant;
            private Collection<Relationship> recommendations=new HashSet<Relationship>();
            double stars;
            double sum;

            public AggregatedRecommendation(final Node restaurant) {
                this.restaurant = restaurant;
            }

            @Override
            public int compareTo(final AggregatedRecommendation o) {
                return stars < o.stars ? 1 : stars == o.stars ? 0 : -1;
            }

            public void add(final Relationship recommendation, final int distance) {
                if (recommendations.add(recommendation)) {
                    final Integer userStars = (Integer)recommendation.getProperty("stars", 0);
                    sum += userStars * Math.pow(0.5D,distance);
                    stars = sum / recommendations.size();
                }
            }

            private RatedRestaurant toRatedRestaurant(final CalculateRatingPredicate calculateRatingPredicate) {
                final RatedRestaurant ratedRestaurant = new RatedRestaurant(graphDatabaseContext.createEntityFromState(restaurant, Restaurant.class));
                for (final Relationship recommendation : recommendations) {
                    ratedRestaurant.add(graphDatabaseContext.createEntityFromState(recommendation, Recommendation.class));
                }
                return ratedRestaurant;
            }
        }

        private final Map<Node, AggregatedRecommendation> recommendedRestaurants=new HashMap<Node, AggregatedRecommendation>();

        public CalculateRatingPredicate() {
        }

        public boolean accept(final Path path) {
            final int distance = path.length();
            final Node friend = path.endNode();
            for (final Relationship recommendation : friend.getRelationships(DynamicRelationshipType.withName("recommends"))) {
                final Node restaurant = recommendation.getEndNode();
                if (!recommendedRestaurants.containsKey(restaurant)) {
                    recommendedRestaurants.put(restaurant,new AggregatedRecommendation(restaurant));
                }
                recommendedRestaurants.get(restaurant).add(recommendation,distance);
            }
            return true;
        }

        public Collection<RatedRestaurant> getRecommendedRestaurants(final int n) {
            final List<AggregatedRecommendation> sorted = new ArrayList<AggregatedRecommendation>(recommendedRestaurants.values());
            Collections.sort(sorted);
            int index=0;
            final Collection<RatedRestaurant> result=new ArrayList<RatedRestaurant>(n);
            for (final AggregatedRecommendation aggregatedRecommendation : sorted) {
                if (index == n) return result;
                result.add(aggregatedRecommendation.toRatedRestaurant(this));
                index++;
            }
            return result;
        }

    }
}
TOP

Related Classes of com.springone.myrestaurants.domain.TopRatedRestaurantFinder$CalculateRatingPredicate$AggregatedRecommendation

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.