+ private final Multimap<Sone, Post> sonePosts = create();
+ private final Map<String, Sone> sones = newHashMap();
+ private Optional<Sone> currentSone = absent();
+ private final Map<String, Post> posts = newHashMap();
+ private final Multimap<Post, PostReply> postReplies = create();
+ private final Multimap<String, Post> directedPosts = create();
+ private final SetMultimap<Post, Sone> postLikingSones = HashMultimap.create();
+ private final SetMultimap<PostReply, Sone> postReplyLikingSones = HashMultimap.create();
+ public final Database database;
+ public final Core core;
+ public final WebInterface webInterface;
+
+ public Mocks() {
+ database = mockDatabase();
+ core = mockCore(database);
+ webInterface = mockWebInterface(core);
+ when(database.getSone()).thenReturn(new Function<String, Optional<Sone>>() {
+ @Override
+ public Optional<Sone> apply(String soneId) {
+ return (soneId == null) ? Optional.<Sone>absent() : fromNullable(sones.get(soneId));
+ }
+ });
+ Answer<Sone> returnCurrentSone = new Answer<Sone>() {
+ @Override
+ public Sone answer(InvocationOnMock invocation) throws Throwable {
+ return currentSone.orNull();
+ }
+ };
+ when(webInterface.getCurrentSone(any(ToadletContext.class))).then(returnCurrentSone);
+ when(webInterface.getCurrentSone(any(Session.class))).then(returnCurrentSone);
+ when(core.getSones()).then(new Answer<Collection<Sone>>() {
+ @Override
+ public Collection<Sone> answer(InvocationOnMock invocation) throws Throwable {
+ return sones.values();
+ }
+ });
+ when(core.getLocalSone(anyString())).then(new Answer<Optional<Sone>>() {
+ @Override
+ public Optional<Sone> answer(InvocationOnMock invocation) throws Throwable {
+ Sone localSone = sones.get(invocation.getArguments()[0]);
+ return ((localSone == null) || (!localSone.isLocal())) ? Optional.<Sone>absent() : of(localSone);
+ }
+ });
+ when(core.getLocalSones()).then(new Answer<Collection<Sone>>() {
+ @Override
+ public Collection<Sone> answer(InvocationOnMock invocation) throws Throwable {
+ return FluentIterable.from(sones.values()).filter(Sone.LOCAL_SONE_FILTER).toList();
+ }
+ });
+ when(core.postCreated()).thenReturn(Optional.<PostCreated>of(new PostCreated() {
+ @Override
+ public void postCreated(Post post) {
+ posts.put(post.getId(), post);
+ sonePosts.put(post.getSone(), post);
+ }
+ }));
+ when(core.postReplyCreated()).then(new Answer<Optional<PostReplyCreated>>() {
+ @Override
+ public Optional<PostReplyCreated> answer(InvocationOnMock invocation) throws Throwable {
+ return Optional.<PostReplyCreated>of(new PostReplyCreated() {
+ @Override
+ public void postReplyCreated(PostReply postReply) {
+ postReplies.put(postReply.getPost().get(), postReply);
+ }
+ });
+ }
+ });
+ Options options = createOptions();
+ when(core.getPreferences()).thenReturn(new Preferences(options));
+ when(database.getDirectedPosts(anyString())).then(new Answer<Collection<Post>>() {
+ @Override
+ public Collection<Post> answer(InvocationOnMock invocation) throws Throwable {
+ return directedPosts.get((String) invocation.getArguments()[0]);
+ }
+ });
+ }
+
+ private Options createOptions() {
+ Options options = new Options();
+ options.addIntegerOption("InsertionDelay", new DefaultOption<Integer>(60, new IntegerRangePredicate(0, Integer.MAX_VALUE)));
+ options.addIntegerOption("PostsPerPage", new DefaultOption<Integer>(10, new IntegerRangePredicate(1, Integer.MAX_VALUE)));
+ options.addIntegerOption("ImagesPerPage", new DefaultOption<Integer>(9, new IntegerRangePredicate(1, Integer.MAX_VALUE)));
+ options.addIntegerOption("CharactersPerPost", new DefaultOption<Integer>(400, Predicates.<Integer>or(new IntegerRangePredicate(50, Integer.MAX_VALUE), Predicates.equalTo(-1))));
+ options.addIntegerOption("PostCutOffLength", new DefaultOption<Integer>(200, Predicates.<Integer>or(new IntegerRangePredicate(50, Integer.MAX_VALUE), Predicates.equalTo(-1))));
+ options.addBooleanOption("RequireFullAccess", new DefaultOption<Boolean>(false));
+ options.addIntegerOption("PositiveTrust", new DefaultOption<Integer>(75, new IntegerRangePredicate(0, 100)));
+ options.addIntegerOption("NegativeTrust", new DefaultOption<Integer>(-25, new IntegerRangePredicate(-100, 100)));
+ options.addStringOption("TrustComment", new DefaultOption<String>("Set from Sone Web Interface"));
+ options.addBooleanOption("ActivateFcpInterface", new DefaultOption<Boolean>(false));
+ options.addIntegerOption("FcpFullAccessRequired", new DefaultOption<Integer>(2));
+ return options;
+ }
+
+ private static Core mockCore(Database database) {