/*******************************************************************************
* 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) {
}
}