/******************************************************************************* * Copyright 2010 Universidade do Minho, Ricardo Vila�a and Francisco Cruz * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package org.ublog.benchmark.social.mysql; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.ublog.benchmark.BenchOperation; import org.ublog.benchmark.ComplexBenchMarkClient; import org.ublog.benchmark.operations.CollectionOperation; import org.ublog.benchmark.operations.DataStoreOperation; import org.ublog.benchmark.operations.DeleteOperation; import org.ublog.benchmark.operations.GetOperation; import org.ublog.benchmark.operations.OperationListener; import org.ublog.benchmark.operations.PutOperation; import org.ublog.benchmark.social.Message; import org.ublog.benchmark.social.SocialBenchmark; import org.ublog.benchmark.social.UserService; import org.ublog.benchmark.social.Utils; public class StopFollowingOperation implements BenchOperation,OperationListener{ private enum Phase {UPDATE_FOLLOWERS,UPDATE_FOLLOWING,UPDATE_TIMELINE} private ComplexBenchMarkClient client; private String userId,toStopUser; private Phase currentPhase; private Map<String, String> user; private Map<String, String> toStop; private boolean get; private boolean finish; private List<String> timeLine; public StopFollowingOperation(ComplexBenchMarkClient client, String userId, String toStopUser) { this.client=client; this.userId=userId; this.toStopUser=toStopUser; this.currentPhase=Phase.UPDATE_FOLLOWERS; this.get=false; this.finish=false; this.user=null; this.toStop=null; } private void addToTimeline(List<String> timeline, int timelineIdx, String timelineId) { timeline.add(timelineIdx, timelineId); } private String getTimelineId(Message tweet) { return tweet.getId() + ":" + tweet.getDate().toString(); } @SuppressWarnings("unchecked") @Override public void handleFinishedOperation(DataStoreOperation op) { switch(this.currentPhase) { case UPDATE_FOLLOWERS: if (this.toStop==null){ this.toStop=(Map<String,String>) ((GetOperation) op).getResult(); } else this.currentPhase=Phase.UPDATE_FOLLOWING; break; case UPDATE_FOLLOWING: if (this.user==null) { this.user=(Map<String,String>) ((GetOperation) op).getResult(); } else this.currentPhase=Phase.UPDATE_TIMELINE; break; case UPDATE_TIMELINE: if (this.timeLine==null) { this.timeLine=(List<String>) ((GetOperation) op).getResult(); if (this.timeLine==null) this.timeLine=new ArrayList<String>(); } else this.client.handleFinishedComplexOperation(this); break; } } @Override public String getName() { return "twitter:stopFollowing"; } @SuppressWarnings("unchecked") @Override public CollectionOperation getNextDBOperation() throws UnsupportedEncodingException { CollectionOperation res=null; switch(this.currentPhase) { case UPDATE_FOLLOWERS: if (!this.get) { List<String> columns = new ArrayList<String>(); columns.add("followers"); res=new GetOperation(client,SocialBenchmark.userTable,this.toStopUser,columns); this.get=true; } else { Set<String> followers = Utils.asSet(this.toStop.get(UserService.FOLLOWERS)); followers.remove(userId); this.toStop.put(UserService.FOLLOWERS, Utils.toString(followers)); res=new PutOperation(client,SocialBenchmark.userTable,this.toStopUser,this.toStop,null); this.get=false; } break; case UPDATE_FOLLOWING: if (!this.get) { List<String> columns = new ArrayList<String>(); columns.add("following"); res=new GetOperation(client,SocialBenchmark.userTable,this.userId,columns); this.get=true; } else { Set<String> following = Utils.asSet(user.get(UserService.FOLLOWING)); following.remove(toStopUser); this.user.put(UserService.FOLLOWING, Utils.toString(following)); res=new PutOperation(client,SocialBenchmark.userTable,this.userId,this.user,null); this.get=false; } break; case UPDATE_TIMELINE: if (!this.get) { this.timeLine=null; res=new GetOperation(client,SocialBenchmark.friendsTimeLineTable,this.userId,250); this.get=true; } else { List<String> columns = new ArrayList<String>(); for (Iterator<String> itr = this.timeLine.iterator(); itr.hasNext();) { String idAndTime =itr.next(); String[] split = idAndTime.split(":"); String id = split[0]; String date = split[1]; if (id.startsWith(this.toStopUser + "-")) { itr.remove(); columns.add(date); } } List<Integer> tags=new ArrayList<Integer>(); tags.add(Utils.getTagUserID(this.userId)); res = new DeleteOperation(client,SocialBenchmark.friendsTimeLineTable,this.userId,columns); this.finish=true; } break; } res.addListener(this); return res; } @Override public boolean hasMoreDBOperations() { return !this.finish; } @Override public String toString() { return "StopFollowingOperation [toStopUser=" + toStopUser + ", userId=" + userId + "]"; } @Override public boolean isReadOnly() { return false; } @Override public boolean isInit() { return false; } @Override public void setInit(boolean init) { } }