package jp.riken.brain.ni.samuraigraph.application;

import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.geom.Rectangle2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.prefs.Preferences;

import javax.print.attribute.standard.MediaSize;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.UIManager;

import jp.riken.brain.ni.samuraigraph.base.SGData;
import jp.riken.brain.ni.samuraigraph.base.SGDialog;
import jp.riken.brain.ni.samuraigraph.base.SGDrawingWindow;
import jp.riken.brain.ni.samuraigraph.base.SGExtensionFileFilter;
import jp.riken.brain.ni.samuraigraph.base.SGFigure;
import jp.riken.brain.ni.samuraigraph.base.SGFileChooser;
import jp.riken.brain.ni.samuraigraph.base.SGIAxisBreakElement;
import jp.riken.brain.ni.samuraigraph.base.SGIAxisElement;
import jp.riken.brain.ni.samuraigraph.base.SGIConstants;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureConstants;
import jp.riken.brain.ni.samuraigraph.base.SGIFigureElement;
import jp.riken.brain.ni.samuraigraph.base.SGIGraphElement;
import jp.riken.brain.ni.samuraigraph.base.SGIGridElement;
import jp.riken.brain.ni.samuraigraph.base.SGILegendElement;
import jp.riken.brain.ni.samuraigraph.base.SGIRootObjectConstants;
import jp.riken.brain.ni.samuraigraph.base.SGISXYGraphElement;
import jp.riken.brain.ni.samuraigraph.base.SGIShapeElement;
import jp.riken.brain.ni.samuraigraph.base.SGISignificantDifferenceElement;
import jp.riken.brain.ni.samuraigraph.base.SGIStringElement;
import jp.riken.brain.ni.samuraigraph.base.SGITimingLineElement;
import jp.riken.brain.ni.samuraigraph.base.SGIVXYGraphElement;
import jp.riken.brain.ni.samuraigraph.base.SGUtility;
import jp.riken.brain.ni.samuraigraph.base.SGUtilityText;
import jp.riken.brain.ni.samuraigraph.data.SGDataTypeConstants;
import jp.riken.brain.ni.samuraigraph.data.SGISXYTypeData;
import jp.riken.brain.ni.samuraigraph.data.SGISXYTypeMultipleData;
import jp.riken.brain.ni.samuraigraph.data.SGSXYData;
import jp.riken.brain.ni.samuraigraph.data.SGSXYDateData;
import jp.riken.brain.ni.samuraigraph.data.SGSXYMultipleData;
import jp.riken.brain.ni.samuraigraph.data.SGSXYSamplingData;
import jp.riken.brain.ni.samuraigraph.data.SGVXYData;
import jp.riken.brain.ni.samuraigraph.figure.SGDrawingElementArrow;
import jp.riken.brain.ni.samuraigraph.figure.SGDrawingElementErrorBar;
import jp.riken.brain.ni.samuraigraph.figure.SGDrawingElementLine;
import jp.riken.brain.ni.samuraigraph.figure.SGDrawingElementSymbol;
import jp.riken.brain.ni.samuraigraph.figure.SGIFigureTypeConstants;
import jp.riken.brain.ni.samuraigraph.figure.SGSXYFigure;
import jp.riken.brain.ni.samuraigraph.figure.SGVXYFigure;
import jp.riken.brain.ni.samuraigraph.figure.SGXYFigure;

import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;




/**
 * The main class of this application.
 * 
 */
public class SGDrawingServer implements SGIApplicationTextConstants
{


	/**
	 * 
	 */
	public static String LOOK_AND_FEEL = null;


	/**
	 * 
	 */
	public static int PORT_NUMBER = 5555;


	/**
	 * 
	 */
	public static String PROPERTY_FILE_NAME = null;


	/**
	 * 
	 */
	public static String ARCHIVE_FILE_NAME = null;


	/**
	 * 
	 */
	public static boolean INPUT_FLAG = false;


	private static final int SUCCEEDED = 0;
	private static final int FAILED = -1;
	private static final int NOT_FOUND = 1;


	private static final int PROPERTY_FILE = 0;
	private static final int ARCHIVE_FILE = 1;


	/**
	 * main method
	 * @param args
	 */
	public static void main( String args[] )
	{

		// interpret command lines
		interpretCommands( args );

		// create a Main thread
		Main m = null;
		if( PROPERTY_FILE_NAME!=null )
		{
			m = new Main( PROPERTY_FILE_NAME, PROPERTY_FILE );
		}
		else if( ARCHIVE_FILE_NAME!=null )
		{
			m = new Main( ARCHIVE_FILE_NAME, ARCHIVE_FILE );
		}
		else
		{
			m = new Main();
		}

		// create a new thread
//		if( PORT_NUMBER!=-1 )
		{
			try
			{
				// wait till the end of Main thread
				m.join();

				// create a server socket object
//				ServerSocket serverSocket
//					= new ServerSocket( SGDrawingServer.PORT_NUMBER );


				// create Connect thread
				if( INPUT_FLAG )
				{
					ServerSocket serverSocket = null;
					Connect c = new Connect( m, serverSocket );
				}
			}
			catch ( Exception ex )
			{
				JOptionPane.showOptionDialog(
					null,
					"Failed to start up Samurai Graph.",
					TITLE_ERROR,
					JOptionPane.DEFAULT_OPTION,
					JOptionPane.WARNING_MESSAGE, 
					null,
					null,
					null
				);
			}
			
		}

//System.out.println("END");
	}



	/**
	 * 
	 */
	private static void interpretCommands( final String[] commands )
	{
		
		for( int ii=0; ii<commands.length; ii++ )
		{
			if( commands[ii].equals("-p") )
			{
				if( ii+1<commands.length )
				{
					Integer n = SGUtilityText.getInteger( commands[ii+1] );
					if( n==null )
					{
						continue;
					}
					PORT_NUMBER = n.intValue();
				}
			}
			else if( commands[ii].equals("-prop") )
			{
				if( ii+1<commands.length )
				{
					PROPERTY_FILE_NAME = commands[ii+1];
				}
			}
			else if( commands[ii].equals("-dataset") )
			{
				if( ii+1<commands.length )
				{
					ARCHIVE_FILE_NAME = commands[ii+1];
				}
			}
			else if( commands[ii].equals("-i") )
			{
				INPUT_FLAG = true;
			}
			else
			{
				String className = getLookAndFeelClassName( commands[ii].toLowerCase() );
				if( className!=null )
				{
					LOOK_AND_FEEL = className;
				}
			}
		}

	}


	/**
	 * Returns the class name of look and feel.
	 * @param name - the short name of look and feel
	 * @return the class name of look and feel
	 */
	private static String getLookAndFeelClassName( String name )
	{
		if( name==null )
		{
			throw new IllegalArgumentException("name==null");
		}
		UIManager.LookAndFeelInfo[] lafArray
			= UIManager.getInstalledLookAndFeels();
		for( int ii=0; ii<lafArray.length; ii++ )
		{
			String name_ = lafArray[ii].getName().toLowerCase();
			if( name_.equals(name.toLowerCase()) )
			{
				LOOK_AND_FEEL = lafArray[ii].getClassName();
			}
		}
		return null;
	}




///**
// * Manage the lock file.
// * 
// */
//private static class LockFileManager extends Thread
//	implements SGIConstants, SGIApplicationConstants
//{
//
//	/**
//	 * Name of the lock file.
//	 */
//	public static final String LOCK_FILE_NAME_EXTENSION = "lock";
//
//
//	/**
//	 * Cycle of creating the lock file.
//	 */
//	public static final int CYCLE = 1000;
//
//	
//	/**
//	 * 
//	 */
//	private Main mMain = null;
//
//	
//	/**
//	 * Create a thread object.
//	 *
//	 */
//	private LockFileManager( Main c )
//	{
//		super();
//		this.mMain = c;
//		this.start();
//	}
//	
//
//	/**
//	 * 
//	 */	
//	public void run()
//	{
//		String fileName = "samurai-graph-"
//			+ MAJOR_VERSION_NUMBER + "."
//			+ MINOR_VERSION_NUMBER + "."
//			+ MICRO_VERSION_NUMBER + "."
//			+ LOCK_FILE_NAME_EXTENSION;
//		File f = new File( TMP_DIR + FILE_SEPARATOR + fileName );
//
//		Main m = this.mMain;
//
//		try
//		{
//			if( f.exists() )
//			{
//				// if the lock file is not so old, delete it and exit
//				final long diff  = System.currentTimeMillis() - f.lastModified();
//				if( diff < 2*CYCLE )
//				{
//					f.delete();
//					System.exit(0);
//				}
//			}
//
//			// loop of observing the lock file
//			while( true )
//			{
//				if( f.exists()==false )
//				{
//					// except the start-up of application, create a new window
//					final int num = m.getWindowNumber();
//					if( num!=0 )
//					{
//						SGDrawingWindow wnd = m.createNewWindow();
//						wnd.setVisible(true);
//					}
//				}
//				
//				// recreate the lock file
//				f.delete();
//				f.createNewFile();
//				f.deleteOnExit();
//				f.setReadOnly();
//
//				// stop this thread
//				Thread.sleep(CYCLE);
//			}
//		}
//		catch( Exception ex )
//		{
//			return;
//		}
//	}
//
//}



/**
 * A class to handle proxy connection.
 * 
 */
private static class ProxyManager
	implements ActionListener, SGIPreferencesConstants
{

	/**
	 * A flag whether access to the internet is direct.
	 */
	private boolean mDirectAccessFlag = true;
	

	/**
	 * The name of proxy server.
	 */
	private String mProxyHostName = null;
	
	
	/**
	 * The port number of proxy.
	 */
	private int mProxyPortNumber = -1;


	/**
	 * 
	 *
	 */
	private ProxyManager()
	{
		this.setProxyOnStartUp();
	}


	/**
	 * 
	 * @return
	 */
	private boolean setProxyOnStartUp()
	{
		Preferences pref = Preferences.userNodeForPackage( this.getClass() );
		final boolean direct = pref.getBoolean( PREF_KEY_DIRECT_ACCESS, true );
		final String hostName = pref.get( PREF_KEY_PROXY_HOST_NAME, "" );
		final int portNumber = pref.getInt( PREF_KEY_PROXY_PORT_NUMBER, -1 );

		this.mDirectAccessFlag = direct;
		if( hostName.equals("") == false )
		{
			this.mProxyHostName = hostName;
		}
		if( portNumber!=-1 )
		{
			this.mProxyPortNumber = portNumber;
		}
		return true;
	}
	


	/**
	 * 
	 * @return
	 */
	public boolean isDirectAccess()
	{
		return this.mDirectAccessFlag;
	}

	
	/**
	 * 
	 * @param b
	 */
	public void setDirectAccess( boolean b )
	{
		this.mDirectAccessFlag = b;
	}
	
	
	/**
	 * 
	 * @return
	 */
	public String getProxyHostName()
	{
		return this.mProxyHostName;
	}

	
	/**
	 * 
	 * @return
	 */
	public int getProxyPortNumber()
	{
		return this.mProxyPortNumber;
	}

	
	/**
	 * 
	 * @param name
	 */
	public void setProxyHostName( final String name )
	{
		this.mProxyHostName = name;
	}

	
	/**
	 * 
	 * @param num
	 */
	public void setProxyPortNumber( final int num )
	{
		this.mProxyPortNumber = num;
	}


	/**
	 * 
	 * @return
	 */
	private boolean showProxySettingDialog( Frame owner )
	{
		SGProxySettingDialog dg = new SGProxySettingDialog(owner,true);
		dg.addActionListener( this );
		dg.setCenter(owner);

		// set properties
		dg.setDirectAccess( this.mDirectAccessFlag );
		dg.setHostName( this.mProxyHostName );
		dg.setPortNumber( this.mProxyPortNumber );

		// show dialog
		dg.setVisible(true);
		
		// dispose
		dg.dispose();

		return true;
	}



	/**
	 * 
	 */
	public void actionPerformed( ActionEvent e )
	{
		Object source = e.getSource();
		SGProxySettingDialog dg = (SGProxySettingDialog)source;
		String command = e.getActionCommand();
		if( command.equals( SGDialog.OK_BUTTON_TEXT ) )
		{
			this.mDirectAccessFlag = dg.isDirectAccess();
			this.mProxyHostName = dg.getHostName();
			this.mProxyPortNumber = dg.getPortNumber();
			
			Preferences pref = Preferences.userNodeForPackage( this.getClass() );
			pref.putBoolean( PREF_KEY_DIRECT_ACCESS, this.mDirectAccessFlag );
			pref.put( PREF_KEY_PROXY_HOST_NAME, this.mProxyHostName );
			pref.putInt( PREF_KEY_PROXY_PORT_NUMBER, this.mProxyPortNumber );
		}
	}


}



/**
 * A class to manage upgrade of the application.
 */
private static class UpgradeManager
	implements ActionListener,
		SGIConstants, SGIUpgradeConstants,
		SGIApplicationConstants, SGIPreferencesConstants
{

	private static final String MSG_LATEST_VERSION_INSTALLED
		= "The latest version is already installed.";

	private static final String MSG_NEW_VERSION_FOUND_BEFORE
		= "Samurai Graph Ver.";

	private static final String MSG_NEW_VERSION_FOUND_AFTER
		= " is found.\n" + "Download now?\n";

	private static final String MSG_UPGRADE_FAILED
		= "Upgrade is failed for some reason.";

	private static final String MSG_UPGRADE_WARNING
		= "This application will be terminated.\n" + "Present work will be lost.";

	private static final String TITLE_WARNING = "Warning";

	private static final String MSG_LOCAL_FILE_NOT_FOUND = "Local file is not found.";

	private static final String MSG_CONNECTION_FAILED = "Connection Failed.";



	/**
	 * A file chooser to download the new version.
	 */
	private JFileChooser mUpgradeFileChooser;


	/**
	 * 
	 */
	private SGUpgradeDialog mUpgradeDialog;


	/**
	 * 
	 */
	private ProxyManager mProxyManager;


	/**
	 * 
	 *
	 */
	private UpgradeManager( ProxyManager p )
	{
		this.mProxyManager = p;
		this.mUpgradeFileChooser = new SGFileChooser();
		this.mUpgradeFileChooser.setCurrentDirectory( new File( USER_HOME ) );
	}
	
	
	/**
	 * 
	 */
	public void actionPerformed( final ActionEvent e )
	{
		Object source = e.getSource();
		String command = e.getActionCommand();

		int type;
		if( command.equals( SGDialog.OK_BUTTON_TEXT ) )
		{
			String cycle = this.mUpgradeDialog.getUpgradeCycle();

			if( cycle.equals( SGUpgradeDialog.NO_UPGRADE ) )
			{
				type = NO_UPGRADE;
			}
			else if( cycle.equals( SGUpgradeDialog.EVERY_TIME ) )
			{
				type = UPGRADE_EVERY_TIME;
			}
			else if( cycle.equals( SGUpgradeDialog.EVERY_DAY ) )
			{
				type = UPGRADE_EVERY_DAY;
			}
			else if( cycle.equals( SGUpgradeDialog.EVERY_WEEK ) )
			{
				type = UPGRADE_EVERY_WEEK;
			}
			else if( cycle.equals( SGUpgradeDialog.EVERY_MONTH ) )
			{
				type = UPGRADE_EVERY_MONTH;
			}
			else
			{
				throw new Error();
			}

			// update the upgrade cycle
			Preferences pref = Preferences.userNodeForPackage( this.getClass() );
			pref.putInt( PREF_KEY_UPGRADE_CYCLE, type );

		}
		else if( command.equals( SGUpgradeDialog.UPGRADE_NOW ) )
		{
			SGUpgradeDialog dg = (SGUpgradeDialog)source;
			if( this.upgradeByCommand(dg) == false )
			{
				return;
			}
		}

	}

	
	/**
	 * 
	 * @param wnd
	 * @return
	 */
	private boolean showUpgradeDialog( Frame owner )
	{
		this.mUpgradeDialog = new SGUpgradeDialog( owner,true );
		this.mUpgradeDialog.addActionListener( this );

		this.mUpgradeDialog.setCenter(owner);

		Preferences pref = Preferences.userNodeForPackage( this.getClass() );
		final int cycleType = pref.getInt( PREF_KEY_UPGRADE_CYCLE, NO_UPGRADE );

		String cycle = null;
		switch( cycleType )
		{
			case NO_UPGRADE:
			{
				cycle = SGUpgradeDialog.NO_UPGRADE;
				break;
			}

			case UPGRADE_EVERY_TIME:
			{
				cycle = SGUpgradeDialog.EVERY_TIME;
				break;
			}

			case UPGRADE_EVERY_DAY:
			{
				cycle = SGUpgradeDialog.EVERY_DAY;
				break;
			}

			case UPGRADE_EVERY_WEEK:
			{
				cycle = SGUpgradeDialog.EVERY_WEEK;
				break;
			}

			case UPGRADE_EVERY_MONTH:
			{
				cycle = SGUpgradeDialog.EVERY_MONTH;
				break;
			}

			default:
			{
				cycle = SGUpgradeDialog.NO_UPGRADE;
			}
		}
		this.mUpgradeDialog.setUpgradeCycle( cycle );


		// show
		this.mUpgradeDialog.setVisible(true);

		return true;
	}



	/**
	 * 
	 *
	 */
	private boolean upgradeOnStartup( Window owner )
	{
		return this.upgrade(owner,true);
	}


	/**
	 * 
	 *
	 */
	private boolean upgradeByCommand( Window owner )
	{
		return this.upgrade(owner,false);
	}

	

	/**
	 * 
	 * @param owner
	 * @param onStartUp
	 */
	private boolean upgrade( final Window owner, final boolean onStartUp )
	{

		final boolean direct = this.mProxyManager.isDirectAccess();
		String host = this.mProxyManager.getProxyHostName();
		int port = this.mProxyManager.getProxyPortNumber();


		// get URL
		URL url = null;
		try
		{
			if( direct )
			{
				url = new URL( PRODUCT_XML_FILE_NAME );
			}
			else
			{
				url = new URL(
						"http",
						host,
						port,
						PRODUCT_XML_FILE_NAME
					);
			}
		}
		catch( MalformedURLException ex )
		{
//			JOptionPane.showMessageDialog(
//					owner,
//					"URL is invalid."
//				);
			return false;
		}

		// create a Document object
		Document doc = SGUtilityText.getDocument( url );
		if( doc==null )
		{
//			JOptionPane.showMessageDialog(
//				owner,
//				"Failed to get information of the latest version."
//			);
			return false;
		}


		// update the date
		if( onStartUp )
		{
			Preferences pref = Preferences.userNodeForPackage( this.getClass() );
			pref.putLong( PREF_KEY_DATE, System.currentTimeMillis() );
		}


		// get root element - product
		Element root = doc.getDocumentElement();

		// compare the version number
		if( this.compareVersion( root ) )
		{
			// start installation
			if( this.installLatestVersion(
				root,
				owner,
				onStartUp ) == false )
			{
				return false;
			}
		}
		else
		{
			if( !onStartUp )
			{
				// show a message dialog
				JOptionPane.showMessageDialog(
					owner, MSG_LATEST_VERSION_INSTALLED );
			}
		}
	
		return true;
	}


	/**
	 * 
	 * @return
	 */
	private boolean compareVersion( Element root )
	{
//		Preferences pref = Preferences.userNodeForPackage( this.getClass() );
//		final int major = pref.getInt( PREF_KEY_MAJOR_VERSION_NUMBER, -1 );
//		final int minor = pref.getInt( PREF_KEY_MINOR_VERSION_NUMBER, -1 );
//		final int micro = pref.getInt( PREF_KEY_MICRO_VERSION_NUMBER, -1 );

		final int major = SGIApplicationConstants.MAJOR_VERSION_NUMBER;
		final int minor = SGIApplicationConstants.MINOR_VERSION_NUMBER;
		final int micro = SGIApplicationConstants.MICRO_VERSION_NUMBER;

		final int nMajor = this.getVersion( root, "majorver" );
		final int nMinor = this.getVersion( root, "minorver" );
		final int nMicro = this.getVersion( root, "microver" );
		final boolean b = Utility.compareVersionNumber( major, minor, micro, nMajor, nMinor, nMicro );
		return b;
	}






	/**
	 * 
	 * @param root
	 * @param tagName
	 * @return
	 */
	private int getVersion( Element root, String tagName )
	{
		Element ver = (Element)root.getElementsByTagName(tagName).item(0);
		String verString = ver.getFirstChild().getNodeValue();
		final int verNumber = Integer.parseInt( verString );
		return verNumber;
	}



	/**
	 * 
	 * @param root
	 * @return
	 * @throws Exception
	 */
	private boolean installLatestVersion(
		Element root, final Window owner, final boolean onStartUp )
	{
		// current version numbers
		final int mMajor = MAJOR_VERSION_NUMBER;
		final int mMinor = MINOR_VERSION_NUMBER;
		final int mMicro = MICRO_VERSION_NUMBER;
		
		// get later releases and the latest release
		NodeList rList = root.getElementsByTagName("release");
		Element latestRelease = null;
		ArrayList laterReleaseList = new ArrayList();
		for( int ii=0; ii<rList.getLength(); ii++ )
		{
			Element el = (Element)rList.item(ii);
			String value = el.getAttribute("latest");
			if( Boolean.TRUE.toString().equals(value) )
			{
				latestRelease = el;
			}

			final int nMajor = this.getVersion( el, "majorver" );
			final int nMinor = this.getVersion( el, "minorver" );
			final int nMicro = this.getVersion( el, "microver" );
			if( Utility.compareVersionNumber( mMajor,mMinor,mMicro,nMajor,nMinor,nMicro ) )
			{
				laterReleaseList.add(el);
			}
		}

		if( latestRelease==null )
		{
//			JOptionPane.showMessageDialog(
//				owner,
//				"Statement in the XML file is wrong."
//			);
			return false;
		}


		// get the latest version numbers
		final int nMajor = this.getVersion( latestRelease, "majorver" );
		final int nMinor = this.getVersion( latestRelease, "minorver" );
		final int nMicro = this.getVersion( latestRelease, "microver" );

		final String major = new Integer( nMajor ).toString();
		final String minor = new Integer( nMinor ).toString();
		final String micro = new Integer( nMicro ).toString();

		// create a message
		String msg = MSG_NEW_VERSION_FOUND_BEFORE + major + "." + minor + "." + micro + MSG_NEW_VERSION_FOUND_AFTER;

		
		// get the change log
		StringBuffer sb = new StringBuffer("<html><head></head><body>-- New Features --");
		String fSize = "<font size=\"3\">";
		sb.append(fSize);
		for( int ii=0; ii<laterReleaseList.size(); ii++ )
		{
			Element release = (Element)laterReleaseList.get(ii);
			StringBuffer sb_ = new StringBuffer();
			NodeList rInfoList = release.getElementsByTagName("releaseinfo");
			Element rInfo = (Element)rInfoList.item(0);
			NodeList cLogList = rInfo.getElementsByTagName("changelog");
			Element cLog = (Element)cLogList.item(0);
			this.printNode(cLog,sb_);
			sb.append(sb_);
		}

		// create a message dialog
		SGUpgradeConfirmDialog cfDialog = null;
		if( owner instanceof Frame )
		{
			cfDialog = new SGUpgradeConfirmDialog( (Frame)owner, true );
		}
		else if( owner instanceof Dialog )
		{
			cfDialog = new SGUpgradeConfirmDialog( (Dialog)owner, true );
		}
		cfDialog.setMessage(msg);
		cfDialog.setPage( new String(sb) );
		cfDialog.pack();
		cfDialog.setCenter(owner);

		// show a message dialog
		cfDialog.setVisible(true);

		// if upgrade is canceled, return true
		if( cfDialog.isCanceled() )
		{
			return true;
		}


		// get OS name
		String name = null;
		if( SGUtility.identifyOS( OS_NAME_WINDOWS ) )
		{
			name = "win32";
		}
		else if( SGUtility.identifyOS( OS_NAME_MACOSX ) )
		{
			name = "macosx";
		}
		else
		{
			name = "other";
		}


		// upgrade
		NodeList pList = latestRelease.getElementsByTagName("package");
		for( int ii=0; ii<pList.getLength(); ii++ )
		{
			Element el = (Element)pList.item(ii);
			String attr = el.getAttribute("category");

			if( attr.equals("win32") )
			{
				if( name.equals("win32") )
				{
					if( this.forWin32(el,major,minor,micro,owner,onStartUp) )
					{
						break;
					}
					else
					{
						return false;
					}
				}
			}
			else if( attr.equals("macosx") )
			{
				if( name.equals("macosx") )
				{
					if( this.forMacOSX(el,major,minor,micro,owner,onStartUp) )
					{
						break;
					}
					else
					{
						return false;
					}
				}
			}
			else if( attr.equals("bin") )
			{
				if( name.equals("other") )
				{
					if( this.forOtherPlatform(el,major,minor,micro,owner,onStartUp) )
					{
						break;
					}
					else
					{
						return false;
					}
				}
			}
			else if( attr.equals("src") )
			{

			}

		}

		return true;
	}



	/**
	 * 
	 * @param el
	 * @param major Major version number of the new version
	 * @param minor Minor version number of the new version
	 * @param micro Micro version number of the new version
	 * @param owner Dialog owner
	 * @param onStartUp whether this upgrade is on the start-up
	 * @return true:success, false:failure
	 */
	private boolean forWin32(
		final Element el,
		final String major,
		final String minor,
		final String micro,
		final Window owner,
		final boolean onStartUp )
	{

		final String failed = MSG_UPGRADE_FAILED;

		// show a message dialog
		if( !onStartUp )
		{
			Object[] options = { "OK", "Cancel" };
			final int ret = JOptionPane.showOptionDialog(
				owner,
				MSG_UPGRADE_WARNING,
				TITLE_WARNING,
				JOptionPane.DEFAULT_OPTION,
				JOptionPane.WARNING_MESSAGE, 
				null,
				options,
				options[0]
			);
			if( ret==JOptionPane.NO_OPTION || ret==JOptionPane.CLOSED_OPTION )
			{
				return true;
			}
		}


		// get the root directory
		String classpath = System.getProperty("java.class.path");
		StringTokenizer stk = new StringTokenizer( classpath, PATH_SEPARATOR );
		String root = null;
		while( stk.hasMoreTokens() )
		{
			String str = stk.nextToken();
			if( str.endsWith("samurai-graph.jar") )
			{
				root = new File( str ).getParent();
				break;
			}
		}
		if( root==null )
		{
			JOptionPane.showMessageDialog(
				owner,
				failed
			);
			return false;
		}

//JOptionPane.showMessageDialog( null, root );

		// copy the helper application from ./lib to the temporay directory
		File helper = new File( root + FILE_SEPARATOR + "lib" + FILE_SEPARATOR + UPGRADE_HELPER_FILE_NAME );
		if( helper.exists() == false )
		{
			JOptionPane.showMessageDialog(
				owner,
//				"Helper application is not found."
				failed
			);
			return false;
		}

//JOptionPane.showMessageDialog( null, helper );


		File helperTempDir = new File( TMP_DIR + FILE_SEPARATOR + HELPER_TEMP_DIR_NAME );
		if( helperTempDir.mkdir() == false )
		{
			JOptionPane.showMessageDialog(
				owner,
//				"Failed to create a temporary directory."
				failed
			);
			return false;
		}
		helperTempDir.deleteOnExit();
		File helperTemp = new File( helperTempDir.getAbsolutePath() + FILE_SEPARATOR + UPGRADE_HELPER_FILE_NAME );
		helperTemp.deleteOnExit();

		try
		{
			SGApplicationUtility.copyBinaryFile( helper, helperTemp );
		}
		catch( IOException ex )
		{
			JOptionPane.showMessageDialog(
				owner,
//				"Failed to copy the helper application."
				failed
			);
			return false;
		}



		//
		// download the installer
		//

		File installer = null;
		try
		{
			installer = File.createTempFile( "tmp_", ".exe" );
		}
		catch( IOException ex )
		{
			return false;
		}
		finally
		{
			if( installer!=null )
			{
				installer.delete();
			}
		}

		if( this.download( el, owner, installer ) == false )
		{
			JOptionPane.showMessageDialog(
				owner,
//				"Failed to download the latest version."
				failed
			);
			installer.delete();
			helperTemp.delete();
			helperTempDir.delete();
			return false;
		}

//installer = new File("D:\\Tmp\\samurai-graph-win32-0.3.1.exe");

		//
		// start the helper application
		//

		String upperDir = new File( root ).getParent();

//JOptionPane.showMessageDialog( owner, "current@"+currentInstDir );
//JOptionPane.showMessageDialog( owner, "upper@"+upperDir );

		String instPath = installer.getAbsolutePath();
		String suffix = major + "." + minor + "." + micro;
//		String pathNew = upperDir + FILE_SEPARATOR + "Samurai Graph "+major+"."+minor+"."+micro;

String pathNew = root;

//JOptionPane.showMessageDialog( owner, "pathNew@"+pathNew );

		String[] cmdArray = new String[6];
		cmdArray[0] = System.getProperty("java.home") + FILE_SEPARATOR + "bin" + FILE_SEPARATOR + "javaw.exe";
		cmdArray[1] = "-jar";
		cmdArray[2] = helperTemp.getAbsolutePath();
		cmdArray[3] = root;			// A pathname string of the old version
		cmdArray[4] = instPath;		// A pathname string of the installer
		cmdArray[5] = pathNew;		// A pathname string of the new version

		if( helperTemp.exists() == false )
		{
			JOptionPane.showMessageDialog(
				owner,
//				"Helper application is not found."
				failed
			);
			return false;
		}

		try
		{
			Runtime.getRuntime().exec( cmdArray, null, new File( upperDir ) );
		}
		catch( IOException ex )
		{
			JOptionPane.showMessageDialog(
				owner,
//				"Failed to start the helper application."
				failed
			);
			return false;
		}
		

		return true;
	}






	/**
	 * 
	 * @param el
	 * @return
	 * @throws Exception
	 */
	private boolean forOtherPlatform(
		final Element el, final String major, final String minor, final String micro,
		final Window owner, final boolean onStartUp )// throws Exception
	{
		return this.downloadWithFileChooser(
			el, major, minor, micro, owner, onStartUp,
			"samurai-graph-bin", "zip", "Zip Archive" );
	}



	/**
	 * 
	 * @param el
	 * @return
	 * @throws Exception
	 */
	private boolean forMacOSX(
		final Element el, final String major, final String minor, final String micro,
		final Window owner, final boolean onStartUp )// throws Exception
	{
		return this.downloadWithFileChooser(
			el, major, minor, micro, owner, onStartUp,
			"samurai-graph-mac", "dmg.gz", "Compressed Disk Image" );
	}



	/**
	 * 
	 * @param el
	 * @param major
	 * @param minor
	 * @param micro
	 * @param owner
	 * @param onStartUp
	 * @param extension
	 * @param description
	 * @return
	 * @throws Exception
	 */
	private boolean downloadWithFileChooser(
		final Element el, final String major, final String minor, final String micro,
		final Window owner, final boolean onStartUp, final String name, final String extension,
				final String description )
	{
		JFileChooser chooser = this.mUpgradeFileChooser;

		// create a file filter object
		SGExtensionFileFilter ff = new SGExtensionFileFilter();
		ff.setDescription( extension );
		ff.addExtension( description );
		chooser.setFileFilter( ff );


		// set file name
		String fileName = name + "-" + major + "." + minor + "." + micro + "." + extension;
		chooser.setSelectedFile( new File( fileName ) );


		// show save dialog
		final int ret = chooser.showSaveDialog(owner);

		File fileSaved = null;
		switch( ret )
		{
			// selected
			case JFileChooser.APPROVE_OPTION :
			{
				fileSaved = chooser.getSelectedFile();
				break;
			}

			// canceled
			case JFileChooser.CANCEL_OPTION :
			{
				return true;
			}

			// error
			case JFileChooser.ERROR_OPTION :
			{
				throw new Error();
			}

			default :
			{
				
			}
		}

		String path = fileSaved.getAbsolutePath();
		if( path.endsWith( extension ) == false
			&& path.endsWith( extension.toUpperCase() ) == false )
		{
			path += "." + extension;
		}
		File file = new File(path);

		// download
		if( this.download( el, owner, file ) == false )
		{
			return false;
		}

		return true;
	}



	/**
	 * 
	 * @param el
	 * @param owner
	 * @param suffix
	 * @return
	 * @throws Exception
	 */
	private boolean download(
		final Element el, final Window owner, final File file )
	{
		BufferedOutputStream bos = null;
		BufferedInputStream bis = null;
		SGProgressMonitorDialog dg = null;

		boolean ret = false;

		try
		{
			// create output stream
			bos = new BufferedOutputStream( new FileOutputStream(file) );
	
			NodeList urlList = el.getElementsByTagName("url");
			for( int ii=0; ii<urlList.getLength(); ii++ )
			{
				Element urlElement = (Element)urlList.item(ii);
				String urlStr = urlElement.getFirstChild().getNodeValue();
	
				// create an URL instance
				URL url = null;
				try
				{
					url = new URL(urlStr);
				}
				catch( MalformedURLException ex )
				{
					continue;
				}
	
				// get input stream
				URLConnection co = null;
				try
				{
					co = url.openConnection();
					bis = new BufferedInputStream( co.getInputStream() );
				}
				catch( IOException ex )
				{
					continue;
				}

				// get file name
				String path = file.getAbsolutePath();
/*				final int nameLen = 20;
				if( path.length() > nameLen )
				{
					path = path.substring(0,nameLen);
					path += "...";
				}
*/

				// get file size
				final int fileSize = co.getContentLength();

				// create a progress monitor dialog
				boolean modal = true;
				if( owner instanceof Dialog )
				{
					dg = new SGProgressMonitorDialog( (Dialog)owner, modal );
				}
				else if( owner instanceof JFrame )
				{
					dg = new SGProgressMonitorDialog( (Frame)owner, modal );
				}


				// set properties of the progress bar
				JProgressBar pBar = dg.getProgressBar();
				pBar.setMinimum(0);
				pBar.setMaximum(fileSize);
				pBar.setStringPainted(true);


				// set properties of the dialog
				dg.setInputSize(fileSize);
				dg.setInputStream(bis);
				dg.setOutputStream(bos);
				dg.setLabel(path);
				dg.pack();
				dg.setCenter(owner);


				// set the mouse cursor
				owner.setCursor(
					Cursor.getPredefinedCursor( Cursor.WAIT_CURSOR ) );


				// start download
				Thread th = new Thread(dg);
				th.start();

				dg.setVisible(true);


				if( dg.isCanceled() == true )
				{
					return false;
				}

				ret = true;
				break;
			}

		}
		catch( FileNotFoundException ex )
		{
			JOptionPane.showMessageDialog(
				owner,
				MSG_LOCAL_FILE_NOT_FOUND
			);
			return false;
		}
		finally
		{

			// set default cursor
			owner.setCursor( Cursor.getDefaultCursor() );

			// clear attributes
			dg.setInputStream(null);
			dg.setOutputStream(null);

			// close streams
			if( bis!=null )
			{
				try
				{
					bis.close();
				}
				catch( IOException ex )
				{
				}
			}
			
			if( bos!=null )
			{
				try
				{
					bos.close();
				}
				catch( IOException ex )
				{
				}
			}
		}


		// when connection failed, return false
		if( !ret )
		{
			JOptionPane.showMessageDialog(
				owner,
				MSG_CONNECTION_FAILED
			);
			return false;
		}

		return true;
	}


	/**
	 * 
	 * @param element
	 * @param tagList
	 * @param out
	 */
	private void printNode(
		Element element, StringBuffer sb )
	{
		printNodeRecursively( element, sb, -1 );
	}



	/**
	 * 
	 * @param node
	 * @return
	 */
	private void printNodeRecursively(
		Element element, StringBuffer sb, final int depth )
	{
		NodeList childList = element.getChildNodes();
		for( int ii=0; ii<childList.getLength(); ii++ )
		{
			Node child = childList.item(ii);
			if( child instanceof Element )
			{
				Element el = (Element)child;
				String tagName = el.getTagName();
				if( tagName.equals("item") )
				{
					NodeList nList = el.getChildNodes();
					final int num = nList.getLength();
					if( num==1 )
					{
						sb.append("<li>");
						printFirstChild( el, sb, depth );
						sb.append("</li>");
					}
					else if( num>1 )
					{
						sb.append("<li>");
						printFirstChild( el, sb, depth );
						sb.append("<ul>");
						for( int jj=0; jj<num; jj++ )
						{
							Node node = nList.item(jj);
							if( node instanceof Element )
							{
								Element el_ = (Element)node;
								printNodeRecursively( el_, sb, depth+1 );
							}
						}
						sb.append("</ul>");
						sb.append("</li>");
					}
				}
				else if( tagName.equals("itemize") )
				{
					sb.append("<ul>");
					printNodeRecursively( el, sb, depth+1 );
					sb.append("</ul>");
				}
			}
			else if( child instanceof Text )
			{
				
			}
		}

	}


	/**
	 * 
	 * @param node
	 * @param out
	 * @param depth
	 */
	private void printFirstChild(
		Node node, StringBuffer sb, final int depth )
	{
		Node child = node.getFirstChild();
		printText( child, sb, depth );
	}


	/**
	 * 
	 * @param node
	 * @param out
	 * @param depth
	 */
	private void printText(
		Node node, StringBuffer sb, final int depth )
	{
		String line = node.getNodeValue();
		String sub = tokenize(line);
		if( sub.length()!=0 )
		{
//System.out.println(sub);
			sb.append(sub);
		}
	}


	/**
	 * 
	 * @param line
	 * @return
	 */
	private String tokenize( String line )
	{
		StringTokenizer tkn = new StringTokenizer(line);
		ArrayList tokenList = new ArrayList();
		while( tkn.hasMoreTokens() )
		{
			tokenList.add( tkn.nextToken() );
		}

		String subStr = "";
		for( int ii=0; ii<tokenList.size(); ii++ )
		{
			String str = (String)tokenList.get(ii);
			subStr += str;
			if( ii!=tokenList.size()-1 )
			{
				subStr += " ";
			}
		}

		return subStr;
	}



}



/**
 * An utility class with static methods.
 */
private static class Utility implements SGIApplicationTextConstants
{
	

	/**
	 * Check whether one version is released later than the other version.
	 * @param m1
	 * @param m2
	 * @param m3
	 * @param n1
	 * @param n2
	 * @param n3
	 * @return	whether the version n is released later than version m
	 */
	public static boolean compareVersionNumber(
		final int m1, final int m2, final int m3,
		final int n1, final int n2, final int n3 )
	{
		boolean b;
		if( m1 < n1 )
		{
			b = true;
		}
		else if( m1 == n1 )
		{
			if( m2 < n2 )
			{
				b = true;
			}
			else if( m2 == n2 )
			{
				b = ( m3 < n3 );
			}
			else
			{
				b = false;
			}
		}
		else
		{
			b = false;
		}

		return b;
	}



	private static final void showDataFileInvalidMessageDialog( final Window owner )
	{
		SGUtility.showErrorMessageDialog(
			owner,
			MSG_DATA_FILE_INVALID,
			TITLE_ERROR
		);
	}

	private static final void showDataTypeInvalidMessageDialog( final Window owner )
	{
		SGUtility.showErrorMessageDialog(
			owner,
			MSG_DATA_TYPE_INVALID,
			TITLE_ERROR
		);
	}

}



/**
 * 
 */
private static class Connect extends Thread
{
	
	/**
	 * Server socket.
	 */
	private ServerSocket mServerSocket = null;


	/**
	 * Main object.
	 */
	private Main mMain;


	/**
	 * Create a thread object with a server socket.
	 * @param main
	 * @param serverSocket
	 */
	private Connect( Main main, ServerSocket serverSocket )
	{
		super();
//System.out.println("Connect");
		this.mMain = main;
		this.mServerSocket = serverSocket;

		this.start();
	}
	

	/**
	 * 
	 */
	public void run()
	{
		//
		// infinite loop as a server process
		//

		BufferedReader br
			= new BufferedReader(
				new InputStreamReader( System.in ) );

//System.out.println("run");
//JOptionPane.showMessageDialog(null,"run");

		BufferedWriter bw
			= new BufferedWriter(
				new OutputStreamWriter( System.out ) );

		try
		{
			while( true )
			{
				String line = br.readLine();
				if( line==null )
				{
					continue;
				}

//				StringTokenizer st = new StringTokenizer(line);
//				ArrayList list = new ArrayList();
//				while( st.hasMoreTokens() )
//				{
//					list.add( st.nextToken() );
//				}
//				String[] array = new String[list.size()];
//				for( int ii=0; ii<array.length; ii++ )
//				{
//					array[ii] = (String)list.get(ii);
//				}
//
//				final boolean ret = this.mMain.executeCommand(array);

				final int ret = this.mMain.exec( line );
				String status = Integer.toString(ret) + "\n";
				bw.write( status );
				bw.flush();
			}
		}
		catch( IOException ex )
		{
			ex.printStackTrace();
			return;
		}



//		while( true )
//		{
//			try
//			{
//				Socket socket = mServerSocket.accept();
//
//				PrintWriter out = new PrintWriter( socket.getOutputStream(), true );
//
//				BufferedReader in = new BufferedReader(
//					new InputStreamReader( socket.getInputStream() ) );
//
//				ArrayList commandList = new ArrayList();
//				String inputLine;
//				while( (inputLine = in.readLine()) != null )
//				{
//					commandList.add( new String( inputLine ) );
//				}
//				if( commandList.size() == 0 )
//				{
//					continue;
//				}
//				String[] commandArray = new String[commandList.size()];
//				for( int ii=0; ii<commandArray.length; ii++ )
//				{
//					commandArray[ii] = (String)commandList.get(ii);
//				}
//
//				if( this.mMain.executeCommand(commandArray) == false )
//				{
//					continue;
//				}
//
//				in.close();
//				out.close();
//
//				socket.close();
//
//			}
//			catch( IOException ex )
//			{
//				ex.printStackTrace();
//			}
//		}
			
	}

}



/**
 * A class for drag and drop.
 * This class is only for JRE 1.4 of Mac OS X.
 */
private static class DropEventHandler extends Thread
{

	/**
	 * 
	 */
	private Main mMain;


	/**
	 * 
	 */
	private DropTargetDropEvent mDropTargetDropEvent = null;


	/**
	 * 
	 */
	private ArrayList mDroppedFileList = null;


	/**
	 * 
	 * @param m
	 */
	private DropEventHandler( Main m, DropTargetDropEvent dtde, List list )
	{
		super();

		this.mMain = m;
		this.mDropTargetDropEvent = dtde;
		this.mDroppedFileList = new ArrayList( list );
		
		this.start();
	}


	/**
	 * 
	 */
	public void run()
	{
		DropTargetDropEvent dtde = this.mDropTargetDropEvent;
		DropTarget tg = (DropTarget)dtde.getSource();
		Component com = tg.getComponent();
		SGDrawingWindow wnd = (SGDrawingWindow)com;
		Point p = dtde.getLocation();

		this.mMain.fromDragAndDrop( p.x, p.y, wnd, this.mDroppedFileList );

		wnd.getContentPane().repaint();

		this.mDropTargetDropEvent = null;
		this.mDroppedFileList = null;
	}

}




/**
 *  The main thread.
 */
private static class Main extends Thread
	implements ActionListener, WindowListener, DropTargetListener,
		PropertyChangeListener, SGIConstants,
		SGIUpgradeConstants, SGIApplicationCommandConstants,
		SGIApplicationConstants, SGIPropertyFileConstants,
		SGIPreferencesConstants, SGIApplicationTextConstants,
		SGIRootObjectConstants, SGIImageConstants, SGIArchiveFileConstants
{

	/**
	 * The class object for SGIAxisElement.
	 */
	private Class mClassOfAxisElement = null;


	/**
	 * The class object for SGIGraphElement of the scalar XY-type.
	 */
	private Class mClassOfSXYGraphElement = null;


	/**
	 * The class object for SGIGraphElement of the vector XY-type.
	 */
	private Class mClassOfVXYGraphElement = null;


	/**
	 * The class object for SGILegendElement.
	 */
	private Class mClassOfLegendElement = null;


	/**
	 * The class object for SGIStringElement.
	 */
	private Class mClassOfStringElement = null;

	
	/**
	 * The class object for SGIAxisBreakElement.
	 */
	private Class mClassOfAxisBreakElement = null;

	
	/**
	 * The class object for SGISignificantDifferenceElement.
	 */
	private Class mClassOfSignificantDifferenceElement = null;
	
	
	/**
	 * The class object for SGITimingLineElement.
	 */
	private Class mClassOfTimingLineElement = null;


	/**
	 * The class object for SGIGridElement.
	 */
	private Class mClassOfGridElement = null;


	/**
	 * The class object for SGIShapeElement.
	 */
	private Class mClassOfShapeElement = null;

	

	/**
	 * The list of windows.
	 */
	private TreeMap mWndMap = new TreeMap();


	/**
	 * Image file creator.
	 */
	private SGImageExportManager mImageFileCreator;


	/**
	 * Property file creator.
	 */
	private SGPropertyFileCreator mPropertyFileCreator;


	/**
	 * Data set file creator.
	 */
	private SGArchiveFileCreator mArchiveFileCreator;
	
	/**
	 * Data set file extractor.
	 */
	private SGArchiveFileExtractor mArchiveFileExtractor;

	/**
	 * Proxy manager.
	 */
	private ProxyManager mProxyManager;


	/**
	 * Upgrade manager.
	 */
	private UpgradeManager mUpgradeManager;


	/**
	 * Data creator.
	 */
	private SGDataCreator mDataCreator;


	// The active window.
	private SGDrawingWindow mActiveWindow = null;


	// The active figure.
	private SGFigure mActiveFigure = null;


	/**
	 * Create a thread object.
	 *
	 */
	public Main()
	{
		super();
		this.start();
	}


	/**
	 * 
	 */
	private String mPropertyFileName;


	/**
	 * Create a thread object.
	 *
	 */
	public Main( String path, final int type )
	{
		super();
		if( type == PROPERTY_FILE )
		{
			this.mPropertyFileName = path;
		}
		else if( type == ARCHIVE_FILE )
		{
			this.mArchiveFileName = path;
		}
		this.start();
	}


	/**
	 * 
	 */
	private String mArchiveFileName;


	/**
	 * 
	 */
	public void run()
	{


//Permitted multiple running temporarily.
//
//
//		// create a lock file
//		LockFileManager lfc = new LockFileManager(this);


//		// dump free memory
//		class memtest extends Thread
//		{
//			memtest()
//			{
//				super();
//				this.start();
//			}
//			public void run()
//			{
//				while(true)
//				{
//					System.err.println( Runtime.getRuntime().freeMemory()/1000 );
//					try
//					{
//						Thread.sleep(1000);
//					}
//					catch( InterruptedException e )
//					{
//					}
//				}
//			}
//		};
//		new memtest();

		
		// remove temporary files used in upgrade
		this.removeTemporaryFiles();


		// create and show the splash window
		SGSplashWindow sw = this.createSplashWindow();
		if( sw==null )
		{
			this.exitApplication(1);
		}
		sw.setProgressValue(0.0f);
		sw.setVisible(true);


		// set Look & Feel
		try
		{
			if( LOOK_AND_FEEL==null )
			{
				UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
			}
			else
			{
				UIManager.setLookAndFeel( LOOK_AND_FEEL );
			}
		}
		catch( Exception ex )
		{
			this.exitApplication(1);
		}


		// create instances in attributes
		this.mDataCreator = new SGDataCreator();
		sw.setProgressValue(0.25f);
		this.mPropertyFileCreator = new SGPropertyFileCreator();
		sw.setProgressValue(0.40f);
		this.mArchiveFileCreator = new SGArchiveFileCreator();
		sw.setProgressValue(0.45f);
		this.mArchiveFileExtractor = new SGArchiveFileExtractor();
		sw.setProgressValue(0.50f);
		this.mImageFileCreator = new SGImageExportManager();
		sw.setProgressValue(0.60f);
		this.mProxyManager = new ProxyManager();
		sw.setProgressValue(0.70f);
		this.mUpgradeManager = new UpgradeManager( this.mProxyManager );
		sw.setProgressValue(0.85f);


		// create the figure element
		boolean flag = true;
		try
		{
			if( this.loadFigureElementClass() == false )
			{
				flag = false;
			}
		}
		catch( Exception ex )
		{
			flag = false;
		}

		if(!flag)
		{
//			JOptionPane.showMessageDialog(
//				null,
//				"Failed to create instances of SGFigureElement classes.",
//				"Error",
//				JOptionPane.ERROR_MESSAGE
//			);
			this.exitApplication(1);
		}
		sw.setProgressValue(1.0f);


		SGDrawingWindow wnd = this.createNewWindow();
		this.mActiveWindow = wnd;
		wnd.setVisible(true);
		boolean b = false;
		if( this.mPropertyFileName!=null)
		{
			// hide the splash window
			sw.setVisible(false);

			File f = new File( this.mPropertyFileName );
			if( this.showMultiDataFileChooserDialog(
				f, new ArrayList(), wnd ) == false )
			{
				this.exitApplication(1);
			}
			
			final int ret = this.mMultiDataFileChooserWizardDialogDD.getCloseOption();
			if( ret==SGDialog.CANCEL_OPTION )
			{
				// exit this application
				this.exitApplication(0);
			}
		}
		else if( this.mArchiveFileName!=null )
		{
			// hide the splash window
			sw.setVisible(false);

			File f = new File( this.mArchiveFileName );
			if( this.loadDataSet( wnd, f ) == -1 )
			{
				// exit this application
				this.exitApplication(0);
			}
		}
//		else
//		{
//			b = true;
//		}


//		if(b)
		{
			// create a window
//			wnd = this.createNewWindow();
//			if( wnd==null )
//			{
////				JOptionPane.showMessageDialog(
////					null,
////					"Failed to create a window.",
////					"Error",
////					JOptionPane.ERROR_MESSAGE
////				);
//				this.exitApplication(1);
//			}
//			wnd.setVisible(true);

			// hide the splash window
			sw.setVisible(false);
		}


		// update the preferences
		this.updatePreferences();

		// decide whether to upgrade
		if( this.checkDate() )
		{
			// upgrade
			this.mUpgradeManager.upgradeOnStartup(wnd);
		}

	}



	/**
	 * Remove temporary files used in upgrade.
	 */
	private void removeTemporaryFiles()
	{
		File temp = new File( TMP_DIR + FILE_SEPARATOR + HELPER_TEMP_DIR_NAME );
		try
		{
			temp = temp.getCanonicalFile();
		}
		catch( IOException ex )
		{
			return;
		}
		if( temp.exists() )
		{
			SGApplicationUtility.deleteRecursively( temp );
		}
	}



	// constants to be removed from the backing store
	private static final String PREF_KEY_MAJOR_VERSION_NUMBER = "Major Version";
	private static final String PREF_KEY_MINOR_VERSION_NUMBER = "Minor Version";
	private static final String PREF_KEY_MICRO_VERSION_NUMBER = "Micro Version";


	/**
	 * 
	 * @return
	 */
	private void updatePreferences()
	{
		Preferences pref = Preferences.userNodeForPackage( this.getClass() );

		// update the upgrade cycle at the first installation
		final int cycle = pref.getInt( PREF_KEY_UPGRADE_CYCLE, -1 );
		if( cycle==-1 )
		{
			pref.putInt( PREF_KEY_UPGRADE_CYCLE, DEFAULT_UPGRADE_CYCLE );
		}

		// update the date
		final String date = pref.get( PREF_KEY_DATE, null );
		pref.putLong( PREF_KEY_DATE, System.currentTimeMillis() );

		// remove old keys
//System.out.println(pref.getInt(PREF_KEY_MAJOR_VERSION_NUMBER,-1));
//System.out.println(pref.getInt(PREF_KEY_MINOR_VERSION_NUMBER,-1));
//System.out.println(pref.getInt(PREF_KEY_MICRO_VERSION_NUMBER,-1));
		pref.remove( PREF_KEY_MAJOR_VERSION_NUMBER );
		pref.remove( PREF_KEY_MINOR_VERSION_NUMBER );
		pref.remove( PREF_KEY_MICRO_VERSION_NUMBER );

//		final int major = pref.getInt( PREF_KEY_MAJOR_VERSION_NUMBER, -1 );
//		final int minor = pref.getInt( PREF_KEY_MINOR_VERSION_NUMBER, -1 );
//		final int micro = pref.getInt( PREF_KEY_MICRO_VERSION_NUMBER, -1 );
//		boolean b = false;
//
//		// At the first installation
//		if( date==null || major==-1 || minor==-1 || micro==-1 )
//		{
//			b = true;
//		}
//		// At the start-up of the application
//		else
//		{
//			b = Utility.compareVersionNumber(
//				major, minor, micro,
//				MAJOR_VERSION_NUMBER, MINOR_VERSION_NUMBER, MICRO_VERSION_NUMBER );
//		}
//
//		if( b )
//		{
//			pref.putLong( PREF_KEY_DATE, System.currentTimeMillis() );
//			pref.putInt( PREF_KEY_MAJOR_VERSION_NUMBER, MAJOR_VERSION_NUMBER );
//			pref.putInt( PREF_KEY_MINOR_VERSION_NUMBER, MINOR_VERSION_NUMBER );
//			pref.putInt( PREF_KEY_MICRO_VERSION_NUMBER, MICRO_VERSION_NUMBER );
//		}
	}




	/**
	 * Check whether to do auto-upgrade.
	 * @return whether to do auto-upgrade
	 */
	private boolean checkDate()
	{
		Preferences pref = Preferences.userNodeForPackage( this.getClass() );
		final long time = pref.getLong( PREF_KEY_DATE, 0 );
		final long current = System.currentTimeMillis();
		final long diff = current - time;

		final long day = 1000*3600*24;
		final long week = 7*day;
		final long month = 30*day;
		final int cycle = pref.getInt( PREF_KEY_UPGRADE_CYCLE, UPGRADE_EVERY_TIME );

		boolean b;
		switch( cycle )
		{
			case NO_UPGRADE :
			{
				b = false;
				break;
			}

			case UPGRADE_EVERY_TIME :
			{
				b = true;
				break;
			}

			case UPGRADE_EVERY_DAY :
			{
				b = ( diff > day );
				break;
			}

			case UPGRADE_EVERY_WEEK :
			{
				b = ( diff > week );
				break;
			}

			case UPGRADE_EVERY_MONTH :
			{
				b = ( diff > month );
				break;
			}

			default :
			{
				b = false;
			}
		}

		return b;
	}




	/**
	 * Create instances of the figure elements.
	 */
	private boolean loadFigureElementClass()
		throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException
	{

		// open the file
		FileInputStream fis = null;

		try
		{
			try
			{
				fis = new FileInputStream( new File("ListOfFigureElement.txt") );
			}
			catch( FileNotFoundException ex )
			{
				// If the file is not found, create instances of the default class.
				this.mClassOfAxisElement = Class.forName(DEFAULT_CLASS_NAME_OF_AXIS_ELEMENT);
				this.mClassOfSXYGraphElement = Class.forName(DEFAULT_CLASS_NAME_OF_SXY_GRAPH_ELEMENT);
				this.mClassOfVXYGraphElement = Class.forName(DEFAULT_CLASS_NAME_OF_VXY_GRAPH_ELEMENT);
				this.mClassOfStringElement = Class.forName(DEFAULT_CLASS_NAME_OF_STRING_ELEMENT);
				this.mClassOfLegendElement = Class.forName(DEFAULT_CLASS_NAME_OF_LEGEND_ELEMENT);
				this.mClassOfAxisBreakElement = Class.forName(DEFAULT_CLASS_NAME_OF_AXIS_BREAK_ELEMENT);
				this.mClassOfSignificantDifferenceElement = Class.forName(DEFAULT_CLASS_NAME_OF_SIGNIFICANT_DIFFERENCE_ELEMENT);
				this.mClassOfTimingLineElement = Class.forName(DEFAULT_CLASS_NAME_OF_TIMING_LINE_ELEMENT);
				this.mClassOfGridElement = Class.forName(DEFAULT_CLASS_NAME_OF_GRID_ELEMENT);
				this.mClassOfShapeElement = Class.forName(DEFAULT_CLASS_NAME_OF_SHAPE_ELEMENT);
				return true;
			}


			// load properties
			Properties p = new Properties();
			p.load(fis);


			//
			// get class objects
			//

			Class cl = null;


			// SGAxisElement
			cl = this.getClassObject(p,"SGAxisElement",SGIAxisElement.class);
			if( cl==null )
			{
				return false;
			}
			this.mClassOfAxisElement = cl;


			// SGSXYGraphElement
			cl = this.getClassObject(p,"SGSXYGraphElement",SGIGraphElement.class);
			if( cl==null )
			{
				return false;
			}
			this.mClassOfSXYGraphElement = cl;


			// SGVXYGraphElement
			cl = this.getClassObject(p,"SGVXYGraphElement",SGIGraphElement.class);
			if( cl==null )
			{
				return false;
			}
			this.mClassOfVXYGraphElement = cl;


			// SGLegendElement
			cl = this.getClassObject(p,"SGLegendElement",SGILegendElement.class);
			if( cl==null )
			{
				return false;
			}
			this.mClassOfLegendElement = cl;


			// SGStringElement
			cl = this.getClassObject(p,"SGStringElement",SGIStringElement.class);
			if( cl==null )
			{
				return false;
			}
			this.mClassOfStringElement = cl;


			// SGAxisBreakElement
			cl = this.getClassObject(p,"SGAxisBreakElement",SGIAxisBreakElement.class);
			if( cl==null )
			{
				return false;
			}
			this.mClassOfAxisBreakElement = cl;


			// SGSignificantDifferenceElement
			cl = this.getClassObject(p,"SGSignificantDifferenceElement",SGISignificantDifferenceElement.class);
			if( cl==null )
			{
				return false;
			}
			this.mClassOfSignificantDifferenceElement = cl;


			// SGTimingLineElement
			cl = this.getClassObject(p,"SGTimingLineElement",SGITimingLineElement.class);
			if( cl==null )
			{
				return false;
			}
			this.mClassOfTimingLineElement = cl;


			// SGGridElement
			cl = this.getClassObject(p,"SGGridElement",SGIGridElement.class);
			if( cl==null )
			{
				return false;
			}
			this.mClassOfGridElement = cl;


			// SGShapeElement
			cl = this.getClassObject(p,"SGShapeElement",SGIShapeElement.class);
			if( cl==null )
			{
				return false;
			}
			this.mClassOfShapeElement = cl;

		}
		finally
		{
			if( fis!=null )
			{
				fis.close();
			}
		}

		return true;
	}



	private Class getClassObject( Properties p, String key, Class supercls )
		throws ClassNotFoundException
	{
		String name = p.getProperty(key);
		if( name==null )
		{
			return null;
		}
		Class cl = Class.forName(name);
		if( supercls.isAssignableFrom(cl) == false )
		{
			return null;
		}

		return cl;
	}


	// returns a string of "true" or "false"
	private String getBooleanString( final String value )
	{
		final String sTrue = Boolean.TRUE.toString();
		final String sFalse = Boolean.FALSE.toString();
		Number num = SGUtilityText.getInteger(value);

		String ret = null;
		if( num!=null )
		{
			ret = ( value.equals("0") ? sTrue : sFalse );
		}
		else
		{
			final String str = value.toLowerCase();
			if( str.equals( sTrue ) )
			{
			   ret = sTrue;
			}
			else if( str.equals( sFalse ) )
			{
			   ret = sFalse;
			}
		}

		return ret;
	}



	/**
	 * Execute a command.
	 * @param line - the command line
	 * @return
	 */
	public int exec( final String line )
	{
//System.out.println(line);

		int ret;
		SGDrawingWindow aWnd = this.mActiveWindow;
		SGFigure aFig = this.mActiveFigure;

		ArrayList argsList = new ArrayList();
		final String command = this.parseCommand( line, argsList );
		if( command == null )
		{
			return FAILED;
		}
		final int argn = argsList.size();


		// basic commands
		ret = this.execBasicCommand( command, argsList );
		if( ret!= NOT_FOUND )
		{
			return ret;
		}


		// commands in the menu-bar
		ret = this.execMenuBarCommand( command, argsList );
		if( ret!= NOT_FOUND )
		{
			return ret;
		}


		// set Window properties
		ret = this.setWindowProperties( command, aWnd, argsList );
		if( ret!= NOT_FOUND )
		{
			return ret;
		}


		// set Figure properties
		ret = this.setFigureProperties( command, aFig, argsList );
		if( ret!= NOT_FOUND )
		{
			return ret;
		}


		// set Figure Element properties
		ret = this.setFigureElementProperties( command, aFig, argsList );
		if( ret!= NOT_FOUND )
		{
			return ret;
		}

//System.out.println(command);
//System.out.println(argsList);
//System.out.println();

		return NOT_FOUND;
	}


	// execute the basic command
	private int execBasicCommand(
		final String command, final ArrayList argsList )
	{
		final int argn = argsList.size();
		final SGDrawingWindow aWnd = this.mActiveWindow;

		int ret;

		if( command.equals( COM_CHWIN ) )
		{
			if( argn<1 )
			{
				return FAILED;
			}

			// window id
			String str = (String)argsList.get(0);
			Number num = SGUtilityText.getInteger(str);
			if( num==null )
			{
				return FAILED;
			}
			final int id = num.intValue();

			// set the active window
			SGDrawingWindow wnd = this.getWindow(id);
			if( wnd==null )
			{
				return FAILED;
			}
			this.mActiveWindow = wnd;

			return SUCCEEDED;
		}
		else if( command.equals( COM_CHFIG ) )
		{
			if( argn!=1 )
			{
				return FAILED;
			}
			if( aWnd==null )
			{
				return FAILED;
			}
			
			// figure id
			String str = (String)argsList.get(0);
			Number num = SGUtilityText.getInteger(str);
			if( num==null )
			{
				return FAILED;
			}
			final int id = num.intValue();

			SGFigure fig = aWnd.getFigure(id);
			if( fig==null )
			{
				return FAILED;
			}
			this.mActiveFigure = fig;

			return SUCCEEDED;
		}
		else if( command.equals( COM_SELECT_FIGURE ) )
		{
			if( argn<1 )
			{
				return FAILED;
			}
			if( aWnd==null )
			{
				return FAILED;
			}

			final int[] idArray = new int[argsList.size()];
			for( int ii=0; ii<argsList.size(); ii++ )
			{
				String str = (String)argsList.get(ii);
				Number num = SGUtilityText.getInteger(str);
				if( num==null )
				{
					return -1;
				}
				idArray[ii] = num.intValue();
			}

			aWnd.setSelectedFigure( idArray );

			return SUCCEEDED;
		}
		// tree
		else if( command.equals( COM_TREE ) )
		{
			if( aWnd==null )
			{
				return FAILED;
			}

			StringBuffer sb = new StringBuffer();
			aWnd.createTree(sb);
			
			System.out.println(sb);
			
			return SUCCEEDED;
		}
		// zoom
		else if( command.equals( COM_ZOOM ) )
		{
			if( argn<1 )
			{
				return FAILED;
			}
			if( aWnd==null )
			{
				return FAILED;
			}

			String str = (String)argsList.get(0);
			final Number num = SGUtilityText.getDouble(str);
			if( num==null )
			{
				return FAILED;
			}
			
			if( aWnd.setZoomValue( num ) == false )
			{
				return FAILED;
			}
			return SUCCEEDED;
		}

		return NOT_FOUND;
	}


	// commands in the menu-bar
	private int execMenuBarCommand(
		final String command, final ArrayList argsList )
	{
		int ret;

		// File
		ret = this.execMenuBarCommandFile( command, argsList );
		if( ret!= NOT_FOUND )
		{
			return ret;
		}

		// Edit
		ret = this.execMenuBarCommandEdit( command, argsList );
		if( ret!= NOT_FOUND )
		{
			return ret;
		}

		// Insert
		ret = this.execMenuBarCommandInsert( command, argsList );
		if( ret!= NOT_FOUND )
		{
			return ret;
		}

		// Layout
		ret = this.execMenuBarCommandLayout( command, argsList );
		if( ret!= NOT_FOUND )
		{
			return ret;
		}

		return NOT_FOUND;
	}


	// commands in the menu-bar File
	private int execMenuBarCommandFile(
		final String command, final ArrayList argsList )
	{
		final int argn = argsList.size();
		final SGDrawingWindow aWnd = this.mActiveWindow;

		// Create New Window
		if( command.equals( COM_WIN_OPEN ) )
		{
			// create a new window
			SGDrawingWindow wnd = this.createNewWindow();
			if( wnd==null )
			{
				return FAILED;
			}
			wnd.setVisible(true);

			return SUCCEEDED;
		}
		// Close Window
		else if( command.equals( COM_WIN_CLOSE ) )
		{
			if( argn==0 )
			{
				if( aWnd!=null )
				{
					this.closeWindow( aWnd );
				}
			}
			else if( argn==1 )
			{
				// window id
				String str = (String)argsList.get(0);
				Number num = SGUtilityText.getInteger(str);
				if( num==null )
				{
					return FAILED;
				}
				final int id = num.intValue();

				// close
				this.closeWindow(id);
			}
			else
			{
				return FAILED;
			}

			return SUCCEEDED;
		}
		// Draw Graph
		else if( command.equals( COM_DRAW_GRAPH ) )
		{
			if( argn<3 )
			{
				return FAILED;
			}
			if( aWnd==null )
			{
				return FAILED;
			}
			String str1 = (String)argsList.get(0);	// figure id
			String str2 = (String)argsList.get(1);	// file path
			String str3 = (String)argsList.get(2);	// data type

			// figure id
			Number num = SGUtilityText.getInteger(str1);
			if( num==null )
			{
				return FAILED;
			}
			final int fid = num.intValue();

			// file path
			final String pathName = str2;
			File f = new File( pathName );
			if( f.exists() == false )
			{
				return FAILED;
			}
			
			// data type
			final String dataType = str3;

			// create info list
			ArrayList infoList = new ArrayList();
			infoList.add( dataType );
			if( dataType.equals( SGDataTypeConstants.SXY_SAMPLING_DATA ) )
			{
				if( argsList.size() < 4 )
				{
					return FAILED;
				}
				String str4 = (String)argsList.get(3);
				Number samplingRate = SGUtilityText.getDouble(str4);
				if( samplingRate==null )
				{
					return FAILED;
				}
				infoList.add( samplingRate );
			}

			// draw the graph
			if( this.drawGraph( aWnd, fid, infoList, pathName, false ) == false )
			{
				return FAILED;
			}

			return SUCCEEDED;
		}
		// load property
		else if( command.equals( COM_LOAD_PROPERTY ) )
		{
			if( argn<1 )
			{
				return FAILED;
			}
			if( aWnd==null )
			{
				return FAILED;
			}
			String str1 = (String)argsList.get(0);	// file path

			File file = new File(str1);
			if( file.exists()==false )
			{
				return FAILED;
			}
			String path = SGUtility.getCanonicalPath( file.getPath() );
			if( path==null )
			{
				return FAILED;
			}

			// check validity of the file
			URL url = null;
			try
			{
				url = file.toURL();
			}
			catch( MalformedURLException ex )
			{
				return FAILED;
			}

			// create a Document object
			Document doc = SGUtilityText.getDocument( url );
			if( doc==null )
			{
				return FAILED;
			}

			//
			Element elWnd = this.getWindowElement( doc );
			NodeList nListFigure = elWnd.getElementsByTagName( SGFigure.TAG_NAME_FIGURE );
			final int figureNum = nListFigure.getLength();
			int cnt = 0;
			final int[] dataNumArray = new int[figureNum];
			for( int ii=0; ii<figureNum; ii++ )
			{
				Node node = nListFigure.item(ii);
				if( ( node instanceof Element ) == false )
				{
					return FAILED;
				}
				Element elFigure = (Element)node;
				NodeList nListData = elFigure.getElementsByTagName( SGIGraphElement.TAG_NAME_DATA );
				dataNumArray[ii] = nListData.getLength();
				cnt += dataNumArray[ii];
			}
			if( cnt!=argn-1 )
			{
				return FAILED;
			}
			
			// list of path-names of data files
			ArrayList pathList = new ArrayList( argsList.subList( 1, argn ) );

			// create a data map
			Map dataMap = new TreeMap();
			cnt = 0;
			for( int ii=0; ii<figureNum; ii++ )
			{
				final int dataNum = dataNumArray[ii];
				ArrayList dataList = new ArrayList();
				for( int jj=0; jj<dataNum; jj++ )
				{
					dataList.add( pathList.get(cnt+jj) );
				}
				dataMap.put( new Integer(ii), dataList );
				cnt+=dataNum;
			}

			// set properties
			if( this.setPropertyFile( aWnd, doc, dataMap ) == false )
			{
				return FAILED;
			}

			return SUCCEEDED;
		}
		// save property
		else if( command.equals( COM_SAVE_PROPERTY ) )
		{
			if( argn<1 )
			{
				return FAILED;
			}
			if( aWnd==null )
			{
				return FAILED;
			}
			if( aWnd.getVisibleFigureList().size()==0 )
			{
				return FAILED;
			}
			String str1 = (String)argsList.get(0);	// path

			final int ret = this.saveProperties( aWnd, str1 );
			aWnd.setSaved( ret == OK_OPTION );

			return SUCCEEDED;
		}
		// load data set
		else if( command.equals( COM_LOAD_DATA_SET ) )
		{
			if( argn<1 )
			{
				return FAILED;
			}
			if( aWnd==null )
			{
				return FAILED;
			}
			String str1 = (String)argsList.get(0);	// path
			File file = new File(str1);
			if( file.exists()==false )
			{
				return FAILED;
			}

			if( this.loadDataSet( aWnd, file ) == -1 )
			{
				return FAILED;
			}

			return SUCCEEDED;
		}
		// save data set
		else if( command.equals( COM_SAVE_DATA_SET ) )
		{
			if( argn<1 )
			{
				return FAILED;
			}
			if( aWnd==null )
			{
				return FAILED;
			}
			if( aWnd.getVisibleFigureList().size()==0 )
			{
				return FAILED;
			}
			String str1 = (String)argsList.get(0);	// path
			final int ret = this.saveDataSet( aWnd, str1 );
			aWnd.setSaved( ret == OK_OPTION );

			return SUCCEEDED;
		}
		// load background image
		else if( command.equals( COM_LOAD_IMAGE ) )
		{
			if( argn<1 )
			{
				return FAILED;
			}
			if( aWnd==null )
			{
				return FAILED;
			}
			String str1 = (String)argsList.get(0);	// path
			if( this.setImage( str1, aWnd ) == false )
			{
				return FAILED;
			}

			return SUCCEEDED;
		}
		// export as image
		else if( command.equals( COM_EXPORT_AS_IMAGE ) )
		{
			if( argn<2 )
			{
				return FAILED;
			}
			if( aWnd==null )
			{
				return FAILED;
			}

			String str0 = (String)argsList.get(0);	// type
			String str1 = (String)argsList.get(1);	// path

			Properties p = new Properties();
			for( int ii=2; ii<argn; ii++ )
			{
				String str = (String)argsList.get(ii);
				if( this.getProperties( str, p ) == false )
				{
					return FAILED;
				}
			}

			aWnd.startExport();

			Component target = aWnd.getExportTarget();

			if( this.mImageFileCreator.export(
				target,
				target.getWidth(),
				target.getHeight(),
				str0,
				str1,
				p
				) == false )
			{
				aWnd.endExport();
				return FAILED;
			}

			aWnd.endExport();

			return SUCCEEDED;
		}
		// print
		else if( command.equals( COM_PRINT ) )
		{
			if( argn!=0 )
			{
				return FAILED;
			}
			if( aWnd==null )
			{
				return FAILED;
			}

			// print in the silent mode
			if( aWnd.printImage( true ) == false )
			{
				return FAILED;
			}
			
			return SUCCEEDED;
		}
		// exit
		else if( command.equals( COM_EXIT ) )
		{
			if( argn!=0 )
			{
				return FAILED;
			}
			this.exit();

			return SUCCEEDED;
		}

		return NOT_FOUND;
	}


	private boolean getProperties(
		final String str, final Properties p )
	{
		final int index = str.indexOf("=");
		if( index==-1 | index==0 | index==str.length()-1 )
		{
			return false;
		}

		final String back = str.substring( 0, index );
		final String front = str.substring( index+1, str.length() );
		p.setProperty( back, front );

		return true;
	}



	// commands in the menu-bar Edit
	private int execMenuBarCommandEdit(
		final String command, final ArrayList argsList )
	{
		final int argn = argsList.size();
		final SGDrawingWindow aWnd = this.mActiveWindow;

		// Undo
		if( command.equals( COM_UNDO ) )
		{
			if( aWnd==null )
			{
				return FAILED;
			}
			aWnd.undo();
			aWnd.repaintContentPane();
			return SUCCEEDED;
		}
		// Redo
		else if( command.equals( COM_REDO ) )
		{
			if( aWnd==null )
			{
				return FAILED;
			}
			aWnd.redo();
			aWnd.repaintContentPane();
			return SUCCEEDED;
		}
		// clear undo buffer
		else if( command.equals( COM_CLEAR_UNDO_BUFFER ) )
		{
			aWnd.clearUndoBuffer();
			return SUCCEEDED;
		}
		// Cut
		else if( command.equals( COM_CUT ) )
		{
			aWnd.doCut();
			return SUCCEEDED;
		}
		// Copy
		else if( command.equals( COM_COPY ) )
		{
			aWnd.doCopy();
			return SUCCEEDED;
		}
		// Paste
		else if( command.equals( COM_PASTE ) )
		{
			aWnd.doPaste();
			return SUCCEEDED;
		}
		// Delete
		else if( command.equals( COM_DELETE ) )
		{
			aWnd.doDelete();
			return SUCCEEDED;
		}
		// Duplicate
		else if( command.equals( COM_DUPLICATE ) )
		{
			aWnd.doDuplicate();
			return SUCCEEDED;
		}
		// Delete Background Image
		else if( command.equals( COM_DELETE_IMAGE) )
		{
			if( aWnd.deleteImage() == false )
			{
				return FAILED;
			}
			return SUCCEEDED;
		}

		return NOT_FOUND;
	}


	/**
	 * 
	 * @param value
	 * @return
	 */
	private Number getNumber(
		final String value, final StringBuffer u )
	{
		return SGUtilityText.getNumber( value, u );
	}


	// commands in the menu-bar Insert
	private int execMenuBarCommandInsert(
		final String command, final ArrayList argsList )
	{
		final SGFigure aFig = this.mActiveFigure;
		if( aFig==null )
		{
			return NOT_FOUND;
		}
		final int argn = argsList.size();

		if( command.equals( COM_INSERT_LABEL ) )
		{
			if( argn==1 )
			{
				String str1 = (String)argsList.get(0);
				if( str1.length()==0 )
				{
					return FAILED;
				}
				aFig.addString(0,0,str1);
			}
			else if( argn==3 )
			{
				String str1 = (String)argsList.get(0);
				String str2 = (String)argsList.get(1);
				String str3 = (String)argsList.get(2);

				StringBuffer unit1 = new StringBuffer();
				StringBuffer unit2 = new StringBuffer();

				Number nx = this.getNumber(str1,unit1);
				if( nx==null )
				{
					return FAILED;
				}
				Number ny = this.getNumber(str2,unit2);
				if( ny==null )
				{
					return FAILED;
				}

				final double nxPt = SGUtilityText.convertToPoint( nx.doubleValue(), unit1.toString() );
				final double nyPt = SGUtilityText.convertToPoint( ny.doubleValue(), unit2.toString() );

				final double x = aFig.getFigureX() + nxPt;
				final double y = aFig.getFigureY() + nyPt;
				aFig.addString( (int)x, (int)y, str3 );
			}
			else
			{
				return FAILED;
			}

			return SUCCEEDED;
		}
		else if(
			command.equals( COM_INSERT_AXIS_BREAK )
			| command.equals( COM_INSERT_SIGNIFICANT_DIFFERENCE )
			| command.equals( COM_INSERT_RECTANGLE )
			| command.equals( COM_INSERT_ELLIPSE )
			| command.equals( COM_INSERT_ARROW )
			| command.equals( COM_INSERT_LINE )
			| command.equals( COM_INSERT_TIMING_LINE ) )
		{
			if( argn==2 )
			{
				String str1 = (String)argsList.get(0);
				String str2 = (String)argsList.get(1);

				StringBuffer unit1 = new StringBuffer();
				StringBuffer unit2 = new StringBuffer();

				Number nx = this.getNumber(str1,unit1);
				if( nx==null )
				{
					return FAILED;
				}
				Number ny = this.getNumber(str2,unit2);
				if( ny==null )
				{
					return FAILED;
				}

				final double nxPt = SGUtilityText.convertToPoint( nx.doubleValue(), unit1.toString() );
				final double nyPt = SGUtilityText.convertToPoint( ny.doubleValue(), unit2.toString() );

				final float mag = aFig.getMagnification();
				final int x = (int)( aFig.getGraphRectX() + mag*nxPt );
				final int y = (int)( aFig.getGraphRectY() + mag*nyPt );

				if( command.equals( COM_INSERT_AXIS_BREAK ) )
				{
					aFig.addAxisBreakSymbol(x,y);
				}
				else if( command.equals( COM_INSERT_SIGNIFICANT_DIFFERENCE ) )
				{
					aFig.addSignificantDifferenceSymbol(x,y);
				}
				else if( command.equals( COM_INSERT_TIMING_LINE ) )
				{
					aFig.addTimingLine( x, y );
				}
				else if( command.equals( COM_INSERT_RECTANGLE ) )
				{
					aFig.addShape( SGIShapeElement.RECTANGLE, x, y );
				}
				else if( command.equals( COM_INSERT_ELLIPSE ) )
				{
					aFig.addShape( SGIShapeElement.ELLIPSE, x, y );
				}
				else if( command.equals( COM_INSERT_ARROW ) )
				{
					aFig.addShape( SGIShapeElement.ARROW, x, y );
				}
				else if( command.equals( COM_INSERT_LINE ) )
				{
					aFig.addShape( SGIShapeElement.LINE, x, y );
				}
				
				aFig.repaint();
			}
			else
			{
				return FAILED;
			}

			return SUCCEEDED;
		}

		return NOT_FOUND;
	}


	// commands in the menu-bar Layout
	private int execMenuBarCommandLayout(
		final String command, final ArrayList argsList )
	{
		final int argn = argsList.size();
		final SGDrawingWindow aWnd = this.mActiveWindow;
		if( aWnd==null )
		{
			return FAILED;
		}

		if( command.equals( COM_PAPER_ALIGNMENT ) )
		{
			return SUCCEEDED;
		}
		else if( command.equals( COM_PAPER_BOUNDING_BOX ) )
		{
			if( aWnd.setBoundingBox() == false )
			{
				return FAILED;
			}
			return SUCCEEDED;
		}
//		else if( command.equals( COM_TOOL_BAR_VISIBLE ) )
//		{
//			return SUCCEEDED;
//		}
//		else if( command.equals( COM_GRID_PLUS ) )
//		{
//			return SUCCEEDED;
//		}
//		else if( command.equals( COM_GRID_MINUS ) )
//		{
//			return SUCCEEDED;
//		}
//		else if( command.equals( COM_SNAP_TO_GRID ) )
//		{
//			return SUCCEEDED;
//		}
//		else if( command.equals( COM_ZOOM_IN ) )
//		{
//			return SUCCEEDED;
//		}
//		else if( command.equals( COM_ZOOM_OUT ) )
//		{
//			return SUCCEEDED;
//		}
//		else if( command.equals( COM_DEFAULT_ZOOM ) )
//		{
//			return SUCCEEDED;
//		}
//		else if( command.equals( COM_ZOOM_WAY_OUT ) )
//		{
//			return SUCCEEDED;
//		}
		else if( command.equals( COM_AUTO_ARRANGEMENT ) )
		{
			if( aWnd.alignFigures() == false )
			{
				return FAILED;
			}
			return SUCCEEDED;
		}
		else if( command.equals( COM_AUTO_ZOOM ) )
		{
			if( argn<1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			Boolean b = SGUtilityText.getBoolean( this.getBooleanString(str) );
			if( b==null )
			{
				return FAILED;
			}
			aWnd.setAutoZoom( b.booleanValue() );
			return SUCCEEDED;
		}
		else if( command.equals( COM_LOCK_FIGURE ) )
		{
			if( argn<1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			Boolean b = SGUtilityText.getBoolean( this.getBooleanString(str) );
			if( b==null )
			{
				return FAILED;
			}
			aWnd.setLocked( b.booleanValue() );
			return SUCCEEDED;
		}

		return NOT_FOUND;
	}


	// set the properties of a window
	private int setWindowProperties(
		final String command, final SGDrawingWindow wnd, final ArrayList argsList )
	{
		final String[] keys = {
			COM_PAPER_WIDTH,
			COM_PAPER_HEIGHT,
			COM_PAPER_SIZE,
			COM_WINDOW_GRID_INTERVAL,
			COM_WINDOW_GRID_LINE_WIDTH,
			COM_WINDOW_GRID_VISIBLE,
			COM_WINDOW_GRID_COLOR,
			COM_WINDOW_BACKGROUND_COLOR,
			COM_IMAGE_X,
			COM_IMAGE_Y,
			COM_IMAGE_SCALING_FACTOR,
			COM_CUT_FIGURE,
			COM_COPY_FIGURE,
			COM_PASTE_FIGURE,
			COM_DELETE_FIGURE,
			COM_DUPLICATE_FIGURE,
			COM_MOVE_TO_FRONT_FIGURE,
			COM_MOVE_TO_BACK_FIGURE
		};
		if( this.contains( keys, command ) == false )
		{
			return NOT_FOUND;
		}

		if( wnd==null )
		{
			return FAILED;
		}

		final int argn = argsList.size();

		if( command.equals( COM_PAPER_WIDTH ) )
		{
			if( argn!=1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			StringBuffer unit = new StringBuffer();
			Number num = this.getNumber( str, unit );
			if( num==null )
			{
				return FAILED;
			}
			if( wnd.setPaperWidthDirectly( num.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_PAPER_HEIGHT ) )
		{
			if( argn!=1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			StringBuffer unit = new StringBuffer();
			Number num = this.getNumber( str, unit );
			if( num==null )
			{
				return FAILED;
			}
			if( wnd.setPaperHeightDirectly( num.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_PAPER_SIZE ) )
		{
			if( argn==1 )
			{
				String str1 = (String)argsList.get(0);
				MediaSize size = SGUtilityText.getMediaSize(str1);
				if( size==null )
				{
					return FAILED;
				}
				if( wnd.setPaperSizeDirectly( size ) == false )
				{
					return FAILED;
				}
			}
			else if( argn==2 )
			{
				String str1 = (String)argsList.get(0);
				StringBuffer unit1 = new StringBuffer();
				Number num1 = this.getNumber( str1, unit1 );
				if( num1==null )
				{
					return FAILED;
				}
				String str2 = (String)argsList.get(1);
				StringBuffer unit2 = new StringBuffer();
				Number num2 = this.getNumber( str2, unit2 );
				if( num2==null )
				{
					return FAILED;
				}
				if( wnd.setPaperSizeDirectly(
					num1.floatValue(), unit1.toString(), num2.floatValue(), unit2.toString() ) == false )
				{
					return FAILED;
				}
			}
		}
		else if( command.equals( COM_WINDOW_GRID_INTERVAL ) )
		{
			if( argn!=1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			StringBuffer unit = new StringBuffer();
			Number num = this.getNumber( str, unit );
			if( num==null )
			{
				return FAILED;
			}
			if( wnd.setGridLineIntervalDirectly( num.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_WINDOW_GRID_LINE_WIDTH ) )
		{
			if( argn!=1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			StringBuffer unit = new StringBuffer();
			Number num = this.getNumber( str, unit );
			if( num==null )
			{
				return FAILED;
			}
			if( wnd.setGridLineWidthDirectly( num.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_WINDOW_GRID_VISIBLE ) )
		{
			if( argn!=1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			String s = this.getBooleanString( str );
			if( s==null )
			{
				return FAILED;
			}
			Boolean b = Boolean.valueOf(s);
			if( wnd.setGridLineVisibleDirectly( b.booleanValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_WINDOW_GRID_COLOR ) )
		{
			if( argn==1 )
			{
				String str = (String)argsList.get(0);
				final Color cl = SGUtilityText.getColor(str);
				if( cl==null )
				{
					return FAILED;
				}
				if( wnd.setGridLineColorDirectly(cl) == false )
				{
					return FAILED;
				}
			}
			else if( argn==3 )
			{
				String str0 = (String)argsList.get(0);
				String str1 = (String)argsList.get(1);
				String str2 = (String)argsList.get(2);
				final Color cl = SGUtilityText.getColor(str0,str1,str2);
				if( cl==null )
				{
					return FAILED;
				}
				if( wnd.setGridLineColorDirectly(cl) == false )
				{
					return FAILED;
				}
			}
			else
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_WINDOW_BACKGROUND_COLOR ) )
		{
			if( argn==1 )
			{
				String str = (String)argsList.get(0);
				final Color cl = SGUtilityText.getColor(str);
				if( cl==null )
				{
					return FAILED;
				}
				if( wnd.setPaperColorDirectly(cl) == false )
				{
					return FAILED;
				}
			}
			else if( argn==3 )
			{
				String str0 = (String)argsList.get(0);
				String str1 = (String)argsList.get(1);
				String str2 = (String)argsList.get(2);
				final Color cl = SGUtilityText.getColor(str0,str1,str2);
				if( cl==null )
				{
					return FAILED;
				}
				if( wnd.setPaperColorDirectly(cl) == false )
				{
					return FAILED;
				}
			}
			else
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_IMAGE_X ) )
		{
			if( argn!=1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			StringBuffer unit = new StringBuffer();
			Number num = this.getNumber( str, unit );
			if( num==null )
			{
				return FAILED;
			}
			if( wnd.setImageLocationXDirectly( num.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_IMAGE_Y ) )
		{
			if( argn!=1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			StringBuffer unit = new StringBuffer();
			Number num = this.getNumber( str, unit );
			if( num==null )
			{
				return FAILED;
			}
			if( wnd.setImageLocationYDirectly( num.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_IMAGE_SCALING_FACTOR ) )
		{
			if( argn!=1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			Number num = SGUtilityText.getFloat(str);
			if( num==null )
			{
				return FAILED;
			}
			if( wnd.setImageScalingFactorDirectly( num.floatValue() ) == false )
			{
				return FAILED;
			}
		}
//		else if( command.equals( COM_CUT_FIGURE ) )
//		{
//			if( argn!=1 )
//			{
//				return FAILED;
//			}
//			String str = (String)argsList.get(0);
//			final Integer num = SGUtilityText.getInteger(str);
//			if( num==null )
//			{
//				return FAILED;
//			}
//			if( wnd.cutOrCopyFigure( num.intValue(), false ) == false )
//			{
//				return FAILED;
//			}
//		}
//		else if( command.equals( COM_COPY_FIGURE ) )
//		{
//			if( argn!=1 )
//			{
//				return FAILED;
//			}
//			String str = (String)argsList.get(0);
//			final Integer num = SGUtilityText.getInteger(str);
//			if( num==null )
//			{
//				return FAILED;
//			}
//			if( wnd.cutOrCopyFigure( num.intValue(), true ) == false )
//			{
//				return FAILED;
//			}
//		}
//		else if( command.equals( COM_PASTE_FIGURE ) )
//		{
//			if( argn!=1 )
//			{
//				return FAILED;
//			}
//			String str = (String)argsList.get(0);
//			final Integer num = SGUtilityText.getInteger(str);
//			if( num==null )
//			{
//				return FAILED;
//			}
//			if( wnd.hideFigure( num.intValue() ) == false )
//			{
//				return FAILED;
//			}
//		}
		else if( command.equals( COM_DELETE_FIGURE ) )
		{
			if( argn!=1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			final Integer num = SGUtilityText.getInteger(str);
			if( num==null )
			{
				return FAILED;
			}
			if( wnd.hideFigure( num.intValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_DUPLICATE_FIGURE ) )
		{
			if( argn!=1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			final Integer num = SGUtilityText.getInteger(str);
			if( num==null )
			{
				return FAILED;
			}
			if( wnd.hideFigure( num.intValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_MOVE_TO_FRONT_FIGURE ) )
		{
			if( argn!=1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			final Integer num = SGUtilityText.getInteger(str);
			if( num==null )
			{
				return FAILED;
			}
			if( wnd.moveFigure( num.intValue(), true ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_MOVE_TO_BACK_FIGURE ) )
		{
			if( argn!=1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			final Integer num = SGUtilityText.getInteger(str);
			if( num==null )
			{
				return FAILED;
			}
			if( wnd.moveFigure( num.intValue(), false ) == false )
			{
				return FAILED;
			}
		}

		return SUCCEEDED;
	}


	// set the properties of a figure
	private int setFigureProperties(
		final String command, final SGFigure fig, final ArrayList argsList )
	{
		if( fig==null )
		{
			return FAILED;
		}

		final String[] keys = {
			COM_FIGURE_X,
			COM_FIGURE_Y,
			COM_FIGURE_WIDTH,
			COM_FIGURE_HEIGHT,
			COM_FIGURE_SPACE_TO_SCALE,
			COM_FIGURE_SPACE_TO_TITLE,
			COM_FIGURE_BACKGROUND_COLOR,
			COM_FIGURE_TRANSPARENT,

			// grid properties
			COM_FIGURE_GRID_AXIS_X,
			COM_FIGURE_GRID_AXIS_Y,
			COM_FIGURE_GRID_VISIBLE,
			COM_FIGURE_GRID_AUTO,
			COM_FIGURE_GRID_STEP_X,
			COM_FIGURE_GRID_STEP_Y,
			COM_FIGURE_GRID_BASE_X,
			COM_FIGURE_GRID_BASE_Y,
			COM_FIGURE_GRID_LINE_WIDTH,
			COM_FIGURE_GRID_LINE_TYPE,
			COM_FIGURE_GRID_LINE_COLOR
		};
		if( this.contains( keys, command ) == false )
		{
			return NOT_FOUND;
		}

		final int argn = argsList.size();
		if( argn<1 )
		{
			return FAILED;
		}
		String str = (String)argsList.get(0);

		if( command.equals( COM_FIGURE_X ) )
		{
			StringBuffer unit = new StringBuffer();
			Number num = this.getNumber( str, unit );
			if( num==null )
			{
				return FAILED;
			}
			if( fig.setFigureXDirectly( num.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_FIGURE_Y ) )
		{
			StringBuffer unit = new StringBuffer();
			Number num = this.getNumber( str, unit );
			if( num==null )
			{
				return FAILED;
			}
			if( fig.setFigureYDirectly( num.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_FIGURE_WIDTH ) )
		{
			StringBuffer unit = new StringBuffer();
			Number num = this.getNumber( str, unit );
			if( num==null )
			{
				return FAILED;
			}
			if( fig.setFigureWidthDirectly( num.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_FIGURE_HEIGHT ) )
		{
			StringBuffer unit = new StringBuffer();
			Number num = this.getNumber( str, unit );
			if( num==null )
			{
				return FAILED;
			}
			if( fig.setFigureHeightDirectly( num.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_FIGURE_SPACE_TO_SCALE ) )
		{
			StringBuffer unit = new StringBuffer();
			Number num = this.getNumber( str, unit );
			if( num==null )
			{
				return FAILED;
			}
			if( fig.setSpaceAxisLineAndNumberDirectly( num.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_FIGURE_SPACE_TO_TITLE ) )
		{
			StringBuffer unit = new StringBuffer();
			Number num = this.getNumber( str, unit );
			if( num==null )
			{
				return FAILED;
			}
			if( fig.setSpaceNumberAndTitleDirectly( num.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_FIGURE_BACKGROUND_COLOR ) )
		{
			if( argn==1 )
			{
				final Color cl = SGUtilityText.getColor(str);
				if( cl==null )
				{
					return FAILED;
				}
				if( fig.setBackgroundColorDirectly(cl) == false )
				{
					return FAILED;
				}
			}
			else if( argn==3 )
			{
				String str0 = str;
				String str1 = (String)argsList.get(1);
				String str2 = (String)argsList.get(2);
				final Color cl = SGUtilityText.getColor(str0,str1,str2);
				if( cl==null )
				{
					return FAILED;
				}
				if( fig.setBackgroundColorDirectly(cl) == false )
				{
					return FAILED;
				}
			}
			else
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_FIGURE_TRANSPARENT ) )
		{
			Boolean b = SGUtilityText.getBoolean( this.getBooleanString( str ) );
			if( fig.setTransparentDirectly( b.booleanValue() ) == false )
			{
				return FAILED;
			}
		}

		if( fig instanceof SGXYFigure )
		{
			SGXYFigure figxy = (SGXYFigure)fig;

			if( command.equals( COM_FIGURE_GRID_AXIS_X ) )
			{
				final int value = this.getAxisLocation( str );
				if( value==-1 )
				{
					return FAILED;
				}
				if( figxy.setXAxisLocationDirectly( value ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_FIGURE_GRID_AXIS_Y ) )
			{
				final int value = this.getAxisLocation( str );
				if( value==-1 )
				{
					return FAILED;
				}
				if( figxy.setYAxisLocationDirectly( value ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_FIGURE_GRID_VISIBLE ) )
			{
				Boolean b = SGUtilityText.getBoolean( this.getBooleanString( str ) );
				if( b==null )
				{
					return FAILED;
				}
				if( figxy.setGridVisibleDirectly( b.booleanValue() ) == false )
				{
					return FAILED;
				} 
			}
			else if( command.equals( COM_FIGURE_GRID_AUTO ) )
			{
				Boolean b = SGUtilityText.getBoolean( this.getBooleanString( str ) );
				if( b==null )
				{
					return FAILED;
				}
				if( figxy.setAutoCalculateRangeDirectly( b.booleanValue() ) == false )
				{
					return FAILED;
				} 
			}
			else if( command.equals( COM_FIGURE_GRID_STEP_X ) )
			{
				Number num = SGUtilityText.getDouble( str );
				if( num==null )
				{
					return FAILED;
				}
				if( figxy.setGridStepValueXDirectly( num.doubleValue() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_FIGURE_GRID_STEP_Y ) )
			{
				Number num = SGUtilityText.getDouble( str );
				if( num==null )
				{
					return FAILED;
				}
				if( figxy.setGridStepValueYDirectly( num.doubleValue() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_FIGURE_GRID_BASE_X ) )
			{
				Number num = SGUtilityText.getDouble( str );
				if( num==null )
				{
					return FAILED;
				}
				if( figxy.setGridBaselineValueXDirectly( num.doubleValue() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_FIGURE_GRID_BASE_Y ) )
			{
				Number num = SGUtilityText.getDouble( str );
				if( num==null )
				{
					return FAILED;
				}
				if( figxy.setGridBaselineValueYDirectly( num.doubleValue() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_FIGURE_GRID_LINE_WIDTH ) )
			{
				StringBuffer unit = new StringBuffer();
				Number num = this.getNumber( str, unit );
				if( num==null )
				{
					return FAILED;
				}
				if( figxy.setGridLineWidthDirectly( num.floatValue(), unit.toString() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_FIGURE_GRID_LINE_TYPE ) )
			{
				final int num = this.getLineType(str);
				if( num==-1 )
				{
					return FAILED;
				}
				if( figxy.setGridLineTypeDirectly( num ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_FIGURE_GRID_LINE_COLOR ) )
			{
				Color cl = null;
				if( argn==1 )
				{
					cl = SGUtilityText.getColor(str);
				}
				else if( argn==3 )
				{
					String str0 = (String)argsList.get(0);
					String str1 = (String)argsList.get(1);
					String str2 = (String)argsList.get(2);
					cl = SGUtilityText.getColor(str0,str1,str2);
				}
				else
				{
					return FAILED;
				}
				if( cl==null )
				{
					return FAILED;
				}
				if( figxy.setGridLineColorDirectly(cl) == false )
				{
					return FAILED;
				}
			}

		}

		return SUCCEEDED;
	}



	// set the properties of SGIFigureElement
	private int setFigureElementProperties(
		final String command, final SGFigure fig, final ArrayList argsList )
	{
		if( fig==null )
		{
			return NOT_FOUND;
		}

		int ret;

		// set Data properties
		SGIGraphElement gElement
			= (SGIGraphElement)fig.getIFigureElement( SGIGraphElement.class );
		if( gElement!=null )
		{
			ret = this.setDataProperties( command, gElement, argsList );
			if( ret!= NOT_FOUND )
			{
				return ret;
			}
		}

		// set Axis properties
		SGIAxisElement aElement
			= (SGIAxisElement)fig.getIFigureElement( SGIAxisElement.class );
		if( aElement!=null )
		{
			ret = this.setAxisProperties( command, aElement, argsList );
			if( ret!= NOT_FOUND )
			{
				return ret;
			}
		}

		// set Legend properties
		SGILegendElement lElement
			= (SGILegendElement)fig.getIFigureElement( SGILegendElement.class );
		if( lElement!=null )
		{
			ret = this.setLegendProperties( command, lElement, argsList );
			if( ret!= NOT_FOUND )
			{
				return ret;
			}
		}

		// set Label properties
		SGIStringElement sElement
			= (SGIStringElement)fig.getIFigureElement( SGIStringElement.class );
		if( sElement!=null )
		{
			ret = this.setLabelProperties( command, sElement, argsList );
			if( ret!= NOT_FOUND )
			{
				return ret;
			}
		}

		// set Significant Difference Symbol properties
		SGISignificantDifferenceElement sdElement
			= (SGISignificantDifferenceElement)fig.getIFigureElement( SGISignificantDifferenceElement.class );
		if( sdElement!=null )
		{
			ret = this.setSigDiffProperties( command, sdElement, argsList );
			if( ret!= NOT_FOUND )
			{
				return ret;
			}
		}

		// set Axis Break Symbol properties
		SGIAxisBreakElement abElement
			= (SGIAxisBreakElement)fig.getIFigureElement( SGIAxisBreakElement.class );
		if( abElement!=null )
		{
			ret = this.setAxisBreakProperties( command, abElement, argsList );
			if( ret!= NOT_FOUND )
			{
				return ret;
			}
		}

		// set Timing Line properties
		SGITimingLineElement tlElement
			= (SGITimingLineElement)fig.getIFigureElement( SGITimingLineElement.class );
		if( tlElement!=null )
		{
			ret = this.setTimingLineProperties( command, tlElement, argsList );
			if( ret!= NOT_FOUND )
			{
				return ret;
			}
		}

		// set Shape properties
		SGIShapeElement shElement
			= (SGIShapeElement)fig.getIFigureElement( SGIShapeElement.class );
		if( shElement!=null )
		{
			ret = this.setShapeProperties( command, shElement, argsList );
			if( ret!= NOT_FOUND )
			{
				return ret;
			}
		}

		return NOT_FOUND;
	}



	// set the properties of Axis
	private int setAxisProperties(
		final String command, final SGIAxisElement el, final ArrayList argsList )
	{

		final String[] keys = {
			// text
			COM_AXIS_FONT,
			COM_AXIS_FONT_NAME,
			COM_AXIS_FONT_STYLE,
			COM_AXIS_FONT_SIZE,
			COM_AXIS_FONT_COLOR,
	
			// frame
			COM_AXIS_FRAME,
			COM_AXIS_FRAME_VISIBLE,
			COM_AXIS_FRAME_LINE_WIDTH,
			COM_AXIS_FRAME_COLOR,
	
			// lines
			COM_AXIS_LINE_WIDTH,
			COM_TICK_MARK_WIDTH,
			COM_TICK_MARK_LENGTH,
			COM_AXIS_LINE_COLOR,
	
			// each axis
			COM_AXIS_VISIBLE,
			COM_AXIS_TITLE_VISIBLE,
			COM_AXIS_TITLE_LABEL,
			COM_AXIS_SCALE_MIN,
			COM_AXIS_SCALE_MAX,
			COM_AXIS_SCALE_TYPE,
			COM_AXIS_TICK_MARK_VISIBLE,
			COM_AXIS_TICK_MARK_AUTO,
			COM_AXIS_TICK_MARK_STEP,
			COM_AXIS_TICK_MARK_BASE,
			COM_AXIS_TICK_MARK_INNER,
			COM_AXIS_FORMAT_VISIBLE,
			COM_AXIS_FORMAT_INTEGER,
			COM_AXIS_FORMAT_EXPONENT_VISIBLE,
			COM_AXIS_FORMAT_EXPONTNE_VALUE,
		};

		if( this.contains( keys, command) == false )
		{
			return NOT_FOUND;
		}

		final int argn = argsList.size();

		if( command.equals( COM_AXIS_FONT_NAME ) )
		{
			String str = (String)argsList.get(0);
			el.setFontNameDirectly( str );
		}
		else if( command.equals( COM_AXIS_FONT_STYLE ) )
		{
			if( argsList.size()<1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			final int style = this.getFontStyle( str );
			if( style==-1 )
			{
				return FAILED;
			}
			if( el.setFontStyleDirectly( style ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_AXIS_FONT_SIZE ) )
		{
			if( argsList.size()<1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			StringBuffer unit = new StringBuffer();
			Number num = this.getNumber( str, unit );
			if( num==null )
			{
				return FAILED;
			}
			if( el.setFontSizeDirectly( num.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_AXIS_FONT_COLOR ) )
		{
			if( argsList.size()==1 )
			{
				String str = (String)argsList.get(0);
				final Color cl = SGUtilityText.getColor(str);
				if( cl==null )
				{
					return FAILED;
				}
				if( el.setFontColorDirectly( cl ) == false )
				{
					return FAILED;
				}
			}
			else if( argsList.size()==3 )
			{
				String str1 = (String)argsList.get(0);
				String str2 = (String)argsList.get(1);
				String str3 = (String)argsList.get(2);
				final Color cl = SGUtilityText.getColor(str1,str2,str3);
				if( cl==null )
				{
					return FAILED;
				}
				if( el.setFontColorDirectly( cl ) == false )
				{
					return FAILED;
				}
			}
			else
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_AXIS_FRAME_VISIBLE ) )
		{
			if( argsList.size()<1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			Boolean b = SGUtilityText.getBoolean( this.getBooleanString(str) );
			if( b==null )
			{
				return FAILED;
			}
			if( el.setFrameVisibleDirectly( b.booleanValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_AXIS_FRAME_LINE_WIDTH ) )
		{
			if( argsList.size()<1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			StringBuffer unit = new StringBuffer();
			Number num = this.getNumber( str, unit );
			if( num==null )
			{
				return FAILED;
			}
			if( el.setFrameLineWidthDirectly( num.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_AXIS_FRAME_COLOR ) )
		{
			if( argsList.size()==1 )
			{
				String str = (String)argsList.get(0);
				final Color cl = SGUtilityText.getColor(str);
				if( cl==null )
				{
					return FAILED;
				}
				if( el.setFrameLineColorDirectly( cl ) == false )
				{
					return FAILED;
				}
			}
			else if( argsList.size()==3 )
			{
				String str1 = (String)argsList.get(0);
				String str2 = (String)argsList.get(1);
				String str3 = (String)argsList.get(2);
				final Color cl = SGUtilityText.getColor(str1,str2,str3);
				if( cl==null )
				{
					return FAILED;
				}
				if( el.setFrameLineColorDirectly(cl) == false )
				{
					return FAILED;
				}
			}
			else
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_AXIS_LINE_WIDTH ) )
		{
			if( argsList.size()<1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			StringBuffer unit = new StringBuffer();
			Number num = this.getNumber( str, unit );
			if( num==null )
			{
				return FAILED;
			}
			if( el.setAxisLineWidthDirectly( num.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_TICK_MARK_WIDTH ) )
		{
			if( argsList.size()<1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			StringBuffer unit = new StringBuffer();
			Number num = this.getNumber( str, unit );
			if( num==null )
			{
				return FAILED;
			}
			if( el.setTickMarkWidthDirectly( num.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_TICK_MARK_LENGTH ) )
		{
			if( argsList.size()<1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			StringBuffer unit = new StringBuffer();
			Number num = this.getNumber( str, unit );
			if( num==null )
			{
				return FAILED;
			}
			if( el.setTickMarkLengthDirectly( num.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_AXIS_LINE_COLOR ) )
		{
			if( argsList.size()==1 )
			{
				String str = (String)argsList.get(0);
				final Color cl = SGUtilityText.getColor(str);
				if( cl==null )
				{
					return FAILED;
				}
				if( el.setLineColorDirectly( cl ) == false )
				{
					return FAILED;
				}
			}
			else if( argsList.size()==3 )
			{
				String str1 = (String)argsList.get(0);
				String str2 = (String)argsList.get(1);
				String str3 = (String)argsList.get(2);
				final Color cl = SGUtilityText.getColor(str1,str2,str3);
				if( cl==null )
				{
					return FAILED;
				}
				if( el.setLineColorDirectly(cl) == false )
				{
					return FAILED;
				}
			}
			else
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_AXIS_VISIBLE ) )
		{
			if( argsList.size()<2 )
			{
				return FAILED;
			}
			String str1 = (String)argsList.get(0);
			String str2 = (String)argsList.get(1);
			Boolean b = SGUtilityText.getBoolean( this.getBooleanString(str2) );
			if( b==null )
			{
				return FAILED;
			}
			if( el.setAxisVisibleDirectly( str1, b.booleanValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_AXIS_TITLE_VISIBLE ) )
		{
			if( argsList.size()<2 )
			{
				return FAILED;
			}
			String str1 = (String)argsList.get(0);
			String str2 = (String)argsList.get(1);
			Boolean b = SGUtilityText.getBoolean( this.getBooleanString(str2) );
			if( b==null )
			{
				return FAILED;
			}
			if( el.setTitleVisibleDirectly( str1, b.booleanValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_AXIS_TITLE_LABEL ) )
		{
			if( argsList.size()<2 )
			{
				return FAILED;
			}
			String str1 = (String)argsList.get(0);
			String str2 = (String)argsList.get(1);
			if( el.setTitleDirectly( str1, str2 ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_AXIS_SCALE_MIN ) )
		{
			if( argsList.size()<2 )
			{
				return FAILED;
			}
			String str1 = (String)argsList.get(0);
			String str2 = (String)argsList.get(1);
			Number num = SGUtilityText.getDouble(str2);
			if( num==null )
			{
				return FAILED;
			}
			if( el.setMinValueDirectly( str1, num.doubleValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_AXIS_SCALE_MAX ) )
		{
			if( argsList.size()<2 )
			{
				return FAILED;
			}
			String str1 = (String)argsList.get(0);
			String str2 = (String)argsList.get(1);
			Number num = SGUtilityText.getDouble(str2);
			if( num==null )
			{
				return FAILED;
			}
			if( el.setMaxValueDirectly( str1, num.doubleValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_AXIS_SCALE_TYPE ) )
		{
			if( argsList.size()<2 )
			{
				return FAILED;
			}
			String str1 = (String)argsList.get(0);
			String str2 = (String)argsList.get(1);
			final int type = this.getScaleType( str2 );
			if( type==-1 )
			{
				return FAILED;
			}
			if( el.setScaleTypeDirectly( str1, type ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_AXIS_TICK_MARK_VISIBLE ) )
		{
			if( argsList.size()<2 )
			{
				return FAILED;
			}
			String str1 = (String)argsList.get(0);
			String str2 = (String)argsList.get(1);
			Boolean b = SGUtilityText.getBoolean( this.getBooleanString(str2) );
			if( b==null )
			{
				return FAILED;
			}
			if( el.setTickMarkVisibleDirectly( str1, b.booleanValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_AXIS_TICK_MARK_AUTO ) )
		{
			if( argsList.size()<2 )
			{
				return FAILED;
			}
			String str1 = (String)argsList.get(0);
			String str2 = (String)argsList.get(1);
			Boolean b = SGUtilityText.getBoolean( this.getBooleanString(str2) );
			if( b==null )
			{
				return FAILED;
			}
			if( el.setTickMarkAutoDirectly( str1, b.booleanValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_AXIS_TICK_MARK_STEP ) )
		{
			if( argsList.size()<2 )
			{
				return FAILED;
			}
			String str1 = (String)argsList.get(0);
			String str2 = (String)argsList.get(1);
			Number num = SGUtilityText.getDouble(str2);
			if( num==null )
			{
				return FAILED;
			}
			if( el.setTickMarkStepDirectly( str1, num.doubleValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_AXIS_TICK_MARK_BASE ) )
		{
			if( argsList.size()<2 )
			{
				return FAILED;
			}
			String str1 = (String)argsList.get(0);
			String str2 = (String)argsList.get(1);
			Number num = SGUtilityText.getDouble(str2);
			if( num==null )
			{
				return FAILED;
			}
			if( el.setTickMarkBaseDirectly( str1, num.doubleValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_AXIS_TICK_MARK_INNER ) )
		{
			if( argsList.size()<2 )
			{
				return FAILED;
			}
			String str1 = (String)argsList.get(0);
			String str2 = (String)argsList.get(1);
			Boolean b = SGUtilityText.getBoolean( this.getBooleanString(str2) );
			if( b==null )
			{
				return FAILED;
			}
			if( el.setTickMarkInnerDirectly( str1, b.booleanValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_AXIS_FORMAT_VISIBLE ) )
		{
			if( argsList.size()<2 )
			{
				return FAILED;
			}
			String str1 = (String)argsList.get(0);
			String str2 = (String)argsList.get(1);
			Boolean b = SGUtilityText.getBoolean( this.getBooleanString(str2) );
			if( b==null )
			{
				return FAILED;
			}
			if( el.setFormatVisibleDirectly( str1, b.booleanValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_AXIS_FORMAT_INTEGER ) )
		{
			if( argsList.size()<2 )
			{
				return FAILED;
			}
			String str1 = (String)argsList.get(0);
			String str2 = (String)argsList.get(1);
			Boolean b = SGUtilityText.getBoolean( this.getBooleanString(str2) );
			if( b==null )
			{
				return FAILED;
			}
			if( el.setFormatIntegerDirectly( str1, b.booleanValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_AXIS_FORMAT_EXPONENT_VISIBLE ) )
		{
			if( argsList.size()<2 )
			{
				return FAILED;
			}
			String str1 = (String)argsList.get(0);
			String str2 = (String)argsList.get(1);
			Boolean b = SGUtilityText.getBoolean( this.getBooleanString(str2) );
			if( b==null )
			{
				return FAILED;
			}
			if( el.setFormatExponentVisibleDirectly( str1, b.booleanValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_AXIS_FORMAT_EXPONTNE_VALUE ) )
		{
			if( argsList.size()<2 )
			{
				return FAILED;
			}
			String str1 = (String)argsList.get(0);
			String str2 = (String)argsList.get(1);
			Number num = SGUtilityText.getInteger( str2 );
			if( num==null )
			{
				return FAILED;
			}
			if( el.setFormatExponentValueDirectly( str1, num.intValue() ) == false )
			{
				return FAILED;
			}
		}

		return SUCCEEDED;
	}


	// returns an integer value for axis location from a string
	private int getAxisLocation( final String location )
	{
		final String str = location.toLowerCase();
		int loc = -1;
		if( SGIAxisElement.AXIS_BOTTOM.toLowerCase().equals(str) )
		{
			loc = SGIAxisElement.AXIS_HORIZONTAL_1;
		}
		else if( SGIAxisElement.AXIS_TOP.toLowerCase().equals(str) )
		{
			loc = SGIAxisElement.AXIS_HORIZONTAL_2;
		}
		else if( SGIAxisElement.AXIS_LEFT.toLowerCase().equals(str) )
		{
			loc = SGIAxisElement.AXIS_PERPENDICULAR_1;
		}
		else if( SGIAxisElement.AXIS_RIGHT.toLowerCase().equals(str) )
		{
			loc = SGIAxisElement.AXIS_PERPENDICULAR_2;
		}

		return loc;
	}


	// returns an integer value for line type from a string
	private int getLineType( final String value )
	{
		Number n = SGUtilityText.getInteger( value );
		if( n!=null )
		{
			final int type = n.intValue();
			if( SGDrawingElementLine.getLineTypeName( type ) !=null )
			{
				return type;
			}
			else
			{
				return -1;
			}
		}
		else
		{
			final String str = value.toLowerCase();
			int type = -1;
			final Integer num = SGDrawingElementLine.getLineTypeFromName(str);
			if( num!=null )
			{
				type = num.intValue();
			}
			return type;
		}
	}


	// returns an integer value for symbol type from a string
	private int getSymbolType( final String value )
	{
		Number n = SGUtilityText.getInteger( value );
		if( n!=null )
		{
			final int type = n.intValue();
			if( SGDrawingElementSymbol.getSymbolTypeName( type ) !=null )
			{
				return type;
			}
			else
			{
				return -1;
			}
		}
		else
		{
			final String str = value.toLowerCase();
			int type = -1;
			final Integer num = SGDrawingElementSymbol.getSymbolTypeFromName(str);
			if( num!=null )
			{
				type = num.intValue();
			}
			return type;
		}
	}


	// returns an integer value for font style from a string
	private int getFontStyle( final String value )
	{
		Number n = SGUtilityText.getInteger( value );
		if( n!=null )
		{
			final int type = n.intValue();
			if( SGUtilityText.getFontStyleName(type)!=null )
			{
				return type;
			}
			else
			{
				return -1;
			}
		}
		else
		{
			final String str = value.toLowerCase();
			final int style = SGUtilityText.getFontStyle(str);
			return style;
		}
	}


	// returns an integer value for scale type from a string
	private int getScaleType( final String value )
	{
		Number n = SGUtilityText.getInteger( value );
		if( n!=null )
		{
			final int type = n.intValue();
			if( SGUtilityText.getScaleTypeName(type)!=null )
			{
				return type;
			}
			else
			{
				return -1;
			}
		}
		else
		{
			final String str = value.toLowerCase();
			final int style = SGUtilityText.getScaleType(str);
			return style;
		}
	}


	// returns an integer value for error bar style from a string
	private int getErrorBarStyle( final String value )
	{
		Number n = SGUtilityText.getInteger( value );
		if( n!=null )
		{
			final int type = n.intValue();
			if( SGDrawingElementErrorBar.getErrorBarStyleName(type)!=null )
			{
				return type;
			}
			else
			{
				return -1;
			}
		}
		else
		{
			final String str = value.toLowerCase();
			int style = -1;
			final Integer num = SGDrawingElementErrorBar.getErrorBarStyleFromName(str);
			if( num!=null )
			{
				style = num.intValue();
			}
			return style;
		}
	}


	// set the properties of Legend
	private int setLegendProperties(
		final String command, final SGILegendElement el, final ArrayList argsList )
	{
		final String[] keys = {
			COM_LEGEND_AXIS_X,
			COM_LEGEND_AXIS_Y,
			COM_LEGEND_LOCATION_X,
			COM_LEGEND_LOCATION_Y,
			COM_LEGEND_VISIBLE,
			COM_LEGEND_FONT_NAME,
			COM_LEGEND_FONT_STYLE,
			COM_LEGEND_FONT_SIZE,
			COM_LEGEND_FONT_COLOR,
			COM_LEGEND_FRAME_VISIBLE,
			COM_LEGEND_FRAME_LINE_WIDTH,
			COM_LEGEND_FRAME_COLOR,
			COM_LEGEND_BACKGROUND_TRANSPARENT,
			COM_LEGEND_BACKGROUND_COLOR,
			COM_LEGEND_SYMBOL_SPAN
		};
		if( this.contains( keys, command ) == false )
		{
			return NOT_FOUND;
		}
		
		final int argn = argsList.size();

		if( command.equals( COM_LEGEND_AXIS_X ) )
		{
			if( argsList.size()<1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			final int loc = this.getAxisLocation( str );
			if( loc==-1 )
			{
				return FAILED;
			}
			if( el.setAxisXDirectly(loc) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_LEGEND_AXIS_Y ) )
		{
			if( argsList.size()<1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			final int loc = this.getAxisLocation( str );
			if( loc==-1 )
			{
				return FAILED;
			}
			if( el.setAxisYDirectly(loc) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_LEGEND_LOCATION_X ) )
		{
			if( argsList.size()<1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			Number num = SGUtilityText.getDouble(str);
			if( num==null )
			{
				return FAILED;
			}
			if( el.setXValueDirectly( num.doubleValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_LEGEND_LOCATION_Y ) )
		{
			if( argsList.size()<1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			Number num = SGUtilityText.getDouble(str);
			if( num==null )
			{
				return FAILED;
			}
			if( el.setYValueDirectly( num.doubleValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_LEGEND_VISIBLE ) )
		{
			if( argsList.size()<1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			Boolean b = SGUtilityText.getBoolean( this.getBooleanString(str) );
			if( b==null )
			{
				return FAILED;
			}
			if( el.setLegendVisibleDirectly( b.booleanValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_LEGEND_FONT_NAME ) )
		{
			if( argsList.size()<1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			if( el.setFontNameDirectly(str) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_LEGEND_FONT_STYLE ) )
		{
			if( argsList.size()<1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			int style = this.getFontStyle( str );
			if( style==-1 )
			{
				return FAILED;
			}
			if( el.setFontStyleDirectly( style ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_LEGEND_FONT_SIZE ) )
		{
			if( argsList.size()<1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			StringBuffer unit = new StringBuffer();
			Number num = this.getNumber( str, unit );
			if( num==null )
			{
				return FAILED;
			}
			if( el.setFontSizeDirectly( num.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_LEGEND_FONT_COLOR ) )
		{
			if( argsList.size()==1 )
			{
				String str = (String)argsList.get(0);
				final Color cl = SGUtilityText.getColor( str );
				if( cl==null )
				{
					return FAILED;
				}
				if( el.setFontColorDirectly( cl ) == false )
				{
					return FAILED;
				}
			}
			else if( argsList.size()==3 )
			{
				String str1 = (String)argsList.get(0);
				String str2 = (String)argsList.get(1);
				String str3 = (String)argsList.get(2);
				final Color cl = SGUtilityText.getColor(str1,str2,str3);
				if( cl==null )
				{
					return FAILED;
				}
				if( el.setFontColorDirectly( cl ) == false )
				{
					return FAILED;
				}
			}
			else
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_LEGEND_FRAME_VISIBLE ) )
		{
			if( argsList.size()<1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			final Boolean b = SGUtilityText.getBoolean( this.getBooleanString(str) );
			if( b==null )
			{
				return FAILED;
			}
			if( el.setFrameVisibleDirectly( b.booleanValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_LEGEND_FRAME_LINE_WIDTH ) )
		{
			if( argsList.size()<1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			StringBuffer unit = new StringBuffer();
			Number num = this.getNumber( str, unit );
			if( num==null )
			{
				return FAILED;
			}
			if( el.setFrameLineWidthDirectly( num.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_LEGEND_FRAME_COLOR ) )
		{
			if( argsList.size()==1 )
			{
				String str = (String)argsList.get(0);
				final Color cl = SGUtilityText.getColor( str );
				if( cl==null )
				{
					return FAILED;
				}
				if( el.setFrameColorDirectly( cl ) == false )
				{
					return FAILED;
				}
			}
			else if( argsList.size()==3 )
			{
				String str1 = (String)argsList.get(0);
				String str2 = (String)argsList.get(1);
				String str3 = (String)argsList.get(2);
				final Color cl = SGUtilityText.getColor( str1, str2, str3 );
				if( cl==null )
				{
					return FAILED;
				}
				if( el.setFrameColorDirectly( cl ) == false )
				{
					return FAILED;
				}
			}
			else
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_LEGEND_BACKGROUND_TRANSPARENT ) )
		{
			if( argsList.size()<1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			Boolean b = SGUtilityText.getBoolean( this.getBooleanString( str ) );
			if( b==null )
			{
				return FAILED;
			}
			if( el.setBackgroundTransparentDirectly( b.booleanValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_LEGEND_BACKGROUND_COLOR ) )
		{
			if( argsList.size()==1 )
			{
				String str = (String)argsList.get(0);
				final Color cl = SGUtilityText.getColor( str );
				if( cl==null )
				{
					return FAILED;
				}
				if( el.setBackgroundColorDirectly( cl ) == false )
				{
					return FAILED;
				}
			}
			else if( argsList.size()==3 )
			{
				String str1 = (String)argsList.get(0);
				String str2 = (String)argsList.get(1);
				String str3 = (String)argsList.get(2);
				final Color cl = SGUtilityText.getColor(str1,str2,str3);
				if( cl==null )
				{
					return FAILED;
				}
				if( el.setBackgroundColorDirectly(cl) == false )
				{
					return FAILED;
				}
			}
			else
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_LEGEND_SYMBOL_SPAN ) )
		{
			if( argsList.size()<1 )
			{
				return FAILED;
			}
			String str = (String)argsList.get(0);
			StringBuffer unit = new StringBuffer();
			Number num = this.getNumber( str, unit );
			if( num==null )
			{
				return FAILED;
			}
			if( el.setSymbolSpanDirectly( num.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}

		return SUCCEEDED;
	}


	// set the properties of Label
	private int setLabelProperties(
		final String command, final SGIStringElement el, final ArrayList argsList )
	{
		final String[] keys =
		{
			COM_LABEL_AXIS_X,
			COM_LABEL_AXIS_Y,
			COM_LABEL_TEXT,
			COM_LABEL_LOCATION_X,
			COM_LABEL_LOCATION_Y,
			COM_LABEL_FONT_NAME,
			COM_LABEL_FONT_STYLE,
			COM_LABEL_FONT_SIZE,
			COM_LABEL_FONT_COLOR,
			COM_LABEL_ANGLE,
			COM_DELETE_LABEL,
			COM_MOVE_TO_FRONT_LABEL,
			COM_MOVE_TO_BACK_LABEL
		};

		if( this.contains( keys, command ) == false )
		{
			return NOT_FOUND;
		}

		final int argn = argsList.size();
		if( argsList.size() < 1 )
		{
			return FAILED;
		}

		String str1 = (String)argsList.get(0);
		final Number id = SGUtilityText.getInteger(str1);
		if( id==null )
		{
			return FAILED;
		}

		if( argn == 1 )
		{
			if( command.equals( COM_DELETE_LABEL ) )
			{
				if( el.hideChildObject( id.intValue() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_MOVE_TO_FRONT_LABEL ) )
			{
				if( el.moveChildObject( id.intValue(), true ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_MOVE_TO_BACK_LABEL ) )
			{
				if( el.moveChildObject( id.intValue(), false ) == false )
				{
					return FAILED;
				}
			}

			return SUCCEEDED;
		}


		String str2 = (String)argsList.get(1);

		if( command.equals( COM_LABEL_AXIS_X ) )
		{
			final int value = this.getAxisLocation( str2 );
			if( value==-1 )
			{
				return FAILED;
			}
			if( el.setAxisXDirectly( id.intValue(), value ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_LABEL_AXIS_Y ) )
		{
			final int value = this.getAxisLocation( str2 );
			if( value==-1 )
			{
				return FAILED;
			}
			if( el.setAxisYDirectly( id.intValue(), value ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_LABEL_TEXT ) )
		{
			if( el.setTextDirectly( id.intValue(), str2 ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_LABEL_LOCATION_X ) )
		{
			final Number value = SGUtilityText.getDouble(str2);
			if( value==null )
			{
				return FAILED;
			}
			if( el.setLocationXDirectly( id.intValue(), value.floatValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_LABEL_LOCATION_Y ) )
		{
			final Number value = SGUtilityText.getDouble(str2);
			if( value==null )
			{
				return FAILED;
			}
			if( el.setLocationYDirectly( id.intValue(), value.floatValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_LABEL_FONT_NAME ) )
		{
			if( el.setFontNameDirectly( id.intValue(), str2 ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_LABEL_FONT_STYLE ) )
		{
			final int value = this.getFontStyle(str2);
			if( value==-1 )
			{
				return FAILED;
			}
			if( el.setFontStyleDirectly( id.intValue(), value ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_LABEL_FONT_SIZE ) )
		{
			StringBuffer unit = new StringBuffer();
			Number value = this.getNumber( str2, unit );
			if( value==null )
			{
				return FAILED;
			}
			if( el.setFontSizeDirectly( id.intValue(), value.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_LABEL_FONT_COLOR ) )
		{
			Color cl = null;
			if( argn==2 )
			{
				cl = SGUtilityText.getColor(str2);
			}
			else if( argn==4 )
			{
				String str3 = (String)argsList.get(2);
				String str4 = (String)argsList.get(3);
				cl = SGUtilityText.getColor(str2,str3,str4);
			}
			else
			{
				return FAILED;
			}

			if( cl==null )
			{
				return FAILED;
			}
			if( el.setFontColorDirectly( id.intValue(), cl ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_LABEL_ANGLE ) )
		{
			final Number value = SGUtilityText.getDouble(str2);
			if( value==null )
			{
				return FAILED;
			}
			final float angle = value.floatValue()*SGIConstants.RADIAN_DEGREE_RATIO;
			if( el.setAngleDirectly( id.intValue(), angle ) == false )
			{
				return FAILED;
			}
		}

		return SUCCEEDED;
	}


	// set the properties of Significant Differece Symbol
	private int setSigDiffProperties(
		final String command, final SGISignificantDifferenceElement el, final ArrayList argsList )
	{
		final String[] keys = {
			COM_SIGDIFF_AXIS_X,
			COM_SIGDIFF_AXIS_Y,
			COM_SIGDIFF_LOCATION_HORIZONTAL_Y,
			COM_SIGDIFF_LOCATION_LEFT_X,
			COM_SIGDIFF_LOCATION_LEFT_Y,
			COM_SIGDIFF_LOCATION_RIGHT_X,
			COM_SIGDIFF_LOCATION_RIGHT_Y,
			COM_SIGDIFF_LINE_VISIBLE,
			COM_SIGDIFF_SPACE,
			COM_SIGDIFF_LINE_WIDTH,
			COM_SIGDIFF_TEXT,
			COM_SIGDIFF_FONT_NAME,
			COM_SIGDIFF_FONT_STYLE,
			COM_SIGDIFF_FONT_SIZE,
			COM_SIGDIFF_COLOR,
			COM_DELETE_SIGDIFF,
			COM_MOVE_TO_FRONT_SIGDIFF,
			COM_MOVE_TO_BACK_SIGDIFF
		};
		if( this.contains( keys, command ) == false )
		{
			return NOT_FOUND;
		}

		final int argn = argsList.size();
		if( argsList.size() < 1 )
		{
			return FAILED;
		}

		String str1 = (String)argsList.get(0);
		final Number id = SGUtilityText.getInteger(str1);
		if( id==null )
		{
			return FAILED;
		}

		if( argn == 1 )
		{
			if( command.equals( COM_DELETE_SIGDIFF ) )
			{
				if( el.hideChildObject( id.intValue() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_MOVE_TO_FRONT_SIGDIFF ) )
			{
				if( el.moveChildObject( id.intValue(), true ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_MOVE_TO_BACK_SIGDIFF ) )
			{
				if( el.moveChildObject( id.intValue(), false ) == false )
				{
					return FAILED;
				}
			}

			return SUCCEEDED;
		}


		String str2 = (String)argsList.get(1);

		if( command.equals( COM_SIGDIFF_AXIS_X ) )
		{
			final int value = this.getAxisLocation( str2 );
			if( value==-1 )
			{
				return FAILED;
			}
			if( el.setAxisXDirectly( id.intValue(), value ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_SIGDIFF_AXIS_Y ) )
		{
			final int value = this.getAxisLocation( str2 );
			if( value==-1 )
			{
				return FAILED;
			}
			if( el.setAxisYDirectly( id.intValue(), value ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_LABEL_TEXT ) )
		{
			if( el.setTextDirectly( id.intValue(), str2 ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_SIGDIFF_LOCATION_HORIZONTAL_Y ) )
		{
			final Number value = SGUtilityText.getDouble(str2);
			if( value==null )
			{
				return FAILED;
			}
			if( el.setLocationHorizontalYDirectly( id.intValue(), value.doubleValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_SIGDIFF_LOCATION_LEFT_X ) )
		{
			final Number value = SGUtilityText.getDouble(str2);
			if( value==null )
			{
				return FAILED;
			}
			if( el.setLocationLeftXDirectly( id.intValue(), value.doubleValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_SIGDIFF_LOCATION_LEFT_Y ) )
		{
			final Number value = SGUtilityText.getDouble(str2);
			if( value==null )
			{
				return FAILED;
			}
			if( el.setLocationLeftYDirectly( id.intValue(), value.doubleValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_SIGDIFF_LOCATION_RIGHT_X ) )
		{
			final Number value = SGUtilityText.getDouble(str2);
			if( value==null )
			{
				return FAILED;
			}
			if( el.setLocationRightXDirectly( id.intValue(), value.doubleValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_SIGDIFF_LOCATION_RIGHT_Y ) )
		{
			final Number value = SGUtilityText.getDouble(str2);
			if( value==null )
			{
				return FAILED;
			}
			if( el.setLocationRightYDirectly( id.intValue(), value.doubleValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_SIGDIFF_FONT_NAME ) )
		{
			if( el.setFontNameDirectly( id.intValue(), str2 ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_SIGDIFF_FONT_STYLE ) )
		{
			final int value = this.getFontStyle(str2);
			if( value==-1 )
			{
				return FAILED;
			}
			if( el.setFontStyleDirectly( id.intValue(), value ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_SIGDIFF_FONT_SIZE ) )
		{
			StringBuffer unit = new StringBuffer();
			Number value = this.getNumber( str2, unit );
			if( value==null )
			{
				return FAILED;
			}
			if( el.setFontSizeDirectly( id.intValue(), value.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_SIGDIFF_COLOR ) )
		{
			Color cl = null;
			if( argn==2 )
			{
				cl = SGUtilityText.getColor(str2);
			}
			else if( argn==4 )
			{
				String str3 = (String)argsList.get(2);
				String str4 = (String)argsList.get(3);
				cl = SGUtilityText.getColor(str2,str3,str4);
			}
			else
			{
				return FAILED;
			}

			if( cl==null )
			{
				return FAILED;
			}
			if( el.setFontColorDirectly( id.intValue(), cl ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_SIGDIFF_LINE_VISIBLE ) )
		{
			Boolean b = SGUtilityText.getBoolean( this.getBooleanString( str2 ) );
			if( b==null )
			{
				return FAILED;
			}
			if( el.setLineVisibleDirectly( id.intValue(), b.booleanValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_SIGDIFF_SPACE ) )
		{
			StringBuffer unit = new StringBuffer();
			Number value = this.getNumber( str2, unit );
			if( value==null )
			{
				return FAILED;
			}
			if( el.setSpaceDirectly( id.intValue(), value.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_SIGDIFF_LINE_WIDTH ) )
		{
			StringBuffer unit = new StringBuffer();
			Number value = this.getNumber( str2, unit );
			if( value==null )
			{
				return FAILED;
			}
			if( el.setLineWidthDirectly( id.intValue(), value.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_SIGDIFF_TEXT ) )
		{
			if( el.setTextDirectly( id.intValue(), str2 ) == false )
			{
				return FAILED;
			}
		}

		return SUCCEEDED;
	}


	// set the properties of Axis Break Symbol
	private int setAxisBreakProperties(
		final String command, final SGIAxisBreakElement el, final ArrayList argsList )
	{

		final String[] keys = {
			COM_BREAK_AXIS_X,
			COM_BREAK_AXIS_Y,
			COM_BREAK_LOCATION_X,
			COM_BREAK_LOCATION_Y,
			COM_BREAK_LENGTH,
			COM_BREAK_INTERVAL,
			COM_BREAK_DISTORTION,
			COM_BREAK_ANGLE,
			COM_BREAK_LINE_WIDTH,
			COM_BREAK_ALIGNMENT,
			COM_BREAK_LINE_COLOR,
			COM_BREAK_INNER_COLOR,
			COM_DELETE_BREAK,
			COM_MOVE_TO_FRONT_BREAK,
			COM_MOVE_TO_BACK_BREAK
		};
		if( this.contains( keys, command ) == false )
		{
			return NOT_FOUND;
		}

		final int argn = argsList.size();
		if( argsList.size() < 1 )
		{
			return FAILED;
		}

		String str1 = (String)argsList.get(0);
		final Number id = SGUtilityText.getInteger(str1);
		if( id==null )
		{
			return FAILED;
		}

		if( argn == 1 )
		{
			if( command.equals( COM_DELETE_BREAK ) )
			{
				if( el.hideChildObject( id.intValue() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_MOVE_TO_FRONT_BREAK ) )
			{
				if( el.moveChildObject( id.intValue(), true ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_MOVE_TO_BACK_BREAK ) )
			{
				if( el.moveChildObject( id.intValue(), false ) == false )
				{
					return FAILED;
				}
			}

			return SUCCEEDED;
		}


		String str2 = (String)argsList.get(1);

		if( command.equals( COM_BREAK_AXIS_X ) )
		{
			final int value = this.getAxisLocation( str2 );
			if( value==-1 )
			{
				return FAILED;
			}
			if( el.setAxisXDirectly( id.intValue(), value ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_BREAK_AXIS_Y ) )
		{
			final int value = this.getAxisLocation( str2 );
			if( value==-1 )
			{
				return FAILED;
			}
			if( el.setAxisYDirectly( id.intValue(), value ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_BREAK_LOCATION_X ) )
		{
			final Number value = SGUtilityText.getDouble(str2);
			if( value==null )
			{
				return FAILED;
			}
			if( el.setLocationXDirectly( id.intValue(), value.doubleValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_BREAK_LOCATION_Y ) )
		{
			final Number value = SGUtilityText.getDouble(str2);
			if( value==null )
			{
				return FAILED;
			}
			if( el.setLocationYDirectly( id.intValue(), value.doubleValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_BREAK_LENGTH ) )
		{
			StringBuffer unit = new StringBuffer();
			Number value = this.getNumber( str2, unit );
			if( value==null )
			{
				return FAILED;
			}
			if( el.setLengthDirectly( id.intValue(), value.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_BREAK_INTERVAL ) )
		{
			StringBuffer unit = new StringBuffer();
			Number value = this.getNumber( str2, unit );
			if( value==null )
			{
				return FAILED;
			}
			if( el.setIntervalDirectly( id.intValue(), value.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_BREAK_DISTORTION ) )
		{
			final Number value = SGUtilityText.getDouble(str2);
			if( value==null )
			{
				return FAILED;
			}
			if( el.setDistortionDirectly( id.intValue(), value.floatValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_BREAK_ANGLE ) )
		{
			final Number value = SGUtilityText.getDouble(str2);
			if( value==null )
			{
				return FAILED;
			}
			final float angle = value.floatValue()*SGIConstants.RADIAN_DEGREE_RATIO;
			if( el.setAngleDirectly( id.intValue(), angle ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_BREAK_LINE_WIDTH ) )
		{
			StringBuffer unit = new StringBuffer();
			Number value = this.getNumber( str2, unit );
			if( value==null )
			{
				return FAILED;
			}
			if( el.setLineWidthDirectly( id.intValue(), value.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_BREAK_ALIGNMENT ) )
		{
			Boolean b = SGUtilityText.getBoolean( this.getBooleanString( str2 ) );
			if( b==null )
			{
				return FAILED;
			}
			if( el.setAlignmentDirectly( id.intValue(), b.booleanValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_BREAK_LINE_COLOR ) )
		{
			Color cl = null;
			if( argn==2 )
			{
				cl = SGUtilityText.getColor(str2);
			}
			else if( argn==4 )
			{
				String str3 = (String)argsList.get(2);
				String str4 = (String)argsList.get(3);
				cl = SGUtilityText.getColor(str2,str3,str4);
			}
			else
			{
				return FAILED;
			}

			if( cl==null )
			{
				return FAILED;
			}
			if( el.setLineColorDirectly( id.intValue(), cl ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_BREAK_INNER_COLOR ) )
		{
			Color cl = null;
			if( argn==2 )
			{
				cl = SGUtilityText.getColor(str2);
			}
			else if( argn==4 )
			{
				String str3 = (String)argsList.get(2);
				String str4 = (String)argsList.get(3);
				cl = SGUtilityText.getColor(str2,str3,str4);
			}
			else
			{
				return FAILED;
			}

			if( cl==null )
			{
				return FAILED;
			}
			if( el.setInnerColorDirectly( id.intValue(), cl ) == false )
			{
				return FAILED;
			}
		}

		return SUCCEEDED;
	}


	// set the properties of Timing Line
	private int setTimingLineProperties(
		final String command, final SGITimingLineElement el, final ArrayList argsList )
	{
		final String[] keys = {
			COM_TIMING_LINE_AXIS,
			COM_TIMING_LINE_WIDTH,
			COM_TIMING_LINE_TYPE,
			COM_TIMING_LINE_COLOR,
			COM_DELETE_TIMING_LINE,
			COM_MOVE_TO_FRONT_TIMING_LINE,
			COM_MOVE_TO_BACK_TIMING_LINE
		};
		if( this.contains( keys, command ) == false )
		{
			return NOT_FOUND;
		}
		
		final int argn = argsList.size();
		if( argsList.size() < 1 )
		{
			return FAILED;
		}

		String str1 = (String)argsList.get(0);
		final Number id = SGUtilityText.getInteger(str1);
		if( id==null )
		{
			return FAILED;
		}

		if( argn == 1 )
		{
			if( command.equals( COM_DELETE_TIMING_LINE ) )
			{
				if( el.hideChildObject( id.intValue() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_MOVE_TO_FRONT_TIMING_LINE ) )
			{
				if( el.moveChildObject( id.intValue(), true ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_MOVE_TO_BACK_TIMING_LINE ) )
			{
				if( el.moveChildObject( id.intValue(), false ) == false )
				{
					return FAILED;
				}
			}

			return SUCCEEDED;
		}


		String str2 = (String)argsList.get(1);

		if( command.equals( COM_TIMING_LINE_AXIS ) )
		{
			final int value = this.getAxisLocation( str2 );
			if( value==-1 )
			{
				return FAILED;
			}
			if( el.setAxisDirectly( id.intValue(), value ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_TIMING_LINE_WIDTH ) )
		{
			StringBuffer unit = new StringBuffer();
			Number value = this.getNumber( str2, unit );
			if( value==null )
			{
				return FAILED;
			}
			if( el.setLineWidthDirectly( id.intValue(), value.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_TIMING_LINE_TYPE ) )
		{
			final int num = this.getLineType(str2);
			if( num==-1 )
			{
				return FAILED;
			}
			if( el.setLineTypeDirectly( id.intValue(), num ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_TIMING_LINE_COLOR ) )
		{
			Color cl = null;
			if( argn==2 )
			{
				cl = SGUtilityText.getColor(str2);
			}
			else if( argn==4 )
			{
				String str3 = (String)argsList.get(2);
				String str4 = (String)argsList.get(3);
				cl = SGUtilityText.getColor(str2,str3,str4);
			}
			else
			{
				return FAILED;
			}

			if( cl==null )
			{
				return FAILED;
			}
			if( el.setColorDirectly( id.intValue(), cl ) == false )
			{
				return FAILED;
			}
		}

		return SUCCEEDED;
	}


	// set the properties of Shape objects
	private int setShapeProperties(
		final String command, final SGIShapeElement el, final ArrayList argsList )
	{
		final String[] keys = {
			// shape properties
			COM_SHAPE_AXIS_X,
			COM_SHAPE_AXIS_Y,

			// rectangular shape
			COM_RECTANGLE_LEFT_X,
			COM_RECTANGLE_RIGHT_X,
			COM_RECTANGLE_TOP_Y,
			COM_RECTANGLE_BOTTOM_Y,
			COM_RECTANGLE_EDGE_LINE_WIDTH,
			COM_RECTANGLE_EDGE_LINE_TYPE,
			COM_RECTANGLE_EDGE_LINE_COLOR,
			COM_RECTANGLE_BACKGROUND_TRANSPARENT,
			COM_RECTANGLE_BACKGROUND_COLOR,

			// arrow
			COM_ARROW_START_X,
			COM_ARROW_START_Y,
			COM_ARROW_END_X,
			COM_ARROW_END_Y,
			COM_ARROW_LINE_WIDTH,
			COM_ARROW_LINE_TYPE,
			COM_ARROW_HEAD_SIZE,
			COM_ARROW_COLOR,
			COM_ARROW_START_TYPE,
			COM_ARROW_END_TYPE,
			COM_ARROW_OPEN_ANGLE,
			COM_ARROW_CLOSE_ANGLE,
			
			//
			COM_DELETE_SHAPE,
			COM_MOVE_TO_FRONT_SHAPE,
			COM_MOVE_TO_BACK_SHAPE
		};
		if( this.contains( keys, command ) == false )
		{
			return NOT_FOUND;
		}

		final int argn = argsList.size();
		if( argsList.size() < 1 )
		{
			return FAILED;
		}

		String str1 = (String)argsList.get(0);
		final Number id = SGUtilityText.getInteger(str1);
		if( id==null )
		{
			return FAILED;
		}

		if( argn == 1 )
		{
			if( command.equals( COM_DELETE_SHAPE ) )
			{
				if( el.hideChildObject( id.intValue() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_MOVE_TO_FRONT_SHAPE ) )
			{
				if( el.moveChildObject( id.intValue(), true ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_MOVE_TO_BACK_SHAPE ) )
			{
				if( el.moveChildObject( id.intValue(), false ) == false )
				{
					return FAILED;
				}
			}

			return SUCCEEDED;
		}


		String str2 = (String)argsList.get(1);

		if( command.equals( COM_SHAPE_AXIS_X ) )
		{
			final int value = this.getAxisLocation( str2 );
			if( value==-1 )
			{
				return FAILED;
			}
			if( el.setAxisXDirectly( id.intValue(), value ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_SHAPE_AXIS_Y ) )
		{
			final int value = this.getAxisLocation( str2 );
			if( value==-1 )
			{
				return FAILED;
			}
			if( el.setAxisYDirectly( id.intValue(), value ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_RECTANGLE_LEFT_X ) )
		{
			final Number value = SGUtilityText.getDouble(str2);
			if( value==null )
			{
				return FAILED;
			}
			if( el.setRectangleLeftXValueDirectly( id.intValue(), value.floatValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_RECTANGLE_RIGHT_X ) )
		{
			final Number value = SGUtilityText.getDouble(str2);
			if( value==null )
			{
				return FAILED;
			}
			if( el.setRectangleRightXValueDirectly( id.intValue(), value.floatValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_RECTANGLE_TOP_Y ) )
		{
			final Number value = SGUtilityText.getDouble(str2);
			if( value==null )
			{
				return FAILED;
			}
			if( el.setRectangleTopYValueDirectly( id.intValue(), value.floatValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_RECTANGLE_BOTTOM_Y ) )
		{
			final Number value = SGUtilityText.getDouble(str2);
			if( value==null )
			{
				return FAILED;
			}
			if( el.setRectangleBottomYValueDirectly( id.intValue(), value.floatValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_RECTANGLE_EDGE_LINE_WIDTH ) )
		{
			StringBuffer unit = new StringBuffer();
			Number value = this.getNumber( str2, unit );
			if( value==null )
			{
				return FAILED;
			}
			if( el.setRectangleEdgeLineWidthDirectly( id.intValue(), value.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_RECTANGLE_EDGE_LINE_TYPE ) )
		{
			final int num = this.getLineType(str2);
			if( num==-1 )
			{
				return FAILED;
			}
			if( el.setRectangleEdgeLineTypeDirectly( id.intValue(), num ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_RECTANGLE_EDGE_LINE_COLOR ) )
		{
			Color cl = null;
			if( argn==2 )
			{
				cl = SGUtilityText.getColor(str2);
			}
			else if( argn==4 )
			{
				String str3 = (String)argsList.get(2);
				String str4 = (String)argsList.get(3);
				cl = SGUtilityText.getColor(str2,str3,str4);
			}
			else
			{
				return FAILED;
			}

			if( cl==null )
			{
				return FAILED;
			}
			if( el.setRectangleEdgeLineColorDirectly( id.intValue(), cl ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_RECTANGLE_BACKGROUND_TRANSPARENT ) )
		{
			Boolean b = SGUtilityText.getBoolean( this.getBooleanString( str2 ) );
			if( b==null )
			{
				return FAILED;
			}
			if( el.setRectangleBackgroundTransparentDirectly( id.intValue(), b.booleanValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_RECTANGLE_BACKGROUND_COLOR ) )
		{
			Color cl = null;
			if( argn==2 )
			{
				cl = SGUtilityText.getColor(str2);
			}
			else if( argn==4 )
			{
				String str3 = (String)argsList.get(2);
				String str4 = (String)argsList.get(3);
				cl = SGUtilityText.getColor(str2,str3,str4);
			}
			else
			{
				return FAILED;
			}

			if( cl==null )
			{
				return FAILED;
			}
			if( el.setRectangleBackgroundColorDirectly( id.intValue(), cl ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_ARROW_START_X ) )
		{
			final Number value = SGUtilityText.getDouble(str2);
			if( value==null )
			{
				return FAILED;
			}
			if( el.setArrowStartXValueDirectly( id.intValue(), value.floatValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_ARROW_START_Y ) )
		{
			final Number value = SGUtilityText.getDouble(str2);
			if( value==null )
			{
				return FAILED;
			}
			if( el.setArrowStartYValueDirectly( id.intValue(), value.floatValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_ARROW_END_X ) )
		{
			final Number value = SGUtilityText.getDouble(str2);
			if( value==null )
			{
				return FAILED;
			}
			if( el.setArrowEndXValueDirectly( id.intValue(), value.floatValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_ARROW_END_Y ) )
		{
			final Number value = SGUtilityText.getDouble(str2);
			if( value==null )
			{
				return FAILED;
			}
			if( el.setArrowEndYValueDirectly( id.intValue(), value.floatValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_ARROW_LINE_WIDTH ) )
		{
			StringBuffer unit = new StringBuffer();
			Number value = this.getNumber( str2, unit );
			if( value==null )
			{
				return FAILED;
			}
			if( el.setArrowLineWidthDirectly( id.intValue(), value.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_ARROW_LINE_TYPE ) )
		{
			final int num = this.getLineType(str2);
			if( num==-1 )
			{
				return FAILED;
			}
			if( el.setArrowLineTypeDirectly( id.intValue(), num ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_ARROW_HEAD_SIZE ) )
		{
			StringBuffer unit = new StringBuffer();
			Number value = this.getNumber( str2, unit );
			if( value==null )
			{
				return FAILED;
			}
			if( el.setArrowHeadSizeDirectly( id.intValue(), value.floatValue(), unit.toString() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_ARROW_COLOR ) )
		{
			Color cl = null;
			if( argn==2 )
			{
				cl = SGUtilityText.getColor(str2);
			}
			else if( argn==4 )
			{
				String str3 = (String)argsList.get(2);
				String str4 = (String)argsList.get(3);
				cl = SGUtilityText.getColor(str2,str3,str4);
			}
			else
			{
				return FAILED;
			}

			if( cl==null )
			{
				return FAILED;
			}
			if( el.setArrowColorDirectly( id.intValue(), cl ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_ARROW_START_TYPE ) )
		{
			final Number value = SGDrawingElementArrow.getSymbolTypeFromName(str2);
			if( value==null )
			{
				return FAILED;
			}
			if( el.setArrowStartTypeDirectly( id.intValue(), value.intValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_ARROW_END_TYPE ) )
		{
			final Number value = SGDrawingElementArrow.getSymbolTypeFromName(str2);
			if( value==null )
			{
				return FAILED;
			}
			if( el.setArrowEndTypeDirectly( id.intValue(), value.intValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_ARROW_OPEN_ANGLE ) )
		{
			final Number value = SGUtilityText.getDouble(str2);
			if( value==null )
			{
				return FAILED;
			}
			final float angle = value.floatValue()*SGIConstants.RADIAN_DEGREE_RATIO;
			if( el.setArrowOpenAngleDirectly( id.intValue(), angle ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_ARROW_CLOSE_ANGLE ) )
		{
			final Number value = SGUtilityText.getDouble(str2);
			if( value==null )
			{
				return FAILED;
			}
			final float angle = value.floatValue()*SGIConstants.RADIAN_DEGREE_RATIO;
			if( el.setArrowCloseAngleDirectly( id.intValue(), angle ) == false )
			{
				return FAILED;
			}
		}

		return SUCCEEDED;
	}


	//
	private boolean contains( final String[] keys, final String str )
	{
		ArrayList list = new ArrayList( Arrays.asList( keys ) );
		return list.contains(str);
	}


	// set the properties of Data objects
	private int setDataProperties(
		final String command, final SGIGraphElement el, final ArrayList argsList )
	{
		final String[] keys = {
			// common
			COM_DATA_AXIS_X,
			COM_DATA_AXIS_Y,
			COM_DATA_VISIBLE_IN_LEGEND,
			COM_DATA_NAME,

			// line
			COM_DATA_LINE_VISIBLE,
			COM_DATA_LINE_WIDTH,
			COM_DATA_LINE_TYPE,
			COM_DATA_LINE_COLOR,

			// symbol
			COM_DATA_SYMBOL_VISIBLE,
			COM_DATA_SYMBOL_TYPE,
			COM_DATA_SYMBOL_BODY_SIZE,
			COM_DATA_SYMBOL_BODY_COLOR,
			COM_DATA_SYMBOL_LINE_WIDTH,
			COM_DATA_SYMBOL_LINE_COLOR,

			// bar
			COM_DATA_BAR_VISIBLE,
			COM_DATA_BAR_BASELINE,
			COM_DATA_BAR_BODY_WIDTH,
			COM_DATA_BAR_BODY_COLOR,
			COM_DATA_BAR_LINE_WIDTH,
			COM_DATA_BAR_LINE_COLOR,

			// error bar
			COM_DATA_ERROR_BAR_VISIBLE,
			COM_DATA_ERROR_BAR_SYMBOL_TYPE,
			COM_DATA_ERROR_BAR_SYMBOL_SIZE,
			COM_DATA_ERROR_BAR_COLOR,
			COM_DATA_ERROR_BAR_LINE_WIDTH,
			COM_DATA_ERROR_BAR_STYLE,

			// tick label
			COM_DATA_TICK_LABEL_VISIBLE,
			COM_DATA_TICK_LABEL_FONT_NAME,
			COM_DATA_TICK_LABEL_FONT_STYLE,
			COM_DATA_TICK_LABEL_FONT_SIZE,
			COM_DATA_TICK_LABEL_FONT_COLOR,
			COM_DATA_TICK_LABEL_HORIZONTAL,

			// arrow
			COM_DATA_ARROW_MAGNITUDE_PER_CM,
			COM_DATA_ARROW_DIRECTION_INVARIANT,
			COM_DATA_ARROW_LINE_WIDTH,
			COM_DATA_ARROW_LINE_TYPE,
			COM_DATA_ARROW_HEAD_SIZE,
			COM_DATA_ARROW_COLOR,
			COM_DATA_ARROW_START_TYPE,
			COM_DATA_ARROW_END_TYPE,
			COM_DATA_ARROW_OPEN_ANGLE,
			COM_DATA_ARROW_CLOSE_ANGLE,

			//
			COM_DELETE_DATA,
			COM_MOVE_TO_FRONT_DATA,
			COM_MOVE_TO_BACK_DATA
		};

		if( this.contains( keys, command) == false )
		{
			return NOT_FOUND;
		}

		final int argn = argsList.size();
		if( argsList.size() < 1 )
		{
			return FAILED;
		}

		String str1 = (String)argsList.get(0);
		final Number id = SGUtilityText.getInteger(str1);
		if( id==null )
		{
			return FAILED;
		}

		if( argn == 1 )
		{
			if( command.equals( COM_DELETE_DATA ) )
			{
				if( el.hideChildObject( id.intValue() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_MOVE_TO_FRONT_DATA ) )
			{
				if( el.moveChildObject( id.intValue(), true ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_MOVE_TO_BACK_DATA ) )
			{
				if( el.moveChildObject( id.intValue(), false ) == false )
				{
					return FAILED;
				}
			}

			return SUCCEEDED;
		}


		String str2 = (String)argsList.get(1);

		if( command.equals( COM_DATA_AXIS_X ) )
		{
			final int value = this.getAxisLocation( str2 );
			if( value==-1 )
			{
				return FAILED;
			}
			if( el.setAxisXDirectly( id.intValue(), value ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_DATA_AXIS_Y ) )
		{
			final int value = this.getAxisLocation( str2 );
			if( value==-1 )
			{
				return FAILED;
			}
			if( el.setAxisYDirectly( id.intValue(), value ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_DATA_VISIBLE_IN_LEGEND ) )
		{
			final Boolean b = SGUtilityText.getBoolean( this.getBooleanString( str2 ) );
			if( b==null )
			{
				return FAILED;
			}
			if( el.setVisibleInLegendDirectly( id.intValue(), b.booleanValue() ) == false )
			{
				return FAILED;
			}
		}
		else if( command.equals( COM_DATA_NAME ) )
		{
			if( el.setNameDirectly( id.intValue(), str2 ) == false )
			{
				return FAILED;
			}
		}


		if( el instanceof SGISXYGraphElement )
		{
			SGISXYGraphElement elsxy = (SGISXYGraphElement)el;

			if( command.equals( COM_DATA_LINE_VISIBLE ) )
			{
				final Boolean b = SGUtilityText.getBoolean( this.getBooleanString( str2 ) );
				if( b==null )
				{
					return FAILED;
				}
				if( elsxy.setLineVisibleDirectly( id.intValue(), b.booleanValue() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_LINE_WIDTH ) )
			{
				StringBuffer unit = new StringBuffer();
				Number value = this.getNumber( str2, unit );
				if( value==null )
				{
					return FAILED;
				}
				if( elsxy.setLineWidthDirectly( id.intValue(), value.floatValue(), unit.toString() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_LINE_TYPE ) )
			{
				final int num = this.getLineType(str2);
				if( num==-1 )
				{
					return FAILED;
				}
				if( elsxy.setLineTypeDirectly( id.intValue(), num ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_LINE_COLOR ) )
			{
				Color cl = null;
				if( argn==2 )
				{
					cl = SGUtilityText.getColor(str2);
				}
				else if( argn==4 )
				{
					String str3 = (String)argsList.get(2);
					String str4 = (String)argsList.get(3);
					cl = SGUtilityText.getColor(str2,str3,str4);
				}
				else
				{
					return FAILED;
				}

				if( cl==null )
				{
					return FAILED;
				}
				if( elsxy.setLineColorDirectly( id.intValue(), cl ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_SYMBOL_VISIBLE ) )
			{
				final Boolean b = SGUtilityText.getBoolean( this.getBooleanString( str2 ) );
				if( b==null )
				{
					return FAILED;
				}
				if( elsxy.setSymbolVisibleDirectly( id.intValue(), b.booleanValue() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_SYMBOL_TYPE ) )
			{
				final int num = this.getSymbolType(str2);
				if( num==-1 )
				{
					return FAILED;
				}
				if( elsxy.setSymbolTypeDirectly( id.intValue(), num ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_SYMBOL_BODY_SIZE ) )
			{
				StringBuffer unit = new StringBuffer();
				Number value = this.getNumber( str2, unit );
				if( value==null )
				{
					return FAILED;
				}
				if( elsxy.setSymbolSizeDirectly( id.intValue(), value.floatValue(), unit.toString() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_SYMBOL_LINE_WIDTH ) )
			{
				StringBuffer unit = new StringBuffer();
				Number value = this.getNumber( str2, unit );
				if( value==null )
				{
					return FAILED;
				}
				if( elsxy.setSymbolLineWidthDirectly( id.intValue(), value.floatValue(), unit.toString() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_SYMBOL_BODY_COLOR ) )
			{
				Color cl = null;
				if( argn==2 )
				{
					cl = SGUtilityText.getColor(str2);
				}
				else if( argn==4 )
				{
					String str3 = (String)argsList.get(2);
					String str4 = (String)argsList.get(3);
					cl = SGUtilityText.getColor(str2,str3,str4);
				}
				else
				{
					return FAILED;
				}

				if( cl==null )
				{
					return FAILED;
				}
				if( elsxy.setSymbolInnerColorDirectly( id.intValue(), cl ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_SYMBOL_LINE_COLOR ) )
			{
				Color cl = null;
				if( argn==2 )
				{
					cl = SGUtilityText.getColor(str2);
				}
				else if( argn==4 )
				{
					String str3 = (String)argsList.get(2);
					String str4 = (String)argsList.get(3);
					cl = SGUtilityText.getColor(str2,str3,str4);
				}
				else
				{
					return FAILED;
				}

				if( cl==null )
				{
					return FAILED;
				}
				if( elsxy.setSymbolLineColorDirectly( id.intValue(), cl ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_BAR_VISIBLE ) )
			{
				final Boolean b = SGUtilityText.getBoolean( this.getBooleanString( str2 ) );
				if( b==null )
				{
					return FAILED;
				}
				if( elsxy.setBarVisibleDirectly( id.intValue(), b.booleanValue() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_BAR_BASELINE ) )
			{
				final Number value = SGUtilityText.getDouble(str2);
				if( value==null )
				{
					return FAILED;
				}
				if( elsxy.setBarBaselineDirectly( id.intValue(), value.floatValue() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_BAR_BODY_WIDTH ) )
			{
				final Number value = SGUtilityText.getDouble(str2);
				if( value==null )
				{
					return FAILED;
				}
				if( elsxy.setBarWidthDirectly( id.intValue(), value.floatValue() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_BAR_LINE_WIDTH ) )
			{
				StringBuffer unit = new StringBuffer();
				Number value = this.getNumber( str2, unit );
				if( value==null )
				{
					return FAILED;
				}
				if( elsxy.setBarEdgeLineWidthDirectly( id.intValue(), value.floatValue(), unit.toString() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_BAR_BODY_COLOR ) )
			{
				Color cl = null;
				if( argn==2 )
				{
					cl = SGUtilityText.getColor(str2);
				}
				else if( argn==4 )
				{
					String str3 = (String)argsList.get(2);
					String str4 = (String)argsList.get(3);
					cl = SGUtilityText.getColor(str2,str3,str4);
				}
				else
				{
					return FAILED;
				}

				if( cl==null )
				{
					return FAILED;
				}
				if( elsxy.setBarInnerColorDirectly( id.intValue(), cl ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_BAR_LINE_COLOR ) )
			{
				Color cl = null;
				if( argn==2 )
				{
					cl = SGUtilityText.getColor(str2);
				}
				else if( argn==4 )
				{
					String str3 = (String)argsList.get(2);
					String str4 = (String)argsList.get(3);
					cl = SGUtilityText.getColor(str2,str3,str4);
				}
				else
				{
					return FAILED;
				}

				if( cl==null )
				{
					return FAILED;
				}
				if( elsxy.setBarLineColorDirectly( id.intValue(), cl ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_ERROR_BAR_VISIBLE ) )
			{
				final Boolean b = SGUtilityText.getBoolean( this.getBooleanString( str2 ) );
				if( b==null )
				{
					return FAILED;
				}
				if( elsxy.setErrorBarVisibleDirectly( id.intValue(), b.booleanValue() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_ERROR_BAR_SYMBOL_TYPE ) )
			{
				final Number value = SGDrawingElementErrorBar.getHeadTypeFromName(str2);
				if( value==null )
				{
					return FAILED;
				}
				if( elsxy.setErrorBarSymbolTypeDirectly( id.intValue(), value.intValue() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_ERROR_BAR_SYMBOL_SIZE ) )
			{
				StringBuffer unit = new StringBuffer();
				Number value = this.getNumber( str2, unit );
				if( value==null )
				{
					return FAILED;
				}
				if( elsxy.setErrorBarSymbolSizeDirectly( id.intValue(), value.floatValue(), unit.toString() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_ERROR_BAR_LINE_WIDTH ) )
			{
				StringBuffer unit = new StringBuffer();
				Number value = this.getNumber( str2, unit );
				if( value==null )
				{
					return FAILED;
				}
				if( elsxy.setErrorBarLineWidthDirectly( id.intValue(), value.floatValue(), unit.toString() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_ERROR_BAR_COLOR ) )
			{
				Color cl = null;
				if( argn==2 )
				{
					cl = SGUtilityText.getColor(str2);
				}
				else if( argn==4 )
				{
					String str3 = (String)argsList.get(2);
					String str4 = (String)argsList.get(3);
					cl = SGUtilityText.getColor(str2,str3,str4);
				}
				else
				{
					return FAILED;
				}

				if( cl==null )
				{
					return FAILED;
				}
				if( elsxy.setErrorBarColorDirectly( id.intValue(), cl ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_ERROR_BAR_STYLE ) )
			{
				final int value = this.getErrorBarStyle(str2);
				if( value==-1 )
				{
					return FAILED;
				}
				if( elsxy.setErrorBarStyleDirectly( id.intValue(), value ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_TICK_LABEL_VISIBLE ) )
			{
				final Boolean b = SGUtilityText.getBoolean( this.getBooleanString( str2 ) );
				if( b==null )
				{
					return FAILED;
				}
				if( elsxy.setTickLabelVisibleDirectly( id.intValue(), b.booleanValue() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_TICK_LABEL_FONT_NAME ) )
			{
				if( elsxy.setTickLabelFontNameDirectly( id.intValue(), str2 ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_TICK_LABEL_FONT_STYLE ) )
			{
				final int value = this.getFontStyle(str2);
				if( value==-1 )
				{
					return FAILED;
				}
				if( elsxy.setTickLabelFontStyleDirectly( id.intValue(), value ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_TICK_LABEL_FONT_SIZE ) )
			{
				StringBuffer unit = new StringBuffer();
				Number value = this.getNumber( str2, unit );
				if( value==null )
				{
					return FAILED;
				}
				if( elsxy.setTickLabelFontSizeDirectly( id.intValue(), value.floatValue(), unit.toString() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_TICK_LABEL_FONT_COLOR ) )
			{
				Color cl = null;
				if( argn==2 )
				{
					cl = SGUtilityText.getColor(str2);
				}
				else if( argn==4 )
				{
					String str3 = (String)argsList.get(2);
					String str4 = (String)argsList.get(3);
					cl = SGUtilityText.getColor(str2,str3,str4);
				}
				else
				{
					return FAILED;
				}

				if( cl==null )
				{
					return FAILED;
				}
				if( elsxy.setTickLabelFontColorDirectly( id.intValue(), cl ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_TICK_LABEL_HORIZONTAL ) )
			{
				final Boolean b = SGUtilityText.getBoolean( this.getBooleanString(str2) );
				if( b==null )
				{
					return FAILED;
				}
				if( elsxy.setTickLabelAngleDirectly( id.intValue(), b.booleanValue() ) == false )
				{
					return FAILED;
				}
			}
		}
		else if( el instanceof SGIVXYGraphElement )
		{
			SGIVXYGraphElement elvxy = (SGIVXYGraphElement)el;

			if( command.equals( COM_DATA_ARROW_MAGNITUDE_PER_CM ) )
			{
				Number value = SGUtilityText.getFloat(str2);
				if( value==null )
				{
					return FAILED;
				}
				if( elvxy.setMagnitudePerCMDirectly( id.intValue(), value.floatValue() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_ARROW_DIRECTION_INVARIANT ) )
			{
				Boolean b = SGUtilityText.getBoolean(str2);
				if( b==null )
				{
					return FAILED;
				}
				if( elvxy.setDirectionInvariantDirectly( id.intValue(), b.booleanValue() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_ARROW_LINE_WIDTH ) )
			{
				StringBuffer unit = new StringBuffer();
				Number value = this.getNumber( str2, unit );
				if( value==null )
				{
					return FAILED;
				}
				if( elvxy.setLineWidthDirectly( id.intValue(), value.floatValue(), unit.toString() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_ARROW_LINE_TYPE ) )
			{
				final int num = this.getLineType(str2);
				if( num==-1 )
				{
					return FAILED;
				}
				if( elvxy.setLineTypeDirectly( id.intValue(), num ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_ARROW_HEAD_SIZE ) )
			{
				StringBuffer unit = new StringBuffer();
				Number value = this.getNumber( str2, unit );
				if( value==null )
				{
					return FAILED;
				}
				if( elvxy.setHeadSizeDirectly( id.intValue(), value.floatValue(), unit.toString() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_ARROW_COLOR ) )
			{
				Color cl = null;
				if( argn==2 )
				{
					cl = SGUtilityText.getColor(str2);
				}
				else if( argn==4 )
				{
					String str3 = (String)argsList.get(2);
					String str4 = (String)argsList.get(3);
					cl = SGUtilityText.getColor(str2,str3,str4);
				}
				else
				{
					return FAILED;
				}

				if( cl==null )
				{
					return FAILED;
				}
				if( elvxy.setColorDirectly( id.intValue(), cl ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_ARROW_START_TYPE ) )
			{
				final Number value = SGDrawingElementArrow.getSymbolTypeFromName(str2);
				if( value==null )
				{
					return FAILED;
				}
				if( elvxy.setStartTypeDirectly( id.intValue(), value.intValue() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_ARROW_END_TYPE ) )
			{
				final Number value = SGDrawingElementArrow.getSymbolTypeFromName(str2);
				if( value==null )
				{
					return FAILED;
				}
				if( elvxy.setEndTypeDirectly( id.intValue(), value.intValue() ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_ARROW_OPEN_ANGLE ) )
			{
				final Number value = SGUtilityText.getDouble(str2);
				if( value==null )
				{
					return FAILED;
				}
				final float angle = value.floatValue()*SGIConstants.RADIAN_DEGREE_RATIO;
				if( elvxy.setOpenAngleDirectly( id.intValue(), angle ) == false )
				{
					return FAILED;
				}
			}
			else if( command.equals( COM_DATA_ARROW_CLOSE_ANGLE ) )
			{
				final Number value = SGUtilityText.getDouble(str2);
				if( value==null )
				{
					return FAILED;
				}
				final float angle = value.floatValue()*SGIConstants.RADIAN_DEGREE_RATIO;
				if( elvxy.setCloseAngleDirectly( id.intValue(), angle ) == false )
				{
					return FAILED;
				}
			}

		}

		return SUCCEEDED;
	}


	// parse given string into the command and arguments
	private String parseCommand( final String line, final ArrayList argsList )
	{
		final int sIndex = line.indexOf('(');
		final int eIndex = line.indexOf(')');
		if( sIndex==-1 | eIndex==-1 )
		{
			return line;
		}
		if( sIndex > eIndex )
		{
			return line;
		}
		if( sIndex==0 )
		{
			return line;
		}

		String command = line.substring(0,sIndex);
		String args = line.substring(sIndex+1,eIndex);

		if( SGUtilityText.tokenize( args, argsList ) == false )
		{
			return line;
		}

		return command;
	}



	/**
	 * Get the simple path name from absolute path name.
	 * @param aPath - given absolute path name
	 * @return simple path name
	 */
	private String getSimpleFileName( final String aPath )
	{
		final String fs = FILE_SEPARATOR;
		StringTokenizer stk = new StringTokenizer( aPath, fs );
		String sub = null;
		while( stk.hasMoreTokens() )
		{
			sub = stk.nextToken();
		}
		if( sub==null )
		{
			throw new Error();
		}

		String name = null;
		StringTokenizer stk2 = new StringTokenizer( sub, Character.toString('.') );
		while( stk2.hasMoreTokens() )
		{
			name = stk2.nextToken();
			break;
		}
		if( name==null )
		{
			name = sub;
		}

		return name;
	}



	/**
	 * Returns a string for the name of new data.
	 * @param figure
	 * @param aPath
	 * @return
	 */
	private String getNewDataName(
		final SGFigure figure, final String aPath )
	{
		String name = this.getSimpleFileName( aPath );
		if( name==null )
		{
			return null;
		}

		List list = figure.getVisibleDataList();
		List dNameList = new ArrayList();
		for( int ii=0; ii<list.size(); ii++ )
		{
			SGData data = (SGData)list.get(ii);
			String dName = figure.getDataName(data);
			dNameList.add( dName );
		}
		
		name = SGUtilityText.getSerialName( dNameList, name );

		return name;
	}



	/**
	 * 
	 * @param wnd
	 * @return
	 */
	private boolean setWindowLocation( final SGDrawingWindow wnd )
	{
		// set the location
		final Dimension scSize = Toolkit.getDefaultToolkit().getScreenSize();
		final int x = (int)( scSize.getWidth() - wnd.getWidth() )/2;
		final int y = (int)( scSize.getHeight() - wnd.getHeight() )/2;
		wnd.setLocation(x,y);
	
		return true;
	}


	/**
	 * 
	 */
	public SGDrawingWindow getWindow( final int wndID )
	{
		return (SGDrawingWindow)this.mWndMap.get( new Integer(wndID) );
	}


	/**
	 * 
	 * @return
	 */
	public int getWindowNumber()
	{
		return this.mWndMap.size();
	}


	/**
	 * 
	 */
	private SGFigure createFigure(
		final int figureID,
		final SGDrawingWindow wnd,
		final SGData data )
	{

		SGFigure figure = null;

		float w;
		float h;
		if( data instanceof SGISXYTypeData | data instanceof SGISXYTypeMultipleData )
		{
			figure = new SGSXYFigure( wnd );
			w = SGSXYFigure.DEFAULT_WIDTH;
			h = SGSXYFigure.DEFAULT_HEIGHT;
		}
		else if( data instanceof SGVXYData )
		{
			figure = new SGVXYFigure( wnd );
			w = SGVXYFigure.DEFAULT_WIDTH;
			h = SGVXYFigure.DEFAULT_HEIGHT;
		}
		else
		{
			return null;
		}

		figure.setVisible( false );
		figure.setID( figureID );
//		figure.setComponent( wnd.getFigurePanel() );

		if( this.createFigureElements( figure, data ) == false )
		{
			return null;
		}

		// set size after created a figure instance
		figure.setFigureWidth( w, SGIFigureConstants.FIGURE_SIZE_UNIT );
		figure.setFigureHeight( h, SGIFigureConstants.FIGURE_SIZE_UNIT );

		return figure;

	}



	/**
	 * 
	 */
	private boolean createFigureElements(
		final SGFigure figure,
		final SGData data )
	{

		try
		{
			// dialog owner
			SGDrawingWindow wnd = figure.getWindow();


			// create a SGAxisElement
			SGIAxisElement axisElement = (SGIAxisElement)this.setIElement(
				this.mClassOfAxisElement, figure, wnd );

			wnd.setProgressValue( 0.15f );

			// create a SGGraphElement
			Class clGraph = null;
			if( data instanceof SGISXYTypeData | data instanceof SGISXYTypeMultipleData)
			{
				clGraph = this.mClassOfSXYGraphElement;
			}
			else if( data instanceof SGVXYData )
			{
				clGraph = this.mClassOfVXYGraphElement;
			}
			else
			{
				return false;
			}
			SGIGraphElement graphElement = (SGIGraphElement)this.setIElement(
				clGraph, figure, wnd );

			wnd.setProgressValue( 0.20f );

			// create a SGLegendElement
			SGILegendElement legendElement = (SGILegendElement)this.setIElement(
				this.mClassOfLegendElement, figure, wnd );

			wnd.setProgressValue( 0.25f );

			// create a SGStringElement
			SGIStringElement stringElement = (SGIStringElement)this.setIElement(
				this.mClassOfStringElement, figure, wnd );

			wnd.setProgressValue( 0.30f );

			// SGAxisBreakElement
			SGIAxisBreakElement axisBreakElement = (SGIAxisBreakElement)this.setIElement(
				this.mClassOfAxisBreakElement, figure, wnd );

			wnd.setProgressValue( 0.35f );
			
			// SGSignificantDifferenceElement
			SGISignificantDifferenceElement sigDiffElement = (SGISignificantDifferenceElement)this.setIElement(
				this.mClassOfSignificantDifferenceElement, figure, wnd );
			
			wnd.setProgressValue( 0.40f );

			// SGTimingLineElement
			SGITimingLineElement timingLineElement = (SGITimingLineElement)this.setIElement(
				this.mClassOfTimingLineElement, figure, wnd );

			wnd.setProgressValue( 0.45f );

			// SGGridElement
			SGIGridElement gridElement = (SGIGridElement)this.setIElement(
				this.mClassOfGridElement, figure, wnd );

			wnd.setProgressValue( 0.50f );

			// SGShapeElement
			SGIShapeElement shapeElement = (SGIShapeElement)this.setIElement(
				this.mClassOfShapeElement, figure, wnd );

			wnd.setProgressValue( 0.55f );

			// set to figure
			figure.setIFigureElement( LAYER_GRID, gridElement );
			figure.setIFigureElement( LAYER_TIMING_LINE, timingLineElement );
			figure.setIFigureElement( LAYER_GRAPH, graphElement );
			figure.setIFigureElement( LAYER_SIGNIFICANT_DIFFERENCE, sigDiffElement );
			figure.setIFigureElement( LAYER_AXIS, axisElement );
			figure.setIFigureElement( LAYER_SHAPE, shapeElement );
			figure.setIFigureElement( LAYER_AXIS_BREAK, axisBreakElement );
			figure.setIFigureElement( LAYER_LEGEND, legendElement );
			figure.setIFigureElement( LAYER_STRING, stringElement );

			// set relation between SGIFigureElement objects
			this.setRelationOfFigureElements( figure );

			wnd.setProgressValue( 0.60f );
		}
		catch( Exception ex )
		{
			ex.printStackTrace();
			return false;
		}
		
		return true;
	}


	private void setRelationOfFigureElements( final SGFigure figure )
	{
		SGIAxisElement axis = (SGIAxisElement)figure.getIFigureElement( SGIAxisElement.class );
		SGIGraphElement graph = (SGIGraphElement)figure.getIFigureElement( SGIGraphElement.class );
		SGILegendElement legend = (SGILegendElement)figure.getIFigureElement( SGILegendElement.class );
		SGIStringElement string = (SGIStringElement)figure.getIFigureElement( SGIStringElement.class );
		SGIAxisBreakElement axisBreak = (SGIAxisBreakElement)figure.getIFigureElement( SGIAxisBreakElement.class );
		SGISignificantDifferenceElement sigDiff = (SGISignificantDifferenceElement)figure.getIFigureElement( SGISignificantDifferenceElement.class );
		SGITimingLineElement timingLine = (SGITimingLineElement)figure.getIFigureElement( SGITimingLineElement.class );
		SGIGridElement grid = (SGIGridElement)figure.getIFigureElement( SGIGridElement.class );
		SGIShapeElement shape = (SGIShapeElement)figure.getIFigureElement( SGIShapeElement.class );

		graph.setAxisElement( axis );
		legend.setAxisElement( axis );
		legend.setGraphElement( graph );
		axisBreak.setAxisElement( axis );
		sigDiff.setAxisElement( axis );
		timingLine.setAxisElement( axis );
		grid.setAxisElement( axis );
		string.setAxisElement( axis );
		shape.setAxisElement( axis );
	}



	/**
	 * Constants of layer.
	 */
	public static final int LAYER_GRID = 10;
	public static final int LAYER_TIMING_LINE = 20;
	public static final int LAYER_GRAPH = 30;
	public static final int LAYER_SIGNIFICANT_DIFFERENCE = 40;
	public static final int LAYER_AXIS = 50;
	public static final int LAYER_SHAPE = 60;
	public static final int LAYER_AXIS_BREAK = 70;
	public static final int LAYER_LEGEND = 80;
	public static final int LAYER_STRING = 90;



	// create SGIFigureElement object
	private SGIFigureElement setIElement(
		final Class cl, final SGFigure figure, final Frame owner )
	{
		Object obj = null;
		try
		{
			obj = cl.newInstance();
		}
		catch( Exception ex )
		{
			ex.printStackTrace();
			return null;
		}

		SGIFigureElement element = (SGIFigureElement)obj;
		element.setComponent( figure.getComponent() );
		element.addActionListener(figure);
		element.setDialogOwner(owner);

		return element;
	}



	// create a data object from a file
	private int createDataFromFile(
		final String pathName, final ArrayList dataList, final SGDrawingWindow wnd )
			throws FileNotFoundException
	{

		// get information from the file
		ArrayList infoList = new ArrayList();
		int ret = this.readFile( pathName, infoList );
		if( ret!=0 )
		{
			return ret;
		}

//		wnd.setProgressValue(0.050f);

		// create a data object
		SGData data = this.mDataCreator.create( pathName, infoList );
		if( data==null )
		{
			return -1;
		}
		dataList.add(data);

		return 0;
	}




	/**
	 * 
	 */
	private SGFigureIDSelectionWizardDialog mFigureIDSelectionWizardDialog = null;


	/**
	 * 
	 */
	private SGMultiDataFileChooserWizardDialog mMultiDataFileChooserWizardDialog = null;


	/**
	 * 
	 */
	private SGSingleDataFileChooserWizardDialog mSingleDataFileChooserWizardDilaog = null;



	/**
	 * 
	 */
	private SGXYDataTypeSelectionWizardDialog mXYDataTypeSelectionWizardDialog = null;



	/**
	 * 
	 */
	private SGXYDataTypeSelectionWizardDialog mXYDataTypeSelectionWizardDialogFromCLorDD = null;


	/**
	 * 
	 */
	private SGPropertyFileChooserWizardDialog mPropertyFileChooserWizardDilaog = null;



	/**
	 * 
	 */
	private boolean createAllWizardDialogsForDataAdditionFromToolBar( final SGDrawingWindow owner )
	{

		//
		// create dialog objects
		//

		// dialog to select ID of window and figure
		this.mFigureIDSelectionWizardDialog
			= new SGFigureIDSelectionWizardDialog( owner, true );
		this.mFigureIDSelectionWizardDialog.getOKButton().setVisible(false);
		this.mFigureIDSelectionWizardDialog.getPreviousButton().setVisible(false);
		this.mFigureIDSelectionWizardDialog.pack();


		// dialog to select data files
		this.mSingleDataFileChooserWizardDilaog
			= new SGSingleDataFileChooserWizardDialog( owner, true );
		this.mSingleDataFileChooserWizardDilaog.getOKButton().setVisible(false);
		this.mSingleDataFileChooserWizardDilaog.pack();


		// set the selected file name
		String path = this.getCurrentFileDirectory();
		this.mSingleDataFileChooserWizardDilaog.setFile( path, this.mCurrentDataFileName );


		// dialog to select the data-type
		this.mXYDataTypeSelectionWizardDialog
			= new SGXYDataTypeSelectionWizardDialog( owner, true );
		this.mXYDataTypeSelectionWizardDialog.getNextButton().setVisible(false);
		this.mXYDataTypeSelectionWizardDialog.pack();


		//
		// set next and previous dialogs
		//
		
		this.mFigureIDSelectionWizardDialog.setNext( this.mSingleDataFileChooserWizardDilaog );
		this.mSingleDataFileChooserWizardDilaog.setPrevious( this.mFigureIDSelectionWizardDialog );
		this.mSingleDataFileChooserWizardDilaog.setNext( this.mXYDataTypeSelectionWizardDialog );
		this.mXYDataTypeSelectionWizardDialog.setPrevious( this.mSingleDataFileChooserWizardDilaog );


		//
		// add action listener
		//

		this.mFigureIDSelectionWizardDialog.addActionListener(this);
		this.mSingleDataFileChooserWizardDilaog.addActionListener(this);
		this.mXYDataTypeSelectionWizardDialog.addActionListener(this);

		return true;
	}



	/**
	 * Path name of the selected data file.
	 */
//	private String mCurrentFileDirectory = null;


	/**
	 * 
	 */
	private String mCurrentDataFileName = null;


	/**
	 * 
	 */
	private String mCurrentPropertyFileName = null;

	/**
	 * 
	 */
	private String mCurrentImageFileName = null;

	/**
	 * 
	 */
	private String mCurrentArchiveFileName = null;

	/**
	 * Returns the current file directory.
	 *
	 */
	private String getCurrentFileDirectory()
	{
		Preferences pref = Preferences.userNodeForPackage( this.getClass() );
		String currentDir = pref.get( PREF_KEY_CURRENT_DIRECTORY, null );

		boolean b = false;
		if( currentDir==null )
		{
			b = true;
		}
		else
		{
			File f = new File( currentDir );
			if( f.exists() == false )
			{
				b = true;
			}
		}

		if( b )
		{
			String path = USER_HOME;
			if( SGUtility.identifyOS( OS_NAME_WINDOWS ) )
			{
				path += FILE_SEPARATOR + MY_DOCUMENTS;
			}
			this.setCurrentFileDirectory(path);
			currentDir = path;
		}
		
		return currentDir;
	}



	/**
	 * 
	 * @param path
	 */
	private void setCurrentFileDirectory( final String path )
	{
		Preferences pref = Preferences.userNodeForPackage( this.getClass() );
		pref.put( PREF_KEY_CURRENT_DIRECTORY, path );
//		this.mCurrentFileDirectory = path;
//System.out.println(path);
	}


	/**
	 * 
	 */
	private boolean createAllWizardDialogsToLoadPropertyFromToolBar(
		final SGDrawingWindow owner )
	{
		
		//
		// create dialog objects
		//

		// dialog to load property file
		this.mPropertyFileChooserWizardDilaog
			= new SGPropertyFileChooserWizardDialog( owner, true );
		this.mPropertyFileChooserWizardDilaog.getPreviousButton().setVisible(false);
		this.mPropertyFileChooserWizardDilaog.getOKButton().setVisible(false);
		this.mPropertyFileChooserWizardDilaog.pack();


		// dialog to select data files
		this.mMultiDataFileChooserWizardDialog
			= new SGMultiDataFileChooserWizardDialog( owner, true );
		this.mMultiDataFileChooserWizardDialog.getNextButton().setVisible(false);
		this.mMultiDataFileChooserWizardDialog.pack();


		// create a file filter object
		SGExtensionFileFilter ff = new SGExtensionFileFilter();
		ff.setDescription( PROPERTY_FILE_DESCRIPTION );
		ff.addExtension( PROPERTY_FILE_EXTENSION );
		this.mPropertyFileChooserWizardDilaog.setFileFilter(ff);


		// get current path
		String path = this.getCurrentFileDirectory();

		// set the selected file name
		this.mPropertyFileChooserWizardDilaog.setFile( path, this.mCurrentPropertyFileName );

		// set the selected file name
		this.mMultiDataFileChooserWizardDialog.setFile( path, this.mCurrentDataFileName );

//System.out.println(path);
//System.out.println(this.mCurrentPropertyFileName);
//System.out.println(this.mCurrentDataFileName);
//System.out.println();


		//
		// next and previous dialog
		//

		this.mPropertyFileChooserWizardDilaog.setNext(
			this.mMultiDataFileChooserWizardDialog );
		this.mMultiDataFileChooserWizardDialog.setPrevious(
			this.mPropertyFileChooserWizardDilaog );				


		//
		// add action listener
		//

		this.mPropertyFileChooserWizardDilaog.addActionListener(this);
		this.mMultiDataFileChooserWizardDialog.addActionListener(this);


		return true;
	}



	/**
	 * 
	 */
	private int readFile(
		final String pathName,
		final ArrayList infoList )
	{

		final Window owner = this.mXYDataTypeSelectionWizardDialogFromCLorDD.getOwner();

		ArrayList cList = new ArrayList();
		try
		{
			if( this.mDataCreator.getFileTypeCandidateList( pathName, cList ) == false )
			{
				return -1;
			}
		}
		catch( FileNotFoundException ex )
		{
			return -1;
		}

		if( cList.size() == 0 )
		{
			return -1;
		}


		String fileType = null;

		// set candidate data-type to the dialog
		if( this.mXYDataTypeSelectionWizardDialogFromCLorDD.setEffectiveDataType(cList) == false )
		{
			return -1;
		}


		// set the location of wizard dialog
		this.mXYDataTypeSelectionWizardDialogFromCLorDD.setCenter( owner );


		// show a modal dialog to choose data-type from candidates
		this.mXYDataTypeSelectionWizardDialogFromCLorDD.setVisible(true);


		//
		// A modal dialog is shown.
		//

		// if canceled, return 1
		final int status = this.mXYDataTypeSelectionWizardDialogFromCLorDD.getCloseOption();
		if( status==SGWizardDialog.CANCEL_OPTION )
		{
			return 1;
		}

	
		// get selected file type
		fileType = this.mXYDataTypeSelectionWizardDialogFromCLorDD.getSelectedDataType();
		if( fileType == null )
		{
			return -1;
		}


		// add information to the list
		infoList.add(fileType);


		// create an array for data-retention
		if( fileType.equals(SGDataTypeConstants.SXY_SAMPLING_DATA) )
		{
			// add information of the sampling rate
			Double d = this.mXYDataTypeSelectionWizardDialogFromCLorDD.getSamplingRate();
			if( d==null )
			{
				return -1;
			}
			infoList.add(d);
		}
		else if( fileType.equals( SGDataTypeConstants.VXY_DATA ) )
		{
			boolean b = this.mXYDataTypeSelectionWizardDialogFromCLorDD.isPolarSelected();
			infoList.add( Boolean.valueOf(b) );
		}

		return 0;
	}



	/**
	 * Create a new window.
	 * @return a created window
	 */
	public SGDrawingWindow createNewWindow()
	{
		SGDrawingWindow wnd = this.createWindow();
		if( wnd==null )
		{
			return null;
		}
		wnd.initPropertiesHistory();
		return wnd;
	}


	/**
	 * Create a new window.
	 * @return a created window
	 */
	private SGDrawingWindow createWindow()
	{
		final int id = this.getCurrentWindowID();
		SGDrawingWindow wnd = this.createWindow(id);
		return wnd;
	}


	/**
	 * 
	 */
	public static final String WINDOW_TITLE_PREFIX = "Samurai Graph - Window : ";


	/**
	 * Create a window with given ID number.
	 * @param id ID number
	 * @return a created window
	 */
	private SGDrawingWindow createWindow( final int id )
	{
		
		// create an instance
		SGDrawingWindow wnd = new SGDrawingWindow();

		// set ID number
		wnd.setID( id );

		// put into the map
		this.mWndMap.put( new Integer(id), wnd );

		// set the close operation
		wnd.setDefaultCloseOperation( JFrame.DO_NOTHING_ON_CLOSE );

		// set window title
		String title = WINDOW_TITLE_PREFIX + wnd.getID();
		wnd.setTitle(title);


		// add this class as an ActionListener of the window
		wnd.addActionListener(this);

		// add this class as a WindowListener of the window
		wnd.addWindowListener(this);

		// add this class as a PropertyChangeListener of the window
		wnd.addPropertyChangeListener(this);


		// create and set the drop target
		DropTarget target = new DropTarget(
			wnd,
			DnDConstants.ACTION_COPY_OR_MOVE,
			this,
			true
		);
		wnd.setDropTarget(target);


		//
		wnd.setImageFileCreator( this.mImageFileCreator );


		// set the tool bar pattern
		Preferences pref = Preferences.userNodeForPackage( this.getClass() );
		final String pattern = pref.get( PREF_KEY_TOOL_BAR_PATTERN, null );
		String[] array;
		if( pattern!=null )
		{
			// tokenize a string
			ArrayList strList = new ArrayList();
			if( SGUtilityText.tokenize( pattern, strList ) )
			{
				ArrayList keyList = new ArrayList();
				for( int ii=0; ii<strList.size(); ii++ )
				{
					String token = (String)strList.get(ii);
					if( token!=null )
					{
						keyList.add( token );
					}
				}

				array = new String[keyList.size()];
				for( int ii=0; ii<keyList.size(); ii++ )
				{
					array[ii] = (String)keyList.get(ii);
				}
			}
			else
			{
				array = SGIRootObjectConstants.TOOLBAR_MENUCMD_ARRAY;
			}
		}
		else
		{
//			array = SGIRootObjectConstants.TOOLBAR_MENUCMD_ARRAY;

			array = new String[]{
				MENUBARCMD_VISIBLE_FILE,
				MENUBARCMD_VISIBLE_INSERT,
				MENUBARCMD_VISIBLE_ZOOM
			};

			// set to preferences
			updateToolBarPatternInPreferences( array );
		}


		// set to the window
		wnd.setToolBarPattern( array );


		// set the location of the window
		{
			wnd.setLocation(100,100);
		}

		// initialize
		if( wnd.init() == false )
		{
			return null;
		}

		// set the menus enabled
		this.setPasteMenuEnabled();	// paste

		return wnd;
	}



	/**
	 * Returns the ID number for a window to be created.
	 * @return ID number
	 */
	private int getCurrentWindowID()
	{
		int id;
		if( this.mWndMap.size()==0 )
		{
			id = 1;
		}
		else
		{
			id = ((Integer)this.mWndMap.lastKey()).intValue() + 1;
		}
		return id;
	}



	/**
	 * 
	 */
	private int setPropertyFile(
		final SGDrawingWindow wnd,
		final Element elWnd,
		final Map dataMap )
	{
		if( wnd.readProperty( elWnd ) == false )
		{
			return SGIConstants.PROPERTY_FILE_INCORRECT;
		}

		// create figure objects in a window
		int ret = this.createFiguresFromPropertyFile(
			elWnd, wnd, dataMap );
		if( ret!=SGIConstants.SUCCESSFUL_COMPLETION )
		{
			return ret;
		}

		// add history
		wnd.initPropertiesHistory();

		// initialize the history of save
		wnd.initSavedHistory();

		// set the saved flag
		wnd.setSaved(true);

		return SGIConstants.SUCCESSFUL_COMPLETION;
	}
	

	//
	private Element getWindowElement( Document doc )
	{
		Element root = doc.getDocumentElement();

		// get the node of window
		NodeList wList = root.getElementsByTagName( SGDrawingWindow.TAG_NAME_WINDOW );
		if( wList.getLength()==0 )
		{
			return null;
		}
		Element elWnd = (Element)wList.item(0);

		return elWnd;
	}

	
	/**
	 * 
	 * @return
	 */
	private boolean setPropertyFile(
		final SGDrawingWindow wnd,
		final Document doc,
		final Map dataMap )
	{

		// Element of the window
		Element elWnd = this.getWindowElement( doc );

		// set the property of the created window from property file
		int ret = this.setPropertyFile( wnd, elWnd, dataMap );

		// get the message
		String msg = null;
		if( ret == SGIConstants.SUCCESSFUL_COMPLETION )
		{
			msg = MSG_SUCCESSFUL_COMPLETION;
		}
		else if( ret == SGIConstants.DATA_NUMBER_SHORTAGE )
		{
			msg = MSG_DATA_NUMBER_SHORTAGE;
		}
		else if( ret == SGIConstants.DATA_NUMBER_EXCESS )
		{
			msg = MSG_DATA_NUMBER_EXCESS;
		}
		else if( ret == SGIConstants.FILE_OPEN_FAILURE )
		{
			msg = MSG_FILE_OPEN_FAILURE;
		}
		else if( ret == SGIConstants.PROPERTY_FILE_INCORRECT )
		{
			msg = MSG_PROPERTY_FILE_INVALID;
		}
		else if( ret == SGIConstants.DATA_FILE_INVALID )
		{
			msg = MSG_DATA_FILE_INVALID;
		}
		else
		{
			throw new Error();
		}

		// show the message dialog
		if( msg!=MSG_SUCCESSFUL_COMPLETION )
		{
			SGUtility.showMessageDialog(
				null, msg, "Property file",
				JOptionPane.ERROR_MESSAGE
			);
			return false;
		}

		return true;
	}
	
	
	
	/**
	 * 
	 * @param elWnd
	 * @param wnd
	 * @return
	 */
	private int createFiguresFromPropertyFile(
		final Element elWnd,
		final SGDrawingWindow wnd,
		final Map dataMap )
	{
		final int ic = SGIConstants.PROPERTY_FILE_INCORRECT;

		Set keySet = dataMap.keySet();
		ArrayList dataListList = new ArrayList( dataMap.values() );

		NodeList nList = elWnd.getElementsByTagName( SGFigure.TAG_NAME_FIGURE );
		final int len = nList.getLength();
		for( int ii=0; ii<len; ii++ )
		{
			Node node = nList.item(ii);
			if( node instanceof Element )
			{
				Element el = (Element)node;
				ArrayList dataList = (ArrayList)dataListList.get(ii);
				if( dataList.contains( SGMultiDataFileChooserWizardDialog.NO_DATA ) )
				{
					dataList = new ArrayList();
				}
				final int ret = this.createSingleFigureFromPropertyFile(
					el, wnd, dataList );
				if( ret!=SGIConstants.SUCCESSFUL_COMPLETION )
				{
					return ret;
				}
			}
		}
		
		return SGIConstants.SUCCESSFUL_COMPLETION;
	}

	
	
	/**
	 * 
	 * @param elFigure
	 * @param figure
	 * @return
	 */
	private int createSingleFigureFromPropertyFile(
		final Element elFigure,
		final SGDrawingWindow wnd,
		final ArrayList dataList )
	{
		
		final int ic = SGIConstants.PROPERTY_FILE_INCORRECT;
		
		String str = null;
		Number num = null;
		Boolean b = null;
		Color cl = null;


		//
		// the name of instance
		//

		str = elFigure.getAttribute( SGFigure.KEY_FIGURE_TYPE );
		if( str.length()==0 )
		{
			return ic;
		}
//		String className;

		SGFigure figure = null;

		if( str.equals( SGIFigureTypeConstants.FIGURE_TYPE_SXY ) )
		{
			figure = new SGSXYFigure( wnd );
//			className = SGSXYFigure.class.getName();
		}
		else if( str.equals( SGIFigureTypeConstants.FIGURE_TYPE_VXY ) )
		{
			figure = new SGVXYFigure( wnd );
//			className = SGVXYFigure.class.getName();
		}
		else
		{
			return ic;
		}


		//
		// create a figure
		//

//		try
//		{
//			Class fClass = Class.forName( className );
//			figure = (SGFigure)fClass.newInstance();
//		}
//		catch( Exception ex )
//		{
//			return ic;
//		}
//		figure.setWindow( wnd );
//		figure.setComponent( wnd.getFigurePanel() );

		final int figureID = wnd.getCurrentFigureId();
		figure.setID( figureID );


		//
		// create SGIFigureElement objects
		//

		if( figure.readProperty( elFigure ) == false )
		{
			return ic;
		}

		if( this.createFigureElementFromPropertyFile( figure, elFigure ) == ic )
		{
			return ic;
		}


		//
		// called after created SGIAxisElement object
		//

		// space axis line and numbers
		str = elFigure.getAttribute( SGFigure.KEY_SPACE_AXIS_LINE_AND_NUMBER );
		if( str.length()!=0 )
		{
			StringBuffer uSpaceLN = new StringBuffer();
			num = SGUtilityText.getNumber( str, uSpaceLN );
			if( num==null )
			{
				return ic;
			}
			final float spaceLN = num.floatValue();
			if( figure.setSpaceAxisLineAndNumber( spaceLN, uSpaceLN.toString() ) == false )
			{
				return ic;
			}
		}


		// space numbers and title
		str = elFigure.getAttribute( SGFigure.KEY_SPACE_NUMBER_AND_TITLE );
		if( str.length()!=0 )
		{
			StringBuffer uSpaceNT = new StringBuffer();
			num = SGUtilityText.getNumber( str, uSpaceNT );
			if( num==null )
			{
				return ic;
			}
			final float spaceNT = num.floatValue();
			if( figure.setSpaceNumberAndTitle( spaceNT, uSpaceNT.toString() ) == false )
			{
				return ic;
			}
		}


		// create data objects
		final int ret = this.createDataObjectsFromPropertyFile(
			elFigure, figure, dataList );
		if( ret!=SGIConstants.SUCCESSFUL_COMPLETION )
		{
			return ret;
		}


		// add the figure to the window
		wnd.addFigure( figure );


		//
		// initialize properties of the figure and figure elements
		//
		
		figure.initPropertiesHistory();


		return SGIConstants.SUCCESSFUL_COMPLETION;
	}
	
	

	
	/**
	 * 
	 * @param figure
	 * @param element
	 * @return
	 */
	public int createFigureElementFromPropertyFile(
		final SGFigure figure, final Element fElement )
	{
		NodeList nList = null;
		Element element = null;
		SGIFigureElement el = null;

		Frame owner = figure.getWindow();
		final int ic = SGIConstants.PROPERTY_FILE_INCORRECT;
		Rectangle2D gRect = figure.getGraphRect();
		

		// axis
		el = this.setIElement( this.mClassOfAxisElement, figure, owner );
		if( el==null )
		{
			return ic;
		}
		el.setGraphRect( gRect );
		SGIAxisElement axisElement = (SGIAxisElement)el;
		figure.setIFigureElement( LAYER_AXIS, axisElement );
		nList = fElement.getElementsByTagName( SGIAxisElement.TAG_NAME_AXES );
		element = (Element)nList.item(0);
		if( el.readProperty( element ) == false )
		{
			return ic;
		}


		// graph
		nList = fElement.getElementsByTagName( SGIGraphElement.TAG_NAME_GRAPH );
		element = (Element)nList.item(0);
		final Class cl;
		if( figure instanceof SGSXYFigure )
		{
			cl = this.mClassOfSXYGraphElement;
		}
		else if( figure instanceof SGVXYFigure )
		{
			cl = this.mClassOfVXYGraphElement;
		}
		else
		{
			throw new Error();
		}
		el = this.setIElement( cl, figure, owner );
		if( el==null )
		{
			return ic;
		}
		el.setGraphRect( gRect );
		SGIGraphElement graphElement = (SGIGraphElement)el;
		figure.setIFigureElement( LAYER_GRAPH, graphElement );
		

		// legend
		el = this.setIElement( this.mClassOfLegendElement, figure, owner );
		if( el==null )
		{
			return ic;
		}
		el.setGraphRect( gRect );
		SGILegendElement legendElement = (SGILegendElement)el;
		figure.setIFigureElement( LAYER_LEGEND, legendElement );
		legendElement.setAxisElement(axisElement);	// set in advance
		nList = fElement.getElementsByTagName( SGILegendElement.TAG_NAME_LEGEND );
		if( nList.getLength()!=0 )
		{
			element = (Element)nList.item(0);
			if( el.readProperty(element) == false )
			{
				return ic;
			}
		}


		// string
		el = this.setIElement( this.mClassOfStringElement, figure, owner );
		if( el==null )
		{
			return ic;
		}
		el.setGraphRect( gRect );
		SGIStringElement stringElement = (SGIStringElement)el;
		figure.setIFigureElement( LAYER_STRING, stringElement );
		stringElement.setAxisElement(axisElement);		// set in advance
		nList = fElement.getElementsByTagName( SGIStringElement.TAG_NAME_STRING_ELEMENT );
		if( nList.getLength()!=0 )
		{
			element = (Element)nList.item(0);
			if( el.readProperty(element) == false )
			{
				return ic;
			}
		}

		
		// axis break
		el = this.setIElement( this.mClassOfAxisBreakElement, figure, owner );
		if( el==null )
		{
			return ic;
		}
		el.setGraphRect( gRect );
		SGIAxisBreakElement axisBreakElement = (SGIAxisBreakElement)el;
		figure.setIFigureElement( LAYER_AXIS_BREAK, axisBreakElement );
		axisBreakElement.setAxisElement(axisElement);		// set in advance
		nList = fElement.getElementsByTagName( SGIAxisBreakElement.TAG_NAME_AXIS_BREAK );
		if( nList.getLength()!=0 )
		{
			element = (Element)nList.item(0);
			if( el.readProperty(element) == false )
			{
				return ic;
			}
		}

		
		// significant difference
		el = this.setIElement( this.mClassOfSignificantDifferenceElement, figure, owner );
		if( el==null )
		{
			return ic;
		}
		el.setGraphRect( gRect );
		SGISignificantDifferenceElement sigDiffElement = (SGISignificantDifferenceElement)el;
		figure.setIFigureElement( LAYER_SIGNIFICANT_DIFFERENCE, sigDiffElement );
		sigDiffElement.setAxisElement(axisElement);	// set in advance
		nList = fElement.getElementsByTagName( SGISignificantDifferenceElement.TAG_NAME_SIGNIFICANT_DIFFERENCE );
		if( nList.getLength()!=0 )
		{
			element = (Element)nList.item(0);
			if( el.readProperty(element) == false )
			{
				return ic;
			}
		}

		
		// timing line
		el = this.setIElement( this.mClassOfTimingLineElement, figure, owner );
		if( el==null )
		{
			return ic;
		}
		el.setGraphRect( gRect );
		SGITimingLineElement timingLineElement = (SGITimingLineElement)el;
		figure.setIFigureElement( LAYER_TIMING_LINE, timingLineElement );
		timingLineElement.setAxisElement(axisElement);	// set in advance
		nList = fElement.getElementsByTagName( SGITimingLineElement.TAG_NAME_TIMING_LINES );
		if( nList.getLength()!=0 )
		{
			element = (Element)nList.item(0);
			if( el.readProperty(element) == false )
			{
				return ic;
			}
		}


//
// Added from version 0.5.0
//
		// grid
		el = this.setIElement( this.mClassOfGridElement, figure, owner );
		if( el==null )
		{
			return ic;
		}
		el.setGraphRect( gRect );
		SGIGridElement gridElement = (SGIGridElement)el;
		figure.setIFigureElement( LAYER_GRID, gridElement );
		gridElement.setAxisElement(axisElement);	// set in advance
		nList = fElement.getElementsByTagName( SGIGridElement.TAG_NAME_GRID_ELEMENT );
		if( nList.getLength()!=0 )
		{
			element = (Element)nList.item(0);
			if( el.readProperty(element) == false )
			{
				return ic;
			}
		}


//
// Added from version 0.8.0
//

		// shape
		el = this.setIElement( this.mClassOfShapeElement, figure, owner );
		SGIShapeElement shapeElement = (SGIShapeElement)el;
		if( el==null )
		{
			return ic;
		}
		el.setGraphRect( gRect );
		figure.setIFigureElement( LAYER_SHAPE, shapeElement );
		shapeElement.setAxisElement(axisElement);	// set in advance
		nList = fElement.getElementsByTagName( SGIShapeElement.TAG_NAME_SHAPE );
		if( nList.getLength()!=0 )
		{
			element = (Element)nList.item(0);
			if( el.readProperty(element) == false )
			{
				return ic;
			}
		}


		// set relation between SGIFigureElement objects
		this.setRelationOfFigureElements( figure );

		return SGIConstants.SUCCESSFUL_COMPLETION;
	}


	
	// create the data object	
	private int createDataObjectsFromPropertyFile(
		final Element elFigure, final SGFigure figure, final ArrayList dataList )
	{

		final int ic = SGIConstants.PROPERTY_FILE_INCORRECT;
		final int di = SGIConstants.DATA_FILE_INVALID;

		NodeList nList = elFigure.getElementsByTagName( SGIGraphElement.TAG_NAME_DATA );
		if( nList.getLength()!=dataList.size() )
		{
			return ic;
		}

		final int len = nList.getLength();
		for( int ii=0; ii<len; ii++ )
		{

			//
			// get information from the Element object
			//

			Node node = nList.item(ii);
			if( ( node instanceof Element ) == false )
			{
				continue;
			}

			Element elData = (Element)node;

			ArrayList infoList = new ArrayList();

			// class
			String dataType = elData.getAttribute( SGIGraphElement.KEY_DATA_TYPE );
			if( dataType==null )
			{
				return ic;
			}
			infoList.add(dataType);

			
			String className = null;
			if( dataType.equals( SGDataTypeConstants.SXY_DATA ) )
			{
				className = SGSXYData.class.getName();
			}
			else if( dataType.equals( SGDataTypeConstants.VXY_DATA ) )
			{
				className = SGVXYData.class.getName();

				String str = elData.getAttribute( SGIGraphElement.KEY_POLAR );
				if( str.length()==0 )
				{
					return ic;
				}
				Boolean b = SGUtilityText.getBoolean(str);
				if( b==null )
				{
					return ic;
				}
				infoList.add(b);
			}
			else if( dataType.equals( SGDataTypeConstants.SXY_MULTIPLE_DATA ) )
			{
				className = SGSXYMultipleData.class.getName();
			}
			else if( dataType.equals( SGDataTypeConstants.SXY_SAMPLING_DATA ) )
			{
				className = SGSXYSamplingData.class.getName();

				String str = elData.getAttribute( SGIGraphElement.KEY_SAMPLING_RATE );
				if( str.length()==0 )
				{
					return ic;
				}
				Double d = SGUtilityText.getDouble(str);
				if( d==null )
				{
					return ic;
				}
				infoList.add(d);
			}
			else if( dataType.equals( SGDataTypeConstants.SXY_DATE_DATA ) )
			{
				className = SGSXYDateData.class.getName();
			}
			else
			{
				return ic;
			}


			// get the Class object
			Class cl = null;
			try
			{
				cl = Class.forName(className);
			}
			catch( ClassNotFoundException ex )
			{
				return ic;
			}
			if( cl==null )
			{
				return ic;
			}


			// create a new SGData object
			SGData data = null;
			try
			{
				data = (SGData)cl.newInstance();
			}
			catch( Exception ex )
			{
				return ic;
			}
			if( data==null )
			{
				return ic;
			}


			// get the data file
			if( dataList.size() == 0 )
			{
				return SGIConstants.DATA_NUMBER_SHORTAGE;
			}


			// get an object from dataList
			Object obj = dataList.get(ii);
			if( obj instanceof String )
			{
				String fileName = (String)obj;
			
				// check the type of data
				ArrayList cList = new ArrayList();
				Frame owner = figure.getWindow();

				try
				{
					if( this.mDataCreator.getFileTypeCandidateList( fileName, cList ) == false )
					{
						return di;
					}
					if( cList.size()==0 || cList.contains(dataType)==false )
					{
						return di;
					}
			
					// create data object
					SGData data_ = this.mDataCreator.create( fileName, infoList );
					if( data_ == null )
					{
						return di;
					}
					if( data.setData(data_) == false )
					{
						return di;
					}
				}
				catch( FileNotFoundException ex )
				{
					return SGIConstants.FILE_OPEN_FAILURE;
				}

			}
			else if( obj instanceof SGData )
			{
				SGData data_ = (SGData)obj;
				if( data.setData( data_ ) == false )
				{
					return ic;
				}
			}
			else
			{
				return ic;
			}


			//
			if( figure.createDataObjectFromPropertyFile( elData, data ) == false )
			{
				return ic;
			}
			
		}
		
		
		SGIFigureElement[] array = figure.getIFigureElementArray();
		for( int ii=0; ii<array.length; ii++ )
		{
			array[ii].initPropertiesHistory();
		}

		return SGIConstants.SUCCESSFUL_COMPLETION;

	}



	/**
	 * 
	 */
	private boolean actionFromWindow( final ActionEvent e )
	{

		Object source = e.getSource();
		String command = e.getActionCommand();

		SGDrawingWindow wnd = (SGDrawingWindow)source;

		if( command.equals( MENUBARCMD_CREATE_NEW_WINDOW ) )
		{
			SGDrawingWindow w = this.createNewWindow();
			if( w==null )
			{
				return false;
			}
			w.setVisible(true);
		}
		else if( command.equals( MENUBARCMD_CLOSE_WINDOW ) )
		{
			this.closeWindow( wnd );
		}
		else if( command.equals( MENUBARCMD_EXIT ) )
		{
			this.exit();
		}
		else if( command.equals( MENUBARCMD_DRAW_GRAPH ) )
		{
			// create wizard dialogs
			this.createAllWizardDialogsForDataAdditionFromToolBar( wnd );

			// set location
			this.mFigureIDSelectionWizardDialog.setCenter( wnd );

			// show the first wizard dialog
			this.mFigureIDSelectionWizardDialog.setVisible(true);

			// update the selected file name
			File f = this.mSingleDataFileChooserWizardDilaog.getSelectedFile();
			if( f!=null )
			{
				this.updateCurrentFile( f, FILE_TYPE_DATA );
			}
		}
		else if( command.equals( MENUBARCMD_SAVE_PROPERTY ) )
		{
			final int ret = this.saveProperties( wnd );
			wnd.setSaved( ret == OK_OPTION );
		}
		else if( command.equals( MENUBARCMD_LOAD_PROPERTY ) )
		{
			if( this.needsConfirmationBeforeDiscard( wnd ) )
			{
				final int ret = this.beforeDiscard(wnd);
				if( ret==CANCEL_OPTION )
				{
					return true;
				}
			}

			// create wizard dialogs
			this.createAllWizardDialogsToLoadPropertyFromToolBar( wnd );

			// set location
			this.mPropertyFileChooserWizardDilaog.setCenter( wnd );

			// show the first wizard dialog
			this.mPropertyFileChooserWizardDilaog.setVisible(true);
			
			// update the selected file name
			File pf = this.mPropertyFileChooserWizardDilaog.getSelectedFile();
			File df = this.mMultiDataFileChooserWizardDialog.getSelectedFile();
			final long pUsed = this.mPropertyFileChooserWizardDilaog.lastUsed();
			final long dUsed = this.mMultiDataFileChooserWizardDialog.lastUsed();
			if( pf!=null & df!=null )
			{
				if( pUsed < dUsed )
				{
					this.updateCurrentFile( df, FILE_TYPE_DATA );
				}
				else
				{
					this.updateCurrentFile( pf, FILE_TYPE_PROPERTY );
				}
			}
			else if( pf!=null )
			{
				this.updateCurrentFile( pf, FILE_TYPE_PROPERTY );
			}
			else if( df!=null )
			{
				this.updateCurrentFile( df, FILE_TYPE_DATA );
			}
		}
		else if( command.equals( MENUBARCMD_SAVE_DATASET ) )
		{
			final int ret = this.saveDataSet( wnd );
			wnd.setSaved( ret == OK_OPTION );
		}
		else if( command.equals( MENUBARCMD_LOAD_DATASET ) )
		{
			if( this.needsConfirmationBeforeDiscard(wnd) )
			{
				final int ret = this.beforeDiscard(wnd);
				if( ret==CANCEL_OPTION )
				{
					return true;
				}
			}
			final int ret = this.loadDataSet( wnd );
			wnd.setSaved( ret == OK_OPTION );
		}
		else if( command.equals( MENUBARCMD_LOAD_BACKGROUND_IMAGE ) )
		{
			JFileChooser chooser = new SGFileChooser();
			
			// set the file extension filter
			SGExtensionFileFilter ff = new SGExtensionFileFilter();
			ff.setDescription( IMAGE_FILE_DESCRIPTION );

			String[] extensions = DRAWABLE_IMAGE_EXTENSIONS;
			for( int ii=0; ii<extensions.length; ii++ )
			{
				ff.addExtension( extensions[ii] );
			}
			chooser.setFileFilter(ff);

			// get current path
			String path = this.getCurrentFileDirectory();

			// set default directory name and file name of the image file
			String fileName = path;
			if( this.mCurrentImageFileName!=null )
			{
				fileName += FILE_SEPARATOR + this.mCurrentImageFileName;
			}
			chooser.setSelectedFile( new File( fileName ) );

			// show open dialog
			final int ret = chooser.showOpenDialog(wnd);

			File file = null;
			if( ret == JFileChooser.APPROVE_OPTION )
			{
				file = chooser.getSelectedFile();
			}

			// set the image to the window
			if( file!=null )
			{
				this.updateCurrentFile( file, FILE_TYPE_IMAGE );
				if( this.setImage( file, wnd ) == false )
				{
					return false;
				}
			}
		}
		else if( command.equals( MENUBARCMD_CUT ) )
		{
			this.cutAndCopy( wnd, false );
		}
		else if( command.equals( MENUBARCMD_COPY ) )
		{
			this.cutAndCopy( wnd, true );
		}
		else if( command.equals( MENUBARCMD_PASTE ) )
		{
			this.pasteToWindow( wnd );
		}
		else if( command.equals( MENUBARCMD_DUPLICATE ) )
		{
			if( this.duplicateFocusedFigures(wnd) == false )
			{
				return false;
			}
		}
		else if( command.equals( MENUBARCMD_EXPORT_AS_IMAGE ) )
		{
			this.mImageFileCreator.setBaseDirectory( this.getCurrentFileDirectory() );
			wnd.exportAsImage( false );
			this.setCurrentFileDirectory( this.mImageFileCreator.getBaseDirectory() );
		}
		else if( command.equals( MENUBARCMD_PRINT ) )
		{
			wnd.printImage( false );
		}
		else if( command.equals( MENUBARCMD_UPGRADE ) )
		{
			this.mUpgradeManager.showUpgradeDialog( wnd );
		}
		else if( command.equals( MENUBARCMD_CHANGE_LOG ) )
		{
			return this.showChangeLogDialog(wnd);
		}
		else if( command.equals( MENUBARCMD_PROXY ) )
		{
			return this.mProxyManager.showProxySettingDialog( wnd );
		}
		else if( command.equals( MENUBARCMD_ABOUT ) )
		{
			this.showAboutDialog(wnd);
		}

		return true;
	}


	/**
	 * Show a dialog to save properties.
	 * @param wnd
	 * @return
	 */
	private int saveProperties( final SGDrawingWindow wnd )
	{
		return this.saveProperties( wnd, this.getCurrentFileDirectory(), this.mCurrentPropertyFileName );
	}


	//
	private int saveProperties( final SGDrawingWindow wnd, final String dir, final String name )
	{
		// set the selected file name
		this.mPropertyFileCreator.setFile( dir, name );

		// create a property file
		final int ret = this.mPropertyFileCreator.create( wnd );
		if( ret!=OK_OPTION )
		{
			return ret;
		}

		File f = this.mPropertyFileCreator.getSelectedFile();
		if( f!=null )
		{
			this.updateCurrentFile( f, FILE_TYPE_PROPERTY );
		}

		return OK_OPTION;
	}


	//
	private int saveProperties( final SGDrawingWindow wnd, final String path )
	{
		// create a property file
		final int ret = this.mPropertyFileCreator.create( wnd, path );
		if( ret!=OK_OPTION )
		{
			return ret;
		}

		return OK_OPTION;
	}

	private static final String DATASET_TEMPDIR_NAME      = "SamuraiGraphArcvhive";
	private static final String DATASET_PROPERTY_FILENAME = "property.sgp";
	private static final String MSG_SAVE_DATASET_FAILED   = "Failed save dataset";
	private static final String MSG_LOAD_DATASET_FAILED   = "Failed load dataset";

	/**
	 * Show a dialog to save Archive.
	 * @param wnd
	 * @return
	 */
	private int saveDataSet( final SGDrawingWindow wnd )
	{
		return this.saveDataSet( wnd, this.getCurrentFileDirectory(), this.mCurrentArchiveFileName );
	}
	
	private ArrayList dumpDataSet( final SGDrawingWindow wnd, final File datasetDir )
	{
		ArrayList flist = new ArrayList();
		
		// output property file
		final String pfname = datasetDir.getPath() + FILE_SEPARATOR + DATASET_PROPERTY_FILENAME;
		int ret = saveProperties(wnd, pfname);
		if( ret!=OK_OPTION )
		{
			return null;
		}
		flist.add(new File(pfname));
		
		// output data files
		ArrayList figures = wnd.getVisibleFigureList();
		for(int ii=0; ii< figures.size(); ii++){
			SGFigure figure = (SGFigure)figures.get(ii);
			List dataList;
			dataList = figure.getVisibleDataList();
			for(int jj=0; jj<dataList.size(); jj++){
				SGData data = (SGData)dataList.get(jj);
				String fname = datasetDir.getPath() + FILE_SEPARATOR + "id" + ii + "-" + jj + ".csv";
				File file = new File(fname);
				if( !data.saveData(file) )
				{
					for(int kk=0; kk<flist.size(); kk++){
						File f = (File)flist.get(kk);
						f.delete();
					}	
					return null;
				}
				flist.add(file);				
			}
		}
		return flist;
		
	}
	
	//
	private int saveDataSet( final SGDrawingWindow wnd, final String dir, final String name )
	{
		final String failed = MSG_SAVE_DATASET_FAILED;
		ArrayList flist;
		
		// create temporary directory
		File datasetTempDir = new File( TMP_DIR + FILE_SEPARATOR + DATASET_TEMPDIR_NAME + System.currentTimeMillis() );
		if( datasetTempDir.mkdir() == false ){
			JOptionPane.showMessageDialog(wnd, failed);
			return -1;
		}

		flist = dumpDataSet( wnd, datasetTempDir );
		if ( flist == null ){
			JOptionPane.showMessageDialog(wnd, failed);
			datasetTempDir.delete();
			return -1;
		}
		
		// set the selected file name
		this.mArchiveFileCreator.setFile( dir, name );

		// create an archive file
		int ret = this.mArchiveFileCreator.create( wnd, datasetTempDir.getPath());
		
		// delete temporary files
		for(int kk=0; kk<flist.size(); kk++){
			File f = (File)flist.get(kk);
			f.delete();
		}	
		datasetTempDir.delete();
		
		if( ret!=OK_OPTION )
		{
			return ret;
		}

		File f = this.mArchiveFileCreator.getSelectedFile();
		if( f!=null )
		{
			this.updateCurrentFile( f, FILE_TYPE_DATASET );
		}

		return OK_OPTION;
	}
	
	//
	private int saveDataSet( final SGDrawingWindow wnd, final String path )
	{
		final String failed = MSG_SAVE_DATASET_FAILED;
		ArrayList flist;
		
		// create temporary directory
		File datasetTempDir = new File( TMP_DIR + FILE_SEPARATOR + DATASET_TEMPDIR_NAME + System.currentTimeMillis() );
		if( datasetTempDir.mkdir() == false ){
			JOptionPane.showMessageDialog(wnd, failed);
			return -1;
		}

		flist = dumpDataSet( wnd, datasetTempDir );
		if ( flist == null ){
			JOptionPane.showMessageDialog(wnd, failed);
			datasetTempDir.delete();
			return -1;
		}
		
		
		// create an archive file
		int ret = this.mArchiveFileCreator.create( wnd, datasetTempDir.getPath(), path);
		
		// delete temporary files
		for(int kk=0; kk<flist.size(); kk++){
			File f = (File)flist.get(kk);
			f.delete();
		}
		datasetTempDir.delete();
		
		if( ret!=OK_OPTION )
		{
			return ret;
		}

		File f = this.mArchiveFileCreator.getSelectedFile();
		if( f!=null )
		{
			this.updateCurrentFile( f, FILE_TYPE_DATASET );
		}

		return OK_OPTION;
	}


	private int loadDataSet( final SGDrawingWindow wnd )
	{
		ArrayList dfnameList = new ArrayList();
		String failed = MSG_LOAD_DATASET_FAILED;

//		// create temporary directory
//		File datasetTempDir = new File( TMP_DIR + FILE_SEPARATOR + DATASET_TEMPDIR_NAME + System.currentTimeMillis() );
//		if( datasetTempDir.mkdir() == false ){
//			JOptionPane.showMessageDialog(wnd, failed);
//			return -1;
//		}

		// create temporary directory
		File datasetTempDir = this.createTemporaryDirectory( wnd );
		if( datasetTempDir==null )
		{
			return -1;
		}
		
		int res = this.mArchiveFileExtractor.extract(wnd, datasetTempDir.getPath());
		ArrayList flist = this.mArchiveFileExtractor.getExtractedFileList();
		if(res != OK_OPTION){
			this.mArchiveFileExtractor.deleteExtractedFiles();
			datasetTempDir.delete();
			return res;
		}

//		// sort datalist
//		final String pfname = datasetTempDir.getAbsolutePath() + FILE_SEPARATOR + DATASET_PROPERTY_FILENAME;
//		if(!flist.contains(new File(pfname))){
//			this.mArchiveFileExtractor.deleteExtractedFiles();
//			datasetTempDir.delete();
//			return -1;
//		}
//		int jj=0;
//		for(int ii=0;;ii++){
//			for(jj=0;;jj++){
//				String fname = datasetTempDir.getAbsolutePath() + FILE_SEPARATOR + "id" + ii + "-" + jj + ".csv";
//				if(!flist.contains(new File(fname))) {
//					break;
//				}
//				dfnameList.add(fname);
//			}
//			if(jj==0){
//				break;
//			}
//		}
//			
//		res = loadDataSet(wnd, pfname, dfnameList);
//		this.mArchiveFileExtractor.deleteExtractedFiles();
//		datasetTempDir.delete();
//		
//		File f = this.mArchiveFileCreator.getSelectedFile();
//		if( f!=null )
//		{
//			this.updateCurrentFile( f, FILE_TYPE_DATASET );
//		}

		res = this.afterExtracted( wnd, datasetTempDir, flist );

		return res;
	}


	private int loadDataSet( final SGDrawingWindow wnd , final String pfname, final ArrayList dfnameList)
	{
		final File pfile = new File(pfname);
		if( pfile.exists()==false )
		{
			return -1;
		}
		final String path = SGUtility.getCanonicalPath( pfile.getPath() );
		if( path==null )
		{
			return -1;
		}

		// check validity of the file
		URL url = null;
		try
		{
			url = pfile.toURL();
		}
		catch( MalformedURLException ex )
		{
			return -1;
		}

		// create a Document object
		Document doc = SGUtilityText.getDocument( url );
		if( doc==null )
		{
			return -1;
		}

		//
		Element elWnd = this.getWindowElement( doc );
		NodeList nListFigure = elWnd.getElementsByTagName( SGFigure.TAG_NAME_FIGURE );
		final int figureNum = nListFigure.getLength();
		int cnt = 0;
		final int[] dataNumArray = new int[figureNum];
		for( int ii=0; ii<figureNum; ii++ )
		{
			Node node = nListFigure.item(ii);
			if( ( node instanceof Element ) == false )
			{
				return -1;
			}
			Element elFigure = (Element)node;
			NodeList nListData = elFigure.getElementsByTagName( SGIGraphElement.TAG_NAME_DATA );
			dataNumArray[ii] = nListData.getLength();
			cnt += dataNumArray[ii];
		}
		if( cnt != dfnameList.size() )
		{
			return -1;
		}
		
		// create a data map
		Map dataMap = new TreeMap();
		cnt = 0;
		for( int ii=0; ii<figureNum; ii++ )
		{
			final int dataNum = dataNumArray[ii];
			ArrayList dataList = new ArrayList();
			for( int jj=0; jj<dataNum; jj++ )
			{
//				System.out.println("prop(id:" + ii + ", no:" + jj +", filename:" + (String)dfnameList.get(cnt+jj) + ")");
				dataList.add( dfnameList.get(cnt+jj) );
			}
			dataMap.put( new Integer(ii), dataList );
			cnt+=dataNum;
		}

		// set properties
		wnd.clearUndoBuffer();
		wnd.removeAllFigures();
		wnd.updateClientRect();
		if( this.setPropertyFile( wnd, doc, dataMap ) == false )
		{
			return -1;
		}

		return OK_OPTION;	
	}


	//
	private int loadDataSet( final SGDrawingWindow wnd, File archiveFile )
	{
		// create temporary directory
		File datasetTempDir = this.createTemporaryDirectory( wnd );
		if( datasetTempDir==null )
		{
			return -1;
		}

		// extract
		int res = this.mArchiveFileExtractor.extract( wnd, datasetTempDir.getPath(), archiveFile );
		ArrayList flist = this.mArchiveFileExtractor.getExtractedFileList();
		if(res != OK_OPTION){
			this.mArchiveFileExtractor.deleteExtractedFiles();
			datasetTempDir.delete();
			return res;
		}

		res = this.afterExtracted( wnd, datasetTempDir, flist );

		return res;
	}


	// called after extracted an archive file
	private int afterExtracted( SGDrawingWindow wnd, File datasetTempDir, ArrayList flist )
	{
		// property file
		final String pfname = datasetTempDir.getAbsolutePath() + FILE_SEPARATOR + DATASET_PROPERTY_FILENAME;
		if(!flist.contains(new File(pfname))){
			this.mArchiveFileExtractor.deleteExtractedFiles();
			datasetTempDir.delete();
			return -1;
		}

		// sort datalist
		ArrayList dfnameList = new ArrayList();
		this.sortDataList( datasetTempDir, flist, dfnameList );

		// load
		int res = loadDataSet(wnd, pfname, dfnameList);
		this.mArchiveFileExtractor.deleteExtractedFiles();
		datasetTempDir.delete();
		
		File f = this.mArchiveFileCreator.getSelectedFile();
		if( f!=null )
		{
			this.updateCurrentFile( f, FILE_TYPE_DATASET );
		}

		return res;		
	}

	// create the temporary directory to extract an archive file
	private File createTemporaryDirectory( Component owner )
	{
		String failed = MSG_LOAD_DATASET_FAILED;

		// create temporary directory
		File datasetTempDir = new File( TMP_DIR + FILE_SEPARATOR + DATASET_TEMPDIR_NAME + System.currentTimeMillis() );
		if( datasetTempDir.mkdir() == false ){
			JOptionPane.showMessageDialog(owner, failed);
			return null;
		}
		
		return datasetTempDir;
	}


	// sort the list of data files
	private void sortDataList( File datasetTempDir, ArrayList flist, ArrayList dfnameList )
	{
		int jj=0;
		for(int ii=0;;ii++){
			for(jj=0;;jj++){
				String fname = datasetTempDir.getAbsolutePath() + FILE_SEPARATOR + "id" + ii + "-" + jj + ".csv";
				if(!flist.contains(new File(fname))) {
					break;
				}
				dfnameList.add(fname);
			}
			if(jj==0){
				break;
			}
		}
	}

	
	/**
	 * Cut or copy the objects.
	 * @param wnd
	 * @param isCopy a flag to set cut/copy
	 * @return true:succeeded, false:failed
	 */
	private boolean cutAndCopy( final SGDrawingWindow wnd, final boolean isCopy )
	{
		// initialize the lists
		this.mCopiedObjectsBuffer.clear();
		this.mCopiedDataObjectBuffer.clear();
		this.mCopiedDataNameBuffer.clear();
		this.mCopiedDataPropertiesBuffer.clear();

		// get copied objects list and add them to the buffer of the attribute
		ArrayList cList = wnd.getCopiedObjectsList();
		this.mCopiedObjectsBuffer.addAll( cList );

		ArrayList dList = wnd.getCopiedObjectsDataList();
		this.mCopiedDataObjectBuffer.addAll( dList );

		ArrayList nList = wnd.getCopiedDataNameList();
		this.mCopiedDataNameBuffer.addAll( nList );

		ArrayList pList = wnd.getCopiedDataPropertiesMapList();
		this.mCopiedDataPropertiesBuffer.addAll( pList );


		WindowInfo info = new WindowInfo();

		if( isCopy )
		{
			if( this.copyFigures( wnd, info ) == false )
			{
				return false;
			}
		}
		else
		{
			if( this.cutFigures( wnd, info ) == false )
			{
				return false;
			}
		}

		// set to the attribute
		this.mWindowInfo = info;


		// set the paste menu enabled
		this.setPasteMenuEnabled();

		return true;
	}


	/**
	 * 
	 *
	 */
	private void setPasteMenuEnabled()
	{
		final boolean b1 = (this.mCopiedObjectsBuffer.size()!=0);
		final boolean b2 = (this.mCopiedDataObjectBuffer.size()!=0);

		boolean b3 = false;
		if( this.mWindowInfo!=null )
		{
			Document doc = this.mWindowInfo.mDocument;
			NodeList nodeList = doc.getElementsByTagName( SGFigure.TAG_NAME_FIGURE );
			final int len = nodeList.getLength();
			b3 = (len!=0);
		}

		final boolean b = ( b1 | b2 | b3 );

		ArrayList wList = new ArrayList( this.mWndMap.values() );
		for( int ii=0; ii<wList.size(); ii++ )
		{
			SGDrawingWindow wnd = (SGDrawingWindow)wList.get(ii);
			wnd.setPasteMenuEnabled(b);
		}
	}



	/**
	 * Paste objects to the window.
	 * @param wnd - the target object
	 * @return
	 */
	private boolean pasteToWindow( SGDrawingWindow wnd )
	{
		// paste the copied objects to figures
		wnd.pasteToFigures(
			this.mCopiedObjectsBuffer,
			this.mCopiedDataObjectBuffer,
			this.mCopiedDataNameBuffer,
			this.mCopiedDataPropertiesBuffer );


		// paste the copied figure objects
		WindowInfo info = this.mWindowInfo;
		if( info==null )
		{
			return false;
		}
		Map dListMap = info.mDataListMap;
	
		// get root element
		Element root = info.mDocument.getDocumentElement();

		// get the node of window
		NodeList wList = root.getElementsByTagName( SGDrawingWindow.TAG_NAME_WINDOW );
		if( wList.getLength()==0 )
		{
			return false;
		}
		Element elWnd = (Element)wList.item(0);

		final int before = wnd.getFigureList().size();

		// create figures from a DOM tree
		final int ret = this.createFiguresFromPropertyFile( elWnd, wnd, dListMap );
		if( ret!=SGIConstants.SUCCESSFUL_COMPLETION )
		{
			return false;
		}

		final int after = wnd.getFigureList().size();
	
		wnd.setChanged( before!=after );

		return true;
	}




	/**
	 * Show the about dialog.
	 * @param wnd
	 */
	private void showAboutDialog( SGDrawingWindow wnd )
	{
		SGAboutDialog dg = new SGAboutDialog(wnd,true);

		final int width = dg.getWidth();
		final int height = dg.getHeight();

		final int x = wnd.getX() + wnd.getWidth()/2 - width/2;
		final int y = wnd.getY() + wnd.getHeight()/2 - height/2;

		dg.setLocation(x,y);

		// show a modal dialog
		dg.setVisible(true);

		// dispose			
		dg.dispose();
	}

	
	
	
	/**
	 * 
	 */
	public static final String TAG_NAME_FOCUSED_FIGURES = "FocusedFigures";

	
	/**
	 * 
	 * @return
	 */
	private boolean duplicateFocusedFigures( SGDrawingWindow wnd )
	{
		wnd.initProgressValue();
		
		DOMImplementation domImpl = SGApplicationUtility.getDOMImplementation();
		if( domImpl==null )
		{
			return false;
		}
	
		// create a Document object
		Document document = domImpl.createDocument( "", TAG_NAME_FOCUSED_FIGURES, null );

		// create a DOM tree
		if( wnd.createDOMTree( document, SGDrawingWindow.FOCUSED_FIGURES_FOR_DUPLICATION ) == false )
		{
			return false;
		}

//		wnd.setProgressValue(1.0f);

		// create a map of figure ID and data list
		TreeMap map = new TreeMap();

		ArrayList fList = wnd.getFocusedObjectsList();
		for( int ii=0; ii<fList.size(); ii++ )
		{
			SGFigure figure = (SGFigure)fList.get(ii);
			ArrayList dList = new ArrayList( figure.getVisibleDataList() );
			dList = (ArrayList)dList.clone();
			map.put( Integer.toString( figure.getID() ), dList );
		}


		// get root element - property
		Element root = document.getDocumentElement();

		// get the node of window
		NodeList wList = root.getElementsByTagName( SGDrawingWindow.TAG_NAME_WINDOW );
		if( wList.getLength()==0 )
		{
			return false;
		}
		Element elWnd = (Element)wList.item(0);

		int before = wnd.getFigureList().size();

		final int ret = this.createFiguresFromPropertyFile( elWnd, wnd, map );
		if( ret!=SGIConstants.SUCCESSFUL_COMPLETION )
		{
			return false;
		}

		int after = wnd.getFigureList().size();
		
		wnd.setChanged( before!=after );

		wnd.initProgressValue();

		return true;
	}



	/**
	 * 
	 * @return
	 */
	private boolean cutFigures(
		SGDrawingWindow wnd,
		WindowInfo info )
	{
		if( this.copyFigures( wnd, info ) == false )
		{
			return false;
		}
		
		if( info.mDataListMap.size()!=0 )
		{
			wnd.hideSelectedObjects();
		}

		return true;
	}


	/**
	 * 
	 * @return
	 */
	private boolean copyFigures( SGDrawingWindow wnd, WindowInfo info )
	{
		DOMImplementation domImpl = SGApplicationUtility.getDOMImplementation();
		if( domImpl==null )
		{
			return false;
		}

		// create a Document object
		Document document = domImpl.createDocument( "", TAG_NAME_FOCUSED_FIGURES, null );

		// create a DOM tree
		if( wnd.createDOMTree( document, SGDrawingWindow.FOCUSED_FIGURES_FOR_DUPLICATION ) == false )
		{
			return false;
		}

		// create a map of figure ID and data list
		Map dListMap = new TreeMap();
		ArrayList fList = wnd.getCopiedFiguresList();
		for( int ii=0; ii<fList.size(); ii++ )
		{
			SGFigure figure = (SGFigure)fList.get(ii);
			ArrayList dList = new ArrayList( figure.getVisibleDataList() );
			dList = (ArrayList)dList.clone();

			String key = Integer.toString( figure.getID() );
			dListMap.put( key, dList );
		}


		// set to the attribute
		info.mDocument = document;
		info.mDataListMap = dListMap;

		return true;
	}




	
	
	/**
	 * The list of copied objects.
	 */
	private ArrayList mCopiedObjectsBuffer = new ArrayList();
	
	
	/**
	 * 
	 */
	private ArrayList mCopiedDataObjectBuffer = new ArrayList();
	
	
	/**
	 * 
	 */
	private ArrayList mCopiedDataNameBuffer = new ArrayList();
	
	
	/**
	 * 
	 */
	private ArrayList mCopiedDataPropertiesBuffer = new ArrayList();


	/**
	 * 
	 */
	private ArrayList mCopiedDataPropertiesForLegendBuffer = new ArrayList();



	/**
	 * Inforamation of the focused figures.
	 */
	private WindowInfo mWindowInfo;


	/**
	 * A private class to store information of a figure.
	 */
	private class WindowInfo
	{
		/**
		 * A DOM tree object of figures.
		 */	
		private Document mDocument;

		/**
		 * The map of the list of data objects.
		 */		
		private Map mDataListMap = new TreeMap();

	}






//	private SGChangeLogDialog mChangeLogDialog = null;


	
	private Document createChangeLogDocument()
	{
		Class inClass = getClass();
		URL url = inClass.getResource( RESOURCES_DIRNAME + "ChangeLog.xml" );
		if( url==null )
		{
			return null;
		}
		Document doc = SGUtilityText.getDocument(url.toString());
		return doc;
	}
	
	
	
	/**
	 * 
	 * @return
	 */
	private boolean showChangeLogDialog( Frame owner )
	{
		// create and set a dialog object
		SGChangeLogDialog dg = new SGChangeLogDialog(owner,true);
		dg.addActionListener( this );
		dg.setCenter(owner);

		// set a message
		String msg = "Change Log of Samurai Graph.";
		dg.setMessage(msg);

		// get the file of change log
		Class inClass = getClass();
		URL url = inClass.getResource( RESOURCES_DIRNAME + "ChangeLog.html" );
		if( url==null )
		{
			JOptionPane.showMessageDialog(
				owner,
				"Failed to get log information."
			);
			return false;
		}
		
		// set the html file
		dg.setPage( url );
		dg.pack();

		// show
		dg.setVisible(true);

		// dispose
		dg.dispose();

		return true;
	}



	/**
	 * 
	 */
	private boolean fromCLorDDWizardDialog( final ActionEvent e )
	{
		Object source = e.getSource();
		SGWizardDialog dg = (SGWizardDialog)source;
		String command = e.getActionCommand();
		return true;
	}



	/**
	 * 
	 * @param e
	 * @return
	 */
	private boolean addDataByToolBar( final ActionEvent e )
	{

		Object source = e.getSource();
		SGWizardDialog dg = (SGWizardDialog)source;
		SGWizardDialog prev = dg.getPrevious();
		SGWizardDialog next = dg.getNext();
		String command = e.getActionCommand();
		Window owner = dg.getOwner();

		
		// cancel or previous
		if( command.equals( SGWizardDialog.CANCEL_BUTTON_TEXT ) )
		{
			dg.setVisible(false);
			return true;
		}
		else if( command.equals( SGWizardDialog.PREVIOUS_BUTTON_TEXT ) )
		{
			dg.showPrevious();
			return true;
		}


		// figure ID
		if( source.equals( this.mFigureIDSelectionWizardDialog ) )
		{
			if( command.equals( SGWizardDialog.NEXT_BUTTON_TEXT ) )
			{
				dg.showNext();
			}
		}
		// data file
		else if( source.equals( this.mSingleDataFileChooserWizardDilaog ) )
		{
			if( command.equals( SGWizardDialog.NEXT_BUTTON_TEXT ) )
			{
				File file = this.mSingleDataFileChooserWizardDilaog.getSelectedFileFromTextField();
				if( file.exists() == false )
				{
					SGUtility.showFileNotFoundMessageDialog( this.mSingleDataFileChooserWizardDilaog );
					return false;
				}
				String pathName = file.getPath();

				ArrayList infoList = new ArrayList();
				ArrayList cList = new ArrayList();
				try
				{
					if( this.mDataCreator.getFileTypeCandidateList( pathName, cList ) == false )
					{
						Utility.showDataFileInvalidMessageDialog(owner);
						return false;
					}
				}
				catch( FileNotFoundException ex )
				{
					SGUtility.showFileNotFoundMessageDialog(owner);
					return false;
				}
				
				if( cList.size() == 0 )
				{
					Utility.showDataFileInvalidMessageDialog(owner);
					return false;
				}
				
				// set candidate data-type to the dialog
				if( this.mXYDataTypeSelectionWizardDialog.setEffectiveDataType(cList) == false )
				{
					Utility.showDataFileInvalidMessageDialog(owner);
					return false;
				}

				// set to the file chooser
				this.mSingleDataFileChooserWizardDilaog.setSelectedFile(file);

				dg.showNext();
			}
	
		}
		// data type
		else if( source.equals( this.mXYDataTypeSelectionWizardDialog ) )
		{

			if( command.equals( SGWizardDialog.OK_BUTTON_TEXT ) )
			{
				// set invisible the dialog
				dg.setVisible(false);

				SGDrawingWindow wnd = dg.getOwnerWindow();
				
				// figure id
				final int figureID = this.mFigureIDSelectionWizardDialog.getFigureID();

				// path of the data file
				File f = this.mSingleDataFileChooserWizardDilaog.getSelectedFile();
				String pathName = f.getPath();

				// get selected file type
				String fileType = this.mXYDataTypeSelectionWizardDialog.getSelectedDataType();
				if( fileType == null )
				{
					SGUtility.showMessageDialog(
						owner,
						"Failed to get the data type.",
						TITLE_ERROR,
						JOptionPane.WARNING_MESSAGE
					);
					return false;
				}
				
				// add information to the list
				ArrayList infoList = new ArrayList();
				infoList.add(fileType);
				
				// create an array for data-retention
				if( fileType.equals( SGDataTypeConstants.SXY_SAMPLING_DATA ) )
				{
					// add the sampling rate to the infoList
					Double d = this.mXYDataTypeSelectionWizardDialog.getSamplingRate();
					if( d==null )
					{
						return false;
					}
					infoList.add(d);
				}
				else if( fileType.equals( SGDataTypeConstants.VXY_DATA ) )
				{
					boolean b = this.mXYDataTypeSelectionWizardDialog.isPolarSelected();
					infoList.add( Boolean.valueOf(b) );
				}

				// draw graph
				if( this.drawGraph( wnd, figureID, infoList, pathName, true ) == false )
				{
					return false;
				}

			}

		}


		return true;
	}




	private boolean drawGraph(
		final SGDrawingWindow wnd,
		final int figureID,
		final ArrayList infoList,
		final String pathName,
		final boolean showDialog )
	{
		if( wnd==null | infoList==null | pathName==null )
		{
			throw new IllegalArgumentException("wnd==null | infoList==null | pathName==null");
		}

		if( infoList.size()==0 )
		{
			return false;
		}

		final SGFigure fig = wnd.getFigure(figureID);

		// create a data object
		SGData data;
		try
		{
			data = this.mDataCreator.create( pathName, infoList );
		}
		catch( FileNotFoundException ex )
		{
			if( showDialog )
			{
				SGUtility.showFileNotFoundMessageDialog( wnd );
			}
			return false;
		}
		if( data == null )
		{
			if( showDialog )
			{
				SGUtility.showMessageDialog(
					wnd,
					"Failed to create a data object.",
					TITLE_ERROR,
					JOptionPane.WARNING_MESSAGE
				);
			}
			return false;
		}

		// add data
		boolean createFigureFlag = (fig==null);
		if( fig!=null )
		{
			if( fig.isVisible() == false )
			{
				createFigureFlag = true;
			}
		}
		if( createFigureFlag )
		{
			String name = this.getSimpleFileName( pathName );
			if( name==null )
			{
				return false;
			}

			if( this.createNewFigure( wnd, figureID, data, new Point(), name ) == null )
			{
				wnd.initProgressValue();
				return false;
			}
		}
		else
		{
			String name = this.getNewDataName( fig, pathName );
			if( name==null )
			{
				return false;
			}

			if( !this.addData(data,name,fig) )
			{
				if( showDialog )
				{
					Utility.showDataFileInvalidMessageDialog( wnd );
				}
				return false;
			}
		}

		// repaint
		wnd.repaint();

		return true;
	}



	/**
	 * determine the data-type from the property file
	 */
	private boolean getDataInfoFromPropertyFile(
		final Document doc, final ArrayList nList, final ArrayList cList )
	{

		// get root element - property
		Element root = doc.getDocumentElement();

		// get the node of window
		NodeList wList = root.getElementsByTagName( SGDrawingWindow.TAG_NAME_WINDOW );
		if( wList.getLength()==0 )
		{
			return false;
		}
		Element wnd = (Element)wList.item(0);

		// get the node list of figures
		NodeList fList = wnd.getElementsByTagName( SGFigure.TAG_NAME_FIGURE );
		for( int ii=0; ii<fList.getLength(); ii++ )
		{
			Node node = fList.item(ii);
			if( node instanceof Element )
			{
				Element figure = (Element)node;
				NodeList dList = figure.getElementsByTagName( SGIGraphElement.TAG_NAME_DATA );
				final int dLength = dList.getLength();
				if( dLength==0 )
				{
					nList.add(null);
					cList.add(null);
				}
				else
				{
					for( int jj=0; jj<dLength; jj++ )
					{
						Node node_ = dList.item(jj);
						if( node_ instanceof Element )
						{
							Element data = (Element)node_;
							String name = data.getAttribute( SGIGraphElement.KEY_DATA_NAME );
							nList.add(name);
							String type = data.getAttribute( SGIGraphElement.KEY_DATA_TYPE );
							cList.add(type);
						}
					}
				}
			}
		}
		
		return true;
	}



	/**
	 * 
	 * @param e
	 * @return
	 */
	private boolean loadProperty( final ActionEvent e )
	{
		Object source = e.getSource();
		String command = e.getActionCommand();
		SGWizardDialog dg = (SGWizardDialog)source;

		if( source instanceof SGPropertyFileChooserWizardDialog )
		{
			SGPropertyFileChooserWizardDialog pdg
				= (SGPropertyFileChooserWizardDialog)dg;

			File f = pdg.getSelectedFile();
			if( f!=null )
			{
				this.updateCurrentFile( f, FILE_TYPE_PROPERTY );
				this.mMultiDataFileChooserWizardDialog.setFile(
					this.getCurrentFileDirectory(), this.mCurrentDataFileName );
			}
			
			if( this.fromPropertyFileChooserDialog( e, dg ) == false )
			{
				return false;
			}
		}
		else if( source instanceof SGMultiDataFileChooserWizardDialog )
		{
			SGMultiDataFileChooserWizardDialog mdg
				= (SGMultiDataFileChooserWizardDialog)dg;

			File f = mdg.getSelectedFile();
			if( f!=null )
			{
				this.updateCurrentFile( f, FILE_TYPE_DATA );
				if( source.equals( this.mMultiDataFileChooserWizardDialog ) )
				{
					this.mPropertyFileChooserWizardDilaog.setFile(
						this.getCurrentFileDirectory(), this.mCurrentPropertyFileName );
				}
			}

			if( this.fromMultiDataFileChooser(e) == false )
			{
				return false;
			}
		}

		// cancel or previous
		if( command.equals( SGWizardDialog.CANCEL_BUTTON_TEXT ) )
		{
			dg.setVisible(false);
		}
		else if( command.equals( SGWizardDialog.PREVIOUS_BUTTON_TEXT ) )
		{
			dg.showPrevious();
		}

		return true;
	}




	public static final int FILE_TYPE_DATA = 0;
	public static final int FILE_TYPE_PROPERTY = 1;
	public static final int FILE_TYPE_IMAGE = 2;
	public static final int FILE_TYPE_DATASET = 3;


	/**
	 * 
	 * @param f
	 * @param type
	 */
	private void updateCurrentFile( File f, int type )
	{
		String path = f.getPath();
		String parent = f.getParent();
		this.setCurrentFileDirectory(parent);
		String name = path.substring( parent.length() + 1 );
		if( type==FILE_TYPE_DATA )
		{
			this.mCurrentDataFileName = name;
		}
		else if( type==FILE_TYPE_PROPERTY )
		{
			this.mCurrentPropertyFileName = name;
		}
		else if( type==FILE_TYPE_IMAGE )
		{
			this.mCurrentImageFileName = name;
		}
		else if( type==FILE_TYPE_DATASET )
		{
			this.mCurrentArchiveFileName = name;
		}
	}


	
	/**
	 * 
	 */
	private Document mPropertyFileDocument = null;

	

	/**
	 * 
	 * @param e
	 * @param dg
	 * @return
	 */
	private boolean fromPropertyFileChooserDialog( ActionEvent e, SGWizardDialog dg )
	{
		String command = e.getActionCommand();
		Window owner = dg.getOwner();
		SGWizardDialog next = dg.getNext();
		if( ( dg instanceof SGPropertyFileChooserWizardDialog ) == false )
		{
			return false;
		}
		if( ( next instanceof SGMultiDataFileChooserWizardDialog ) == false )
		{
			return false;
		}
		SGPropertyFileChooserWizardDialog pdg = (SGPropertyFileChooserWizardDialog)dg;
		SGMultiDataFileChooserWizardDialog mdg = (SGMultiDataFileChooserWizardDialog)next;
		if( command.equals( SGWizardDialog.NEXT_BUTTON_TEXT ) )
		{
			if( this.fromPropertyFileChooserDialogNext(pdg,mdg) == false )
			{
				return false;
			}
		}

		return true;
	}


	
	/**
	 * 
	 * @param pdg
	 * @param mdg
	 * @return
	 */
	private boolean fromPropertyFileChooserDialogNext(
		final SGPropertyFileChooserWizardDialog pdg,
		final SGMultiDataFileChooserWizardDialog mdg )
	{

		// get file type from the selected file
		File file = pdg.getSelectedFileFromTextField();
		if( file.exists() == false )
		{
			SGUtility.showFileNotFoundMessageDialog( pdg );
			return false;
		}

		// set the selected file to the file chooser
		pdg.setSelectedFile( file );

		// get information from the property file
		ArrayList idList = new ArrayList();
		ArrayList nList = new ArrayList();
		ArrayList cList = new ArrayList();
		if( this.getInfoFromPropertyFile( file, pdg, idList, nList, cList ) == false )
		{
			return false;
		}

		// initialize the dialog
		mdg.init( idList.size() );		

		// set the id list and the class type list
		// to the multi data file chooser
		if( this.setMultiDataFileChooser( idList, nList, cList, mdg )==false )
		{
			return false;
		}
		
		// show the multi data chooser dialog
		pdg.showNext();

		return true;
	}
	
	

	/**
	 * 
	 * @param file
	 * @param com
	 * @param idList
	 * @param nList
	 * @param cList
	 * @return
	 */
	private boolean getInfoFromPropertyFile(
		final File file,
		final Component com,
		final ArrayList idList,
		final ArrayList nList,
		final ArrayList cList )
	{
		
		String path = SGUtility.getCanonicalPath( file.getPath() );
		if( path==null )
		{
			SGUtility.showMessageDialog( 
				com, MSG_FILE_OPEN_FAILURE, TITLE_FILE_OPEN_FAILURE, JOptionPane.ERROR_MESSAGE );
			return false;
		}

		// check validity of the file
		URL url = null;
		try
		{
			url = file.toURL();
		}
		catch( MalformedURLException ex )
		{
			return false;
		}

		
		// create a Document object
		Document doc = SGUtilityText.getDocument( url );
		if( doc==null )
		{
			SGUtility.showMessageDialog(
				com, MSG_PROPERTY_FILE_INVALID,
				TITLE_FILE_OPEN_FAILURE, JOptionPane.ERROR_MESSAGE );
			return false;
		}
		this.mPropertyFileDocument = doc;


		// figure ID
		NodeList figureNodeList
			= doc.getElementsByTagName( SGFigure.TAG_NAME_FIGURE );
		if( figureNodeList.getLength()==0 )
		{
			// if figure does not exist, return false
			SGUtility.showMessageDialog(
				com, MSG_PROPERTY_FILE_INVALID,
				TITLE_FILE_OPEN_FAILURE, JOptionPane.ERROR_MESSAGE );
			return false;
		}
		final int fnLength = figureNodeList.getLength();
		for( int ii=0; ii<fnLength; ii++ )
		{
			Node node = figureNodeList.item(ii);
			if( ( node instanceof Element ) == false )
			{
				continue;
			}

			Element figure = (Element)node;
			NodeList dataList = figure.getElementsByTagName(
				SGIGraphElement.TAG_NAME_DATA );
			final int id = ii+1;
			final int dataNum = dataList.getLength();
			if( dataNum==0 )
			{
				idList.add( new Integer(id) );
			}
			else
			{
				for( int jj=0; jj<dataNum; jj++ )
				{
					idList.add( new Integer(id) );
				}
			}
		}

		
		// read the property file and get a list of candidates of data-type
		if( this.getDataInfoFromPropertyFile( doc, nList, cList ) == false )
		{
			SGUtility.showMessageDialog(
				com, MSG_PROPERTY_FILE_INVALID,
				TITLE_FILE_OPEN_FAILURE, JOptionPane.ERROR_MESSAGE );
			return false;
		}


		// if the candidate does not exist, return false
/*		if( cList.size()==0 )
		{
			SGUtility.showMessageDialog(
				com, ERRMSG_PROPERTY_FILE_INCORRECT,
				TITLE_FILE_CHECK, JOptionPane.ERROR_MESSAGE );
			return false;
		}
*/		if( cList.size() != idList.size() )
		{
			SGUtility.showMessageDialog(
				com, MSG_PROPERTY_FILE_INVALID,
				TITLE_FILE_OPEN_FAILURE, JOptionPane.ERROR_MESSAGE );
			return false;
		}
		
		
		
		return true;
	}
	
	

	
	/**
	 * 
	 * @param idList
	 * @param cList
	 * @param mdg
	 * @return
	 */
	private boolean setMultiDataFileChooser(
		final ArrayList idList,
		final ArrayList nList,
		final ArrayList cList,
		final SGMultiDataFileChooserWizardDialog mdg )
	{
		final int dataNum = cList.size();

		// set the number of files
		mdg.setFileNumber( dataNum );

		final String NO = SGMultiDataFileChooserWizardDialog.NO_DATA;

		// figure id
		String[] idArray = new String[dataNum];
		for( int ii=0; ii<dataNum; ii++ )
		{
			idArray[ii] = ((Integer)idList.get(ii)).toString();
		}

		ArrayList noDataList = new ArrayList();
		
		// data name
		String[] nArray = new String[dataNum];
		for( int ii=0; ii<dataNum; ii++ )
		{
			Object obj = nList.get(ii);
			if( obj==null )
			{
				obj = NO;
				noDataList.add( new Integer(ii) );
			}
			nArray[ii] = (String)obj;
		}

		
		// data type
		String[] cArray = new String[dataNum];
		for( int ii=0; ii<dataNum; ii++ )
		{
			Object obj = cList.get(ii);
			if( noDataList.contains( new Integer(ii) ) )
			{
				obj = NO;
			}
			cArray[ii] = (String)obj;
		}


		// data name
		String[] fArray = new String[dataNum];
		for( int ii=0; ii<dataNum; ii++ )
		{
			if( noDataList.contains( new Integer(ii) ) )
			{
				fArray[ii] = NO;
			}
		}

		
		// set to the dialog
		mdg.setFigureIDArray( idArray );
		mdg.setDataNameArray( nArray );
		mdg.setDataTypeArray( cArray );
		mdg.setFileNameArray( fArray );
		
		return true;
	}

	
	
	/**
	 * 
	 * @param e
	 * @return
	 */
	private boolean fromMultiDataFileChooser( final ActionEvent e )
	{
		Object source = e.getSource();
		SGWizardDialog dg = (SGWizardDialog)source;
		String command = e.getActionCommand();
		SGMultiDataFileChooserWizardDialog mdg = (SGMultiDataFileChooserWizardDialog)dg;
		Object owner = dg.getOwner();

		//
		if( command.equals( SGWizardDialog.OK_BUTTON_TEXT ) )
		{
			SGDrawingWindow wnd = (SGDrawingWindow)owner;

			wnd.deleteImage();
			wnd.clearUndoBuffer();
			wnd.removeAllFigures();
			wnd.updateClientRect();

			// get the map of data file list
			TreeMap map = mdg.getSelectedFilePathListMap();

			// set properties
			if( this.setPropertyFile( wnd, this.mPropertyFileDocument, map ) == false )
			{
				return false;
			}

			wnd.updateClientRect();
			
			// hide the wizard dialog
			dg.setVisible(false);

		}
		else if( command.equals( SGWizardDialog.CANCEL_BUTTON_TEXT ) )
		{
			dg.setVisible(false);
		}

		return true;
	}



	/**
	 * 
	 */
	private boolean actionFromWizardDialog( final ActionEvent e )
	{

		Object source = e.getSource();
		SGWizardDialog dg = (SGWizardDialog)source;

		String command = e.getActionCommand();

		//
		// from the command line or drag&drop
		//

		if( source.equals( this.mXYDataTypeSelectionWizardDialogFromCLorDD ) )
		{
			return this.fromCLorDDWizardDialog(e);
		}
		

		//
		// from the tool bar
		//

		// New Graph
		if( source.equals( this.mFigureIDSelectionWizardDialog )
			|| source.equals( this.mSingleDataFileChooserWizardDilaog )
			|| source.equals( this.mXYDataTypeSelectionWizardDialog ) )
		{
			return this.addDataByToolBar(e);
		}

		// Load Property
		if( source.equals( this.mPropertyFileChooserWizardDilaog )
			|| source.equals( this.mMultiDataFileChooserWizardDialog )
			|| source.equals( this.mMultiDataFileChooserWizardDialogDD ) )
		{
			return this.loadProperty(e);
		}

		return true;
	}


	
	/**
	 * 
	 */
	public void actionPerformed( final ActionEvent e )
	{

		Object source = e.getSource();
		String command = e.getActionCommand();

		// From the windows
		if( source instanceof SGDrawingWindow )
		{
			this.actionFromWindow(e);
		}
		// From the wizard dialogs
		else if( source instanceof SGWizardDialog )
		{
			this.actionFromWizardDialog(e);
		}

	}


	/**
	 * 
	 */
	public void windowOpened( final WindowEvent e )
	{
		
	}


	/**
	 * 
	 */
	public void windowClosed( final WindowEvent e )
	{
	}



	/**
	 * 
	 */
	public void windowClosing( final WindowEvent e )
	{
		Object source = e.getSource();
//System.out.println(e);
		if( source instanceof SGDrawingWindow )
		{
			final SGDrawingWindow wnd = (SGDrawingWindow)e.getSource();
			this.closeWindow( wnd );
		}
	}


	// show the confirmation dialog for saving properties of the window
	private int confirmBeforeClosing( SGDrawingWindow wnd )
	{
		final Object[] options = {
			MSG_CLOSE_WITHOUT_SAVING,
			SGDialog.CANCEL_BUTTON_TEXT,
			MSG_SAVE };
		return this.showConfirmationDialog( wnd, options, new SGCloseWindowConfirmPanel() );
	}


	// show the confirmation dialog for saving properties of the window
	private int confirmBeforeDiscard( SGDrawingWindow wnd )
	{
		final Object[] options = {
//			MSG_DISCARD_WITHOUT_SAVING,
			MSG_CLOSE_WITHOUT_SAVING,
			SGDialog.CANCEL_BUTTON_TEXT,
			MSG_SAVE };
		return this.showConfirmationDialog( wnd, options, new SGCloseWindowConfirmPanel() );
	}


	//
	private int showConfirmationDialog(
		SGDrawingWindow wnd, Object[] options, Object message )
	{
		// beep
		Toolkit.getDefaultToolkit().beep();

		// show a dialog
		final int ret = JOptionPane.showOptionDialog(
			wnd,
			message,
			TITLE_CONFIRMATION,
			JOptionPane.YES_NO_CANCEL_OPTION,
			JOptionPane.WARNING_MESSAGE,
			null,
			options,
			options[2] );

		return ret;
	}



	/**
	 * Close the window with confirmation.
	 * @param id - ID number of the window to close
	 */
	public void closeWindow( final int id )
	{
		SGDrawingWindow wnd = this.getWindow(id);
		if( wnd==null )
		{
			return;
		}
		this.closeWindow(wnd);
	}


	/**
	 * Close the window with confirmation.
	 * @param wnd - a window to be closed
	 */
	public int closeWindow( final SGDrawingWindow wnd )
	{
		if( this.needsConfirmationBeforeDiscard( wnd ) )
		{
			final int ret = this.confirmBeforeClosing( wnd );
			if( ret==JOptionPane.YES_OPTION )
			{
				this.removeWindow(wnd);
			}
			else if( ret==JOptionPane.NO_OPTION | ret==JOptionPane.CLOSED_OPTION )
			{
				// canceled and there is nothing to do
				return CANCEL_OPTION;
			}
			else if( ret==JOptionPane.CANCEL_OPTION )
			{
				// save the properties
				final int retSave = this.saveProperties( wnd );
				if( retSave == OK_OPTION )
				{
					this.removeWindow(wnd);
				}

				return retSave;
			}
		}
		else
		{
			this.removeWindow(wnd);
		}

		return OK_OPTION;
	}



	/**
	 * Exit the application normally with confirmation.
	 */
	public void exit()
	{
		final ArrayList wndList = new ArrayList( this.mWndMap.values() );
		for( int ii=wndList.size()-1; ii>=0; ii-- )
		{
			SGDrawingWindow wnd = (SGDrawingWindow)wndList.get(ii);
			final int ret = this.closeWindow(wnd);
			if( ret==CANCEL_OPTION )
			{
				break;
			}
		}
	}



	// Exit the application.
	private void exitApplication( final int status )
	{
		if( status!=0 )
		{
			String msg = "A fatal error has occured.\n"
				+ "The current application will be terminated.";
			String title = " Forced termination";
			SGUtility.showMessageDialog(
				null,
				msg,
				title,
				JOptionPane.ERROR_MESSAGE
			);
		}
		System.exit(status);
	}



	// Remove the window from window map.
	private boolean removeWindow( final SGDrawingWindow wnd )
	{
		final int id = wnd.getID();
		this.mWndMap.remove( new Integer(id) );
		wnd.removeWindowListener( this );
		wnd.removeActionListener( this );
		wnd.setVisible(false);
		wnd.dispose();

		// run the garbage collector
		System.gc();

		// if all windows are closed, exit the application
		if( this.mWndMap.size() == 0 )
		{
			this.exitApplication(0);
		}

		return true;
	}



	/**
	 * 
	 */
	public void windowActivated( final WindowEvent e )
	{
		
	}


	/**
	 * 
	 */
	public void windowDeactivated( final WindowEvent e )
	{
		
	}


	/**
	 * 
	 */
	public void windowIconified( final WindowEvent e )
	{
		
	}


	/**
	 * 
	 */
	public void windowDeiconified( final WindowEvent e )
	{
		
	}


	/**
	 * 
	 */
	public void dragEnter( final DropTargetDragEvent dtde )
	{
		dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
	}


	/**
	 * 
	 */
	public void dragExit( final DropTargetEvent dte )
	{
	}


	/**
	 * 
	 */
	public void dropActionChanged( final DropTargetDragEvent dtde )
	{
	}


	/**
	 * 
	 */
	public void dragOver( final DropTargetDragEvent dtde )
	{
	}



	/**
	 * 
	 */
	public void drop( final DropTargetDropEvent dtde )
	{
		DropTarget tg = (DropTarget)dtde.getSource();
		Component com = tg.getComponent();
		SGDrawingWindow wnd = (SGDrawingWindow)com;
		dtde.acceptDrop( DnDConstants.ACTION_COPY_OR_MOVE );
		try
		{
			if( ( dtde.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE ) != 0 )
			{
				Transferable trans = dtde.getTransferable();
				List list = (List)trans.getTransferData( DataFlavor.javaFileListFlavor );

				// set attributes
				DropEventHandler th = new DropEventHandler( this, dtde, list );
			}
		}
		catch ( Exception ex )
		{

		}
		finally
		{
			dtde.dropComplete( false );
		}

	}

	


	/**
	 * 
	 */
	private boolean fromDragAndDrop(
		final int x, final int y,
		final SGDrawingWindow wnd, final ArrayList fileList )
	{

		// set unabled the window
		wnd.setEnabled(false);
		
		try
		{
			// analyze the file list
			ArrayList dataFileList = new ArrayList();
			File propertyFile = null;
			File archiveFile = null;
			File imageFile = null;
			for( int ii=0; ii<fileList.size(); ii++ )
			{
				File file = (File)fileList.get(ii);
				String path = file.getAbsolutePath();

				// property file?
				final boolean propertyFlag = path.endsWith( PROPERTY_FILE_EXTENSION );

				// archive file?
				final boolean archiveFlag = path.endsWith( ARCHIVE_FILE_EXTENSION );

				// image file?
				boolean imageFlag = false;
				String[] imgArray = SGIImageConstants.DRAWABLE_IMAGE_EXTENSIONS;
				for( int jj=0; jj<imgArray.length; jj++ )
				{
					if( path.endsWith( imgArray[jj] ) | path.endsWith( imgArray[jj].toUpperCase() ) )
					{
						imageFlag = true;
						break;
					}
				}

				// as a property file
				if( propertyFlag )
				{
					propertyFile = file;
				}
				else if( archiveFlag )
				{
					archiveFile = file;
				}
				// as an image file
				else if( imageFlag )
				{
					imageFile = file;
				}
				// as a data file
				else
				{
					dataFileList.add(file);
				}
			}

			// initialize progress value
			wnd.initProgressValue();

			// use property file
			if( propertyFile!=null )
			{
				if( this.needsConfirmationBeforeDiscard( wnd ) )
				{
					final int ret = this.beforeDiscard(wnd);
					if( ret==CANCEL_OPTION )
					{
						return true;
					}
				}

				if( this.showMultiDataFileChooserDialog(
					propertyFile, dataFileList, wnd ) == false )
				{
					return false;
				}
			}
			else if( archiveFile!=null )
			{
				if( this.needsConfirmationBeforeDiscard( wnd ) )
				{
					final int ret = this.beforeDiscard(wnd);
					if( ret==CANCEL_OPTION )
					{
						return true;
					}
				}

				final int ret = this.loadDataSet( wnd, archiveFile );
				wnd.setSaved( ret == OK_OPTION );
			}
			else if( imageFile!=null )
			{
				if( this.setImage( imageFile, wnd ) == false )
				{
					return false;
				}
			}
			// add data
			else
			{
				if( this.addDataByDragAndDrop(
					x, y, wnd, dataFileList ) == false )
				{
					return false;
				}
			}
		}
		finally
		{
			// initialize progress value
			wnd.initProgressValue();
			
			// set enabled the window
			wnd.setEnabled(true);
		}

		return true;
	}


	//
	private boolean setImage( String path, SGDrawingWindow wnd )
	{
		File f = new File(path);
		if( f.exists() == false )
		{
			return false;
		}
		return this.setImage( f, wnd );
	}


	//
	private boolean setImage( File f, SGDrawingWindow wnd )
	{
		// create an image object
		try
		{
			URL url = f.toURL();
			Image img = Toolkit.getDefaultToolkit().getImage(url);

			// set the media tracker
			MediaTracker mt = new MediaTracker(wnd);
			mt.addImage( img, 0 );
			try
			{
				mt.waitForAll();
			}
			catch (InterruptedException ex)
			{

			}

			// add an image to the window
			wnd.setImage(img);
		}
		catch( MalformedURLException e )
		{
			e.printStackTrace();
			return false;
		}

		return true;
	}


	//
	private boolean needsConfirmationBeforeDiscard( SGDrawingWindow wnd )
	{
		return ( wnd.getVisibleFigureList().size()!=0 & !wnd.isSaved() );
	}


	// call before discarded a window
	private int beforeDiscard( final SGDrawingWindow wnd )
	{
		final int ret = this.confirmBeforeDiscard( wnd );
		if( ret==JOptionPane.YES_OPTION )
		{

		}
		else if( ret==JOptionPane.NO_OPTION | ret==JOptionPane.CLOSED_OPTION )
		{
			// canceled and there is nothing to do
			return CANCEL_OPTION;
		}
		else if( ret==JOptionPane.CANCEL_OPTION )
		{
			// save the properties
			final int retSave = this.saveProperties( wnd );
			return retSave;
		}

		return OK_OPTION;
	}



	/**
	 * 
	 */
	public void propertyChange( PropertyChangeEvent e )
	{
		Object source = e.getSource();
		String name = e.getPropertyName();

		if( source instanceof SGDrawingWindow )
		{
			if( SGDrawingWindow.PROPERTY_NAME_TOOL_BAR.equals( name ) )
			{
				SGDrawingWindow wnd = (SGDrawingWindow)source;
				this.updateToolBarPatternInPreferences( wnd.getToolBarPattern() );
			}
		}
	}


	// Update the pattern of the tool bar in the preferences.
	private void updateToolBarPatternInPreferences( final String[] array )
	{
		Preferences pref = Preferences.userNodeForPackage( this.getClass() );

		// update the tool bar pattern
		String str = "";
		for( int ii=0; ii<array.length; ii++ )
		{
			str += array[ii];
			if( ii!=array.length-1 )
			{
				str += ",";
			}
		}
		pref.put( PREF_KEY_TOOL_BAR_PATTERN, str );
	}



	//
	// Wizard
	//

	
	/**
	 * 
	 */
	private SGMultiDataFileChooserWizardDialog
		mMultiDataFileChooserWizardDialogDD = null;

	
	/**
	 * 
	 * @param propertyFile
	 * @param fileList
	 * @return
	 */
	private boolean showMultiDataFileChooserDialog(
		final File propertyFile,
		final ArrayList dataFileList,
		final Frame owner )
	{

		if( propertyFile.exists() == false )
		{
			SGUtility.showMessageDialog( 
				owner, MSG_FILE_OPEN_FAILURE, TITLE_FILE_OPEN_FAILURE, JOptionPane.ERROR_MESSAGE );
			return false;
		}

		
		// create data chooser dialog
		this.mMultiDataFileChooserWizardDialogDD
			= new SGMultiDataFileChooserWizardDialog(owner,true);

		SGMultiDataFileChooserWizardDialog dg
			= this.mMultiDataFileChooserWizardDialogDD;
		
		dg.getPreviousButton().setVisible(false);
		dg.getNextButton().setVisible(false);
		dg.pack();
		dg.addActionListener(this);


		// set directory
		this.mMultiDataFileChooserWizardDialogDD.setFile(
			this.getCurrentFileDirectory(), this.mCurrentDataFileName );

		
		// get information from the property file
		ArrayList idList = new ArrayList();
		ArrayList nList = new ArrayList();
		ArrayList cList = new ArrayList();
		if( this.getInfoFromPropertyFile(
			propertyFile, owner, idList, nList, cList ) == false )
		{
			return false;
		}
		
		// initialize the dialog
		dg.init( idList.size() );		

		// set the id list and the class type list
		// to the multi data file chooser
		if( this.setMultiDataFileChooser(
			idList, nList, cList, dg ) == false )
		{
			return false;
		}
		
		// show dialog
		if( owner!=null )
		{
			dg.setCenter( owner );
		}
		else
		{
			dg.setLocationRelativeTo(null);
		}
		dg.setVisible(true);


		return true;
	}
	
	

	/**
	 * 
	 */
	private boolean addDataByDragAndDrop(
		final int x, final int y,
		final SGDrawingWindow wnd, final ArrayList fileList )
	{

		// dialog to select data-type
		this.mXYDataTypeSelectionWizardDialogFromCLorDD
			= new SGXYDataTypeSelectionWizardDialog( wnd, true );
		this.mXYDataTypeSelectionWizardDialogFromCLorDD.addActionListener(this);
		this.mXYDataTypeSelectionWizardDialogFromCLorDD.mPreviousButton.setVisible(false);
		this.mXYDataTypeSelectionWizardDialogFromCLorDD.mNextButton.setVisible(false);
		this.mXYDataTypeSelectionWizardDialogFromCLorDD.pack();


		// create data objects
		final int ii = 0;
//		for( int ii=0; ii<fileList.size(); ii++ )
		{
			File file = (File)fileList.get(ii);

			ArrayList list = new ArrayList();
			int ret;
			try
			{
				ret = this.createDataFromFile( file.getPath(), list, wnd );
			}
			catch( FileNotFoundException ex )
			{
				SGUtility.showFileNotFoundMessageDialog( wnd );
				return false;
			}
			if( ret==-1 )
			{
				Utility.showDataFileInvalidMessageDialog(wnd);
				return false;
			}

//			wnd.setProgressValue(0.10f);

			if( ret==1 )
			{
				return true;
			}

			if( list.size() == 0 )
			{
				return false;
			}
			SGData data = (SGData)list.get(0);

			String path = file.getAbsolutePath();

			Object com = wnd.getComponent(x,y);
			if( com instanceof SGDrawingWindow )
			{
				// get current figure ID
				int figureID = wnd.getCurrentFigureId();

				SGFigure figure = wnd.getFigure( figureID );
				if( figure==null )
				{
					String name = this.getSimpleFileName( path );
					if( name==null )
					{
						return false;
					}

					Point pos = new Point(x, y);
					figure = this.createNewFigure(
						wnd, figureID, data, pos, name );
					if( figure==null )
					{
						wnd.initProgressValue();
						return false;
					}
				}
				else
				{
					String name = this.getNewDataName( figure, path );
					if( name==null )
					{
						return false;
					}

					// add data to the figure
					if( this.addData( data, name, figure ) == false )
					{
						Utility.showDataTypeInvalidMessageDialog( wnd );
						return false;
					}
				}

			}
			else if( com instanceof SGFigure )
			{
				SGFigure figure = (SGFigure)com;
				String name = this.getNewDataName( figure, path );
				if( name==null )
				{
					return false;
				}

				if( this.addData( data, name, figure ) == false )
				{
					Utility.showDataTypeInvalidMessageDialog( wnd );
					return false;
				}
			}
			else
			{
				return false;
			}

		}

		return true;
	}

	
	
	
	/**
	 * 
	 * @param wnd
	 * @param figureID
	 * @param data
	 * @param pos : mouse location of window
	 * @return
	 */
	private SGFigure createNewFigure(
		final SGDrawingWindow wnd,
		final int figureID,
		final SGData data,
		final Point pos,
		final String name )
	{

		// create a figure instance
		SGFigure figure = this.createFigure( figureID, wnd, data );
		if( figure==null )
		{
			return null;
		}

		wnd.setProgressValue(0.80f);

		// add a new figure to the window
		if( wnd.addFigure( figure, pos ) == false )
		{
			return null;
		}

		wnd.setProgressValue(1.0f);

		// add data object to the figure
		if( !this.addData(data,name,figure) )
		{
			return null;
		}

		// init the history of the properties after the data is added
		SGIFigureElement[] array = figure.getIFigureElementArray();
		for( int ii=0; ii<array.length; ii++ )
		{
			if( array[ii].initPropertiesHistory() == false )
			{
				return null;
			}
		}


		// draw back the figure into the paper
		wnd.drawBackFigure( figure );


		// initialize the history of the properties
		// after drawn back
		figure.initPropertiesHistory();


		//
		figure.setVisible(true);

		wnd.setChanged(true);
		wnd.notifyToRoot();


		// show the window and figure
		wnd.setVisible(true);


		// update the items after the figure is set visible
		wnd.updateItemsByFigureNumbers();

		//
		wnd.initProgressValue();

		return figure;
	}



	private boolean addData( final SGData data, final String name, final SGFigure figure )
	{
		SGIFigureElement[] array = figure.getIFigureElementArray();
		ArrayList list = new ArrayList( Arrays.asList(array) );
		SGIAxisElement aElement = figure.getAxisElement();
		list.remove(aElement);
		list.add(0,aElement);

		SGIFigureElement[] newArray = (SGIFigureElement[])list.toArray( new SGIFigureElement[]{} );

		return figure.addData( data, name, newArray );
	}



	/**
	 * 
	 * @param wnd
	 * @return
	 */
	private SGSplashWindow createSplashWindow()
	{
		// set the image and the text
		Class inClass = getClass();
		String name = RESOURCES_DIRNAME + "Splash.png";
		URL url = inClass.getResource(name);
		Image image = Toolkit.getDefaultToolkit().getImage( url );
		if( image==null )
		{
			return null;
		}
		SGSplashWindow sw = new SGSplashWindow( image );
		return sw;
	}

}


}

