Coverage report

  %line %branch
tsukuba_bunko.peko.scenario.SceneProcessor
0% 
0% 

 1  
 /*
 2  
  * All Rights Reserved.
 3  
  * Copyright (C) 1999-2005 Tsukuba Bunko.
 4  
  *
 5  
  * Licensed under the BSD License ("the License"); you may not use
 6  
  * this file except in compliance with the License.
 7  
  * You may obtain a copy of the License at
 8  
  *
 9  
  *       http://www.tsukuba-bunko.org/licenses/LICENSE.txt
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  *
 17  
  * $Id: SceneProcessor.java,v 1.8 2005/11/23 05:41:15 ppoi Exp $
 18  
  */
 19  
 package tsukuba_bunko.peko.scenario;
 20  
 
 21  
 import java.io.FileNotFoundException;
 22  
 import	java.io.InputStream;
 23  
 
 24  
 import	java.net.URL;
 25  
 
 26  
 import	javax.xml.parsers.ParserConfigurationException;
 27  
 import	javax.xml.parsers.SAXParser;
 28  
 import	javax.xml.parsers.SAXParserFactory;
 29  
 
 30  
 import	org.xml.sax.Attributes;
 31  
 import	org.xml.sax.InputSource;
 32  
 import	org.xml.sax.SAXException;
 33  
 import	org.xml.sax.SAXParseException;
 34  
 import	org.xml.sax.helpers.DefaultHandler;
 35  
 
 36  
 import	tsukuba_bunko.peko.ActionControler;
 37  
 import	tsukuba_bunko.peko.Logger;
 38  
 import	tsukuba_bunko.peko.PekoSystem;
 39  
 
 40  
 import	tsukuba_bunko.peko.resource.ResourceManager;
 41  
 
 42  
 import	tsukuba_bunko.peko.scenario.select.SelectCoordinator;
 43  
 
 44  
 import	tsukuba_bunko.peko.scenario.stage.StageCoordinator;
 45  
 
 46  
 import	tsukuba_bunko.peko.scenario.text.TextCoordinator;
 47  
 
 48  
 import	tsukuba_bunko.peko.session.Session;
 49  
 
 50  
 
 51  
 /**
 52  
  * シーンの処理を行うプロセッサモジュールです。
 53  
  * @author	$Author: ppoi $
 54  
  * @version	$Revision: 1.8 $
 55  
  */
 56  
 public class SceneProcessor	extends DefaultHandler	implements Runnable	{
 57  
 
 58  
 	/**
 59  
 	 * PSML 1.0 Scene DTD Public ID
 60  
 	 */
 61  
 	public static final String	PSML_PUBLICID = "-//Tsukuba Bunko//DTD PSML 1.0 Scene//EN";
 62  
 
 63  
 	/**
 64  
 	 * PSML 1.0 Scene (ILLEGAL) DTD Public ID
 65  
 	 */
 66  
 	public static final String	PSML_PUBLICID_ILLEGAL = "-//Tsukuba Bunko//DTD PSML Scene 1.0//EN";
 67  
 
 68  
 	/**
 69  
 	 * PSML 1.0 Scene DTD System ID
 70  
 	 */
 71  
 	public static final String	PSML_SYSTEMID = "http://softlab.tsukuba-bunko.org/dtd/psml10-scene.dtd";
 72  
 
 73  
 
 74  
 	/**
 75  
 	 * PSML 解析を行う SAX Parser
 76  
 	 */
 77  0
 	protected SAXParser	_parser = null;
 78  
 
 79  
 	/**
 80  
 	 * 処理状態フラグ
 81  
 	 */
 82  0
 	protected boolean	_running = false;
 83  
 
 84  
 	/**
 85  
 	 * 中止フラグ
 86  
 	 */
 87  0
 	protected boolean	_aborted = false;
 88  
 
 89  
 	/**
 90  
 	 * 処理中のシーン
 91  
 	 */
 92  0
 	protected URL	_sceneURL = null;
 93  
 
 94  
 	/**
 95  
 	 * 処理中のシーンのコンテクスト
 96  
 	 */
 97  0
 	protected SceneContext	_sceneContext = null;
 98  
 
 99  
 	/**
 100  
 	 * この SceneProcessor を制御する ScenarioProcessor
 101  
 	 */
 102  0
 	protected ScenarioProcessor	_owner = null;
 103  
 
 104  
 	/**
 105  
 	 * 現在のツリー中のレベル
 106  
 	 */
 107  0
 	protected int	_level = -1;
 108  
 
 109  
 	/**
 110  
 	 * ElementHandler が処理中のサブツリーの開始レベル
 111  
 	 */
 112  0
 	protected int	_processStartedLevel = -1;
 113  
 
 114  
 	/**
 115  
 	 * 評価しないサブツリーの開始レベル
 116  
 	 */
 117  0
 	protected int	_ignoreStartedLevel = -1;
 118  
 
 119  
 	/**
 120  
 	 * ハンドラレジストリ
 121  
 	 */
 122  0
 	protected HandlerRegistry	_registry = null;
 123  
 
 124  
 	/**
 125  
 	 * 現在要素を処理中の ElementHandler
 126  
 	 */
 127  0
 	protected ElementHandler	_handler = null;
 128  
 
 129  
 	/**
 130  
 	 * スタートのノード位置
 131  
 	 */
 132  0
 	protected SceneContext.Node	_startNode = null;
 133  
 
 134  
 
 135  
 	/**
 136  
 	 * TextCanvas コーディネータ
 137  
 	 */
 138  0
 	protected TextCoordinator	_textCoordinator = null;
 139  
 
 140  
 	/**
 141  
 	 * StageCanvas コーディネータ
 142  
 	 */
 143  0
 	protected StageCoordinator	_stageCoordinator = null;
 144  
 
 145  
 	/**
 146  
 	 * SelectCanvas コーディネータ
 147  
 	 */
 148  0
 	protected SelectCoordinator	_selectCoordinator = null;
 149  
 
 150  
 
 151  
 	/**
 152  
 	 * <code>SceneProcessor</code> のインスタンスを生成します。
 153  
 	 * @param	owner	この SceneProcessor インスタンスを制御する ScenarioProcessor
 154  
 	 */
 155  
 	public SceneProcessor( ScenarioProcessor owner )
 156  
 	{
 157  0
 		super();
 158  0
 		_owner = owner;
 159  0
 		_registry = HandlerRegistry.newInstance();
 160  0
 		getSAXParser();
 161  0
 		Logger.debug( "[scenario] create SceneProcessor." );
 162  0
 	}
 163  
 
 164  
 
 165  
 	/**
 166  
 	 * シーンコンテクストを取得します。
 167  
 	 * @return	シーンコンテクスト
 168  
 	 */
 169  
 	public SceneContext getSceneContext()
 170  
 	{
 171  0
 		return _sceneContext;
 172  
 	}
 173  
 
 174  
 
 175  
 	/**
 176  
 	 * ハンドラレジストリを取得します。
 177  
 	 * @return	ハンドラレジストリ
 178  
 	 */
 179  
 	public HandlerRegistry getHandlerRegistry()
 180  
 	{
 181  0
 		return _registry;
 182  
 	}
 183  
 
 184  
 	/**
 185  
 	 * TextCanvas コーディネータを設定します。
 186  
 	 * @param	coordinator	TextCanvas コーディネータ
 187  
 	 */
 188  
 	public void setTextCoordinator( TextCoordinator coordinator )
 189  
 	{
 190  0
 		_textCoordinator = coordinator;
 191  0
 	}	
 192  
 
 193  
 	/**
 194  
 	 * TextCanvas コーディネータを取得します。
 195  
 	 * @return	TextCanvas コーディネータ
 196  
 	 */
 197  
 	public TextCoordinator getTextCoordinator()
 198  
 	{
 199  0
 		return _textCoordinator;
 200  
 	}
 201  
 
 202  
 	/**
 203  
 	 * StageCanvas コーディネータを設定します。
 204  
 	 * @param	coordinator	StageCanvas コーディネータ
 205  
 	 */
 206  
 	public void setStageCoordinator( StageCoordinator coordinator )
 207  
 	{
 208  0
 		_stageCoordinator = coordinator;
 209  0
 	}
 210  
 
 211  
 	/**
 212  
 	 * StageCanvas コーディネータを取得します。
 213  
 	 * @return	StageCanvas コーディネータ
 214  
 	 */
 215  
 	public StageCoordinator getStageCoordinator()
 216  
 	{
 217  0
 		return _stageCoordinator;
 218  
 	}
 219  
 
 220  
 	/**
 221  
 	 * SelectCanvas コーディネータを設定します。
 222  
 	 * @param	coordinator	SelectCanvas コーディネータ
 223  
 	 */
 224  
 	public void setSelectCoordinator( SelectCoordinator coordinator )
 225  
 	{
 226  0
 		_selectCoordinator = coordinator;
 227  0
 	}
 228  
 
 229  
 	/**
 230  
 	 * SelectCanvas コーディネータを取得します。
 231  
 	 * @return	SelectCanvas コーディネータ
 232  
 	 */
 233  
 	public SelectCoordinator getSelectCoordinator()
 234  
 	{
 235  0
 		return _selectCoordinator;
 236  
 	}
 237  
 
 238  
 
 239  
 	/**
 240  
 	 * シーンの処理を開始します。
 241  
 	 * @param	sceneName	処理するシーンのシーン名
 242  
 	 */
 243  
 	public void process( String sceneName, Session session )
 244  
 	{
 245  0
 		if( _running )	{
 246  0
 			IllegalStateException	ise = new IllegalStateException( "scene processor is still running." );
 247  0
 			Logger.fatal( MessageIDs.SCN0007F );
 248  0
 			PekoSystem.showErrorDialog( MessageIDs.SCN0007F.getMessage(), ise.fillInStackTrace(), true );
 249  
 		}
 250  0
 		_sceneURL = getSceneURL( sceneName );
 251  0
 		_sceneContext = new SceneContext( sceneName, session, this );
 252  0
 		_startNode = _sceneContext.getLastCommittedNode();
 253  0
 		if( _startNode != null )	{
 254  0
 			Logger.debug( "[scenario.scene] start from: " + _startNode.getPath() );
 255  
 		}
 256  
 
 257  0
 		Thread	thread = new Thread( this );
 258  0
 		session.setSceneContext( _sceneContext, thread );
 259  
 
 260  0
 		_textCoordinator.prepare( _sceneContext, thread );
 261  0
 		_stageCoordinator.prepare( _sceneContext, thread );
 262  0
 		_selectCoordinator.prepare( _sceneContext, thread );
 263  
 
 264  0
 		_aborted = false;
 265  0
 		thread.start();
 266  0
 	}
 267  
 
 268  
 	/**
 269  
 	 * シーンの処理を中止します。
 270  
 	 */
 271  
 	public void abort()
 272  
 	{
 273  0
 		_aborted = true;
 274  0
 		_textCoordinator.dormantize();
 275  0
 		_stageCoordinator.dormantize();
 276  0
 		_selectCoordinator.dormantize();
 277  0
 		Logger.debug( "[scenario] release stopped thread." );
 278  0
 		ActionControler	controler = PekoSystem.getInstance().getActionControler();
 279  0
 		controler.start();
 280  0
 	}
 281  
 
 282  
 	/**
 283  
 	 * シーン処理が中止されているかどうかを判定します。
 284  
 	 * @return	シーン処理が中止されている場合 <code>true</code>、それ以外の場合 <code>false</code>
 285  
 	 */
 286  
 	public boolean isAborted()
 287  
 	{
 288  0
 		return _aborted;
 289  
 	}
 290  
 
 291  
 	/**
 292  
 	 * PSML Scene データの構文解析を行う SAX パーザを取得します。
 293  
 	 * @return	PSML Scene データの構文解析を行う SAX パーザ
 294  
 	 */
 295  
 	protected SAXParser getSAXParser()
 296  
 	{
 297  0
 		if( _parser == null )	{
 298  
 			try	{
 299  0
 				SAXParserFactory	factory = SAXParserFactory.newInstance();
 300  0
 				factory.setNamespaceAware( true );
 301  0
 				if( "on".equals(System.getProperty("debug", "off")) )	{
 302  0
 					Logger.debug( "[scenario.scene] set PSML validating on." );
 303  0
 					factory.setValidating( true );
 304  0
 				}
 305  
 				else	{
 306  0
 					Logger.debug( "[scenario.scene] set PSML validating off." );
 307  0
 					factory.setValidating( false );
 308  
 				}
 309  0
 				_parser = factory.newSAXParser();
 310  
 			}
 311  0
 			catch( SAXException se )	{
 312  0
 				Logger.fatal( MessageIDs.SCN0000F );
 313  0
 				PekoSystem.showErrorDialog( MessageIDs.SCN0000F.getMessage(), se, true );
 314  
 			}
 315  0
 			catch( ParserConfigurationException pce )	{
 316  0
 				Logger.fatal( MessageIDs.SCN0000F );
 317  0
 				PekoSystem.showErrorDialog( MessageIDs.SCN0000F.getMessage(), pce, true );
 318  0
 			}
 319  
 		}
 320  0
 		return _parser;
 321  
 	}
 322  
 
 323  
 	/**
 324  
 	 * シーンデータの URL を取得します。
 325  
 	 * @param	scene	シーン名
 326  
 	 * @return	シーンデータの URL
 327  
 	 */
 328  
 	protected URL getSceneURL( String scene )
 329  
 	{
 330  0
 		ResourceManager	resources = ResourceManager.getInstance();
 331  0
 		URL	sceneDir = resources.getLocationResources().getScenesDirecotryURL();
 332  
 		try	{
 333  0
 			return new URL( sceneDir, scene );
 334  
 		}
 335  0
 		catch( Exception e )	{
 336  0
 			Logger.fatal( MessageIDs.SCN0006F, e );
 337  0
 			PekoSystem.showErrorDialog( MessageIDs.SCN0006F.getMessage(), e, true );
 338  0
 			return null;
 339  
 		}
 340  
 	}
 341  
 
 342  
 //
 343  
 //	Runnable の実装
 344  
 //
 345  
 	public void run()
 346  
 	{
 347  0
 		_running = true;
 348  0
 		InputStream	is = null;
 349  
 		try	{
 350  0
 			Logger.debug( _sceneURL.toString() );
 351  0
 			is = _sceneURL.openStream();
 352  0
 			SAXParser	parser = getSAXParser();
 353  0
 			parser.parse( is, this );
 354  
 		}
 355  0
 		catch( SAXParseException spe )	{
 356  0
 			PekoSystem.getInstance().getActionControler().returnTitle( true );
 357  
 		}
 358  0
 		catch( FileNotFoundException fnfe )	{
 359  0
 			Logger.error( MessageIDs.SCN0014E, new Object[]{getSceneContext().getSceneName()} );
 360  0
 			PekoSystem.getInstance().getActionControler().returnTitle( true );
 361  
 		}
 362  0
 		catch( Exception e )	{
 363  0
 			Logger.fatal( MessageIDs.SCN0005F, new Object[]{_sceneContext.getCurrentPath()}, e );
 364  0
 			PekoSystem.showErrorDialog( MessageIDs.SCN0005F.getMessage(new Object[]{_sceneContext.getCurrentPath()}), e, true );
 365  
 		}
 366  
 		finally	{
 367  0
 			if( is != null )	{
 368  
 				try	{
 369  0
 					is.close();
 370  0
 					Logger.debug( "[scene] close scene. scene=" + getSceneContext().getSceneName() );
 371  
 				}
 372  0
 				catch( Exception e )	{
 373  
 					//ignore.
 374  0
 				}
 375  0
 			}
 376  0
 		}
 377  0
 		_running = false;
 378  0
 		_owner.pushSceneProcessor( this );
 379  0
 	}
 380  
 
 381  
 
 382  
 //
 383  
 //	ContentHandler の実装
 384  
 //
 385  
 	public void startDocument()
 386  
 		throws SAXException
 387  
 	{
 388  0
 		if( _aborted )	{
 389  0
 			return;
 390  
 		}
 391  
 
 392  0
 		_level  = 0;
 393  0
 		_processStartedLevel = -1;
 394  0
 		_ignoreStartedLevel = -1;
 395  0
 		_handler = null;
 396  0
 	}
 397  
 
 398  
 	public void endDocument()
 399  
 		throws SAXException
 400  
 	{
 401  0
 		if( _aborted )	{
 402  0
 			return;
 403  
 		}
 404  
 		else	{
 405  0
 			_owner.sceneEnded( this );
 406  
 		}
 407  0
 	}
 408  
 
 409  
 	public void startElement( String namespaceURI, String localName, String qName, Attributes attrs )
 410  
 		throws SAXException
 411  
 	{
 412  0
 		if( _aborted )	{
 413  0
 			return;
 414  
 		}
 415  
 
 416  0
 		++_level;
 417  0
 		_sceneContext.pushNode( qName );
 418  
 
 419  0
 		if( _startNode != null )	{
 420  0
 			if( _sceneContext.isCurrentNode(_startNode) )	{
 421  0
 				_startNode = null;
 422  0
 			}
 423  
 			else	{
 424  0
 				return;
 425  
 			}
 426  
 		}
 427  0
 		else if( _ignoreStartedLevel != -1 )	{
 428  0
 			return;
 429  
 		}
 430  0
 		else if( !PSMLUtil.isEvaluatable(attrs, _sceneContext) )	{
 431  0
 			_ignoreStartedLevel = _level;
 432  0
 			return;
 433  
 		}
 434  
 
 435  0
 		if( _handler == null )	{
 436  0
 			_handler = _registry.getElementHandler( namespaceURI, localName );
 437  0
 			if( _handler == null )	{
 438  0
 				return;
 439  
 			}
 440  
 			else	{
 441  0
 				_sceneContext.saveCurrentNode();
 442  0
 				_handler.setSceneContext( _sceneContext );
 443  0
 				_processStartedLevel = _level;
 444  0
 				_handler.startDocument();
 445  
 			}
 446  
 		}
 447  
 		try	{
 448  0
 			_handler.startElement( namespaceURI, localName, qName, attrs );
 449  
 		}
 450  0
 		catch( Exception e )	{
 451  0
 			Logger.fatal( MessageIDs.SCN0005F, new Object[]{_sceneContext.getCurrentPath()}, e );
 452  0
 			PekoSystem.showErrorDialog( MessageIDs.SCN0005F.getMessage(new Object[]{_sceneContext.getCurrentPath()}), e, true );
 453  0
 		}
 454  0
 	}
 455  
 
 456  
 	public void endElement( String namespaceURI, String localName, String qName )
 457  
 		throws SAXException
 458  
 	{
 459  0
 		if( _aborted )	{
 460  0
 			return;
 461  
 		}
 462  
 
 463  0
 		if( _startNode != null )	{
 464  
 			//NOOP
 465  0
 		}
 466  0
 		else if( _level == _ignoreStartedLevel )	{
 467  0
 			_ignoreStartedLevel = -1;
 468  0
 		}
 469  0
 		else if( _ignoreStartedLevel != -1 )	{
 470  
 			//NOOP
 471  0
 		}
 472  0
 		else if( _handler != null )	{
 473  
 			try	{
 474  0
 				_handler.endElement( namespaceURI, localName, qName );
 475  0
 				if( _level == _processStartedLevel )	{
 476  0
 					_handler.endDocument();
 477  0
 					if( _handler.isEndOfScene() )	{
 478  0
 						_owner.sceneEnded( this );
 479  0
 						_aborted = true;
 480  
 					}
 481  0
 					_handler = null;
 482  0
 					_processStartedLevel = -1;
 483  
 				}
 484  
 			}
 485  0
 			catch( Exception e )	{
 486  0
 				Logger.fatal( MessageIDs.SCN0005F, new Object[]{_sceneContext.getCurrentPath()}, e );
 487  0
 				PekoSystem.showErrorDialog( MessageIDs.SCN0005F.getMessage(new Object[]{_sceneContext.getCurrentPath()}), e, true );
 488  0
 			}
 489  
 		}
 490  
 
 491  0
 		--_level;
 492  0
 		_sceneContext.popNode();
 493  0
 	}
 494  
 
 495  
 	public void characters( char[] ch, int begin, class="keyword">int length )
 496  
 		throws SAXException
 497  
 	{
 498  0
 		if( _aborted )	{
 499  0
 			return;
 500  
 		}
 501  
 
 502  0
 		if( (_ignoreStartedLevel != -1 ) || (_handler == null) )	{
 503  0
 			return;
 504  
 		}
 505  0
 		else if( _handler != null )	{
 506  0
 			_handler.characters( ch, begin, length );
 507  
 		}
 508  0
 	}
 509  
 
 510  
 	public void processingInstruction( String target, String data )
 511  
 	{
 512  0
 	}
 513  
 
 514  
 //
 515  
 //	ErrorHandler の実装
 516  
 //
 517  
 	public void warning( SAXParseException exception )
 518  
 	{
 519  0
 		Logger.warn( MessageIDs.SCN0002W, new Object[]{exception.getMessage(), _sceneContext.getCurrentPath()}, exception );
 520  0
 	}
 521  
 
 522  
 	public void error( SAXParseException exception )
 523  
 	{
 524  0
 		Logger.error( MessageIDs.SCN0003E, new Object[]{exception.getMessage(), _sceneContext.getCurrentPath()}, exception );
 525  0
 	}
 526  
 
 527  
 	public void fatalError( SAXParseException exception )
 528  
 	{
 529  0
 		Logger.error( MessageIDs.SCN0004E, new Object[]{exception.getMessage(), _sceneContext.getCurrentPath()}, exception );
 530  0
 	}
 531  
 
 532  
 
 533  
 //
 534  
 //	EntityResolver の実装
 535  
 //
 536  
 	public InputSource resolveEntity( String class="keyword">publicId, String systemId )
 537  
 	{
 538  0
 		boolean	isPSMLScene = false;
 539  0
 		if( publicId != null )	{
 540  0
 			if( SceneProcessor.PSML_PUBLICID.equals(publicId) )	{
 541  0
 				isPSMLScene = true;
 542  0
 			}
 543  0
 			else if( SceneProcessor.PSML_PUBLICID_ILLEGAL.equals(publicId) )	{
 544  0
 				Logger.warn( MessageIDs.SCN0013W );
 545  0
 				isPSMLScene = true;
 546  0
 			}
 547  
 		}
 548  0
 		else if( systemId != null )	{
 549  0
 			if( SceneProcessor.PSML_SYSTEMID.equals(systemId) )	{
 550  0
 				isPSMLScene = true;
 551  
 			}
 552  
 		}
 553  
 
 554  0
 		if( isPSMLScene )	{
 555  0
 			InputStream	is = null;
 556  0
 			Logger.debug( "Load internal PSML 1.0 Scene DTD." );
 557  
 			try	{
 558  0
 				is = getClass().getClassLoader().getResourceAsStream( "psml10-scene.dtd" );
 559  
 			}
 560  0
 			catch( Exception e )	{
 561  0
 				Logger.warn( MessageIDs.SCN0001W, e );
 562  0
 				return null;
 563  0
 			}
 564  
 
 565  0
 			if( is != null )	{
 566  0
 				return new InputSource( is );
 567  
 			}
 568  
 			else	{
 569  0
 				Logger.warn( MessageIDs.SCN0001W );
 570  0
 				return null;
 571  
 			}
 572  
 		}
 573  
 		else	{
 574  0
 			return null;
 575  
 		}
 576  
 	}
 577  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.