package mediawiki;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import mediawiki.event.RequestEvent;
import mediawiki.event.RequestListener;
import mediawiki.info.LoginCredentials;
import mediawiki.info.Project;
import mediawiki.request.LoginRequest;
import mediawiki.request.LogoutRequest;
import mediawiki.request.ManipulativeRequest;
public class MediaWikiConnection implements Cloneable {
private String apihref = "";
private LoginRequest loginrequest = null;
private boolean login = false;
private boolean bot = false;
private boolean teststate = false;
private HashMap<String, String> cookies = new HashMap<>();
private Map<Class<? extends MediaWikiRequest<?>>, Integer> statistic = new HashMap<>();
private final Object editsynchronizer = new Object();
private ArrayList<RequestListener> listener = new ArrayList<>();
private GlobalMediaWikiConnection globalcon = null;
private long editInterval = 0L;
private Date lastEdit = null;
private int maxlag = 5;
public MediaWikiConnection(String apihref){
setApihref(apihref);
}
public MediaWikiConnection(String language, String wikiname){
this("https://"+language+"."+wikiname+"/w/api.php");
}
public MediaWikiConnection(Project s){
this(s.getURLPrefix(),s.getURLSuffix());
}
public <T> T request(MediaWikiRequest<T> r) throws Exception{
if(r instanceof LoginRequest)
setLoginRequest((LoginRequest)r);
T o = null;
if(r instanceof ManipulativeRequest){
if(isTestState()){
System.out.println("test state edit: "+r.toString());
return null;
}else{
if(editInterval != 0L && lastEdit != null && (new Date().getTime() < lastEdit.getTime()+editInterval)){
Thread.currentThread().sleep(lastEdit.getTime()+editInterval-new Date().getTime());
}
synchronized(editsynchronizer){
o = r.request(this);
}
lastEdit = new Date();
}
}else{
o = r.request(this);
}
log(r);
fireRequestEvent(new RequestEvent(r));
return o;
}
public <T> void requestConcurrently(MediaWikiRequest<T> r) {
new Thread(new RequestRunnable(r)).start();
}
public String getApihref() {
return apihref;
}
public void setApihref(String apihref) {
this.apihref = apihref;
}
private void log(MediaWikiRequest<?> r){
if(statistic.containsKey(r.getClass())){
statistic.put(((Class<? extends MediaWikiRequest<?>>) r.getClass()), statistic.get(r.getClass())+1);
}else{
statistic.put((Class<? extends MediaWikiRequest<?>>) r.getClass(), 1);
}
}
public void putCookie(String k, String v) {
cookies.put(k, v);
if(isGloballyConnected())
getGlobalConnection().putGlobalCookie(k, v);
}
public void putCookies(Map<String, String> m){
cookies.putAll(m);
if(isGloballyConnected())
getGlobalConnection().putGlobalCookies(m);
}
public Map<String, String> getCookies(){
return cookies;
}
public boolean isBot() {
return bot;
}
public void setBot(boolean bot) {
this.bot = bot;
}
public void close() throws IOException {
new LogoutRequest().request(this);
loginrequest = null;
login = false;
cookies.clear();
statistic.clear();
}
protected LoginRequest getLoginRequest() {
return loginrequest;
}
public boolean isLoggedIn(){
return login;
}
public void setLoggedIn(boolean l){
login = l;
if(isGloballyConnected())
getGlobalConnection().setLoggedIn(l);
}
public void setLoginRequest(LoginRequest loginrequest) {
this.loginrequest = loginrequest;
if(isGloballyConnected())
getGlobalConnection().setLoginRequest(loginrequest);
}
public Object relogin() throws Exception {
return request(getLoginRequest());
}
public Map<Class<? extends MediaWikiRequest<?>>, Integer> getStatistic(){
return statistic;
}
public void resetStatistic(){
statistic.clear();
}
public void addRequestListener(RequestListener r){
listener.add(r);
}
public int getStatisticOf(Class<? extends MediaWikiRequest<?>> s){
return statistic.containsKey(s) ? statistic.get(s) : 0;
}
protected void fireRequestEvent(RequestEvent r){
for(RequestListener rl : listener)
rl.requestPerformed(r);
}
public int getEditCount(){
int i = 0;
for(Entry<Class<? extends MediaWikiRequest<?>>, Integer> e : statistic.entrySet()){
for(Class<?> c : e.getKey().getInterfaces()){
if(c.equals(ManipulativeRequest.class)){
i += e.getValue();
break;
}
}
}
return i;
}
public void setTestState(boolean test){
teststate = test;
}
public boolean isTestState(){
return teststate;
}
public GlobalMediaWikiConnection getGlobalConnection() {
return globalcon;
}
public void setGlobalConnection(GlobalMediaWikiConnection globalcon) {
this.globalcon = globalcon;
}
public boolean isGloballyConnected(){
return getGlobalConnection() != null;
}
public void setEditInterval(long milliseconds){
editInterval = milliseconds;
}
public long getEditInterval(){
return editInterval;
}
public Project getProject() throws MalformedURLException{
return Project.forAPIhref(getApihref());
}
public String getUser() {
if(isGloballyConnected())
return ! getGlobalConnection().isLoggedIn() ? null : getGlobalConnection().getLoginRequest().getUser();
return ! isLoggedIn() ? null : getLoginRequest().getUser();
}
public boolean allowsBots(String wikitext) {
if(getUser() == null)
return true;
return MediaWikiUtil.allowBots(wikitext, getUser());
}
public class RequestRunnable implements Runnable {
private MediaWikiRequest<?> r;
public RequestRunnable(MediaWikiRequest<?> r){
this.r = r;
}
@Override
public void run() {
try {
MediaWikiConnection.this.request(r);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public String login(LoginCredentials cred) throws Exception {
return request(new LoginRequest(cred));
}
public int getMaxlag() {
return maxlag;
}
public void setMaxlag(int maxlag) {
this.maxlag = maxlag;
}
}