//
// @(#)FlocImporter.java 9/2003
//
// Copyright 2003 the jDip development team. All rights reserved.
// Use is subject to license terms.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// Or from http://www.gnu.org/
//
package dip.judge.net;
import dip.judge.parser.JudgeImport;
import dip.order.OrderFactory;
import dip.world.World;
import dip.misc.Utils;
import java.io.*;
import java.net.*;
import javax.swing.text.html.*;
import javax.swing.text.html.parser.*;
/**
*
* @author Mannkind aka Dustin Brewer, Zach DelProposto
*
* FlocImporter: Imports games from floc.net.
* Designed as a Runnable so it can be threaded.
*
*/
public class FlocImporter implements Runnable
{
// i18n constants (for messages)
private static final String READING_CONTACT = "FlocImporter.message.contact";
private static final String READING_FROM_NET = "FlocImporter.message.netread";
private static final String CREATING_WORLD = "FlocImporter.message.createworld";
// how to tell if game is registered or not.
private static final String NOT_REGISTERED = "This game is not registered";
// instance fields
private final String gameName;
private final String judgeName;
private final FlocImportCallback fic;
private final OrderFactory orderFactory;
private Thread netThread = null;;
private boolean isInProgress = false;
/**
* Create a floc.net importer. Null parameters are not accepted.
*
*/
public FlocImporter(String gameName, String judgeName, OrderFactory orderFactory, FlocImportCallback fic)
{
if(gameName == null || judgeName == null || fic == null || orderFactory == null)
{
throw new IllegalArgumentException();
}
this.gameName = gameName;
this.judgeName = judgeName;
this.orderFactory = orderFactory;
this.fic = fic;
}// FlocImporter()
/** Start a FlocImporter in a new Thread. */
public void start()
{
if(netThread != null)
{
throw new IllegalStateException("thread already started.");
}
netThread = new Thread(this);
netThread.start();
}// start()
/** Abort an in-progress FlocImporter that was started */
public void abort()
{
isInProgress = false;
if(netThread != null)
{
netThread = null;
}
}// abort()
/** This is the interface which defines the callback */
public static interface FlocImportCallback
{
/** An exception (given as an argument) occured during import. */
public void flocImportException(IOException e);
/**
* Floc Text import completed successfully.
* String contains imported text, and should never be null.
* <p>
* Note: return <code>true</code> if processor should continue on
* to convert text into a World object; return <code>false</code> if
* FlocImport is complete and automatic World object creation is
* not required.
*/
public boolean flocTextImportComplete(String text);
/**
* Floc World import completed successfully. World should never be null.
* <p>
* Note: this method only excecutes if flocTextImportComplete() returns
* <code>true</code>
*/
public void flocWorldImportComplete(World world);
/**
* Floc import progress message (displays import progress)
*/
public void flocImportMessage(String message);
/** Import failed; the game is not registered. */
public void flocImportUnregistered();
}// interface FlocImportCallback
/**
* Do the work (import text)
*
*/
public void run()
{
isInProgress = true;
try
{
final String text = getGameInfo();
if(!isInProgress)
{
return;
}
// see if game is registered
if(text.length() == 0 || text.indexOf(NOT_REGISTERED) >= 0)
{
fic.flocImportUnregistered();
return;
}
// game is registered
if(fic.flocTextImportComplete(text))
{
// now, process into a World object
fic.flocImportMessage(Utils.getLocalString(CREATING_WORLD));
JudgeImport ji = new JudgeImport(orderFactory, new StringReader(text), null);
if(!isInProgress)
{
return;
}
fic.flocWorldImportComplete(ji.getWorld());
}
}
catch(IOException e)
{
fic.flocImportException(e);
}
catch(Exception e)
{
// do nothing (catches any thread-abort errors)
}
}// run()
/**
* Get the game information.
* <p>
* Returns the imported text.
*/
private String getGameInfo()
throws IOException
{
final StringBuffer gameInformation = new StringBuffer(16384);
URL u = null;
BufferedReader reader = null;
try
{
u =
new URL(
"http://www.floc.net/observer.py?judge="
+ judgeName
+ "&game="
+ gameName
+ "&page=history&history_from=0&history_to=999999");
fic.flocImportMessage(Utils.getLocalString(READING_CONTACT));
// output is in HTML, so using the HTML editor kit parser removes
// HTML cruft.
//
reader = new BufferedReader(new InputStreamReader(u.openStream()));
if(!isInProgress)
{
return "";
}
ParserDelegator parser = new ParserDelegator();
parser.parse(reader, new HTMLEditorKit.ParserCallback()
{
public void handleText(char[] text, int pos)
{
if(!isInProgress)
{
gameInformation.setLength(0); // abort!
return;
}
fic.flocImportMessage(Utils.getLocalString(READING_FROM_NET));
gameInformation.append(text);
gameInformation.append("\n");
}// handleText()
},
false);
}
finally
{
if(reader != null)
{
reader.close();
}
}
return gameInformation.toString();
}// getGameInfo()
/*
public String registerGame(String nameOfGame, String judgeName) {
URL u = null;
BufferedReader reader = null;
try {
u =
new URL(
"http://www.floc.net/observer.py?judge="
+ judgeName
+ "&game="
+ nameOfGame
+ "&Register=Register&page=game");
reader = new BufferedReader(new InputStreamReader(u.openStream()));
ParserDelegator parser = new ParserDelegator();
parser.parse(reader, this, false);
} catch (MalformedURLException m) {
// just catching stuff.
} catch (IOException e) {
// just catching this too, for now.
}
* Should return something like... if successful
* The game 'giggs' on DEDO has been registered
* The game page will be available when the judge replies : /observer.py?page=game&judge=DEDO&game=giggs
*
* OR if not...
*
* This game is already registered
return gameInformation.toString();
}
*/
/*
// for testing
public static void main(String[] args){
FlocImportCallback ficb = new FlocImportCallback()
{
public void flocImportException(IOException e)
{System.out.println(e);}
public void flocImportComplete(String text)
{System.out.println(text);}
public void flocImportUnregistered()
{System.out.println("*** NOT REGISTERED ***");}
};
FlocImporter fi = new FlocImporter("basic8", "NZMB", ficb);
//FlocImporter fi = new FlocImporter("skldfa832939ksdf", "NZMB", ficb);
fi.run();
}
*/
}// class FlocImporter