public enum Labels implements Label {
    User,
    Post,
    Tag
} public enum  RelationshipTypes implements RelationshipType {
    BLOCKS,
    FOLLOWS,
    MUTES,
    LIKES,
    REPLIED_TO
} @Path("/users/{username}/mentions")
public class Mentions {

    private static final Pattern mentionsPattern = Pattern.compile("@(\\S+)");

    private final GraphDatabaseService db;
    private static final ObjectMapper objectMapper = new ObjectMapper();

    public Mentions(@Context DatabaseManagementService dbms ) {
        this.db = dbms.database( "neo4j" );;
    }

    @GET
    public Response getMentions(@PathParam("username") final String username,
                                @QueryParam("limit") @DefaultValue("25") final Integer limit,
                                @QueryParam("since") final Long since,
                                @QueryParam("username2") final String username2) throws IOException {
        ArrayList<Map<String, Object>> results = new ArrayList<>();
        LocalDateTime dateTime;
        if (since == null) {
            dateTime = LocalDateTime.now(utc);
        } else {
            dateTime = LocalDateTime.ofEpochSecond(since, 0, ZoneOffset.UTC);
        }
        Long latest = dateTime.toEpochSecond(ZoneOffset.UTC);

        try (Transaction tx = db.beginTx()) {
            Node user = Users.findUser(username, tx);
            Node user2 = null;
            if (username2 != null) {
                user2 = Users.findUser(username2, tx);
            }

            HashSet<Node> blocked = new HashSet<>();
            for (Relationship r1 : user.getRelationships(Direction.OUTGOING, RelationshipTypes.BLOCKS)) {
                blocked.add(r1.getEndNode());
            }
            LocalDateTime earliest = LocalDateTime.ofEpochSecond((Long)user.getProperty(TIME), 0, ZoneOffset.UTC);
            int count = 0;
            while (count < limit && (dateTime.isAfter(earliest))) {
                RelationshipType relType = RelationshipType.withName("MENTIONED_ON_" +
                        dateTime.format(dateFormatter));

                for (Relationship r1 : user.getRelationships(Direction.INCOMING, relType)) {
                    Node post = r1.getStartNode();
                    Map<String, Object> result = post.getAllProperties();
                    Long time = (Long)r1.getProperty("time");
                    if(time < latest) {
                        Node author = getAuthor(post, time);
                        if (!blocked.contains(author)) {
                            result.put(TIME, time);
                            result.put(USERNAME, author.getProperty(USERNAME));
                            result.put(NAME, author.getProperty(NAME));
                            result.put(HASH, author.getProperty(HASH));
                            result.put(LIKES, post.getDegree(RelationshipTypes.LIKES));
                            result.put(REPOSTS, post.getDegree(Direction.INCOMING)
                                    - 1 // for the Posted Relationship Type
                                    - post.getDegree(RelationshipTypes.LIKES)
                                    - post.getDegree(RelationshipTypes.REPLIED_TO));
                            if (user2 != null) {
                                result.put(LIKED, userLikesPost(user2, post));
                                result.put(REPOSTED, userRepostedPost(user2, post));
                            }

                            results.add(result);
                            count++;
                        }
                    }
                }
                dateTime = dateTime.minusDays(1);
            }
            tx.commit();
        }

        results.sort(Comparator.comparing(m -> (Long) m.get(TIME), reverseOrder()));

        return Response.ok().entity(objectMapper.writeValueAsString(results)).build();
    }

    public static void createMentions(Node post, HashMap<String, Object> input, LocalDateTime dateTime, Transaction tx) {
        Matcher mat = mentionsPattern.matcher(((String)input.get("status")).toLowerCase());

        for (Relationship r1 : post.getRelationships(Direction.OUTGOING, RelationshipType.withName("MENTIONED_ON_" +
                dateTime.format(dateFormatter)))) {
            r1.delete();
        }

        Set<Node> mentioned = new HashSet<>();
        while (mat.find()) {
            String username = mat.group(1);
            Node user = tx.findNode(Labels.User, USERNAME, username);
            if (user != null && !mentioned.contains(user)) {
                Relationship r1 = post.createRelationshipTo(user, RelationshipType.withName("MENTIONED_ON_" +
                        dateTime.format(dateFormatter)));
                r1.setProperty(TIME, dateTime.toEpochSecond(ZoneOffset.UTC));
                mentioned.add(user);
            }
        }
    }
} @Path("/tags")
public class Tags {

    private static final Pattern hashtagPattern = Pattern.compile("#(\\S+)");

    private static GraphDatabaseService db = null;
    private static final ObjectMapper objectMapper = new ObjectMapper();

    public Tags(@Context DatabaseManagementService dbms ) {
        db = dbms.database( "neo4j" );;
    }

    // Cache
    private static LoadingCache<String, List<Map<String, Object>>> trends = Caffeine.newBuilder()
            .expireAfterWrite(1, TimeUnit.DAYS)
            .refreshAfterWrite(5, TimeUnit.MINUTES)
            .build(Tags::getTrends);

    private static List<Map<String, Object>> getTrends(String key) {
        ArrayList<Map<String, Object>> results = new ArrayList<>();
        LocalDateTime dateTime = LocalDateTime.now(utc);
        RelationshipType tagged = RelationshipType.withName("TAGGED_ON_" +
                dateTime.format(dateFormatter));
        try (Transaction tx = db.beginTx()) {
            ResourceIterator<Node> tags = tx.findNodes(Labels.Tag);
            while (tags.hasNext()) {
                Node tag = tags.next();
                int taggings = tag.getDegree(tagged, Direction.INCOMING);
                if ( taggings > 0) {
                    HashMap<String, Object> result = new HashMap<>();
                    result.put(NAME, tag.getProperty(NAME));
                    result.put(COUNT, taggings);
                    results.add(result);
                }
            }
            tx.commit();
        }

        results.sort(Comparator.comparing(m -> (Integer) m.get(COUNT), reverseOrder()));
        return results.subList(0, Math.min(results.size(), 10));
    }

    @GET
    @Path("/{hashtag}")
    public Response getTags(@PathParam("hashtag") final String hashtag,
                             @QueryParam("limit") @DefaultValue("25") final Integer limit,
                             @QueryParam("since") final Long since,
                             @QueryParam("username") final String username) throws IOException {
        ArrayList<Map<String, Object>> results = new ArrayList<>();
        LocalDateTime dateTime;
        if (since == null) {
            dateTime = LocalDateTime.now(utc);
        } else {
            dateTime = LocalDateTime.ofEpochSecond(since, 0, ZoneOffset.UTC);
        }
        Long latest = dateTime.toEpochSecond(ZoneOffset.UTC);

        try (Transaction tx = db.beginTx()) {
            Node user = null;
            if (username != null) {
                user = Users.findUser(username, tx);
            }

            Node tag = tx.findNode(Labels.Tag, NAME, hashtag.toLowerCase());
            if (tag != null) {
                LocalDateTime earliestTag = LocalDateTime.ofEpochSecond((Long) tag.getProperty(TIME), 0, ZoneOffset.UTC);

                int count = 0;
                while (count < limit && (dateTime.isAfter(earliestTag))) {
                    RelationshipType relType = RelationshipType.withName("TAGGED_ON_" +
                            dateTime.format(dateFormatter));

                    for (Relationship r1 : tag.getRelationships(Direction.INCOMING, relType)) {
                        Node post = r1.getStartNode();
                        Map<String, Object> result = post.getAllProperties();
                        Long time = (Long) result.get("time");

                        if (count < limit && time < latest) {
                            Node author = getAuthor(post, time);
                            Map userProperties = author.getAllProperties();
                            result.put(USERNAME, userProperties.get(USERNAME));
                            result.put(NAME, userProperties.get(NAME));
                            result.put(HASH, userProperties.get(HASH));
                            result.put(LIKES, post.getDegree(RelationshipTypes.LIKES));
                            result.put(REPOSTS, post.getDegree(Direction.INCOMING)
                                    - 1 // for the Posted Relationship Type
                                    - post.getDegree(RelationshipTypes.LIKES)
                                    - post.getDegree(RelationshipTypes.REPLIED_TO));
                            if (user != null) {
                                result.put(LIKED, userLikesPost(user, post));
                                result.put(REPOSTED, userRepostedPost(user, post));
                            }
                            results.add(result);
                            count++;
                        }
                    }
                    dateTime = dateTime.minusDays(1);
                }
                tx.commit();
                results.sort(Comparator.comparing(m -> (Long) m.get(TIME), reverseOrder()));
            } else {
                throw TagExceptions.tagNotFound();
            }
        }
        return Response.ok().entity(objectMapper.writeValueAsString(results)).build();
    }

    public static void createTags(Node post, HashMap<String, Object> input, LocalDateTime dateTime, Transaction tx) {
        Matcher mat = hashtagPattern.matcher(((String)input.get(STATUS)).toLowerCase());
        for (Relationship r1 : post.getRelationships(Direction.OUTGOING, RelationshipType.withName("TAGGED_ON_" +
                dateTime.format(dateFormatter)))) {
            r1.delete();
        }
        Set<Node> tagged = new HashSet<>();
        while (mat.find()) {
            String tag = mat.group(1);
            Node hashtag = tx.findNode(Labels.Tag, NAME, tag);
            if (hashtag == null) {
                hashtag = tx.createNode(Labels.Tag);
                hashtag.setProperty(NAME, tag);
                hashtag.setProperty(TIME, dateTime.truncatedTo(ChronoUnit.DAYS).toEpochSecond(ZoneOffset.UTC));
            }
            if (!tagged.contains(hashtag)) {
                post.createRelationshipTo(hashtag, RelationshipType.withName("TAGGED_ON_" +
                        dateTime.format(dateFormatter)));
                tagged.add(hashtag);
            }
        }
    }

    @GET
    public Response getTrends(@Context GraphDatabaseService db) throws IOException {
        List<Map<String, Object>> results;
        try (Transaction tx = db.beginTx()) {
            results = trends.get("trends");
        }

        return Response.ok().entity(objectMapper.writeValueAsString(results)).build();
    }
} @Path("/users")
public class Users {

    private final GraphDatabaseService db;
    private static final ObjectMapper objectMapper = new ObjectMapper();

    public Users(@Context DatabaseManagementService dbms ) {
        this.db = dbms.database( "neo4j" );;
    }

    @GET
    @Path("/{username}")
    public Response getUser(@PathParam("username") final String username) throws IOException {
        Map<String, Object> results;
        try (Transaction tx = db.beginTx()) {
            Node user = findUser(username, tx);
            results = user.getAllProperties();
            tx.commit();
        }
        return Response.ok().entity(objectMapper.writeValueAsString(results)).build();
    }

    @GET
    @Path("/{username}/profile")
    public Response getProfile(@PathParam("username") final String username,
                               @QueryParam("username2") final String username2) throws IOException {
        Map<String, Object> results;
        try (Transaction tx = db.beginTx()) {
            Node user = findUser(username, tx);
            results = getUserAttributes(user);

            if (username2 != null && !username.equals(username2)) {
                Node user2 = findUser(username2, tx);
                HashSet<Node> followed = new HashSet<>();
                for (Relationship r1 : user.getRelationships(Direction.OUTGOING, RelationshipTypes.FOLLOWS)) {
                    followed.add(r1.getEndNode());
                }
                HashSet<Node> followed2 = new HashSet<>();
                for (Relationship r1 : user2.getRelationships(Direction.OUTGOING, RelationshipTypes.FOLLOWS)) {
                    followed2.add(r1.getEndNode());
                }

                boolean follows_me = followed.contains(user2);
                boolean i_follow = followed2.contains(user);
                results.put(I_FOLLOW, i_follow);
                results.put(FOLLOWS_ME, follows_me);

                followed.retainAll(followed2);

                results.put(FOLLOWERS_YOU_KNOW_COUNT, followed.size());
                ArrayList<Map<String, Object>> followers_sample = new ArrayList<>();
                int count = 0;
                for (Node follower : followed) {
                    count++;
                    Map<String, Object> properties = follower.getAllProperties();
                    properties.remove(PASSWORD);
                    properties.remove(EMAIL);
                    followers_sample.add(properties);
                    if (count > 10) { break; };
                }

                results.put(FOLLOWERS_YOU_KNOW, followers_sample);

            }

            tx.commit();
        }
        return Response.ok().entity(objectMapper.writeValueAsString(results)).build();
    }

    @POST
    public Response createUser(String body) throws IOException {
        HashMap parameters = UserValidator.validate(body);
        Map<String, Object> results;
        try (Transaction tx = db.beginTx()) {
            Node user = tx.findNode(Labels.User, USERNAME, parameters.get(USERNAME));
            if (user == null) {
                user = tx.findNode(Labels.User, EMAIL, parameters.get(EMAIL));
                if (user == null) {
                    user = tx.createNode(Labels.User);
                    user.setProperty(EMAIL, parameters.get(EMAIL));
                    user.setProperty(NAME, parameters.get(NAME));
                    user.setProperty(USERNAME, parameters.get(USERNAME));
                    user.setProperty(PASSWORD, parameters.get(PASSWORD));
                    user.setProperty(HASH, new Md5Hash(((String)parameters.get(EMAIL)).toLowerCase()).toString());

                    LocalDateTime dateTime = LocalDateTime.now(utc);
                    user.setProperty(TIME, dateTime.truncatedTo(ChronoUnit.DAYS).toEpochSecond(ZoneOffset.UTC));

                    results = user.getAllProperties();
                } else {
                    throw UserExceptions.existingEmailParameter();
                }
            } else {
                throw UserExceptions.existingUsernameParameter();
            }
            tx.commit();
        }
        return Response.ok().entity(objectMapper.writeValueAsString(results)).build();
    }

    @GET
    @Path("/{username}/followers")
    public Response getFollowers(@PathParam("username") final String username,
                                 @QueryParam("limit") @DefaultValue("25") final Integer limit,
                                 @QueryParam("since") final Long since) throws IOException {
        ArrayList<Map<String, Object>> results = new ArrayList<>();
        // TODO: 4/3/17 Add Recent Array for Users with > 100k Followers
        LocalDateTime dateTime;
        if (since == null) {
            dateTime = LocalDateTime.now(utc);
        } else {
            dateTime = LocalDateTime.ofEpochSecond(since, 0, ZoneOffset.UTC);
        }
        Long latest = dateTime.toEpochSecond(ZoneOffset.UTC);

        try (Transaction tx = db.beginTx()) {
            Node user = findUser(username, tx);
            for (Relationship r1: user.getRelationships(Direction.INCOMING, RelationshipTypes.FOLLOWS)) {
                Long time = (Long)r1.getProperty(TIME);
                if(time < latest) {
                    Node follower = r1.getStartNode();
                    Map<String, Object> result = getUserAttributes(follower);
                    result.put(TIME, time);
                    results.add(result);
                }
            }
            tx.commit();
        }
        results.sort(Comparator.comparing(m -> (Long) m.get(TIME), reverseOrder()));

        return Response.ok().entity(objectMapper.writeValueAsString(
                results.subList(0, Math.min(results.size(), limit))))
                .build();
    }

    @GET
    @Path("/{username}/following")
    public Response getFollowing(@PathParam("username") final String username,
                                 @QueryParam("limit") @DefaultValue("25") final Integer limit,
                                 @QueryParam("since") final Long since) throws IOException {
        ArrayList<Map<String, Object>> results = new ArrayList<>();
        LocalDateTime dateTime;
        if (since == null) {
            dateTime = LocalDateTime.now(utc);
        } else {
            dateTime = LocalDateTime.ofEpochSecond(since, 0, ZoneOffset.UTC);
        }
        Long latest = dateTime.toEpochSecond(ZoneOffset.UTC);


        try (Transaction tx = db.beginTx()) {
            Node user = findUser(username, tx);
            for (Relationship r1: user.getRelationships(Direction.OUTGOING, RelationshipTypes.FOLLOWS)) {
                Long time = (Long)r1.getProperty(TIME);
                if(time < latest) {
                    Node following = r1.getEndNode();
                    Map<String, Object> result = getUserAttributes(following);
                    result.put(TIME, time);
                    results.add(result);
                }
            }
            tx.commit();
        }
        results.sort(Comparator.comparing(m -> (Long) m.get(TIME), reverseOrder()));

        return Response.ok().entity(objectMapper.writeValueAsString(
                results.subList(0, Math.min(results.size(), limit))))
                .build();
    }

    @POST
    @Path("/{username}/follows/{username2}")
    public Response createFollows(@PathParam("username") final String username,
                                 @PathParam("username2") final String username2) throws IOException {
        Map<String, Object> results;
        try (Transaction tx = db.beginTx()) {
            Node user = findUser(username, tx);
            Node user2 = findUser(username2, tx);
            if (user.equals(user2)) {
                throw UserExceptions.userSame();
            } else {
                HashSet<Node> blocked = new HashSet<>();
                for (Relationship r1 : user2.getRelationships(Direction.OUTGOING, RelationshipTypes.BLOCKS)) {
                    blocked.add(r1.getEndNode());
                }

                if (blocked.contains(user)) {
                    throw UserExceptions.userBlocked();
                }

                Relationship follows = user.createRelationshipTo(user2, RelationshipTypes.FOLLOWS);
                LocalDateTime dateTime = LocalDateTime.now(utc);
                follows.setProperty(TIME, dateTime.toEpochSecond(ZoneOffset.UTC));
                results = user2.getAllProperties();
                results.remove(EMAIL);
                results.remove(PASSWORD);
                tx.commit();
            }
        }
        return Response.ok().entity(objectMapper.writeValueAsString(results)).build();
    }

    @DELETE
    @Path("/{username}/follows/{username2}")
    public Response removeFollows(@PathParam("username") final String username,
                                  @PathParam("username2") final String username2) throws IOException {
        Map<String, Object> results;
        try (Transaction tx = db.beginTx()) {
            Node user = findUser(username, tx);
            Node user2 = findUser(username2, tx);

            if (user.getDegree(RelationshipTypes.FOLLOWS, Direction.OUTGOING)
                    < user2.getDegree(RelationshipTypes.FOLLOWS, Direction.INCOMING)) {
                for (Relationship r1: user.getRelationships(Direction.OUTGOING, RelationshipTypes.FOLLOWS) ) {
                    if (r1.getEndNode().equals(user2)) {
                        r1.delete();
                    }
                }
            } else {
                for (Relationship r1 : user2.getRelationships(Direction.INCOMING, RelationshipTypes.FOLLOWS)) {
                    if (r1.getStartNode().equals(user)) {
                        r1.delete();
                    }
                }
            }

            tx.commit();
        }
        return Response.noContent().build();
    }

    public static Node findUser(String username, Transaction tx) {
        if (username == null) { return null; }
        Node user = tx.findNode(Labels.User, USERNAME, username);
        if (user == null) { throw UserExceptions.userNotFound(); }
        return user;
    }

    public static Map<String, Object> getUserAttributes(Node user) {
        Map<String, Object> results;
        results = user.getAllProperties();
        results.remove(EMAIL);
        results.remove(PASSWORD);
        Integer following = user.getDegree(RelationshipTypes.FOLLOWS, Direction.OUTGOING);
        Integer followers = user.getDegree(RelationshipTypes.FOLLOWS, Direction.INCOMING);
        Integer likes = user.getDegree(RelationshipTypes.LIKES, Direction.OUTGOING);
        Integer posts = user.getDegree(Direction.OUTGOING) - following - likes;
        results.put("following", following);
        results.put("followers", followers);
        results.put("likes", likes);
        results.put("posts", posts);
        return results;
    }

    public static Node getPost(Node author, Long time) {
        LocalDateTime postedDateTime = LocalDateTime.ofEpochSecond(time, 0, ZoneOffset.UTC);
        RelationshipType original = RelationshipType.withName("POSTED_ON_" +
                postedDateTime.format(dateFormatter));
        Node post = null;
        for(Relationship r1 : author.getRelationships(Direction.OUTGOING, original)) {
            Node potential = r1.getEndNode();
            if (time.equals(potential.getProperty(TIME))) {
                post = potential;
                break;
            }
        }
        if(post == null) { throw PostExceptions.postNotFound(); };

        return post;
    }


} public final class Properties {

    private Properties() {
        throw new IllegalAccessError("Utility class");
    }

    public static final String COUNT = "count";
    public static final String EMAIL = "email";
    public static final String FOLLOWERS_YOU_KNOW = "followers_you_know";
    public static final String FOLLOWERS_YOU_KNOW_COUNT = "followers_you_know_count";
    public static final String HASH = "hash";
    public static final String I_FOLLOW = "i_follow";
    public static final String FOLLOWS_ME = "follows_me";
    public static final String LIKES = "likes";
    public static final String LIKED = "liked";
    public static final String LIKED_TIME = "liked_time";
    public static final String NAME = "name";
    public static final String PASSWORD = "password";
    public static final String USERNAME = "username";
    public static final String REPOSTS = "reposts";
    public static final String REPOSTED = "reposted";
    public static final String REPOSTED_TIME = "reposted_time";
    public static final String REPOSTER_NAME = "reposter_name";
    public static final String REPOSTER_USERNAME = "reposter_username";
    public static final String STATUS = "status";
    public static final String TIME = "time";

} public static final DateTimeFormatter dateFormatter = DateTimeFormatter
        .ofPattern("yyyy_MM_dd")
        .withZone(utc); public static final ZoneId utc = TimeZone.getTimeZone("UTC").toZoneId(); public static boolean userLikesPost(Node user, Node post) {
    boolean alreadyLiked = false;
    if (user.getDegree(RelationshipTypes.LIKES, Direction.OUTGOING)
            < post.getDegree(RelationshipTypes.LIKES, Direction.INCOMING) ) {
        for (Relationship r1 : user.getRelationships(Direction.OUTGOING, RelationshipTypes.LIKES)) {
            if (r1.getEndNode().equals(post)) {
                alreadyLiked = true;
                break;
            }
        }
    } else {
        for (Relationship r1 : post.getRelationships(Direction.INCOMING, RelationshipTypes.LIKES)) {
            if (r1.getStartNode().equals(user)) {
                alreadyLiked = true;
                break;
            }
        }
    }
    return alreadyLiked;
} public static Node getPost(Node author, Long time) {
    LocalDateTime postedDateTime = LocalDateTime.ofEpochSecond(time, 0, ZoneOffset.UTC);
    RelationshipType original = RelationshipType.withName("POSTED_ON_" +
            postedDateTime.format(dateFormatter));
    Node post = null;
    for(Relationship r1 : author.getRelationships(Direction.OUTGOING, original)) {
        Node potential = r1.getEndNode();
        if (time.equals(potential.getProperty(TIME))) {
            post = potential;
            break;
        }
    }
    if(post == null) { throw PostExceptions.postNotFound(); };

    return post;
}
import com.fasterxml.jackson.databind.ObjectMapper;
import com.maxdemarzi.Labels;
import com.maxdemarzi.RelationshipTypes;
import com.maxdemarzi.mentions.Mentions;
import com.maxdemarzi.tags.Tags;
import com.maxdemarzi.users.Users;
import org.neo4j.dbms.api.DatabaseManagementService;
import org.neo4j.graphdb.*;
import javax.ws.rs.Path;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import static com.maxdemarzi.Properties.*;
import static com.maxdemarzi.Time.dateFormatter;
import static com.maxdemarzi.Time.utc;
import static com.maxdemarzi.likes.Likes.userLikesPost;
import static com.maxdemarzi.users.Users.getPost;
import static java.util.Collections.reverseOrder;
package com.maxdemarzi.posts;




@Path("/users/{username}/posts")
public class Posts {

    private final GraphDatabaseService db;
    private static final ObjectMapper objectMapper = new ObjectMapper();

    public Posts(@Context DatabaseManagementService dbms ) {
        this.db = dbms.database( "neo4j" );;
    }

    @GET
    public Response getPosts(@PathParam("username") final String username,
                             @QueryParam("limit") @DefaultValue("25") final Integer limit,
                             @QueryParam("since") final Long since,
                             @QueryParam("username2") final String username2) throws IOException {
        ArrayList<Map<String, Object>> results = new ArrayList<>();
        LocalDateTime dateTime;
        if (since == null) {
            dateTime = LocalDateTime.now(utc);
        } else {
            dateTime = LocalDateTime.ofEpochSecond(since, 0, ZoneOffset.UTC);
        }
        Long latest = dateTime.toEpochSecond(ZoneOffset.UTC);

        try (Transaction tx = db.beginTx()) {
            Node user = Users.findUser(username, tx);
            Node user2 = null;
            if (username2 != null) {
                user2 = Users.findUser(username2, tx);
            }

            Map userProperties = user.getAllProperties();
            LocalDateTime earliest = LocalDateTime.ofEpochSecond((Long)userProperties.get(TIME), 0, ZoneOffset.UTC);
            int count = 0;
            while (count < limit && (dateTime.isAfter(earliest))) {
                RelationshipType relType = RelationshipType.withName("POSTED_ON_" +
                        dateTime.format(dateFormatter));