[Xulu-commits] r2 - in trunk: . defaults defaults/plugin defaults/plugin/GTVisualisationColorMapPlugin defaults/plugin/GeoModelCodeGenerator defaults/plugin/LoggerPlugin defaults/plugin/RasterCalculator lib lib/JavaRInterface lib/jai-1_1_3 lib/jai-1_1_3/lib lib/jai-1_1_3/lib/native_win lib/jini lib/jini/lib lib/schmitzm lib/xulu resource resource/icons resource/locales resource/unused src src/META-INF src/appl src/appl/data src/appl/ext src/appl/parallel src/appl/parallel/client src/appl/parallel/data src/appl/parallel/data/splittable src/appl/parallel/data/xulugridfile src/appl/parallel/data/xulugridfile/factories src/appl/parallel/event src/appl/parallel/gui src/appl/parallel/model src/appl/parallel/plugin src/appl/parallel/plugin/event src/appl/parallel/server src/appl/parallel/services src/appl/parallel/spmd src/appl/parallel/spmd/split src/appl/parallel/starter src/appl/parallel/starter/client src/appl/parallel/starter/server src/appl/parallel/test src/appl/parallel/thread src/appl/parallel/util src/appl/plugin src/appl/plugin/multimodelcontrol src/appl/util src/appl/util/benchmark src/de src/de/skrueger src/de/skrueger/xulu src/de/skrueger/xulu/plugin src/de/skrueger/xulu/plugin/gnur src/de/skrueger/xulu/plugin/gnur/Rcode src/edu src/edu/bonn src/edu/bonn/xulu src/edu/bonn/xulu/appl src/edu/bonn/xulu/data src/edu/bonn/xulu/gui src/edu/bonn/xulu/io src/edu/bonn/xulu/model src/edu/bonn/xulu/model/event src/edu/bonn/xulu/plugin src/edu/bonn/xulu/plugin/appl src/edu/bonn/xulu/plugin/data src/edu/bonn/xulu/plugin/data/feature src/edu/bonn/xulu/plugin/data/grid src/edu/bonn/xulu/plugin/data/misc src/edu/bonn/xulu/plugin/gui src/edu/bonn/xulu/plugin/io src/edu/bonn/xulu/plugin/io/feature src/edu/bonn/xulu/plugin/io/feature/gt src/edu/bonn/xulu/plugin/io/grid src/edu/bonn/xulu/plugin/io/grid/array src/edu/bonn/xulu/plugin/io/grid/awt src/edu/bonn/xulu/plugin/io/grid/gt src/edu/bonn/xulu/plugin/io/grid/lateloading src/edu/bonn/xulu/plugin/io/misc src/edu/bonn/xulu/plugin/model src/edu/bonn/xulu/plugin/model/ca src/edu/bonn/xulu/plugin/model/ca/agric src/edu/bonn/xulu/plugin/model/ca/fire src/edu/bonn/xulu/plugin/model/ca/reservoir src/edu/bonn/xulu/plugin/model/clue src/edu/bonn/xulu/plugin/model/parallel src/edu/bonn/xulu/plugin/model/parallel/demo src/edu/bonn/xulu/plugin/model/test src/edu/bonn/xulu/plugin/vis src/skrueger src/skrueger/gol

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Wed Feb 25 12:57:17 CET 2009


Author: mojays
Date: 2009-02-25 12:54:01 +0100 (Wed, 25 Feb 2009)
New Revision: 2

Added:
   trunk/InitXulu.bat
   trunk/defaults/
   trunk/defaults/.classpath
   trunk/defaults/.project
   trunk/defaults/DefaultProperties
   trunk/defaults/XuluProperties
   trunk/defaults/plugin/
   trunk/defaults/plugin/GTVisualisationColorMapPlugin/
   trunk/defaults/plugin/GTVisualisationColorMapPlugin/gtcolormaps.xif
   trunk/defaults/plugin/GeoModelCodeGenerator/
   trunk/defaults/plugin/GeoModelCodeGenerator/ModelContentManager.tpl
   trunk/defaults/plugin/GeoModelCodeGenerator/StepModel.tpl
   trunk/defaults/plugin/GeoModelCodeGenerator/XuluModel.tpl
   trunk/defaults/plugin/LoggerPlugin/
   trunk/defaults/plugin/LoggerPlugin/log4j.cfg
   trunk/defaults/plugin/RasterCalculator/
   trunk/defaults/plugin/RasterCalculator/default_filter.inp
   trunk/defaults/registry.xif
   trunk/defaults/registry_ProxyGrid.xif
   trunk/defaults/registry_arrayGrid.xif
   trunk/defaults/startXULU.bat
   trunk/doc/
   trunk/lib/
   trunk/lib/JavaRInterface/
   trunk/lib/JavaRInterface/JRI.jar
   trunk/lib/jai-1_1_3/
   trunk/lib/jai-1_1_3/COPYRIGHT-jai.txt
   trunk/lib/jai-1_1_3/DISTRIBUTIONREADME-jai.txt
   trunk/lib/jai-1_1_3/LICENSE-jai.txt
   trunk/lib/jai-1_1_3/THIRDPARTYLICENSEREADME-jai.txt
   trunk/lib/jai-1_1_3/UNINSTALL-jai
   trunk/lib/jai-1_1_3/lib/
   trunk/lib/jai-1_1_3/lib/clibwrapper_jiio.jar
   trunk/lib/jai-1_1_3/lib/jai_codec.jar
   trunk/lib/jai-1_1_3/lib/jai_core.jar
   trunk/lib/jai-1_1_3/lib/jai_imageio.jar
   trunk/lib/jai-1_1_3/lib/mlibwrapper_jai.jar
   trunk/lib/jai-1_1_3/lib/native_linux/
   trunk/lib/jai-1_1_3/lib/native_win/
   trunk/lib/jai-1_1_3/lib/native_win/mlib_jai.dll
   trunk/lib/jai-1_1_3/lib/native_win/mlib_jai_mmx.dll
   trunk/lib/jai-1_1_3/lib/native_win/mlib_jai_util.dll
   trunk/lib/jini/
   trunk/lib/jini/lib/
   trunk/lib/jini/lib/tools.jar
   trunk/lib/schmitzm/
   trunk/lib/schmitzm/schmitzm.jar
   trunk/lib/xulu/
   trunk/lib/xulu/XuluModellingPlatform.jar
   trunk/readme.txt
   trunk/resource/
   trunk/resource/icons/
   trunk/resource/icons/xulu_icon.png
   trunk/resource/icons/xulu_info.png
   trunk/resource/icons/xulu_start.png
   trunk/resource/locales/
   trunk/resource/locales/StandardBundleExtension.properties
   trunk/resource/locales/XuluMainAppl.properties
   trunk/resource/locales/XuluMainAppl_de.properties
   trunk/resource/locales/XuluMainError.properties
   trunk/resource/locales/XuluMainError_de.properties
   trunk/resource/locales/XuluModel_Clue.properties
   trunk/resource/locales/XuluModel_Clue_de.properties
   trunk/resource/locales/XuluModel_ImpetusFireCA.properties
   trunk/resource/locales/XuluModel_ImpetusFireCA_de.properties
   trunk/resource/locales/XuluModel_SmallReservoirModel.properties
   trunk/resource/locales/XuluModel_SmallReservoirModel_de.properties
   trunk/resource/locales/XuluVisualisationTool.properties
   trunk/resource/locales/XuluVisualisationTool_de.properties
   trunk/resource/unused/
   trunk/resource/unused/edit_clear.gif
   trunk/resource/unused/edit_redo.gif
   trunk/resource/unused/edit_undo.gif
   trunk/resource/unused/layer_cancel3.png
   trunk/resource/unused/xulu_icon.gif
   trunk/resource/unused/xulu_icon_green.gif
   trunk/resource/unused/xulu_icon_red.gif
   trunk/resource/unused/xulu_icon_yellow.gif
   trunk/resource/unused/xuluv.png
   trunk/src/
   trunk/src/META-INF/
   trunk/src/META-INF/PREFERRED.LIST
   trunk/src/appl/
   trunk/src/appl/data/
   trunk/src/appl/data/DataLoader.java
   trunk/src/appl/data/DataProxy.java
   trunk/src/appl/data/DataUnloader.java
   trunk/src/appl/data/FactoryLoader.java
   trunk/src/appl/data/ImportFactoryLoader.java
   trunk/src/appl/data/LateLoadingProxy.java
   trunk/src/appl/data/SerializedDataLoader.java
   trunk/src/appl/data/WritableGridArrayLoader.java
   trunk/src/appl/data/WritableGridLLProxy.java
   trunk/src/appl/data/package.html
   trunk/src/appl/ext/
   trunk/src/appl/ext/ConfigurationEditor.java
   trunk/src/appl/ext/ConfigurationEditorEngine.java
   trunk/src/appl/ext/ConfigurationEditorGUI.java
   trunk/src/appl/ext/ConfigurationEditorPlugin.java
   trunk/src/appl/ext/XuluConfig.java
   trunk/src/appl/ext/package.html
   trunk/src/appl/package.html
   trunk/src/appl/parallel/
   trunk/src/appl/parallel/ComputingResource.java
   trunk/src/appl/parallel/ComputingResourceContainer.java
   trunk/src/appl/parallel/ComputingResourceProperties.java
   trunk/src/appl/parallel/SimpleResourceProperties.java
   trunk/src/appl/parallel/client/
   trunk/src/appl/parallel/client/ClientDataServer.java
   trunk/src/appl/parallel/client/DataServer.java
   trunk/src/appl/parallel/client/RemoteEventHandler.java
   trunk/src/appl/parallel/client/RemoteExecutionController.java
   trunk/src/appl/parallel/client/ResourceChangeListener.java
   trunk/src/appl/parallel/client/package.html
   trunk/src/appl/parallel/data/
   trunk/src/appl/parallel/data/AbstractDataHandler.java
   trunk/src/appl/parallel/data/DataLoadHandler.java
   trunk/src/appl/parallel/data/PartitionDataHandler.java
   trunk/src/appl/parallel/data/PartitionHandlerFactory.java
   trunk/src/appl/parallel/data/WritableGridArrayPartition.java
   trunk/src/appl/parallel/data/XuluClientLoader.java
   trunk/src/appl/parallel/data/package.html
   trunk/src/appl/parallel/data/splittable/
   trunk/src/appl/parallel/data/splittable/GridListFactory.java
   trunk/src/appl/parallel/data/splittable/GridListFactory_ArcInfoAsciiGrid.java
   trunk/src/appl/parallel/data/splittable/MultiGridFactory.java
   trunk/src/appl/parallel/data/splittable/MultiGridFactory_ArcInfoAsciiGrid.java
   trunk/src/appl/parallel/data/splittable/SingleGridFactory.java
   trunk/src/appl/parallel/data/splittable/SingleGridFactory_ArcInfoAsciiGrid.java
   trunk/src/appl/parallel/data/splittable/SingleGridFactory_GeoTiff.java
   trunk/src/appl/parallel/data/splittable/SplittableGridLLFactory.java
   trunk/src/appl/parallel/data/splittable/SplittableLLProxyGrid.java
   trunk/src/appl/parallel/data/splittable/package.html
   trunk/src/appl/parallel/data/xulugridfile/
   trunk/src/appl/parallel/data/xulugridfile/BufferedHelper.java
   trunk/src/appl/parallel/data/xulugridfile/BufferedRandomAccessFile.java
   trunk/src/appl/parallel/data/xulugridfile/GridFileDataLoader.java
   trunk/src/appl/parallel/data/xulugridfile/XuluGridFile.java
   trunk/src/appl/parallel/data/xulugridfile/XuluGridFileConverter.java
   trunk/src/appl/parallel/data/xulugridfile/XuluGridFileException.java
   trunk/src/appl/parallel/data/xulugridfile/XuluGridSharedFileSystemLoader.java
   trunk/src/appl/parallel/data/xulugridfile/XuluWritableGridFile.java
   trunk/src/appl/parallel/data/xulugridfile/factories/
   trunk/src/appl/parallel/data/xulugridfile/factories/GridListFactory.java
   trunk/src/appl/parallel/data/xulugridfile/factories/GridListFactory_ArcInfoAsciiGrid.java
   trunk/src/appl/parallel/data/xulugridfile/factories/MultiGridFactory.java
   trunk/src/appl/parallel/data/xulugridfile/factories/MultiGridFactory_ArcInfoAsciiGrid.java
   trunk/src/appl/parallel/data/xulugridfile/factories/SingleGridFactory.java
   trunk/src/appl/parallel/data/xulugridfile/factories/SingleGridFactory_ArcInfoAsciiGrid.java
   trunk/src/appl/parallel/data/xulugridfile/factories/XuluGridFactory.java
   trunk/src/appl/parallel/data/xulugridfile/factories/package.html
   trunk/src/appl/parallel/data/xulugridfile/package.html
   trunk/src/appl/parallel/event/
   trunk/src/appl/parallel/event/CommEvent.java
   trunk/src/appl/parallel/event/CommEventSink.java
   trunk/src/appl/parallel/event/RemoteEvent.java
   trunk/src/appl/parallel/event/RemoteEventSink.java
   trunk/src/appl/parallel/event/SimpleConsoleMonitor.java
   trunk/src/appl/parallel/event/TimeEvent.java
   trunk/src/appl/parallel/event/TimeMonitor.java
   trunk/src/appl/parallel/event/TransferEvent.java
   trunk/src/appl/parallel/event/TransferMonitor.java
   trunk/src/appl/parallel/event/package.html
   trunk/src/appl/parallel/gui/
   trunk/src/appl/parallel/gui/ModelControlContainer_parallel.java
   trunk/src/appl/parallel/gui/ModelControlFrame_Tabbed.java
   trunk/src/appl/parallel/gui/ModelControlFrame_parallel.java
   trunk/src/appl/parallel/gui/ParallelControlPanel.java
   trunk/src/appl/parallel/gui/ParallelControlPanelEngine.java
   trunk/src/appl/parallel/gui/SimplePropertyTable.java
   trunk/src/appl/parallel/gui/package.html
   trunk/src/appl/parallel/model/
   trunk/src/appl/parallel/model/AbstractParallelStepModel.java
   trunk/src/appl/parallel/model/ParallelStepModel.java
   trunk/src/appl/parallel/model/package.html
   trunk/src/appl/parallel/package.html
   trunk/src/appl/parallel/plugin/
   trunk/src/appl/parallel/plugin/event/
   trunk/src/appl/parallel/plugin/event/SimpleCommEventMonitor.java
   trunk/src/appl/parallel/plugin/event/SimpleCommEventMonitorEngine.java
   trunk/src/appl/parallel/plugin/event/SimpleCommEventMonitorPlugin.java
   trunk/src/appl/parallel/plugin/event/package.html
   trunk/src/appl/parallel/server/
   trunk/src/appl/parallel/server/MasterSlaveResource.java
   trunk/src/appl/parallel/server/PartitionDataManager.java
   trunk/src/appl/parallel/server/PartitionDataServer.java
   trunk/src/appl/parallel/server/SPMDResource.java
   trunk/src/appl/parallel/server/ServerMulticastReceiver.java
   trunk/src/appl/parallel/server/XuluServer.java
   trunk/src/appl/parallel/server/XuluServerProperties.java
   trunk/src/appl/parallel/server/package.html
   trunk/src/appl/parallel/services/
   trunk/src/appl/parallel/services/DiscoveryService.java
   trunk/src/appl/parallel/services/GlobalDiscoveryService.java
   trunk/src/appl/parallel/services/HostnameDiscoveryService.java
   trunk/src/appl/parallel/services/MulticastDiscoveryService.java
   trunk/src/appl/parallel/services/RemoteEventProxy.java
   trunk/src/appl/parallel/services/Service.java
   trunk/src/appl/parallel/services/package.html
   trunk/src/appl/parallel/spmd/
   trunk/src/appl/parallel/spmd/AbstractSPMDTask.java
   trunk/src/appl/parallel/spmd/AdvancedSPMDClientController.java
   trunk/src/appl/parallel/spmd/AdvancedSPMDClientInterface.java
   trunk/src/appl/parallel/spmd/AdvancedSPMDServerController.java
   trunk/src/appl/parallel/spmd/AdvancedSPMDServerInterface.java
   trunk/src/appl/parallel/spmd/MultiDataInfo.java
   trunk/src/appl/parallel/spmd/MultiDataObject.java
   trunk/src/appl/parallel/spmd/MultiDataPartitionObject.java
   trunk/src/appl/parallel/spmd/SPMDClientController.java
   trunk/src/appl/parallel/spmd/SPMDClientInterface.java
   trunk/src/appl/parallel/spmd/SPMDServerController.java
   trunk/src/appl/parallel/spmd/SPMDServerInterface.java
   trunk/src/appl/parallel/spmd/SPMDTask.java
   trunk/src/appl/parallel/spmd/SyncPoint.java
   trunk/src/appl/parallel/spmd/package.html
   trunk/src/appl/parallel/spmd/split/
   trunk/src/appl/parallel/spmd/split/AbstractSplitMap.java
   trunk/src/appl/parallel/spmd/split/DataPartition.java
   trunk/src/appl/parallel/spmd/split/PartitionInfo.java
   trunk/src/appl/parallel/spmd/split/SinglePartitionInfo.java
   trunk/src/appl/parallel/spmd/split/SplitMap.java
   trunk/src/appl/parallel/spmd/split/SplitMap1DHorizontal.java
   trunk/src/appl/parallel/spmd/split/SplitMap1DVertical.java
   trunk/src/appl/parallel/spmd/split/SplitMap2D.java
   trunk/src/appl/parallel/spmd/split/SplittableGrid.java
   trunk/src/appl/parallel/spmd/split/SplittableResource.java
   trunk/src/appl/parallel/spmd/split/WritableGridPartition.java
   trunk/src/appl/parallel/spmd/split/package.html
   trunk/src/appl/parallel/starter/
   trunk/src/appl/parallel/starter/Starter.java
   trunk/src/appl/parallel/starter/client/
   trunk/src/appl/parallel/starter/client/StarterClientGUI.java
   trunk/src/appl/parallel/starter/client/StarterContainer.java
   trunk/src/appl/parallel/starter/client/XuluStarterClientPanel.java
   trunk/src/appl/parallel/starter/client/XuluStarterController.java
   trunk/src/appl/parallel/starter/client/XuluStarterControllerFrame.java
   trunk/src/appl/parallel/starter/client/XuluStarterControllerPlugin.java
   trunk/src/appl/parallel/starter/client/package.html
   trunk/src/appl/parallel/starter/package.html
   trunk/src/appl/parallel/starter/server/
   trunk/src/appl/parallel/starter/server/XuluServerStarter.java
   trunk/src/appl/parallel/starter/server/XuluStarterServerGUI.java
   trunk/src/appl/parallel/starter/server/package.html
   trunk/src/appl/parallel/test/
   trunk/src/appl/parallel/test/AverageNeighborhoodTestTask.java
   trunk/src/appl/parallel/test/AverageNeighborhoodTestTask_MultiGrid.java
   trunk/src/appl/parallel/test/MulticastSocketTest.java
   trunk/src/appl/parallel/test/PartitialGridTest.java
   trunk/src/appl/parallel/test/PingTestObject.java
   trunk/src/appl/parallel/test/SPMDTest.java
   trunk/src/appl/parallel/test/SPMDTest.testsuite
   trunk/src/appl/parallel/test/SPMDTest_MultiGrid.java
   trunk/src/appl/parallel/test/SplitMapTest.java
   trunk/src/appl/parallel/test/SplitMaps.testsuite
   trunk/src/appl/parallel/test/XuluGridTestCase.java
   trunk/src/appl/parallel/test/XuluGridTestCase.testsuite
   trunk/src/appl/parallel/test/XuluServerTest.java
   trunk/src/appl/parallel/test/XuluServerTest.testsuite
   trunk/src/appl/parallel/test/generalTestClass.java
   trunk/src/appl/parallel/test/package.html
   trunk/src/appl/parallel/thread/
   trunk/src/appl/parallel/thread/ComputingResourceThread.java
   trunk/src/appl/parallel/thread/DataServerThread.java
   trunk/src/appl/parallel/thread/ExecutionThread.java
   trunk/src/appl/parallel/thread/OneMethodThread.java
   trunk/src/appl/parallel/thread/package.html
   trunk/src/appl/parallel/util/
   trunk/src/appl/parallel/util/Helper.java
   trunk/src/appl/parallel/util/PartitionUtil.java
   trunk/src/appl/parallel/util/package.html
   trunk/src/appl/plugin/
   trunk/src/appl/plugin/multimodelcontrol/
   trunk/src/appl/plugin/multimodelcontrol/ModelListObject.java
   trunk/src/appl/plugin/multimodelcontrol/MultiModelControlFrame.java
   trunk/src/appl/plugin/multimodelcontrol/MultiModelControlHandler.java
   trunk/src/appl/plugin/multimodelcontrol/MultiModelControlPlugin.java
   trunk/src/appl/plugin/multimodelcontrol/package.html
   trunk/src/appl/util/
   trunk/src/appl/util/GeneralUtil.java
   trunk/src/appl/util/NonEditableTableModel.java
   trunk/src/appl/util/RasterUtil.java
   trunk/src/appl/util/XuluFrameAdapter.java
   trunk/src/appl/util/benchmark/
   trunk/src/appl/util/benchmark/Benchmark.java
   trunk/src/appl/util/benchmark/SimpleBenchmark.java
   trunk/src/appl/util/benchmark/package.html
   trunk/src/appl/util/package.html
   trunk/src/de/
   trunk/src/de/skrueger/
   trunk/src/de/skrueger/xulu/
   trunk/src/de/skrueger/xulu/plugin/
   trunk/src/de/skrueger/xulu/plugin/gnur/
   trunk/src/de/skrueger/xulu/plugin/gnur/GnuRGUI.java
   trunk/src/de/skrueger/xulu/plugin/gnur/GnuRPlugin.java
   trunk/src/de/skrueger/xulu/plugin/gnur/JRTextArea.java
   trunk/src/de/skrueger/xulu/plugin/gnur/PropertytypeNotConvertableToRVar.java
   trunk/src/de/skrueger/xulu/plugin/gnur/RConsolePanel.java
   trunk/src/de/skrueger/xulu/plugin/gnur/RVar.java
   trunk/src/de/skrueger/xulu/plugin/gnur/RVarAdapter.java
   trunk/src/de/skrueger/xulu/plugin/gnur/RVarMatrix.java
   trunk/src/de/skrueger/xulu/plugin/gnur/RVarScalar.java
   trunk/src/de/skrueger/xulu/plugin/gnur/RVarSingleGrid.java
   trunk/src/de/skrueger/xulu/plugin/gnur/RVarsTable.java
   trunk/src/de/skrueger/xulu/plugin/gnur/RVarsTableModel.java
   trunk/src/de/skrueger/xulu/plugin/gnur/Rcode/
   trunk/src/de/skrueger/xulu/plugin/gnur/Rcode/funGeneric.r
   trunk/src/de/skrueger/xulu/plugin/gnur/Rcode/functions.R
   trunk/src/de/skrueger/xulu/plugin/gnur/Rcode/logit_regression_all_v1.3.R
   trunk/src/de/skrueger/xulu/plugin/gnur/SwingIO.java
   trunk/src/de/skrueger/xulu/plugin/gnur/TextReader.java
   trunk/src/de/skrueger/xulu/plugin/gnur/testsomethong.java
   trunk/src/edu/
   trunk/src/edu/bonn/
   trunk/src/edu/bonn/xulu/
   trunk/src/edu/bonn/xulu/XuluModellingPlatform.java
   trunk/src/edu/bonn/xulu/appl/
   trunk/src/edu/bonn/xulu/appl/AbstractCommandInterpreter.java
   trunk/src/edu/bonn/xulu/appl/AbstractHandler.java
   trunk/src/edu/bonn/xulu/appl/AbstractManager.java
   trunk/src/edu/bonn/xulu/appl/AbstractScriptInterpreter.java
   trunk/src/edu/bonn/xulu/appl/AbstractXuluPlugin.java
   trunk/src/edu/bonn/xulu/appl/DataPool.java
   trunk/src/edu/bonn/xulu/appl/EventHandler.java
   trunk/src/edu/bonn/xulu/appl/EventManager.java
   trunk/src/edu/bonn/xulu/appl/Handler.java
   trunk/src/edu/bonn/xulu/appl/HandlerFactory.java
   trunk/src/edu/bonn/xulu/appl/ModelControlManager.java
   trunk/src/edu/bonn/xulu/appl/RecentImports.java
   trunk/src/edu/bonn/xulu/appl/RecentScripts.java
   trunk/src/edu/bonn/xulu/appl/ScriptInterpreter.java
   trunk/src/edu/bonn/xulu/appl/ScriptablePlugin.java
   trunk/src/edu/bonn/xulu/appl/VisualisationManager.java
   trunk/src/edu/bonn/xulu/appl/VisualisationTool.java
   trunk/src/edu/bonn/xulu/appl/VisualisationUpdateListener.java
   trunk/src/edu/bonn/xulu/appl/XuluComponent.java
   trunk/src/edu/bonn/xulu/appl/XuluComponentUtil.java
   trunk/src/edu/bonn/xulu/appl/XuluConstants.java
   trunk/src/edu/bonn/xulu/appl/XuluPlugin.java
   trunk/src/edu/bonn/xulu/appl/XuluRegistry.java
   trunk/src/edu/bonn/xulu/appl/XuluRegistryReader.java
   trunk/src/edu/bonn/xulu/appl/package.html
   trunk/src/edu/bonn/xulu/data/
   trunk/src/edu/bonn/xulu/data/AbstractXuluObject.java
   trunk/src/edu/bonn/xulu/data/DuplicateXuluObjectIDException.java
   trunk/src/edu/bonn/xulu/data/DuplicateXuluObjectNameException.java
   trunk/src/edu/bonn/xulu/data/DynamicXuluObject.java
   trunk/src/edu/bonn/xulu/data/XuluDataException.java
   trunk/src/edu/bonn/xulu/data/XuluObject.java
   trunk/src/edu/bonn/xulu/data/package.html
   trunk/src/edu/bonn/xulu/gui/
   trunk/src/edu/bonn/xulu/gui/AbstractManagerFrame.java
   trunk/src/edu/bonn/xulu/gui/DataPoolFrame.java
   trunk/src/edu/bonn/xulu/gui/DataPoolInputOption.java
   trunk/src/edu/bonn/xulu/gui/DataPoolMenu.java
   trunk/src/edu/bonn/xulu/gui/DataPoolMenu.sav
   trunk/src/edu/bonn/xulu/gui/DataPoolTreeModel.java
   trunk/src/edu/bonn/xulu/gui/ModelContentManagerContainer.java
   trunk/src/edu/bonn/xulu/gui/ModelControlFrame.java
   trunk/src/edu/bonn/xulu/gui/ModelManagerTreeModel.java
   trunk/src/edu/bonn/xulu/gui/ObjectOrModelInputOption.java
   trunk/src/edu/bonn/xulu/gui/RegistryFrame.java
   trunk/src/edu/bonn/xulu/gui/StatusFrame.java
   trunk/src/edu/bonn/xulu/gui/XuluErrorResource.20080424
   trunk/src/edu/bonn/xulu/gui/XuluErrorResource_en.20080424
   trunk/src/edu/bonn/xulu/gui/XuluGUIMessages.java
   trunk/src/edu/bonn/xulu/gui/XuluGUIResource.20080424
   trunk/src/edu/bonn/xulu/gui/XuluGUIResource_en.20080424
   trunk/src/edu/bonn/xulu/gui/XuluGUIUtil.java
   trunk/src/edu/bonn/xulu/gui/XuluInternalFrame.java
   trunk/src/edu/bonn/xulu/gui/XuluLanguageManagerFrame.java
   trunk/src/edu/bonn/xulu/gui/XuluMainFrame.java
   trunk/src/edu/bonn/xulu/gui/XuluMainFrameInfo.java
   trunk/src/edu/bonn/xulu/gui/XuluStartingFrame.java
   trunk/src/edu/bonn/xulu/gui/package.html
   trunk/src/edu/bonn/xulu/io/
   trunk/src/edu/bonn/xulu/io/AbstractFactory.java
   trunk/src/edu/bonn/xulu/io/ExportFactory.java
   trunk/src/edu/bonn/xulu/io/Factory.java
   trunk/src/edu/bonn/xulu/io/FactoryCanceledException.java
   trunk/src/edu/bonn/xulu/io/IODefinition.java
   trunk/src/edu/bonn/xulu/io/ImportFactory.java
   trunk/src/edu/bonn/xulu/io/InstantiationFactory.java
   trunk/src/edu/bonn/xulu/io/TypeMapping.java
   trunk/src/edu/bonn/xulu/io/TypeMappingException.java
   trunk/src/edu/bonn/xulu/io/package.html
   trunk/src/edu/bonn/xulu/model/
   trunk/src/edu/bonn/xulu/model/AbstractModelContentManager.java
   trunk/src/edu/bonn/xulu/model/AbstractModelResource.java
   trunk/src/edu/bonn/xulu/model/AbstractStepModel.java
   trunk/src/edu/bonn/xulu/model/AbstractXuluModel.java
   trunk/src/edu/bonn/xulu/model/DefaultModelResource.java
   trunk/src/edu/bonn/xulu/model/ModelCanceledException.java
   trunk/src/edu/bonn/xulu/model/ModelContentManager.java
   trunk/src/edu/bonn/xulu/model/ModelResource.java
   trunk/src/edu/bonn/xulu/model/PropertiesResource.java
   trunk/src/edu/bonn/xulu/model/StepModel.java
   trunk/src/edu/bonn/xulu/model/StepModelThread.java
   trunk/src/edu/bonn/xulu/model/ValuePropertyResource.java
   trunk/src/edu/bonn/xulu/model/XuluModel.java
   trunk/src/edu/bonn/xulu/model/XuluModelThread.java
   trunk/src/edu/bonn/xulu/model/event/
   trunk/src/edu/bonn/xulu/model/event/AbstractIterationStepEvent.java
   trunk/src/edu/bonn/xulu/model/event/AbstractModelEvent.java
   trunk/src/edu/bonn/xulu/model/event/AbstractStepModelEvent.java
   trunk/src/edu/bonn/xulu/model/event/ModelAdapter.java
   trunk/src/edu/bonn/xulu/model/event/ModelDisposedEvent.java
   trunk/src/edu/bonn/xulu/model/event/ModelEvent.java
   trunk/src/edu/bonn/xulu/model/event/ModelInitialisedEvent.java
   trunk/src/edu/bonn/xulu/model/event/ModelIterationStepFinishedEvent.java
   trunk/src/edu/bonn/xulu/model/event/ModelIterationStepStartedEvent.java
   trunk/src/edu/bonn/xulu/model/event/ModelListener.java
   trunk/src/edu/bonn/xulu/model/event/ModelStartedEvent.java
   trunk/src/edu/bonn/xulu/model/event/ModelStepFinishedEvent.java
   trunk/src/edu/bonn/xulu/model/event/ModelStepStartedEvent.java
   trunk/src/edu/bonn/xulu/model/event/ModelStoppedEvent.java
   trunk/src/edu/bonn/xulu/model/event/StepModelAdapter.java
   trunk/src/edu/bonn/xulu/model/package.html
   trunk/src/edu/bonn/xulu/package.html
   trunk/src/edu/bonn/xulu/plugin/
   trunk/src/edu/bonn/xulu/plugin/appl/
   trunk/src/edu/bonn/xulu/plugin/appl/AbstractMenuPlugin.java
   trunk/src/edu/bonn/xulu/plugin/appl/DataExportHandler.java
   trunk/src/edu/bonn/xulu/plugin/appl/DataExportHandlerFactory.java
   trunk/src/edu/bonn/xulu/plugin/appl/DataScriptInterpreter_Basic.java
   trunk/src/edu/bonn/xulu/plugin/appl/DateTimePlugin.java
   trunk/src/edu/bonn/xulu/plugin/appl/DateTimeWindowPlugin.java
   trunk/src/edu/bonn/xulu/plugin/appl/FileExportHandlerFactory.java
   trunk/src/edu/bonn/xulu/plugin/appl/GTVisualisationColorMapPlugin.java
   trunk/src/edu/bonn/xulu/plugin/appl/GeoModelCodeGenerator.java
   trunk/src/edu/bonn/xulu/plugin/appl/GeoModelCodeGeneratorGUI.java
   trunk/src/edu/bonn/xulu/plugin/appl/GeoModelCodeGeneratorPlugin.java
   trunk/src/edu/bonn/xulu/plugin/appl/LoggerPlugin.java
   trunk/src/edu/bonn/xulu/plugin/appl/ModelResourceMappingScriptInterpreter_Basic.java
   trunk/src/edu/bonn/xulu/plugin/appl/ModelTimeSnifferPlugin.java
   trunk/src/edu/bonn/xulu/plugin/appl/RasterCalculatorGUI.070821
   trunk/src/edu/bonn/xulu/plugin/appl/RasterCalculatorGUI.java
   trunk/src/edu/bonn/xulu/plugin/appl/RasterCalculatorPanel.java
   trunk/src/edu/bonn/xulu/plugin/appl/RasterCalculatorPlugin.java
   trunk/src/edu/bonn/xulu/plugin/appl/VisualisationHandler.java
   trunk/src/edu/bonn/xulu/plugin/appl/VisualisationHandlerFactory.java
   trunk/src/edu/bonn/xulu/plugin/appl/XuluRegistryReader_BasicAscii.java
   trunk/src/edu/bonn/xulu/plugin/appl/package.html
   trunk/src/edu/bonn/xulu/plugin/data/
   trunk/src/edu/bonn/xulu/plugin/data/feature/
   trunk/src/edu/bonn/xulu/plugin/data/feature/SingleFeatureCollection.java
   trunk/src/edu/bonn/xulu/plugin/data/grid/
   trunk/src/edu/bonn/xulu/plugin/data/grid/GridList.java
   trunk/src/edu/bonn/xulu/plugin/data/grid/MultiGrid.java
   trunk/src/edu/bonn/xulu/plugin/data/grid/SingleGrid.java
   trunk/src/edu/bonn/xulu/plugin/data/misc/
   trunk/src/edu/bonn/xulu/plugin/data/misc/CAArea.java
   trunk/src/edu/bonn/xulu/plugin/data/misc/CASettlementArea.java
   trunk/src/edu/bonn/xulu/plugin/data/package.html
   trunk/src/edu/bonn/xulu/plugin/gui/
   trunk/src/edu/bonn/xulu/plugin/gui/AbstractManagerFrame_BasicTable.java
   trunk/src/edu/bonn/xulu/plugin/gui/DataPoolFrame_BasicTable.java
   trunk/src/edu/bonn/xulu/plugin/gui/DataPoolFrame_Tree.java
   trunk/src/edu/bonn/xulu/plugin/gui/DisplayContainer_GeomAndGrid.java
   trunk/src/edu/bonn/xulu/plugin/gui/DisplayContainer_ListProperty.java
   trunk/src/edu/bonn/xulu/plugin/gui/DisplayContainer_MatrixProperty.java
   trunk/src/edu/bonn/xulu/plugin/gui/DisplayContainer_Properties.java
   trunk/src/edu/bonn/xulu/plugin/gui/DisplayContainer_Table.java
   trunk/src/edu/bonn/xulu/plugin/gui/EventManagerFrame_BasicTable.java
   trunk/src/edu/bonn/xulu/plugin/gui/ModelControlContainer.java
   trunk/src/edu/bonn/xulu/plugin/gui/ModelControlFrame_Basic.java
   trunk/src/edu/bonn/xulu/plugin/gui/PluginManagerFrame_BasicTable.java
   trunk/src/edu/bonn/xulu/plugin/gui/RegistryFrame_Tree.java
   trunk/src/edu/bonn/xulu/plugin/gui/StatusFrame_BasicTextArea.java
   trunk/src/edu/bonn/xulu/plugin/gui/package.html
   trunk/src/edu/bonn/xulu/plugin/io/
   trunk/src/edu/bonn/xulu/plugin/io/IOUtil.java
   trunk/src/edu/bonn/xulu/plugin/io/feature/
   trunk/src/edu/bonn/xulu/plugin/io/feature/gt/
   trunk/src/edu/bonn/xulu/plugin/io/feature/gt/SingleFeatureCollectionFactory.java
   trunk/src/edu/bonn/xulu/plugin/io/feature/gt/SingleFeatureCollectionFactory_ShapeFile.java
   trunk/src/edu/bonn/xulu/plugin/io/feature/gt/package.html
   trunk/src/edu/bonn/xulu/plugin/io/feature/package.html
   trunk/src/edu/bonn/xulu/plugin/io/grid/
   trunk/src/edu/bonn/xulu/plugin/io/grid/WritableGridFactory.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/array/
   trunk/src/edu/bonn/xulu/plugin/io/grid/array/GridListFactory.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/array/GridListFactory_ArcInfoAsciiGrid.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/array/MultiGridFactory.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/array/MultiGridFactory_ArcInfoAsciiGrid.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/array/SingleGridFactory.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/array/SingleGridFactory_ArcInfoAsciiGrid.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/array/SingleGridFactory_GeoTiff.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/array/WritableGridArrayFactory.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/array/WritableGridArrayFactory_ArcInfoAsciiGrid.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/array/WritableGridArrayFactory_GeoTiff.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/awt/
   trunk/src/edu/bonn/xulu/plugin/io/grid/awt/GridListFactory.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/awt/GridListFactory_ArcInfoAsciiGrid.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/awt/MultiGridFactory.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/awt/MultiGridFactory_ArcInfoAsciiGrid.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/awt/SingleGridFactory.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/awt/SingleGridFactory_ArcInfoAsciiGrid.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/awt/SingleGridFactory_GeoTiff.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/awt/WritableGridRasterFactory.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/awt/WritableGridRasterFactory_ArcInfoAsciiGrid.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/awt/WritableGridRasterFactory_GeoTiff.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/awt/package.html
   trunk/src/edu/bonn/xulu/plugin/io/grid/gt/
   trunk/src/edu/bonn/xulu/plugin/io/grid/gt/GridCoverageFactory.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/gt/GridCoverageFactory_ArcInfoAsciiGrid.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/gt/GridCoverageFactory_GeoTiff.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/gt/GridListFactory.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/gt/GridListFactory_ArcInfoAsciiGrid.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/gt/MultiGridFactory.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/gt/MultiGridFactory_ArcInfoAsciiGrid.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/gt/SingleGridFactory.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/gt/SingleGridFactory_ArcInfoAsciiGrid.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/gt/SingleGridFactory_GeoTiff.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/gt/package.html
   trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/
   trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/GridListFactory.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/GridListFactory_ArcInfoAsciiGrid.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/MultiGridFactory.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/MultiGridFactory_ArcInfoAsciiGrid.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/SingleGridFactory.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/SingleGridFactory_ArcInfoAsciiGrid.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/SingleGridFactory_GeoTiff.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/WritableGridLLFactory.java
   trunk/src/edu/bonn/xulu/plugin/io/grid/package.html
   trunk/src/edu/bonn/xulu/plugin/io/misc/
   trunk/src/edu/bonn/xulu/plugin/io/misc/CAAreaListFactory_ShapeFile.java
   trunk/src/edu/bonn/xulu/plugin/io/misc/CASettlementAreaListFactory_ShapeFile.java
   trunk/src/edu/bonn/xulu/plugin/io/misc/DynamicXuluObjectFactory_BasicStructure.java
   trunk/src/edu/bonn/xulu/plugin/io/misc/package.html
   trunk/src/edu/bonn/xulu/plugin/io/package.html
   trunk/src/edu/bonn/xulu/plugin/model/
   trunk/src/edu/bonn/xulu/plugin/model/ca/
   trunk/src/edu/bonn/xulu/plugin/model/ca/MultiCellularAutomaton.java
   trunk/src/edu/bonn/xulu/plugin/model/ca/agric/
   trunk/src/edu/bonn/xulu/plugin/model/ca/agric/ImpetusCellularAutomaton.java
   trunk/src/edu/bonn/xulu/plugin/model/ca/fire/
   trunk/src/edu/bonn/xulu/plugin/model/ca/fire/ImpetusFireCA.java
   trunk/src/edu/bonn/xulu/plugin/model/ca/fire/ImpetusFireCAContentManager.java
   trunk/src/edu/bonn/xulu/plugin/model/ca/reservoir/
   trunk/src/edu/bonn/xulu/plugin/model/ca/reservoir/SmallReservoirModel.java
   trunk/src/edu/bonn/xulu/plugin/model/ca/reservoir/SmallReservoirModelContentManager.java
   trunk/src/edu/bonn/xulu/plugin/model/clue/
   trunk/src/edu/bonn/xulu/plugin/model/clue/ClueModel.java
   trunk/src/edu/bonn/xulu/plugin/model/clue/ClueModelContentManager.java
   trunk/src/edu/bonn/xulu/plugin/model/clue/ClueModel_Optimized.java
   trunk/src/edu/bonn/xulu/plugin/model/clue/ClueModel_Original.java
   trunk/src/edu/bonn/xulu/plugin/model/parallel/
   trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueModelContentManager.java
   trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueModelParallel.java
   trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueModel_deterministic.java
   trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueParallelTuned.java
   trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueTask.java
   trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueTaskDefinition.java
   trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueTaskTuned.java
   trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/
   trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/AVNTask.java
   trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/AVNTuned.java
   trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/AVNTunedTask.java
   trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/AverageNeighborhoodContentManager.java
   trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/AverageNeighborhoodParallelDemoModel.java
   trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/AverageNeighborhoodSerialDemoModel.java
   trunk/src/edu/bonn/xulu/plugin/model/test/
   trunk/src/edu/bonn/xulu/plugin/model/test/TestModel.java
   trunk/src/edu/bonn/xulu/plugin/package.html
   trunk/src/edu/bonn/xulu/plugin/vis/
   trunk/src/edu/bonn/xulu/plugin/vis/GTEditorTool.java
   trunk/src/edu/bonn/xulu/plugin/vis/GTVisualisationTool.java
   trunk/src/edu/bonn/xulu/plugin/vis/JFreeChartVisualisationTool.java
   trunk/src/edu/bonn/xulu/plugin/vis/package.html
   trunk/src/overview.html
   trunk/src/schmitzm/
   trunk/src/skrueger/
   trunk/src/skrueger/gol/
   trunk/src/skrueger/gol/GameOfLife.java
   trunk/src/skrueger/gol/GameOfLifeContentManager.java
   trunk/startXULU.bat
Modified:
   trunk/
Log:
First Commit, corresponds to Revision 1008 of Wikisquare-SVN 


Property changes on: trunk
___________________________________________________________________
Name: svn:ignore
   + classes
javadoc


Added: trunk/InitXulu.bat
===================================================================
--- trunk/InitXulu.bat	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/InitXulu.bat	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,134 @@
+ at echo off
+rem =====================================================================
+rem  Initializes the XULU folder structure after the first SVN checkout
+rem  by copying default configuration files from the "defaults" folder
+rem  to their expected location.
+rem 
+rem  The default behavior is only to copy not existing files. If you
+rem  want to completly reset you configuration (in case of a partially
+rem  deleted or damaged configuration) you can use the command parameter
+rem  "/reset" to overwrite all files with their default.
+rem
+rem  Summery:
+rem     - copy "DefaultProperties" to main folder
+rem     - copy Eclipse configuration to main folder
+rem              - .classpath
+rem              - .project
+rem     - copy "startXulu.bat" to main folder
+rem     - copy XULU registry files to main folder
+rem              - registry.xif
+rem              - registry_arrayGrid.xif
+rem              - registry_ProxyGrid.xif
+rem     - XULU plugin configurations
+rem              - plugin\GeoModelCodeGenerator\* to plugin folder
+rem              - plugin\GTVisualisationColorMapPlugin\* to plugin folder
+rem              - plugin\LoggerPlugin\* to plugin folder
+rem              - plugin\RasterCalculator\* to plugin folder
+rem =====================================================================
+
+setlocal
+
+set SOURCE_DIR=defaults
+
+rem *** Reset mode >> Overwrite without confirm ***
+if "%1"=="/init"  (set COPY_PARAM=/Y) else set COPY_PARAM=/-Y
+if "%1"=="/init" goto overwrite
+rem *** Update mode >> Overwrite with confirm ***
+if "%1"=="/reset" goto overwrite
+rem *** Default mode >> only copy not existing files ***
+goto no_overwrite
+
+rem ************************** Update routine **************************
+:no_overwrite
+echo.
+echo.The XULU configuration will be updated with new files...
+echo.*** DefaultProperties ***
+if not exist DefaultProperties (copy %SOURCE_DIR%\DefaultProperties .) else echo.        'DefaultProperties' skipped!
+if not exist XuluProperties    (copy %SOURCE_DIR%\XuluProperties .)    else echo.        'XuluProperties' skipped!
+echo.*** Eclipse configuration ***
+if not exist .classpath (copy %SOURCE_DIR%\.classpath .) else echo.        '.classpath' skipped!
+if not exist .project   (copy %SOURCE_DIR%\.project .)   else echo.        '.project' skipped!
+echo.*** startXulu.bat ***
+if not exist startXulu.bat (copy %SOURCE_DIR%\startXulu.bat .) else echo.        'startXulu.bat' skipped!
+echo.*** sample XULU registry files ***
+if not exist registry.xif           (copy %SOURCE_DIR%\registry.xif .)           else echo.        'registry.xif' skipped!
+if not exist registry_arrayGrid.xif (copy %SOURCE_DIR%\registry_arrayGrid.xif .) else echo.        'registry_arrayGrid.xif' skipped!
+if not exist registry_ProxyGrid.xif (copy %SOURCE_DIR%\registry_ProxyGrid.xif .) else echo.        'registry_ProxyGrid.xif' skipped!
+echo.*** Plugin folder ***
+if not exist plugin (mkdir plugin)  else echo.        'plugin' folder already exists!
+echo.*** Template files for GeoModelCodeGenerator plugin ***
+set DDIR=plugin\GeoModelCodeGenerator
+set SDIR=%SOURCE_DIR%\%DDIR%
+if not exist %DDIR%                         (mkdir %DDIR%)                                         else echo.        folder '%DDIR%' already exists!
+if not exist %DDIR%\ModelContentManager.tpl (copy %SDIR%\ModelContentManager.tpl %DDIR%)           else echo.        'ModelContentManager.tpl' skipped!
+if not exist %DDIR%\StepModel.tpl           (copy %SDIR%\StepModel.tpl           %DDIR%)           else echo.        'StepModel.tpl' skipped!
+if not exist %DDIR%\XuluModel.tpl           (copy %SDIR%\XuluModel.tpl           %DDIR%)           else echo.        'XuluModel.tpl' skipped!
+echo.*** Template files for GTVisualisationColorMapPlugin ***
+set DDIR=plugin\GTVisualisationColorMapPlugin
+set SDIR=%SOURCE_DIR%\%DDIR%
+if not exist %DDIR%                 (mkdir %DDIR%)                        else echo.        folder '%DDIR%' already exists!
+if not exist %DDIR%\gtcolormaps.xif (copy %SDIR%\gtcolormaps.xif %DDIR%)  else echo.        'gtcolormaps.xif' skipped!
+echo.*** Template files for LoggerPlugin ***
+set DDIR=plugin\LoggerPlugin
+set SDIR=%SOURCE_DIR%\%DDIR%
+if not exist %DDIR%           (mkdir %DDIR%)                  else echo.        folder '%DDIR%' already exists!
+if not exist %DDIR%\log4j.cfg (copy %SDIR%\log4j.cfg %DDIR%)  else echo.        'log4j.cfg' skipped!
+echo.*** Template files for LoggerPlugin ***
+set DDIR=plugin\RasterCalculator
+set SDIR=%SOURCE_DIR%\%DDIR%
+if not exist %DDIR%                    (mkdir %DDIR%)                           else echo.        folder '%DDIR%' already exists!
+if not exist %DDIR%\default_filter.inp (copy %SDIR%\default_filter.inp %DDIR%)  else echo.        'default_filter.inp' skipped!
+
+goto finish
+
+rem ************************ Overwrite routine *************************
+:overwrite
+echo.
+echo.The XULU configuration will be completly reset!!
+echo.*** DefaultProperties ***
+copy %SOURCE_DIR%\DefaultProperties . %COPY_PARAM%
+copy %SOURCE_DIR%\XuluProperties    . %COPY_PARAM%
+echo.*** Eclipse configuration ***
+copy %SOURCE_DIR%\.classpath . %COPY_PARAM%
+copy %SOURCE_DIR%\.project .   %COPY_PARAM%
+echo.*** startXulu.bat ***
+copy %SOURCE_DIR%\startXulu.bat .   %COPY_PARAM%
+echo.*** sample XULU registry files ***
+copy %SOURCE_DIR%\registry.xif           .   %COPY_PARAM%
+copy %SOURCE_DIR%\registry_arrayGrid.xif .   %COPY_PARAM%
+copy %SOURCE_DIR%\registry_ProxyGrid.xif .   %COPY_PARAM%
+echo.*** Plugin folder ***
+if not exist plugin (mkdir plugin) else echo.        'plugin' folder already exists!
+echo.*** Template files for GeoModelCodeGenerator plugin ***
+set DDIR=plugin\GeoModelCodeGenerator
+set SDIR=%SOURCE_DIR%\%DDIR%
+if not exist %DDIR% (mkdir %DDIR%) else echo.        folder '%DDIR%' already exists!
+copy %SDIR%\ModelContentManager.tpl %DDIR% %COPY_PARAM%
+copy %SDIR%\StepModel.tpl           %DDIR% %COPY_PARAM%
+copy %SDIR%\XuluModel.tpl           %DDIR% %COPY_PARAM%
+echo.*** Template files for GTVisualisationColorMapPlugin ***
+set DDIR=plugin\GTVisualisationColorMapPlugin
+set SDIR=%SOURCE_DIR%\%DDIR%
+if not exist %DDIR% (mkdir %DDIR%) else echo.        folder '%DDIR%' already exists!
+copy %SDIR%\gtcolormaps.xif %DDIR% %COPY_PARAM%
+echo.*** Template files for LoggerPlugin ***
+set DDIR=plugin\LoggerPlugin
+set SDIR=%SOURCE_DIR%\%DDIR%
+if not exist %DDIR% (mkdir %DDIR%) else echo.        folder '%DDIR%' already exists!
+copy %SDIR%\log4j.cfg %DDIR% %COPY_PARAM%
+echo.*** Template files for LoggerPlugin ***
+set DDIR=plugin\RasterCalculator
+set SDIR=%SOURCE_DIR%\%DDIR%
+if not exist %DDIR% (mkdir %DDIR%) else echo.        folder '%DDIR%' already exists!
+copy %SDIR%\default_filter.inp %DDIR% %COPY_PARAM%
+
+
+goto finish
+
+
+rem ************************** Finish routine **************************
+:finish
+echo.Finished.
+echo.
+
+endlocal

Added: trunk/defaults/.classpath
===================================================================
--- trunk/defaults/.classpath	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/defaults/.classpath	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry excluding="**/.svn/" kind="src" path="src"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/SCHMITZM"/>
+	<classpathentry kind="lib" path="lib/jai-1_1_3/lib/clibwrapper_jiio.jar"/>
+	<classpathentry kind="lib" path="lib/jai-1_1_3/lib/jai_codec.jar"/>
+	<classpathentry kind="lib" path="lib/jai-1_1_3/lib/jai_core.jar"/>
+	<classpathentry kind="lib" path="lib/jai-1_1_3/lib/jai_imageio.jar"/>
+	<classpathentry kind="lib" path="lib/jai-1_1_3/lib/mlibwrapper_jai.jar"/>
+	<classpathentry kind="lib" path="lib/JavaRInterface/JRI.jar"/>
+	<classpathentry kind="lib" path="lib/jini/lib/tools.jar"/>
+	<classpathentry kind="lib" path="lib/schmitzm/schmitzm.jar"/>
+	<classpathentry kind="output" path="classes"/>
+</classpath>

Added: trunk/defaults/.project
===================================================================
--- trunk/defaults/.project	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/defaults/.project	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>XULU</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>

Added: trunk/defaults/DefaultProperties
===================================================================
--- trunk/defaults/DefaultProperties	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/defaults/DefaultProperties	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,145 @@
+#Default Properties for the Xulu Modelling Plattform
+#Thu Jan 25 20:20:05 CET 2007
+
+
+#************************************************************
+#********************* CRS Preferences **********************
+#************************************************************
+# Supported are EPSG-Codes "EPSG:..." and WKT-specifications
+# Benin --> UTM (zone xx) = EPSG:326xx
+General.DefaultCRS = EPSG\:32631
+General.DefaultCRS.doc = Default Coordinate-Reference-System for prj-less data (here: UTM zone 31 for Benin; allowed: EPSG-Codes "EPSG:..." or WKT-specifications as used in prj-files)
+
+#************************************************************
+#**************** XULU General Preferences ******************
+#************************************************************
+General.useSystemLookAndFeel = true
+General.useSystemLookAndFeel.doc = set this entry to false, if you have problems (e.g. with gnome), when using the system look and feel (
+
+Datatypes.proxy.enableUnloading = true
+Datatypes.proxy.enableUnloading.doc = if true the Xulu-models have the ability to unload no longer used data into a temporaray folder
+Datatypes.proxy.unloadFolder = Temp
+Datatypes.proxy.unloadFolder.doc = The folder in which the models are unloaded (if unloading is enabled)
+Datatypes.xulugrid.alwaysconvert = true
+Datatypes.xulugrid.alwaysconvert.doc = if true, every time a arcgridraster is converted to xulugridfile (in a new file). If false, this is only done if no xulugridfile with the same name exists
+Datatypes.xulugrid.creationFolder = Temp
+Datatypes.xulugrid.creationFolder.doc  = The folder where new empty xulugridfiles are created
+
+#************************************************************
+#**************** XULU/V General Preferences ****************
+#************************************************************
+
+#General#
+Parallel.splitmapforclass.default = appl.parallel.spmd.split.SplitMap1DVertical
+Parallel.splitmapforclass.default.doc = The default splitmap used for partitioning
+Parallel.splitmapforclass.XuluWritableGridFile = appl.parallel.spmd.split.SplitMap1DVertical
+Parallel.splitmapforclass.XuluWritableGridFile.doc = The Splitmap used for partitioning SplittableProxyGrids
+Parallel.splitmapforclass.SplittableLLProxyGrid = appl.parallel.spmd.split.SplitMap1DVertical
+Parallel.splitmapforclass.SplittableLLProxyGrid.doc = The Splitmap used for partitioning SplittableProxyGrids
+
+Parallel.partitionhandlerfactory.classname = appl.parallel.data.XuluClientLoader
+Parallel.partitionhandlerfactory.classname.doc = the loader used for data loading.
+
+## Benchmark ##
+Benchmark.SimpleBench.gridwidth = 100
+Benchmark.SimpleBench.gridwidth.doc = The width and height of the grid used for benchmarking
+Benchmark.SimpleBench.runningtime = 1500
+Benchmark.SimpleBench.runningtime.doc = The time in ms the benchmark runs. The longer the bench runs, the higher the rating and the accuracy
+Benchmark.SimpleBench.neighborhood = 10
+Benchmark.SimpleBench.neighborhood.doc = The neighborhood range which is used in the bench. Higher values will decrease the rating
+Benchmark.SimpleBench.calibrator = 4.25
+Benchmark.SimpleBench.calibrator.doc = After calculation the rating is divided by this integer value
+
+#***********************************************************
+#*************** XULU/V Client Preferences *****************
+#***********************************************************
+
+XuluClient.registryport.doc = Port for the registry on clientside
+XuluClient.registryport = 1099
+
+##Initialize Options##
+RemoteExecutionController.startlocalxuluserver=true
+RemoteExecutionController.startlocalxuluserver.doc = if true a local instance of the xuluServer is started
+RemoteExecutionController.spmd.start=true
+RemoteExecutionController.spmd.start.doc = if true a SPMDClient is started
+RemoteExecutionController.http.start = true
+RemoteExecutionController.http.start.doc = starts the HTTP-Server each time the controller is started
+RemoteExecutionController.http.basedir = ./classes
+RemoteExecutionController.http.basedir.doc = Use slashes or double backslashes as seperator! The directory which will be the root directory of the http-server (should be the root of your classfiles)
+RemoteExecutionController.http.port = 80
+RemoteExecutionController.http.port.doc = The port of the httpserver (should be 80)
+RemoteExecutionController.http.verbose = true
+RemoteExecutionController.http.verbose.doc = if true the http-server gives output to the console
+
+## Discovery ##
+DiscoveryServices.activeServices.doc = All active Discovery Services. Separate multiple entries by ';'
+DiscoveryServices.activeServices = appl.parallel.services.HostnameDiscoveryService
+DiscoveryServices.timeout = 500
+DiscoveryServices.timeout.doc = The time the discovery service waits on a response from the server
+DiscoveryServices.hostname.hosts.doc = The hosts which should be checked for computing resources (only when HostnameDiscovery is enabled). Separate multiple entries by ';'
+DiscoveryServices.hostname.hosts = localhost
+DiscoveryServices.hostname.refresh.doc = if refresh is set to 0 resources are only discovered once. Only existing resources are refreshed.
+DiscoveryServices.hostname.refresh = 1
+DiscoveryServices.multicast.port.doc = The port for multicastMessages on client side
+DiscoveryServices.multicast.port = 10000
+DiscoveryServices.multicast.group.doc = The multicast group IP
+DiscoveryServices.multicast.group = 239.1.1.1
+#DiscoveryServices.multicast.renewal.doc = currently not used
+#DiscoveryServices.multicast.renewal = 500
+
+#************************************************************
+#**************** XULU/V Server Preferences *****************
+#************************************************************
+XuluServer.priority = 3
+XuluServer.priority.doc = The priority for task execution on serverside. Use values from 1 to 5 with 3=normal 
+
+XuluServer.useThreads = max
+XuluServer.useThreads.doc = The number of threads to be used by the server for tasks that support multi-threading. Per default one thread is created for every available Processors (value='max'). More threads than processors may be useful for testing tasks which support multihreading or for processors which support hyperthreading 
+XuluServer.benchmarkclass = appl.util.benchmark.SimpleBenchmark
+XuluServer.benchmarkclass.doc = The benchmark-class used for getting rating. Leave blank for disabling the bench.
+XuluServer.runbench = true
+XuluServer.runbench.doc = if true, the benchmark is automatically run
+
+XuluServer.multicastgroup.doc = The XuluServerMulticast group IP (should be the same as MulticastDiscoveryService.multicastgroup)
+XuluServer.multicastgroup = 239.1.1.1
+XuluServer.registryport.doc = The port which is used for the registry in XuluServer
+XuluServer.registryport = 1099
+XuluServer.multicastport.doc = The port which is used on serverside to receive and send multicast messages
+XuluServer.multicastport = 10000
+
+XuluServer.eventDelay = 100
+XuluServer.eventDelay.doc = Events are collected on serverside and submitted ever <DELAY> milliseconds
+
+XuluServer.log4j.logLevel = warn
+XuluServer.log4j.logLevel.doc = Possible Values: info,debug,warn,error,fatal,off
+XuluServer.log4j.mode = console
+XuluServer.log4j.mode.doc = Possible Values: chainsaw, console, file
+
+XuluServer.useCodeDownloading = false
+XuluServer.useCodeDownloading.doc = Set to true, if you want to use the code downloading functionality
+
+### Xulu/V starter
+XuluServerStarter.port = 1099
+XuluServerStarter.port.doc = The port where the starter creates the registry, if needed
+XuluServerStarter.javaprogram = java
+XuluServerStarter.javaprogram.doc The path to the java.exe which should be used for execution (or just java, if in the classpath)
+XuluServerStarter.codebasedir = ./classes
+XuluServerStarter.codebasedir.doc = The codebase path (the path to the binaries)
+XuluServerStarter.securitypolicy = security.policy
+XuluServerStarter.securitypolicy.doc = The security policy which should be used for Server starting
+XuluServerStarter.furtherjavaarguments =
+XuluServerStarter.furtherjavaarguments.doc = further arguments for the Java VM
+XuluServerStarter.classpath = .;classes
+XuluServerStarter.classpath.doc = libaries, which should be on the classpath
+XuluServerStarter.memorymax = 64
+XuluServerStarter.memorymin = 4
+
+## ********************** Documentation only ******************
+SimpleCommEventMonitor.timemonitoring.doc = if true, timeEvents are generated for parallel computation. This may cost some performance
+SimpleCommEventMonitor.transfermonitoring.doc = if true, transferEvents are generated for parallel computation. This WILL cost a lot of performance
+
+## *************** Filter (excluding key from editor view)***********
+Filter.prefixes = Filter;SimpleCommEventMonitor
+Filter.prefixes.doc =  all prefixes which show up here are not displayed in the Configuration editor. Divide by ;
+Filter.keys =
+Filter.keys.doc = all keys (=Prefix + "." + Suffix) which show up here are not displayed in the configuration editor. Divide by ;

Added: trunk/defaults/XuluProperties
===================================================================
--- trunk/defaults/XuluProperties	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/defaults/XuluProperties	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,7 @@
+#Stored properties of the Xulu modelling platform
+#Wed Feb 25 12:47:39 WAT 2009
+RecentImports.MAXLOAD=10
+RecentImports.SIZE=0
+RecentScripts.SIZE=0
+Console.Logging=false
+RecentScripts.MAXLOAD=10

Added: trunk/defaults/plugin/GTVisualisationColorMapPlugin/gtcolormaps.xif
===================================================================
--- trunk/defaults/plugin/GTVisualisationColorMapPlugin/gtcolormaps.xif	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/defaults/plugin/GTVisualisationColorMapPlugin/gtcolormaps.xif	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,96 @@
+//========================================================================
+//
+//   Bei dieser Datei handelt es sich um die Input-Datei des Xulu-Plugins
+//    >>> schmitzm.dipl.xulu.plugin.appl.GTVisualisationColorMapPlugin <<<
+//   Dieses laed vordefinierte Farbpaletten fuer Rasterdaten in die
+//   Xulu-Visualisierungstools der Klasse
+//    >>> schmitzm.dipl.xulu.plugin.vis.GTVisualisationTool <<<
+//
+//   Damit das Plugin diese Datei korrekt einlesen kann, muss die Datei den
+//   statischen Namen "gtcolormaps.xif" tragen!!
+//
+//   Die Datei kann mehrere Farbpaletten enthalten. Jede Farbpalette wird
+//   von einem [..]-Tag eingeleitet, wobei die Bezeichnung zwischen den
+//   Klammern als Name fuer die Farbpalette verwendet wird.
+//   Nach dem [..]-Tag folgen die Farbpaletten-Eintraege der Form
+//
+//                 <raster wert> <color> [<label>]
+//
+//   Die Farbe kann auf mehrere Arten spezifiziert werden:
+//     a) Als RGB-Werte der Form "RGB(<red>,<green>,<blue>)".
+//        Die RGB-Werte muessen durch Komma und OHNE Leerzeichen
+//        voneinander getrennt sein.
+//     b) Als dezimaler (1234) oder hexadezimaler Integer-Wert (0x123456),
+//        aus dem die 3 RGB-Komponenten extrahiert werden
+//     c) Als String, der die Farbe identifiziert. Hierfuer sind alle
+//        Farb-Bezeichnungen zulaessig, die in der Klasse java.awt.Color
+//        als (statische) Felder deklariert sind.
+//        z.B. Black, Blue, Cyan, Gray, Green, Magenta, Orange, Pink,
+//             Red, White, Yellow
+//
+//========================================================================
+
+
+//###### Black & White Color-Map #######
+[Black/White]
+0	0x000000 #RGB(0,0,0)
+9999	0xFFFFFF #RGB(255,255,255)
+
+//###### Red & Green Color-Map #######
+[Red/Green]
+0	0xFF0000 # Rot   = RGB(255,0,0)
+9999	0x00FF00 # Gruen = RGB(0,255,00)
+
+//###### Bunte Test-Farbpalette ######
+[Bunt-Test]
+0	RGB(0,0,255)      # Blau
+1	RGB(128,128,128)  # Grau
+2	RGB(255,255,0)    # Gelb
+3	RGB(255,0,0)      # Rot
+4	RGB(0,255,255)    # Cyan
+5	RGB(255,0,255)    # Magenta
+
+//###### Bunte Test-Farbpalette ######
+[Name-Test]
+0	BLUE
+1	Gray
+2	Yellow
+3	Red
+4	cyan
+5	magenta
+
+//###### Farbschema fuer Impetus Clue (1) ######
+[Impetus Clue 0-5]
+0	BLUE            # Blau = Siedlung
+1	RGB(51,51,0)    # Dunkel-Braun = intesive Landwirtschaft
+2	RGB(204,153,80) # Hell-Braun = weniger intensive Landwirtschaft
+3	RGB(0,160,0)    # Dunkel-Gruen = dichter Wald
+4	RGB(170,255,0)  # Gruen = dichte Savanne
+5	RGB(204,255,0)  # Hell-Gruen = restliche Savanne / Sonstiges
+
+//###### Farbschema fuer Impetus Clue (2) ######
+[Impetus Clue 0-3]
+0	RED            # Rot = Siedlung
+1	RGB(204,153,0) # Braun = Landwirtschaft
+2	RGB(0,160,0)   # Dunkel-Gruen = dichter Wald/Savanne
+3	RGB(204,255,0) # Hell-Gruen = restliche Savanne / Sonstiges
+
+//###### Farbschema fuer den Impetus CA ######
+[Impetus CA]
+DEFAULT
+0	WHITE            // Weiss = Unclassified
+1	RGB(0,160,0)     // Dunkel-Gruen = Forest dense
+2	RGB(204,255,0)   // Hell-Gruen = Foret claire
+3	RGB(102,102,0)   // Braun-Gruen = Savanne Boise
+4	RGB(153,153,0)   // Ocker = Savanne Arboree
+5	RGB(102,255,102) // Hell-Gruen = Inselberg with Vegetation
+6	RGB(51,51,0)     // Dunkel-Braun = Savanne Saxicole
+7	BLACK            // Schwarz = Bas Fond
+8	BLUE             // Blau = Fluss
+9	RGB(153,153,255) // Hell-Blau = Flussbett
+10	RGB(204,0,0)     // Dunkel-Rot = Dichte Siedlung (Stadt)
+11	RGB(255,102,102) // Hell-Rot = Lockere Siedlung (Dorf)
+12	RGB(204,153,80)  // Hell-Braun = Feld/Brache
+13	RGB(170,255,0)   // Gruen = Inselberg
+14	RGB(204,153,0)   // Braun = Brache
+15	CYAN             // Cyan = Siedlungsexpansion
\ No newline at end of file

Added: trunk/defaults/plugin/GeoModelCodeGenerator/ModelContentManager.tpl
===================================================================
--- trunk/defaults/plugin/GeoModelCodeGenerator/ModelContentManager.tpl	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/defaults/plugin/GeoModelCodeGenerator/ModelContentManager.tpl	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,29 @@
+package $FIELD(Package);
+
+$LOOP(ClassImport)
+import $FIELD(ClassImport);
+$ENDLOOP()
+
+/**
+ * Diese Klasse definiert und verwaltet die $FIELD(ResourceCount)
+ * Ressourcen fuer das Modell {@linkplain $FIELD(ModelName)}
+ * und prueft diese auf Korrektheit.<br>
+ * Die Art der benoetigten Ressourcen ist der {@linkplain $FIELD(ModelName)}-Doku
+ * zu entnehmen.
+ * @see ClueModelContentManager
+ * @author automatisch generiert durch {@link edu.bonn.xulu.plugin.appl.GeoModelCodeGenerator}
+ * @version 1.0
+ */
+public class $FIELD(ModelCMName) extends $FIELD(ModelCMSuperClass) {
+
+  /**
+   * Erzeugt einen neuen ContentManager fuer das Modell {@linkplain $FIELD(ModelName)}.
+   */
+  public $FIELD(ModelCMName)() {
+    super($FIELD(ResourceCount));
+    // ===== Ressourcen festlegen =====
+$LOOP(Resources)
+    // $FIELD(ResourceDesc)
+    resource[$FIELD(ResourceNo)] = $FIELD(ResourceDefinition);
+$ENDLOOP()  }
+}

Added: trunk/defaults/plugin/GeoModelCodeGenerator/StepModel.tpl
===================================================================
--- trunk/defaults/plugin/GeoModelCodeGenerator/StepModel.tpl	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/defaults/plugin/GeoModelCodeGenerator/StepModel.tpl	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,94 @@
+package $FIELD(Package);
+
+$LOOP(ClassImport)
+import $FIELD(ClassImport);
+$ENDLOOP()
+
+/**
+ * Diese Klasse stellt eine Implementierung des Modells {@linkplain $FIELD(ModelName)}
+ * dar. Dieses benoetigt $FIELD(ResourceCount) Ressourcen, welche durch den
+ * {@linkplain $FIELD(ModelCMName)} spezifiziert werden:
+ * <ol>
+$LOOP(Resources)
+ * <li><b>$FIELD(ResourceDesc) ({@code $FIELD(ResourceVar)}):</b>
+ *     @todo Detaillierte Ressoucen-Beschreibung einfuegen
+ *     </li>
+$ENDLOOP() * </ol>
+ * @see $FIELD(ModelCMName)
+ * @author automatisch generiert durch {@link edu.bonn.xulu.plugin.appl.GeoModelCodeGenerator}
+ * @version 1.0
+ */
+public class $FIELD(ModelName) extends $FIELD(ModelSuperClass) {
+  /** Speichert den ContentManager fuer das Modell.
+   *  @see $FIELD(ModelCMName) */
+  protected $FIELD(ModelCMName) contManager;
+
+  //********** Lese/Schreibrechte, die fuer den gesamten ***********
+  //********** Modellanlauf gehalten werden muessen      ***********
+$LOOP(PropertyResources)
+  private $FIELD(ResourceAccessType)  $FIELD(ResourceAccessVar) = null;  // $FIELD(PropertyResourceDesc)
+$ENDLOOP()
+  //**************** Variablen mit denen gearbeitet wird *******************
+$LOOP(Resources)
+  private  $FIELD(ResourceVarType)  $FIELD(ResourceVar) = null; // $FIELD(ResourceDesc)
+$ENDLOOP()
+  /**
+   * Erzeugt eine neue Instanz des Modells.
+   */
+  public $FIELD(ModelName)() {
+    super( new $FIELD(ModelCMName)() );
+    contManager = ($FIELD(ModelCMName))super.contManager;
+  }
+
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////   Implementierung von AbstractXuluModel   //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Initialisiert das Model, indem die Ressourcen aus dem ContentManager
+   * geladen werden und mit Lese/Schreib-Rechten versehen werden. Zudem
+   * werden Referenzen auf die Ressourcen in lokalen Variablen
+   * gespeichert, um waehrend des Modellablaufs effizienter darauf zugreifen
+   * zu koennen.
+   */
+  public void performModelInit() {
+    if ( contManager == null )
+      return;
+    // Zugriffsrechte aus Ressourcen/Propertys holen
+$LOOP(PropertyResources)
+    $FIELD(ResourceAccessVar) = null;
+    if ( contManager.getResource($FIELD(PropertyResourceNo)).getData() != null )
+      $FIELD(ResourceAccessVar) = (($FIELD(PropertyResourceType))contManager.getResource($FIELD(PropertyResourceNo)).getData())$FIELD(ResourceAccessAlloc);
+$ENDLOOP()
+    // Variablen belegen mit denen gearbeitet wird
+$LOOP(Resources)
+    $FIELD(ResourceVar) = $FIELD(ResourceVarAlloc);
+$ENDLOOP()
+     // WICHTIG:
+     // An dieser Stelle die Anzahl an Modellschritten (aus einer
+     // Ressource) zuweisen, die das Modell laufen soll!
+     // Sonst laeuft das Modell nicht an!!
+    this.stepCount = 0;
+  }
+
+  /**
+   * Gibt die Lese/Schreibrechte auf das Ein- und Ausgaberaster wieder frei.
+   * Interne Ressourcen brauchen keine aus dem Speicher entfernt werden.
+   */
+  public void performModelDispose() {
+    // Ressourcen wieder freigeben
+$LOOP(PropertyResources)
+    releaseAccess($FIELD(ResourceAccessVar));
+$ENDLOOP()  }
+
+  /**
+   * Fuehrt einen Schritt des Modellablaufs durch.
+   * @param stepNo zu modellierender Schritt (beginnend bei 1!)
+   */
+  public void performModelStep(int stepNo) {
+    // @todo An dieser Stelle den Ablauf eines Modellschritts implementieren
+    
+    // Ueber die Variable 'statusOut' koennen Status-Ausgaben im
+    // Modellfenster ausgegeben werden.
+  }
+}

Added: trunk/defaults/plugin/GeoModelCodeGenerator/XuluModel.tpl
===================================================================
--- trunk/defaults/plugin/GeoModelCodeGenerator/XuluModel.tpl	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/defaults/plugin/GeoModelCodeGenerator/XuluModel.tpl	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,87 @@
+package $FIELD(Package);
+
+$LOOP(ClassImport)
+import $FIELD(ClassImport);
+$ENDLOOP()
+
+/**
+ * Diese Klasse stellt eine Implementierung des Modells {@linkplain $FIELD(ModelName)}
+ * dar. Dieses benoetigt $FIELD(ResourceCount) Ressourcen, welche durch den
+ * {@linkplain $FIELD(ModelCMName)} spezifiziert werden:
+ * <ol>
+$LOOP(Resources)
+ * <li><b>$FIELD(ResourceDesc) ({@code $FIELD(ResourceVar)}):</b>
+ *     @todo Detaillierte Ressoucen-Beschreibung einfuegen
+ *     </li>
+$ENDLOOP() * </ol>
+ * @see $FIELD(ModelCMName)
+ * @author automatisch generiert durch {@link edu.bonn.xulu.plugin.appl.GeoModelCodeGenerator}
+ * @version 1.0
+ */
+public class $FIELD(ModelName) extends $FIELD(ModelSuperClass) {
+  /** Speichert den ContentManager fuer das Modell.
+   *  @see $FIELD(ModelCMName) */
+  protected $FIELD(ModelCMName) contManager;
+
+  //********** Lese/Schreibrechte, die fuer den gesamten ***********
+  //********** Modellanlauf gehalten werden muessen      ***********
+$LOOP(PropertyResources)
+  private $FIELD(ResourceAccessType)  $FIELD(ResourceAccessVar) = null;  // $FIELD(PropertyResourceDesc)
+$ENDLOOP()
+  //**************** Variablen mit denen gearbeitet wird *******************
+$LOOP(Resources)
+  private  $FIELD(ResourceVarType)  $FIELD(ResourceVar) = null; // $FIELD(ResourceDesc)
+$ENDLOOP()
+  /**
+   * Erzeugt eine neue Instanz des Modells.
+   */
+  public $FIELD(ModelName)() {
+    super( new $FIELD(ModelCMName)() );
+    contManager = ($FIELD(ModelCMName))super.contManager;
+  }
+
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////   Implementierung von AbstractXuluModel   //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Initialisiert das Model, indem die Ressourcen aus dem ContentManager
+   * geladen werden und mit Lese/Schreib-Rechten versehen werden. Zudem
+   * werden Referenzen auf die Ressourcen in lokalen Variablen
+   * gespeichert, um waehrend des Modellablaufs effizienter darauf zugreifen
+   * zu koennen.
+   */
+  public void performModelInit() {
+    if ( contManager == null )
+      return;
+    // Zugriffsrechte aus Ressourcen/Propertys holen
+$LOOP(PropertyResources)
+    $FIELD(ResourceAccessVar) = null;
+    if ( contManager.getResource($FIELD(PropertyResourceNo)).getData() != null )
+      $FIELD(ResourceAccessVar) = (($FIELD(PropertyResourceType))contManager.getResource($FIELD(PropertyResourceNo)).getData())$FIELD(ResourceAccessAlloc);
+$ENDLOOP()
+    // Variablen belegen mit denen gearbeitet wird
+$LOOP(Resources)
+    $FIELD(ResourceVar) = $FIELD(ResourceVarAlloc);
+$ENDLOOP()  }
+
+  /**
+   * Gibt die Lese/Schreibrechte auf das Ein- und Ausgaberaster wieder frei.
+   * Interne Ressourcen brauchen keine aus dem Speicher entfernt werden.
+   */
+  public void performModelDispose() {
+    // Ressourcen wieder freigeben
+$LOOP(PropertyResources)
+    releaseAccess($FIELD(ResourceAccessVar));
+$ENDLOOP()  }
+
+  /**
+   * Fuehrt den kompletten Modellablauf durch.
+   */
+  public void performModelStart() {
+    // @todo An dieser Stelle den Ablauf des Modells implementieren
+    
+    // Ueber die Variable 'statusOut' koennen Status-Ausgaben im
+    // Modellfenster ausgegeben werden.
+  }
+}

Added: trunk/defaults/plugin/LoggerPlugin/log4j.cfg
===================================================================
--- trunk/defaults/plugin/LoggerPlugin/log4j.cfg	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/defaults/plugin/LoggerPlugin/log4j.cfg	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,42 @@
+# Consolen-Appender mit TTCC-Layout definieren
+log4j.appender.CONSOLE        = org.apache.log4j.ConsoleAppender
+log4j.appender.CONSOLE.layout = org.apache.log4j.PatternLayout
+log4j.appender.CONSOLE.layout.ConversionPattern =%d{yyyy-MM-dd\thh:mm:ss}\t%r\t%p\t%c\t%m%n
+
+
+
+# File-Appender "xulu.log" mit TTCC-Layout definieren
+log4j.appender.XULULOG             = org.apache.log4j.RollingFileAppender
+log4j.appender.XULULOG.File        = log\\xulu.log
+log4j.appender.XULULOG.MaxFileSize = 10MB
+log4j.appender.XULULOG.layout = org.apache.log4j.PatternLayout
+log4j.appender.XULULOG.layout.ConversionPattern =%d{yyyy-MM-dd\thh:mm:ss}\t%r\t%p\t%c\t%m%n
+
+
+# File-Appender "clue_log.csv" mit TTCC-Layout definieren
+log4j.appender.CLUELOG             = org.apache.log4j.RollingFileAppender
+log4j.appender.CLUELOG.File        = log\\clue_log.csv
+log4j.appender.CLUELOG.MaxFileSize = 10MB
+#log4j.appender.CLUELOG.append      = false
+log4j.appender.CLUELOG.layout = org.apache.log4j.PatternLayout
+#log4j.appender.CLUELOG.layout.ConversionPattern =%d{yyyy-MM-dd;hh:mm:ss};%r;%p;%c;%C:%L;%m%n
+log4j.appender.CLUELOG.layout.ConversionPattern =%d{yyyy-MM-dd|hh:mm:ss}|%r|%p|%c|%C:%L|%m%n
+
+
+# Root-Logger definieren
+log4j.rootLogger = ERROR, CONSOLE
+
+# Applikations-Logger definieren
+log4j.logger.edu.bonn.xulu = ERROR, XULULOG
+
+# Modell-Logger
+# --> alle Log-Ausgaben von Modellen sollen nicht auch noch in die Xulu-Log
+#     geschrieben oder auf der Console ausgegeben werden (edu.bonn.xulu.model.XXX
+#     erbt Appender von edu.bonn.xulu)
+# --> Dummy-Logger erzeugen ohne Additivitaet (und ohne Appender)
+log4j.logger.edu.bonn.xulu.plugin.model = OFF
+log4j.additivity.edu.bonn.xulu.plugin.model = FALSE
+
+log4j.logger.edu.bonn.xulu.plugin.model.ClueModel = OFF, CLUELOG
+log4j.logger.edu.bonn.xulu.plugin.model.ClueModel_Optimized = OFF, CLUELOG
+

Added: trunk/defaults/plugin/RasterCalculator/default_filter.inp
===================================================================
--- trunk/defaults/plugin/RasterCalculator/default_filter.inp	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/defaults/plugin/RasterCalculator/default_filter.inp	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,10 @@
+#===================================
+# Name des Xulu-Objekts
+XuluObjectName = DEFAULT-FILTER
+#===================================
+
+[Test]
+Type  = schmitzm.data.property.MatrixProperty; 3; 3
+Value =	0;	1;	0;
+Value =	1;	1;	1;
+Value =	0;	1;	0;

Added: trunk/defaults/registry.xif
===================================================================
--- trunk/defaults/registry.xif	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/defaults/registry.xif	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,74 @@
+//########### Klassen werden "fuer alles" registriert ###########
+[Global]
+
+//########### Klassen werden als Datentyp registriert ###########
+[DataType]
+edu.bonn.xulu.data.DynamicXuluObject
+edu.bonn.xulu.plugin.data.grid.SingleGrid
+ 
+ 
+//########### Klassen als Default-Factory registriert ###########
+[DefaultFactory]
+edu.bonn.xulu.data.DynamicXuluObject$DefaultFactory
+edu.bonn.xulu.plugin.io.grid.awt.SingleGridFactory
+ 
+//########### Klassen als Import-Factory registriert ###########
+[ImportFactory]
+edu.bonn.xulu.plugin.io.grid.awt.SingleGridFactory_ArcInfoAsciiGrid		SingleGrid aus ArcInfoASCII
+edu.bonn.xulu.plugin.io.grid.awt.SingleGridFactory_GeoTiff			SingleGrid aus GeoTiff
+edu.bonn.xulu.plugin.io.feature.gt.SingleFeatureCollectionFactory_ShapeFile	FeatureCollection aus ShapeFile
+edu.bonn.xulu.plugin.io.misc.DynamicXuluObjectFactory_BasicStructure		Dynamisches Xulu-Objekt aus ASCII-File
+edu.bonn.xulu.plugin.io.grid.awt.GridListFactory_ArcInfoAsciiGrid		GridList aus ArcausfoASCII 
+edu.bonn.xulu.plugin.io.grid.awt.MultiGridFactory_ArcInfoAsciiGrid		MultiGrid aus ArcInfoASCII
+edu.bonn.xulu.plugin.io.misc.CAAreaListFactory_ShapeFile			CA-Areas aus ShapeFile
+ 
+//########### Klassen als Export-Factory registriert ###########
+[ExportFactory]
+edu.bonn.xulu.plugin.io.grid.awt.SingleGridFactory_ArcInfoAsciiGrid		SingleGrid in ArcInfoASCII
+edu.bonn.xulu.plugin.io.grid.awt.SingleGridFactory_GeoTiff			SingleGrid in GeoTiff
+edu.bonn.xulu.plugin.io.feature.gt.SingleFeatureCollectionFactory_ShapeFile	FeatureCollection in ShapeFile
+edu.bonn.xulu.plugin.io.misc.DynamicXuluObjectFactory_BasicStructure		Dynamisches Xulu-Objekt in ASCII-File
+edu.bonn.xulu.plugin.io.grid.awt.GridListFactory_ArcInfoAsciiGrid		GridList in ArcInfoASCII 
+edu.bonn.xulu.plugin.io.grid.awt.MultiGridFactory_ArcInfoAsciiGrid		MultiGrid in ArcInfoASCII
+
+//########### TypeMapping ###########
+[TypeMapping]
+// Format:
+// DatenTyp-Klasse                                              Default-Factory-Klasse                                                  [Im/Export-Klassen ...] 
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+edu.bonn.xulu.data.DynamicXuluObject                       edu.bonn.xulu.data.DynamicXuluObject$DefaultFactory                edu.bonn.xulu.plugin.io.misc.DynamicXuluObjectFactory_BasicStructure
+edu.bonn.xulu.plugin.data.grid.SingleGrid                  edu.bonn.xulu.plugin.io.grid.awt.SingleGridFactory                 edu.bonn.xulu.plugin.io.grid.awt.SingleGridFactory_ArcInfoAsciiGrid
+edu.bonn.xulu.plugin.data.grid.GridList                    edu.bonn.xulu.plugin.io.grid.awt.GridListFactory                   edu.bonn.xulu.plugin.io.grid.awt.GridListFactory_ArcInfoAsciiGrid
+edu.bonn.xulu.plugin.data.grid.MultiGrid                   edu.bonn.xulu.plugin.io.grid.awt.MultiGridFactory                  edu.bonn.xulu.plugin.io.grid.awt.MultiGridFactory_ArcInfoAsciiGrid
+edu.bonn.xulu.plugin.data.feature.SingleFeatureCollection  edu.bonn.xulu.plugin.io.feature.gt.SingleFeatureCollectionFactory  edu.bonn.xulu.plugin.io.feature.gt.SingleFeatureCollectionFactory_ShapeFile
+
+//########### Visualisierungstools ###########
+[Visualisation]
+edu.bonn.xulu.plugin.vis.GTVisualisationTool
+edu.bonn.xulu.plugin.vis.GTEditorTool
+edu.bonn.xulu.plugin.vis.JFreeChartVisualisationTool
+
+//########### Modellklassen ###########
+[Model]
+edu.bonn.xulu.plugin.model.clue.ClueModel
+edu.bonn.xulu.plugin.model.test.TestModel
+edu.bonn.xulu.plugin.model.ca.agric.ImpetusCellularAutomaton
+edu.bonn.xulu.plugin.model.ca.fire.ImpetusFireCA
+edu.bonn.xulu.plugin.model.ca.reservoir.SmallReservoirModel
+skrueger.gol.GameOfLife
+
+//########### Skript-Interpreter ###########
+[Script]
+edu.bonn.xulu.plugin.appl.DataScriptInterpreter_Basic Datenpool-Skript
+edu.bonn.xulu.plugin.appl.ModelResourceMappingScriptInterpreter_Basic Modell-Daten-Zuordnung
+
+//########### Plugins ###########
+[Plugin]
+edu.bonn.xulu.plugin.appl.LoggerPlugin                  AUTOSTART Anzeige und Kontrolle von Log4j-Loggern
+edu.bonn.xulu.plugin.appl.DateTimePlugin                          Aktuelle Zeit in der Titelleiste
+edu.bonn.xulu.plugin.appl.DateTimeWindowPlugin                    Aktuelle Zeit in einem Fenster
+edu.bonn.xulu.plugin.appl.GTVisualisationColorMapPlugin AUTOSTART Farbpaletten fuer GTVisualisationTool
+edu.bonn.xulu.plugin.appl.ModelTimeSnifferPlugin                  Modell-Laufzeiten messen und ausgeben
+edu.bonn.xulu.plugin.appl.GeoModelCodeGeneratorPlugin   AUTOSTART SourceCode-Generator fuer Geo-Modelle
+edu.bonn.xulu.plugin.appl.RasterCalculatorPlugin        AUTOSTART Taschenrechner fuer Raster
+appl.ext.ConfigurationEditorPlugin                      AUTOSTART Konfigurationsfenster

Added: trunk/defaults/registry_ProxyGrid.xif
===================================================================
--- trunk/defaults/registry_ProxyGrid.xif	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/defaults/registry_ProxyGrid.xif	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,74 @@
+//########### Klassen werden "fuer alles" registriert ###########
+[Global]
+
+//########### Klassen werden als Datentyp registriert ###########
+[DataType]
+edu.bonn.xulu.data.DynamicXuluObject
+edu.bonn.xulu.plugin.data.grid.SingleGrid
+ 
+ 
+//########### Klassen als Default-Factory registriert ###########
+[DefaultFactory]
+edu.bonn.xulu.data.DynamicXuluObject$DefaultFactory
+edu.bonn.xulu.plugin.io.grid.lateloading.SingleGridFactory
+ 
+//########### Klassen als Import-Factory registriert ###########
+[ImportFactory]
+edu.bonn.xulu.plugin.io.grid.lateloading.SingleGridFactory_ArcInfoAsciiGrid		SingleGrid aus ArcInfoASCII
+edu.bonn.xulu.plugin.io.grid.lateloading.SingleGridFactory_GeoTiff			SingleGrid aus GeoTiff
+edu.bonn.xulu.plugin.io.feature.gt.SingleFeatureCollectionFactory_ShapeFile	FeatureCollection aus ShapeFile
+edu.bonn.xulu.plugin.io.misc.DynamicXuluObjectFactory_BasicStructure		Dynamisches Xulu-Objekt aus ASCII-File
+edu.bonn.xulu.plugin.io.grid.lateloading.GridListFactory_ArcInfoAsciiGrid		GridList aus ArcausfoASCII 
+edu.bonn.xulu.plugin.io.grid.lateloading.MultiGridFactory_ArcInfoAsciiGrid		MultiGrid aus ArcInfoASCII
+edu.bonn.xulu.plugin.io.misc.CAAreaListFactory_ShapeFile			CA-Areas aus ShapeFile
+ 
+//########### Klassen als Export-Factory registriert ###########
+[ExportFactory]
+edu.bonn.xulu.plugin.io.grid.array.SingleGridFactory_ArcInfoAsciiGrid		SingleGrid in ArcInfoASCII
+edu.bonn.xulu.plugin.io.grid.array.SingleGridFactory_GeoTiff			SingleGrid in GeoTiff
+edu.bonn.xulu.plugin.io.feature.gt.SingleFeatureCollectionFactory_ShapeFile	FeatureCollection in ShapeFile
+edu.bonn.xulu.plugin.io.misc.DynamicXuluObjectFactory_BasicStructure		Dynamisches Xulu-Objekt in ASCII-File
+edu.bonn.xulu.plugin.io.grid.array.GridListFactory_ArcInfoAsciiGrid		GridList in ArcInfoASCII 
+edu.bonn.xulu.plugin.io.grid.array.MultiGridFactory_ArcInfoAsciiGrid		MultiGrid in ArcInfoASCII
+
+//########### TypeMapping ###########
+[TypeMapping]
+// Format:
+// DatenTyp-Klasse                                              Default-Factory-Klasse                                        [Im/Export-Klassen ...] 
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+edu.bonn.xulu.data.DynamicXuluObject                       edu.bonn.xulu.data.DynamicXuluObject$DefaultFactory                edu.bonn.xulu.plugin.io.misc.DynamicXuluObjectFactory_BasicStructure
+edu.bonn.xulu.plugin.data.grid.SingleGrid                  edu.bonn.xulu.plugin.io.grid.lateloading.SingleGridFactory               edu.bonn.xulu.plugin.io.grid.lateloading.SingleGridFactory_ArcInfoAsciiGrid
+edu.bonn.xulu.plugin.data.grid.GridList                    edu.bonn.xulu.plugin.io.grid.lateloading.GridListFactory                 edu.bonn.xulu.plugin.io.grid.lateloading.GridListFactory_ArcInfoAsciiGrid
+edu.bonn.xulu.plugin.data.grid.MultiGrid                   edu.bonn.xulu.plugin.io.grid.lateloading.MultiGridFactory                edu.bonn.xulu.plugin.io.grid.lateloading.MultiGridFactory_ArcInfoAsciiGrid
+edu.bonn.xulu.plugin.data.feature.SingleFeatureCollection  edu.bonn.xulu.plugin.io.feature.gt.SingleFeatureCollectionFactory  edu.bonn.xulu.plugin.io.feature.gt.SingleFeatureCollectionFactory_ShapeFile
+
+//########### Visualisierungstools ###########
+[Visualisation]
+edu.bonn.xulu.plugin.vis.GTVisualisationTool
+edu.bonn.xulu.plugin.vis.GTEditorTool
+edu.bonn.xulu.plugin.vis.JFreeChartVisualisationTool
+
+//########### Modellklassen ###########
+[Model]
+edu.bonn.xulu.plugin.model.clue.ClueModel
+//edu.bonn.xulu.plugin.model.test.TestModel
+//edu.bonn.xulu.plugin.model.ca.agric.ImpetusCellularAutomaton
+//edu.bonn.xulu.plugin.model.ca.fire.ImpetusFireCA
+//edu.bonn.xulu.plugin.model.ca.reservoir.SmallReservoirModel
+
+//########### Skript-Interpreter ###########
+[Script]
+edu.bonn.xulu.plugin.appl.DataScriptInterpreter_Basic Datenpool-Skript
+edu.bonn.xulu.plugin.appl.ModelResourceMappingScriptInterpreter_Basic Modell-Daten-Zuordnung
+
+//########### Plugins ###########
+[Plugin]
+edu.bonn.xulu.plugin.appl.DateTimePlugin                          Aktuelle Zeit in der Titelleiste
+edu.bonn.xulu.plugin.appl.DateTimeWindowPlugin                    Aktuelle Zeit in einem Fenster
+edu.bonn.xulu.plugin.appl.GTVisualisationColorMapPlugin AUTOSTART Farbpaletten fuer GTVisualisationTool
+edu.bonn.xulu.plugin.appl.ModelTimeSnifferPlugin        AUTOSTART Modell-Laufzeiten messen und ausgeben
+edu.bonn.xulu.plugin.appl.LoggerPlugin                  AUTOSTART Logging
+edu.bonn.xulu.plugin.appl.GeoModelCodeGeneratorPlugin   AUTOSTART Code Generator
+de.skrueger.xulu.plugin.gnur.GnuRPlugin							  Gnu R Plugin
+edu.bonn.xulu.plugin.appl.RasterCalculatorPlugin        AUTOSTART Taschenrechner fuer Raster
+appl.ext.ConfigurationEditorPlugin                      AUTOSTART Konfigurationsfenster

Added: trunk/defaults/registry_arrayGrid.xif
===================================================================
--- trunk/defaults/registry_arrayGrid.xif	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/defaults/registry_arrayGrid.xif	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,74 @@
+//########### Klassen werden "fuer alles" registriert ###########
+[Global]
+
+//########### Klassen werden als Datentyp registriert ###########
+[DataType]
+edu.bonn.xulu.data.DynamicXuluObject
+edu.bonn.xulu.plugin.data.grid.SingleGrid
+ 
+ 
+//########### Klassen als Default-Factory registriert ###########
+[DefaultFactory]
+edu.bonn.xulu.data.DynamicXuluObject$DefaultFactory
+edu.bonn.xulu.plugin.io.grid.array.SingleGridFactory
+ 
+//########### Klassen als Import-Factory registriert ###########
+[ImportFactory]
+edu.bonn.xulu.plugin.io.grid.array.SingleGridFactory_ArcInfoAsciiGrid		SingleGrid aus ArcInfoASCII
+edu.bonn.xulu.plugin.io.grid.array.SingleGridFactory_GeoTiff			SingleGrid aus GeoTiff
+edu.bonn.xulu.plugin.io.feature.gt.SingleFeatureCollectionFactory_ShapeFile	FeatureCollection aus ShapeFile
+edu.bonn.xulu.plugin.io.misc.DynamicXuluObjectFactory_BasicStructure		Dynamisches Xulu-Objekt aus ASCII-File
+edu.bonn.xulu.plugin.io.grid.array.GridListFactory_ArcInfoAsciiGrid		GridList aus ArcausfoASCII 
+edu.bonn.xulu.plugin.io.grid.array.MultiGridFactory_ArcInfoAsciiGrid		MultiGrid aus ArcInfoASCII
+edu.bonn.xulu.plugin.io.misc.CAAreaListFactory_ShapeFile			CA-Areas aus ShapeFile
+ 
+//########### Klassen als Export-Factory registriert ###########
+[ExportFactory]
+edu.bonn.xulu.plugin.io.grid.array.SingleGridFactory_ArcInfoAsciiGrid		SingleGrid in ArcInfoASCII
+edu.bonn.xulu.plugin.io.grid.array.SingleGridFactory_GeoTiff			SingleGrid in GeoTiff
+edu.bonn.xulu.plugin.io.feature.gt.SingleFeatureCollectionFactory_ShapeFile	FeatureCollection in ShapeFile
+edu.bonn.xulu.plugin.io.misc.DynamicXuluObjectFactory_BasicStructure		Dynamisches Xulu-Objekt in ASCII-File
+edu.bonn.xulu.plugin.io.grid.array.GridListFactory_ArcInfoAsciiGrid		GridList in ArcInfoASCII 
+edu.bonn.xulu.plugin.io.grid.array.MultiGridFactory_ArcInfoAsciiGrid		MultiGrid in ArcInfoASCII
+
+//########### TypeMapping ###########
+[TypeMapping]
+// Format:
+// DatenTyp-Klasse                                              Default-Factory-Klasse                                        [Im/Export-Klassen ...] 
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+edu.bonn.xulu.data.DynamicXuluObject                       edu.bonn.xulu.data.DynamicXuluObject$DefaultFactory                edu.bonn.xulu.plugin.io.misc.DynamicXuluObjectFactory_BasicStructure
+edu.bonn.xulu.plugin.data.grid.SingleGrid                  edu.bonn.xulu.plugin.io.grid.array.SingleGridFactory               edu.bonn.xulu.plugin.io.grid.array.SingleGridFactory_ArcInfoAsciiGrid
+edu.bonn.xulu.plugin.data.grid.GridList                    edu.bonn.xulu.plugin.io.grid.array.GridListFactory                 edu.bonn.xulu.plugin.io.grid.array.GridListFactory_ArcInfoAsciiGrid
+edu.bonn.xulu.plugin.data.grid.MultiGrid                   edu.bonn.xulu.plugin.io.grid.array.MultiGridFactory                edu.bonn.xulu.plugin.io.grid.array.MultiGridFactory_ArcInfoAsciiGrid
+edu.bonn.xulu.plugin.data.feature.SingleFeatureCollection  edu.bonn.xulu.plugin.io.feature.gt.SingleFeatureCollectionFactory  edu.bonn.xulu.plugin.io.feature.gt.SingleFeatureCollectionFactory_ShapeFile
+
+//########### Visualisierungstools ###########
+[Visualisation]
+edu.bonn.xulu.plugin.vis.GTVisualisationTool
+edu.bonn.xulu.plugin.vis.GTEditorTool
+edu.bonn.xulu.plugin.vis.JFreeChartVisualisationTool
+
+//########### Modellklassen ###########
+[Model]
+edu.bonn.xulu.plugin.model.clue.ClueModel
+edu.bonn.xulu.plugin.model.test.TestModel
+edu.bonn.xulu.plugin.model.ca.agric.ImpetusCellularAutomaton
+edu.bonn.xulu.plugin.model.ca.fire.ImpetusFireCA
+edu.bonn.xulu.plugin.model.ca.reservoir.SmallReservoirModel
+
+//########### Skript-Interpreter ###########
+[Script]
+edu.bonn.xulu.plugin.appl.DataScriptInterpreter_Basic Datenpool-Skript
+edu.bonn.xulu.plugin.appl.ModelResourceMappingScriptInterpreter_Basic Modell-Daten-Zuordnung
+
+//########### Plugins ###########
+[Plugin]
+edu.bonn.xulu.plugin.appl.LoggerPlugin                  AUTOSTART Anzeige und Kontrolle von Log4j-Loggern
+edu.bonn.xulu.plugin.appl.DateTimePlugin                          Aktuelle Zeit in der Titelleiste
+edu.bonn.xulu.plugin.appl.DateTimeWindowPlugin                    Aktuelle Zeit in einem Fenster
+edu.bonn.xulu.plugin.appl.GTVisualisationColorMapPlugin AUTOSTART Farbpaletten fuer GTVisualisationTool
+edu.bonn.xulu.plugin.appl.ModelTimeSnifferPlugin                  Modell-Laufzeiten messen und ausgeben
+edu.bonn.xulu.plugin.appl.GeoModelCodeGeneratorPlugin   AUTOSTART SourceCode-Generator fuer Geo-Modelle
+edu.bonn.xulu.plugin.appl.RasterCalculatorPlugin        AUTOSTART Taschenrechner fuer Raster
+appl.ext.ConfigurationEditorPlugin                      AUTOSTART Konfigurationsfenster
+

Added: trunk/defaults/startXULU.bat
===================================================================
--- trunk/defaults/startXULU.bat	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/defaults/startXULU.bat	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,93 @@
+ at echo off
+setlocal
+
+set LIB_ROOT="..\xululib"
+
+rem ###################################################################
+rem #############   Xulu library paths and parameters   ###############
+rem ###################################################################
+set XULU_LIB=classes
+set XULU_MODELS_LIB=classes_models
+if "%1"=="/useXuluJar"     set XULU_LIB=%LIB_ROOT%\xulu\XuluModellingPlatform.jar
+if "%1"=="/useXuluJar"     set XULU_MODELS_LIB=%LIB_ROOT%\xulu\XuluModellingPlatformModels.jar
+if "%1"=="/useXuluClasses" set XULU_LIB=classes
+if "%1"=="/useXuluClasses" set XULU_MODELS_LIB=classes_models
+
+set XULU_REGISTRY=registry_arrayGrid.xif
+set XULU_LANGUAGE=de
+set XULU_WORK_DIR=C:\
+set XULU_START_SCRIPTS=
+set XULU_RESOURCE=resource
+
+rem ####################################################
+rem #############   External libraries   ###############
+rem ####################################################
+
+rem ##### Where to find "Java Advanced Imaging" (and ImageIO) #####
+set JAI_ROOT=%LIB_ROOT%\jai-1_1_3\lib
+
+rem ##### Where to find "GeoTools" #####
+set GT_ROOT=%LIB_ROOT%\gt2-2.4.4
+
+rem ##### Where to find gt2-arcgrid-2.1.x.jar (from SpearfishDemo) #####
+set GT_ARCGRID_ROOT=%LIB_ROOT%\geotoolsArcGrid
+
+rem ##### Where to find "Adagios" #####
+set ADAGIOS_ROOT=%LIB_ROOT%\ADaGIoS
+
+rem ##### Where to find "Log4j" #####
+set LOG4J_ROOT=%LIB_ROOT%\log4j-1.2.14
+
+rem ##### Where to find "JINI" #####
+set JINI_ROOT=%LIB_ROOT%\jini
+
+rem ##### Where to find "R" #####
+set R_ROOT=%LIB_ROOT%\JavaRInterface
+
+rem ##### Where to find "jFreeChart" #####
+set JFREECHART_ROOT=%LIB_ROOT%\jFreeChart
+
+rem ##### combine the external libs #####
+set JAI_LIB=%JAI_ROOT%\*
+set GT_LIB=%GT_ROOT%\*
+set GT_LIB=%GT_LIB%;%GT_ARCGRID_ROOT%\gt2-arcgrid-2.3.0-M0.jar;%GT_ARCGRID_ROOT%\junit-4.4.jar
+set ADAGIOS_LIB=%ADAGIOS_ROOT%\AdagiosJavaLib.jar
+set JINI_LIB=%JINI_ROOT%\lib\*;%JINI_ROOT%\lib-dl\*;%JINI_ROOT%\lib-ext\*
+rem set JINI_LIB=%JINI_ROOT%\lib\jsk-platform.jar;%JINI_ROOT%\lib\tools.jar
+set LOG4J_LIB=%LOG4J_ROOT%\log4j-1.2.14.jar
+set R_LIB=%R_ROOT%\JRI.jar;%R_ROOT%\libjri.so;%R_ROOT%\libR.so
+set JFREECHART_LIB=%JFREECHART_ROOT%\jfreechart-1.0.6.jar;%JFREECHART_ROOT%\jcommon-1.0.10.jar
+
+set LIB_ALL=%XULU_LIB%;%JAI_LIB%;%GT_LIB%;%ADAGIOS_LIB%;%LOG4J_LIB%;%JINI_LIB%;%R_LIB%;%JFREECHART_LIB%
+
+rem ##### combine the native libs #####
+rem set JAI_NATIVE=%JAI_ROOT%\native_win\mlib_jai.dll;%JAI_ROOT%\native_win\mlib_jai_mmx.dll;%JAI_ROOT%\native_win\mlib_jai_util.dll
+set JAI_NATIVE=%JAI_ROOT%\native_win
+
+set LIB_NATIVE=%JAI_NATIVE%
+
+
+rem ##### combine Xulu starting parameters #####
+set XULU_PARAMS=
+if not "%XULU_LANGUAGE%"==""        set XULU_PARAMS=%XULU_PARAMS% -l %XULU_LANGUAGE%
+if not "%XULU_REGISTRY%"==""        set XULU_PARAMS=%XULU_PARAMS% -rf %XULU_REGISTRY%
+if not "%XULU_MODELS_LIB%"==""      set XULU_PARAMS=%XULU_PARAMS% -d %XULU_MODELS_LIB%
+if not "%XULU_WORK_DIR%"==""        set XULU_PARAMS=%XULU_PARAMS% -w "%XULU_WORK_DIR%"
+if not "%XULU_START_SCRIPTS%"==""   set XULU_PARAMS=%XULU_PARAMS% -s "%XULU_START_SCRIPTS%"
+
+
+rem ##### determine java interpreter #####
+set JAVA_PRG=start /B javaw
+rem set JAVA_PRG=java
+rem ##### for command line help, use java instead of javaw #####
+if "%1"=="/?"     set JAVA_PRG=java
+if "%1"=="?"      set JAVA_PRG=java
+if "%1"=="-?"     set JAVA_PRG=java
+if "%1"=="--help" set JAVA_PRG=java
+if "%1"=="-h"     set JAVA_PRG=java
+
+
+rem ##### start Xulu #####
+%JAVA_PRG% -Xms300M -Xmx1000M -version:1.6 -cp %XULU_RESOURCE%;%LIB_ALL% -Djava.library.path=%LIB_NATIVE% -splash:resource\icons\xulu_start.png edu.bonn.xulu.XuluModellingPlatform %XULU_PARAMS% %*
+
+endlocal

Added: trunk/lib/JavaRInterface/JRI.jar
===================================================================
(Binary files differ)


Property changes on: trunk/lib/JavaRInterface/JRI.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/lib/jai-1_1_3/COPYRIGHT-jai.txt
===================================================================
--- trunk/lib/jai-1_1_3/COPYRIGHT-jai.txt	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/lib/jai-1_1_3/COPYRIGHT-jai.txt	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,34 @@
+Copyright © 2006 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+California 95054, U.S.A. All rights reserved. U.S. Government Rights -
+Commercial software. Government users are subject to the Sun Microsystems,
+Inc. standard license agreement and applicable provisions of the FAR and its 
+supplements. Use is subject to license terms. This distribution may include
+materials developed by third parties. Sun, Sun Microsystems, the Sun logo
+and Java are trademarks or registered trademarks of Sun Microsystems, Inc.
+in the U.S. and other countries. This product is covered and controlled by
+U.S.Export Control laws and may be subject to the export or import laws in
+other countries. Nuclear, missile, chemical biological weapons or nuclear
+maritime end uses or end users, whether direct or indirect, are strictly
+prohibited. Export or reexport to countries subject to U.S. embargo or to
+entities identified on U.S. export exclusion lists, including, but not
+limited to, the denied persons and specially designated nationals lists is
+strictly prohibited.
+
+Copyright © 2006 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+California 95054, Etats-Unis. Tous droits réservés.L'utilisation est soumise
+aux termes de la Licence.Cette distribution peut comprendre des composants
+développés par des tierces parties.Sun, Sun Microsystems, le logo Sun et
+Java sont des marques de fabrique ou des marques déposées de Sun Microsystems,
+Inc. aux Etats-Unis et dans d'autres pays.Ce produit est soumis à la
+législation américaine en matière de contrôle des exportations et peut être
+soumis à la règlementation en vigueur dans d'autres pays dans le domaine des
+exportations et importations. Les utilisations, ou utilisateurs finaux, pour
+des armes nucléaires,des missiles, des armes biologiques et chimiques ou du
+nucléaire maritime, directement ou indirectement, sont strictement interdites.
+Les exportations ou réexportations vers les pays sous embargo américain, ou
+vers des entités figurant sur les listes d'exclusion d'exportation 
+américaines, y compris, mais de manière non exhaustive, la liste de personnes
+qui font objet d'un ordre de ne pas participer, d'une façon directe ou
+indirecte, aux exportations des produits ou des services qui sont régis  par
+la législation américaine en matière de contrôle des exportations et la liste
+de ressortissants spécifiquement désignés, sont rigoureusement interdites.

Added: trunk/lib/jai-1_1_3/DISTRIBUTIONREADME-jai.txt
===================================================================
--- trunk/lib/jai-1_1_3/DISTRIBUTIONREADME-jai.txt	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/lib/jai-1_1_3/DISTRIBUTIONREADME-jai.txt	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,27 @@
+DistributionREADME
+
+DISTRIBUTION BY DEVELOPERS.  Subject to the terms and conditions of the Software License Agreement and the obligations, restrictions, and exceptions set forth below, You may reproduce and distribute the portions of Software identified below ("each a Redistributable"), provided that you comply with the following (note that You may be entitled to reproduce and distribute other portions of the Software not defined here as a Redistributable under certain other licenses as described in the THIRDPARTYLICENSEREADME):
+
+(a) You distribute the Redistributable complete and unmodified and only bundled as part of Your applets and applications ("Programs"), 
+
+(b) You do not distribute additional software intended to replace any
+component(s) of the Redistributable,
+
+(c) You do not remove or alter any proprietary legends or notices contained in or on the Redistributable.
+ 
+(d) You only distribute the Redistributable subject to a license agreement that protects Sun's interests consistent with the terms contained in the Software License Agreement, and
+
+(e) You agree to defend and indemnify Sun and its licensors from and against any damages, costs, liabilities, settlement amounts and/or expenses  (including attorneys' fees) incurred in connection with any claim, lawsuit or action by any third party that arises or results from the use or distribution of any and all Programs and/or Redistributable.  
+
+The following files are each a Redistributable:
+
+The following Redistributables may be redistributed only as a whole
+
+JAVA Advanced Imaging API, Version 1.1.3
+
+
+The following Redistributables may be redistributed separately
+
+JAI Codecs - jai_codec.jar
+
+JAI Java Implementation - jai_core.jar and jai_codec.jar (required to be redistributed together)

Added: trunk/lib/jai-1_1_3/LICENSE-jai.txt
===================================================================
--- trunk/lib/jai-1_1_3/LICENSE-jai.txt	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/lib/jai-1_1_3/LICENSE-jai.txt	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,55 @@
+Sun Microsystems, Inc.
+Binary Code License Agreement
+
+JAVA ADVANCED IMAGING API, VERSION 1.1.3
+
+READ THE TERMS OF THIS AGREEMENT AND ANY PROVIDED SUPPLEMENTAL LICENSE TERMS (COLLECTIVELY "AGREEMENT") CAREFULLY BEFORE OPENING THE SOFTWARE MEDIA PACKAGE.  BY OPENING THE SOFTWARE MEDIA PACKAGE, YOU AGREE TO THE TERMS OF THIS AGREEMENT.  IF YOU ARE ACCESSING THE SOFTWARE ELECTRONICALLY, INDICATE YOUR ACCEPTANCE OF THESE TERMS BY SELECTING THE "ACCEPT" BUTTON AT THE END OF THIS AGREEMENT.  IF YOU DO NOT AGREE TO ALL THESE TERMS, PROMPTLY RETURN THE UNUSED SOFTWARE TO YOUR PLACE OF PURCHASE FOR A REFUND OR, IF THE SOFTWARE IS ACCESSED ELECTRONICALLY, SELECT THE "DECLINE" BUTTON AT THE END OF THIS AGREEMENT. 
+
+1.  LICENSE TO USE.  Sun grants you a non-exclusive and non-transferable license for the internal use only of the accompanying software and documentation and any error corrections provided by Sun (collectively "Software"), by the number of users and the class of computer hardware for which the corresponding fee has been paid. 
+
+2.  RESTRICTIONS.  Software is confidential and copyrighted. Title to Software and all associated intellectual property rights is retained by Sun and/or its licensors.  Except as specifically authorized in any Supplemental License Terms, you may not make copies of Software, other than a single copy of Software for archival purposes.  Unless enforcement is prohibited by applicable law, you may not modify, decompile, or reverse engineer Software.  Licensee acknowledges that Software is not designed or intended for use in the design, construction, operation or maintenance of any nuclear facility. Sun Microsystems, Inc. disclaims any express or implied warranty of fitness for such uses.   No right, title or interest in or to any trademark, service mark, logo or trade name of Sun or its licensors is granted under this Agreement. 
+
+3.  LIMITED WARRANTY.  Sun warrants to you that for a period of ninety (90) days from the date of purchase, as evidenced by a copy of the receipt, the media on which Software is furnished (if any) will be free of defects in materials and workmanship under normal use.  Except for the foregoing, Software is provided "AS IS".  Your exclusive remedy and Sun's entire liability under this limited warranty will be at Sun's option to replace Software media or refund the fee paid for Software. 
+
+4.  DISCLAIMER OF WARRANTY.  UNLESS SPECIFIED IN THIS AGREEMENT, ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT ARE DISCLAIMED, EXCEPT TO THE EXTENT THAT THESE DISCLAIMERS ARE HELD TO BE LEGALLY INVALID. 
+
+5.  LIMITATION OF LIABILITY.  TO THE EXTENT NOT PROHIBITED BY LAW, IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR SPECIAL, INDIRECT, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF OR RELATED TO THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.  In no event will Sun's liability to you, whether in contract, tort (including negligence), or otherwise, exceed the amount paid by you for Software under this Agreement.  The foregoing limitations will apply even if the above stated warranty fails of its essential purpose. 
+
+6.  Termination.  This Agreement is effective until terminated.  You may terminate this Agreement at any time by destroying all copies of Software.  This Agreement will terminate immediately without notice from Sun if you fail to comply with any provision of this Agreement.  Upon Termination, you must destroy all copies of Software. 
+
+7.  Export Regulations. All Software and technical data delivered under this Agreement are subject to US export control laws and may be subject to export or import regulations in other countries.  You agree to comply strictly with all such laws and regulations and acknowledge that you have the responsibility to obtain such licenses to export, re-export, or import as may be required after delivery to you. 
+
+8.  U.S. Government Restricted Rights.  If Software is being acquired by or on behalf of the U.S. Government or by a U.S. Government prime contractor or subcontractor (at any tier), then the Government's rights in Software and accompanying documentation will be only as set forth in this Agreement; this is in accordance with 48 CFR 227.7201 through 227.7202-4 (for Department of Defense (DOD) acquisitions) and with 48 CFR 2.101 and 12.212 (for non-DOD acquisitions). 
+
+9.  Governing Law.  Any action related to this Agreement will be governed by California law and controlling U.S. federal law.  No choice of law rules of any jurisdiction will apply. 
+
+10. Severability. If any provision of this Agreement is held to be unenforceable, this Agreement will remain in effect with the provision omitted, unless omission would frustrate the intent of the parties, in which case this Agreement will immediately terminate. 
+
+11. Integration.  This Agreement is the entire agreement between you and Sun relating to its subject matter.  It supersedes all prior or contemporaneous oral or written communications, proposals, representations and warranties and prevails over any conflicting or additional terms of any quote, order, acknowledgment, or other communication between the parties relating to its subject matter during the term of this Agreement.  No modification of this Agreement will be binding, unless in writing and signed by an authorized representative of each party. 
+
+ 
+                    JAVA ADVANCED IMAGING, VERSION 1.1.3
+                         
+                         SUPPLEMENTAL LICENSE TERMS
+
+These supplemental license terms ("Supplemental Terms") add to or modify the terms of the Binary Code License Agreement (collectively, the "Agreement"). Capitalized terms not defined in these Supplemental Terms shall have the same meanings ascribed to them in the Agreement. These Supplemental Terms shall supersede any inconsistent or conflicting terms in the Agreement, or in any license contained within the Software. 
+
+1. Software Internal Use and Development License Grant.  Subject to the terms and conditions of this Agreement, including, but not limited to Section 3 (Java Technology Restrictions) of these Supplemental Terms, Sun grants you a non-exclusive, non-transferable, limited license to reproduce internally and use internally the binary form of the Software, complete and unmodified, for the sole purpose of designing, developing and testing your Java applets and applications ("Programs"). 
+
+2. License to Distribute Software.  In addition to the license granted in Section 1 (Software Internal Use and Development License Grant) of these Supplemental Terms, subject to the terms and conditions of this Agreement, including but not limited to, Section 3 (Java Technology Restrictions) of these Supplemental Terms, Sun grants you a non-exclusive, non-transferable, limited license to reproduce and distribute the Software in binary code form only, provided that you (i) distribute the Software complete and unmodified and only bundled as part of your Programs, (ii) do not distribute additional software intended to replace any component(s) of the Software, (iii) do not remove or alter any proprietary legends or notices contained in the Software, (iv) only distribute the Software subject to a license agreement that protects Sun's interests consistent with the terms contained in this Agreement, and (v) agree to defend and indemnify Sun and its licensors from and against any damages, costs, liabilities, settlement amounts and/or expenses (including attorneys' fees) incurred in connection with any claim, lawsuit or action by any third party that arises or results from the use or distribution of any and all Programs and/or Software. 
+
+3. Java Technology Restrictions. You may not modify the Java Platform Interface ("JPI", identified as classes contained within the "java" package or any subpackages of the "java" package), by creating additional classes within the JPI or otherwise causing the addition to or modification of the classes in the JPI.  In the event that you create an additional class and associated API(s) which (i) extends the functionality of the Java platform, and (ii) is exposed to third party software developers for the purpose of developing additional software which invokes such additional API, you must promptly publish broadly an accurate specification for such API for free use by all developers.  You may not create, or authorize your licensees to create additional classes, interfaces, or subpackages that are in any way identified as "java", "javax", "sun" or similar convention as specified by Sun in any naming convention designation. 
+
+4.  Java Runtime Availability.  Refer to the appropriate version of the Java Runtime Environment binary code license (currently located at http://www.java.sun.com/jdk/index.html) for the availability of runtime code which may be distributed with Java applets and applications.
+
+5. Trademarks and Logos. You acknowledge and agree as between you and Sun that Sun owns the SUN, SOLARIS, JAVA, JINI, FORTE, and iPLANET trademarks and all SUN, SOLARIS, JAVA, JINI, FORTE, and iPLANET-related trademarks, service marks, logos and other brand designations ("Sun Marks"), and you agree to comply with the Sun Trademark and Logo Usage Requirements currently located at http://www.sun.com/policies/trademarks. Any use you make of the Sun Marks inures to Sun's benefit. 
+
+6. Source Code. Software may contain source code that is provided solely for reference purposes pursuant to the terms of this Agreement.  Source code may not be redistributed unless expressly provided for in this Agreement. 
+
+7. Termination for Infringement.  Either party may terminate this Agreement immediately should any Software become, or in either party's opinion be likely to become, the subject of a claim of infringement of any intellectual property right.
+
+8. Third Party Code. Additional copyright notices and license terms applicable to portions of the Software are set forth in the THIRDPARTYLICENSEREADME. In addition to any terms and conditions of any third party open source/freeware license identified in the THIRDPARTYLICENSEREADME, the disclaimer of warranty and limitation of liability provisions in paragraphs 5 and 6 of the Binary Code License Agreement shall apply to all Software in this distribution.
+
+For inquiries please contact: Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, California 95054, U.S.A
+
+(LFI#143342/Form ID#011801)

Added: trunk/lib/jai-1_1_3/THIRDPARTYLICENSEREADME-jai.txt
===================================================================
--- trunk/lib/jai-1_1_3/THIRDPARTYLICENSEREADME-jai.txt	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/lib/jai-1_1_3/THIRDPARTYLICENSEREADME-jai.txt	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,54 @@
+DO NOT TRANSLATE OR LOCALIZE.
+
+%% The following software may be included in this product:  NeuQuant Color Quantization.  Use of any of this software is governed by the terms of the license below: 
+
+* NeuQuant Neural-Net Quantization Algorithm
+ * ------------------------------------------
+ *
+ * Copyright (c) 1994 Anthony Dekker
+ *
+ * NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994.
+ * See "Kohonen neural networks for optimal colour quantization"
+ * in "Network: Computation in Neural Systems" Vol. 5 (1994) pp 351-367.
+ * for a discussion of the algorithm.
+ * See also  http://www.acm.org/~dekker/NEUQUANT.HTML
+ *
+ * Any party obtaining a copy of these files from the author, directly or
+ * indirectly, is granted, free of charge, a full and unrestricted irrevocable,
+ * world-wide, paid up, royalty-free, nonexclusive right and license to deal
+ * in this software and documentation files (the "Software"), including without
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense,
+ * and/or sell copies of the Software, and to permit persons who receive
+ * copies from any such party to do so, with the only requirement being
+ * that this copyright notice remain intact.
+ */
+
+%% The following software may be included in this product: Oct-Tree Color Quantization.  Use of any of this software is governed by the terms of the license below: 
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%  Permission is hereby granted, free of charge, to any person obtaining a    %
+%  copy of this software and associated documentation files ("ImageMagick"),  %
+%  to deal in ImageMagick without restriction, including without limitation   %
+%  the rights to use, copy, modify, merge, publish, distribute, sublicense,   %
+%  and/or sell copies of ImageMagick, and to permit persons to whom the       %
+%  ImageMagick is furnished to do so, subject to the following conditions:    %
+%                                                                             %
+%  The above copyright notice and this permission notice shall be included in %
+%  all copies or substantial portions of ImageMagick.                         %
+%                                                                             %
+%  The software is provided "as is", without warranty of any kind, express or %
+%  implied, including but not limited to the warranties of merchantability,   %
+%  fitness for a particular purpose and noninfringement.  In no event shall   %
+%  E. I. du Pont de Nemours and Company be liable for any claim, damages or   %
+%  other liability, whether in an action of contract, tort or otherwise,      %
+%  arising from, out of or in connection with ImageMagick or the use or other %
+%  dealings in ImageMagick.                                                   %
+%                                                                             %
+%  Except as contained in this notice, the name of the E. I. du Pont de       %
+%  Nemours and Company shall not be used in advertising or otherwise to       %
+%  promote the sale, use or other dealings in ImageMagick without prior       %
+%  written authorization from the E. I. du Pont de Nemours and Company.       %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+

Added: trunk/lib/jai-1_1_3/UNINSTALL-jai
===================================================================
--- trunk/lib/jai-1_1_3/UNINSTALL-jai	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/lib/jai-1_1_3/UNINSTALL-jai	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,19 @@
+#!/bin/sh
+# @(#)UNINSTALL-jai	3.1 06/05/25 18:35:35
+# usage: UNINSTALL-jai
+
+echo "Uninstalling Java Advanced Imaging"
+
+rm -f *jai.txt
+rm -f lib/jai_core.jar
+rm -f lib/jai_codec.jar
+rm -f lib/mlibwrapper_jai.jar
+rm -f lib/libmlib_jai.so
+if [ \( "`uname`" = "SunOS" \) -a \( "`uname -p`" = "sparc" \) ]; then
+    rm -f lib/libmlib_jai_vis.so
+    rm -f lib/libmlib_jai_vis2.so
+fi
+rmdir lib
+rm -f UNINSTALL-jai
+
+echo "Done"

Added: trunk/lib/jai-1_1_3/lib/clibwrapper_jiio.jar
===================================================================
(Binary files differ)


Property changes on: trunk/lib/jai-1_1_3/lib/clibwrapper_jiio.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/lib/jai-1_1_3/lib/jai_codec.jar
===================================================================
(Binary files differ)


Property changes on: trunk/lib/jai-1_1_3/lib/jai_codec.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/lib/jai-1_1_3/lib/jai_core.jar
===================================================================
(Binary files differ)


Property changes on: trunk/lib/jai-1_1_3/lib/jai_core.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/lib/jai-1_1_3/lib/jai_imageio.jar
===================================================================
(Binary files differ)


Property changes on: trunk/lib/jai-1_1_3/lib/jai_imageio.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/lib/jai-1_1_3/lib/mlibwrapper_jai.jar
===================================================================
(Binary files differ)


Property changes on: trunk/lib/jai-1_1_3/lib/mlibwrapper_jai.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/lib/jai-1_1_3/lib/native_win/mlib_jai.dll
===================================================================
(Binary files differ)


Property changes on: trunk/lib/jai-1_1_3/lib/native_win/mlib_jai.dll
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/lib/jai-1_1_3/lib/native_win/mlib_jai_mmx.dll
===================================================================
(Binary files differ)


Property changes on: trunk/lib/jai-1_1_3/lib/native_win/mlib_jai_mmx.dll
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/lib/jai-1_1_3/lib/native_win/mlib_jai_util.dll
===================================================================
(Binary files differ)


Property changes on: trunk/lib/jai-1_1_3/lib/native_win/mlib_jai_util.dll
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/lib/jini/lib/tools.jar
===================================================================
(Binary files differ)


Property changes on: trunk/lib/jini/lib/tools.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/lib/schmitzm/schmitzm.jar
===================================================================
(Binary files differ)


Property changes on: trunk/lib/schmitzm/schmitzm.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/lib/xulu/XuluModellingPlatform.jar
===================================================================
(Binary files differ)


Property changes on: trunk/lib/xulu/XuluModellingPlatform.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/readme.txt
===================================================================
--- trunk/readme.txt	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/readme.txt	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,166 @@
+TODO:
+- startXulu.bat erweitern:
+   - /useXuluClasses auf SCHMITZM erweitern
+- SCHMITZM in Xulu\lib aufnehmen
+- How to start XULU from Eclipse
+- How to develop XULU
+
+==============================================================
+=== XULU README (2009-02-24, Martin Schmitz)               ===
+===                                                        ===
+=== http://wald.intevation.org/projects/xulu/              ===
+=== http://wald.intevation.org/projects/schmitzm/          ===
+==============================================================
+This file contains some informations ...
+
+(1) about the XULU modelling platform
+(2) how to proceed after the first SVN checkout
+(3) about the folder structur of XULU
+(4) how to start XULU
+    a) Requirements
+    b) Start XULU from command line
+    c) Start XULU from Eclipse
+(5) how to develop XULU
+
+
+
+-----------------------------------------------------------
+(1) General informations about XULU
+-----------------------------------------------------------
+XULU (eXtendable Unified Land Use Modelling Platform) is a stand-alone
+Java software which was designed as a part of my diploma thesis (Martin Schmitz,
+2005, Institite of computer science, University of Bonn/Germany).
+The goal was the create a generic framework, which provides general functionalities
+needed for (simulation) modelling, without any relationship to a concrete
+model context:
+- data maintenance
+- data types
+- data import/export
+- data visualisation
+- GUI
+
+With these components implemented once (--> XULU) there is no further need to
+take into account during implementation of any model. The model designer and
+programmer can concentrate on implementing themodel algorithm.
+The interfaces to the upper mentioned components are realised as plugins,
+so the field of application is not static.
+Because the of the close cooperation with the ZFL (Zentrum für Fernerkundung der
+Landoberfläche) and IMPETUS (http://www.impetus.de) the most plugins which
+are currently implemented are for land use modelling:
+- maintain raster and vector data (based on the Geotools Java library)
+- layer based geo visualisation (based on the Geotools Java library)
+- raster based models
+
+But generally - with implementing appropriate plugins - XULU can also be used for
+complete other application fields
+
+
+-----------------------------------------------------------
+(2) Initialize XULU after the first SVN checkout
+-----------------------------------------------------------
+The XULU folders contain multiple files to configure defaults for
+the XULU main application as well as for XULU plugins.
+Because the "normal" user defined changes on these files should not be
+updated in SVN, these configuration files are initially located in the
+"defaults" folder, instead of their "correct" position.
+
+Therefore after the first SVN checkout you have to call the
+
+                            InitXulu.bat
+
+once to copy the configuration files from the "defaults" folder to their
+expected locations. After that you can make changes on all config files
+without any unintended effect on the whole XULU community.
+
+The default behavior of "InitXulu.bat" is not to overwrite files if they
+already exist. In case of trouble (e.g. deleted or damaged config files)
+you can call
+                        InitXulu.bat /reset
+                    or  InitXulu.bat /init   (no overwrite confirmation!)
+
+to overwrite all configuration files with their defaults.
+
+NOTE: PLEASE DO NOT UPDATE (AND COMMIT) CHANGES ON FILES IN THE
+      "DEFAULT" FOLDER!!
+
+
+-----------------------------------------------------------
+(3) The folder structure of XULU
+-----------------------------------------------------------
+main folder: The main folder contains some configuration files for
+             the XULU main application as well as the startXulu.bat
+             which can be used to start XULU from out of an
+             development environment (like Eclipse):
+             - InitXulu.bat: initializes the folder structure after
+                             the first SVN checkout (see (2))
+             - DefaultProperties: Defaults for XULU properties; after
+                                  the first XULU start a new file
+                                  "XuluProperties" is created with the
+                                  user defined properties
+             - registry.xif: contains the plugins used in XULU
+             - readme.txt: this file :-)
+
+defaults: Contains default configuration files for the XULU main
+          application and plugins. By calling "InitXulu.bat" (see (2))
+          these files are copied to the expected locations.
+          NOTE: PLEASE DO NOT UPDATE (AND COMMIT) CHANGES ON FILES IN
+	        THIS FOLDER!!
+
+classes: Contains the compliled java classes of the XULU application
+         and plugins.
+
+doc:     Contains the JavaDoc for Xulu. Also the target folder of
+         "makeDoc.bat"
+
+lib:     Contains all the external libraries required to run/compile XULU.
+         All JARs in this folder must be integrated in the Java classpath.
+
+plugin:  Contains configuration files for XULU plugins.
+
+src:     Contains the java source code of the XULU application and plugins.
+
+Temp:    Usually empty. Needed for temporary files.
+
+
+-----------------------------------------------------------
+(4) How to start XULU
+-----------------------------------------------------------
+
+a) Requirements
+---------------
+Besides the external libraries in "lib" folder, it is required that
+the following components are installed on system:
+- JRE 1.6
+- JAI 1.1.3
+
+b) Start XULU from command line
+-------------------------------
+To start XULU from command line there are 2 main variants:
+
+ 1) "startXulu.bat /useXuluJar"     (Default)
+    uses the XuluModellingPlatform.jar and SCHMITZM.jar from the
+    "lib" folder to run XULU. This option is recommended, if you
+    only want to "use" XULU and not to develop.
+
+ 2) "startXulu.bat /useXuluClasses"
+    uses the "classes" folder to run XULU. Use this option, if you
+    want to take your own changes (or plugin extension) take effekt.
+    This option requires that
+      - XULU is previously compiled to "classes" folder
+      - SCHMITZM is previously compiled to
+
+c) Start XULU from Eclipse
+--------------------------
+t.b.c.
+
+
+-----------------------------------------------------------
+(4) How to develop XULU
+-----------------------------------------------------------
+t.b.c.
+
+
+===========================================================
+http://wald.intevation.org/projects/xulu/
+http://wald.intevation.org/projects/schmitzm/
+===========================================================
\ No newline at end of file

Added: trunk/resource/icons/xulu_icon.png
===================================================================
(Binary files differ)


Property changes on: trunk/resource/icons/xulu_icon.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/resource/icons/xulu_info.png
===================================================================
(Binary files differ)


Property changes on: trunk/resource/icons/xulu_info.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/resource/icons/xulu_start.png
===================================================================
(Binary files differ)


Property changes on: trunk/resource/icons/xulu_start.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/resource/locales/StandardBundleExtension.properties
===================================================================
--- trunk/resource/locales/StandardBundleExtension.properties	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/resource/locales/StandardBundleExtension.properties	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,53 @@
+# ----------------------------------------------------------------------------------
+#  LANGUAGE: English                               
+#
+#  Xulu extention of standard the bundles
+#
+#      schmitzm-swing
+#           bundle: schmitzm.swing.resource.locales.SwingResourceBundle
+#           prefix: schmitzm.swing
+#
+#      schmitzm-jFreeChart
+#           bundle: schmitzm.jfree.resource.locales.JFreeResourceBundle
+#           prefix: schmitzm.jfree
+#
+#      schmitzm-geotools:  
+#           bundle: schmitzm.geotools.gui.resource.locales.GTResourceBundle
+#           prefix: schmitzm.gt
+# 
+#  Besides extending a resource bundle <bundle> in this file, it is also necessary
+#  to programm the extention of the standard bundle in XuluModellingPlatform:
+#
+#    static {
+#        <extendedResourceBundle>.resetResourceBundle(
+#                                     "locales.StandardBundleExtention",
+#                                     <bundle prefix>
+#        )
+#        ...
+#    }
+#
+# ----------------------------------------------------------------------------------
+
+
+# -------------------------------------------------------------------------
+# Extention of bundle schmitzm.swing.resource.locales.SwingResourceBundle
+# Prefix: schmitzm.swing
+# -------------------------------------------------------------------------
+
+
+
+# ------------------------------------------------------------------------
+# Extention of bundle schmitzm.jfree.resource.locales.JFreeResourceBundle
+# Prefix: schmitzm.jfree
+# ------------------------------------------------------------------------
+
+
+
+
+# ----------------------------------------------------------------------------
+# Extention of bundle schmitzm.geotools.gui.resource.locales.GTResourceBundle
+# Prefix: schmitzm.gt
+# ----------------------------------------------------------------------------
+
+
+

Added: trunk/resource/locales/XuluMainAppl.properties
===================================================================
--- trunk/resource/locales/XuluMainAppl.properties	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/resource/locales/XuluMainAppl.properties	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,88 @@
+# ----------------------------------------------------------------------
+# ------ Default Translations (english) for Xulu main application ------
+# ----------------------------------------------------------------------
+
+XuluTitle=XULU - eXtendable Unified Land Use Modelling Platform
+Menu_File=File
+Menu_File_Exit=Exit
+Menu_Model=Model
+Menu_Model_New=New
+Menu_Model_Reload=Reload model class
+Menu_View=View
+Menu_View_Arrange=Arrange Windows
+Menu_View_AutoArrange=Auto-Arrange
+Menu_Scripts=Scripts
+Menu_RecentScripts=Recent scripts
+Menu_Help=Help
+Menu_Help_Info=About...
+Menu_Advanced_Preferences=Xulu Preferences
+Menu_Advanced_Languages=Xulu Language-Packs
+Menu_Advanced=Advanced
+Menu_DataPool=Datapool
+Menu_DataPool_Del=Delete
+Menu_DataPool_New=New
+Menu_DataPool_New_CopyStr=Copy structure
+Menu_DataPool_Import=Import
+Menu_DataPool_RecentImport=Recent imports
+Menu_DataPool_Export=Export
+Menu_DataPool_RecentExport=Recent exports
+Menu_DataPool_Display=Display
+Menu_DataPool_Display_Actualise=Actualise
+Menu_DataPool_Display_New=New
+Comp_DataPool=Xulu Datapool
+Comp_Registry=Xulu Registry
+Comp_Models=Loaded Models
+Comp_EventManager=Event Manager
+Comp_PluginManager=Plugins
+Comp_Log=Status Messages
+Comp_Visualisation=Visualisation Tools
+Model=Model
+DynModel=Dynamic model
+Access=access
+ReadAccess=read access
+WriteAccess=write access
+ScriptProgressMess=Script is working...
+ImportProgressMess=Import in progress...
+ExportProgressMess=Export in progress...
+ModelChoiceMess=Please choose a model...
+DefaultModelName=New model
+ModelClassChoiceMess=Please choose a model class...
+DynModelChoiceMess=Please choose a dynamic model from datapool...
+ModelReloadSuccessMess=Model class reloaded successfully...
+Name=Name
+Type=Type
+Object=Object
+Event=Event
+Handler=Handler
+EventObject=Object to listen for
+VisualisationUpdate=Update visualisation
+UpdateObject=Object to visualise
+VisTool=Visualisationtool
+FileExport=Export to file
+ExportSource=Export object
+ExportFactory=Export method
+ExportDest=Export destination
+new=neu
+StartMess=Starting Xulu
+LangFrame.Title=Xulu language packs
+LangFrame.Bundle=Language bundle
+LangFrame.ExtentionOf=Extention of...
+LangFrame.RootLang=Root language
+LangFrame.AdditionalLang=Additional languages
+LangFrame.NewLang=Create new language...
+LangFrame.OtherLang=<other language>
+LangFrame.Language=Language
+LangFrame.LanguageCode=Language code
+LangFrame.FinishMess=Property files successfully created...
+LangFrame.InfoText=To change the program language it is necessary to restart XULU and use the "-l <ISO-639>" command line parameter (e.g. "-l de" or "-l en"). You can also specifiy the language code in the variable XULU_LANGUAGE of the startXulu.bat. The translations are handled by property files located in /resource/locales. When creating a new language by the button below, files for the new language (with dummy translations) are created automatically. They can be modified with a common text editor.
+Model.ErrorOccured=AN ERROR OCCURED!!!
+Model.Init=Model initialised
+Model.Start=Model started
+Model.Stop=Model stopped
+Model.Dispose=Model disposed
+Model.Step.Started=Model step ${0} started
+Model.Step.Finished=Model step ${0} finished
+ModelResource.Type.Null=Resource-Type can not be NULL!
+ModelResource.Data.Null=Resource-Data can not be NULL!
+ModelResource.Cat.Unknown=Unknown resource category (${0})
+ModelResource.Data.Error=Resource '${0}': ${1} expected
\ No newline at end of file

Added: trunk/resource/locales/XuluMainAppl_de.properties
===================================================================
--- trunk/resource/locales/XuluMainAppl_de.properties	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/resource/locales/XuluMainAppl_de.properties	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,88 @@
+# -----------------------------------------------------------
+# ------ German Translations for Xulu main application ------
+# -----------------------------------------------------------
+
+XuluTitle=XULU - eXtendable Unified Land Use Modelling Platform
+Menu_File=Datei
+Menu_File_Exit=Beenden
+Menu_Model=Modell
+Menu_Model_New=Neu
+Menu_Model_Reload=Modell-Klasse neu laden
+Menu_View=Ansicht
+Menu_View_Arrange=Fenster anordnen
+Menu_View_AutoArrange=Autom. Fenster-Anordnung
+Menu_Scripts=Skripte
+Menu_RecentScripts=Skript erneut ausführen
+Menu_Help=Hilfe
+Menu_Help_Info=Über...
+Menu_Advanced_Preferences=Xulu Einstellungen
+Menu_Advanced_Languages=Xulu Sprach-Pakete
+Menu_Advanced=Erweitert
+Menu_DataPool=Daten-Pool
+Menu_DataPool_Del=Löschen
+Menu_DataPool_New=Neu
+Menu_DataPool_New_CopyStr=Struktur kopieren
+Menu_DataPool_Import=Import
+Menu_DataPool_RecentImport=Erneut importieren
+Menu_DataPool_Export=Export
+Menu_DataPool_RecentExport=Erneut exportieren
+Menu_DataPool_Display=Visualisieren
+Menu_DataPool_Display_Actualise=Aktualisieren
+Menu_DataPool_Display_New=Neu
+Comp_DataPool=Xulu-Datenpool
+Comp_Registry=Xulu-Registry
+Comp_Models=Geladene Modelle
+Comp_EventManager=Ereignis-Manager
+Comp_PluginManager=Plugins
+Comp_Log=Status-Ausgaben
+Comp_Visualisation=Visualisierungstools
+Model=Modell
+DynModel=Dynamisches Modell
+Access=Zugriffsrecht
+ReadAccess=Leserecht
+WriteAccess=Schreibrecht
+ScriptProgressMess=Skript wird verarbeitet...
+ImportProgressMess=Import wird durchgeführt...
+ExportProgressMess=Export wird durchgeführt...
+ModelChoiceMess=Modell auswählen...
+DefaultModelName=Neues Modell
+ModelClassChoiceMess=Modell-Klasse auswählen...
+DynModelChoiceMess=Dynamisches Modell aus Datenpool auswählen...
+ModelReloadSuccessMess=Modell-Klasse erfolgreich aktualisiert...
+Name=Name
+Type=Typ
+Object=Objekt
+Event=Ereignis
+Handler=Handler
+EventObject=Zu beobachtendes Objekt
+VisualisationUpdate=Visualisierung aktualisieren
+UpdateObject=Darzustellendes Objekt
+VisTool=Visualisierungstool
+FileExport=Datei-Export
+ExportSource=Zu exportierendes Objekt
+ExportFactory=Export-Methode
+ExportDest=Export-Ziel
+new=neu
+StartMess=Starte Xulu
+LangFrame.Title=Xulu Sprach-Pakete
+LangFrame.Bundle=Sprach Paket
+LangFrame.ExtentionOf=Erweiterung von...
+LangFrame.RootLang=Standard Sprache
+LangFrame.AdditionalLang=Weitere Sprachen
+LangFrame.NewLang=Neue Sprache anlegen...
+LangFrame.OtherLang=<andere Sprache>
+LangFrame.Language=Sprache
+LangFrame.LanguageCode=Sprachcode
+LangFrame.FinishMess=Property-Dateien erfolgreich erstellt...
+LangFrame.InfoText=Um die Sprache zu wechseln muss XULU neu gestartet werden und der Kommandozeilen-Parameter "-l <ISO-639 code>" entsprechend gesetzt werden (z.B. "-l de" oder "-l en"). Alternativ kann die Sprache auch über die Variable XULU_LANGUAGE in der startXulu.bat gesteuert werden.  Die Übersetzungen werden über Property-Dateien im Ordner /resource/locales verwaltet. Beim Anlegen einer neuen Sprache (über den Button unten), werden die entsprechenden Dateien (mit Dummy-Übersetzungen) automatisch erzeugt und können mit einem einfachen Text-Editor bearbeitet werden.
+Model.ErrorOccured=ES IST EIN FEHLER AUFGETRETEN!!!
+Model.Init=Modell initialisiert
+Model.Start=Modell gestartet
+Model.Stop=Modell gestoppt
+Model.Dispose=Modell disposed
+Model.Step.Started=Modell-Schritt ${0} gestarted
+Model.Step.Finished=Modell-Schritt ${0} beendet
+ModelResource.Type.Null=Typ der Ressource darf nicht NULL sein!
+ModelResource.Data.Null=Datenobjekt der Ressource darf nicht NULL sein!
+ModelResource.Cat.Unknown=Unbekannte Ressourcen-Kategorie (${0})
+ModelResource.Data.Error=Ressource '${0}': ${1} erwartet

Added: trunk/resource/locales/XuluMainError.properties
===================================================================
--- trunk/resource/locales/XuluMainError.properties	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/resource/locales/XuluMainError.properties	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,24 @@
+# --------------------------------------------------------------------
+# ------ Default Translations (english) for Xulu error messages ------
+# --------------------------------------------------------------------
+
+Access=access
+ReadAccess=read access
+WriteAccess=write access
+AccessError=Access violation
+AccessErrMess_1=You don't have
+AccessErrMess_2=to this object at the time
+DataTypeError=Data type error
+TypeCastErrMess=Typ cast not possible
+InstantiationError=Instantiation error
+InstantiationErrMess=Class must be instantiable! Abstact classes or interfaces are not allowed!
+ClassCastError=Class cast error
+InstExpMess_1=Instance of
+InstExpMess_2=expected!
+DataError=Data error
+DuplXuluObjectNameMessIntro=Datapool already contains an object with name
+DuplModelNameMessIntro=Xulu already contains a model with name
+ClassError=Class error
+ClassNotFoundErrMess=The indicated class could not be found
+NoEvents=No events available for this object!
+NoHandler=No handler available for this object!

Added: trunk/resource/locales/XuluMainError_de.properties
===================================================================
--- trunk/resource/locales/XuluMainError_de.properties	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/resource/locales/XuluMainError_de.properties	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,24 @@
+# ---------------------------------------------------------
+# ------ German Translations for Xulu error messages ------
+# ---------------------------------------------------------
+
+Access=Zugriffsrecht
+ReadAccess=Leserecht
+WriteAccess=Schreibrecht
+AccessError=Zugriffsfehler
+AccessErrMess_1=Sie haben (zur Zeit) kein
+AccessErrMess_2=auf dieses Objekt
+DataTypeError=Datentyp-Fehler
+TypeConvErrMess=Typumwandunlung kann nicht vorgenommen werden
+InstantiationError=Instanziierungs-Fehler
+InstantiationErrMess=Klasse muss instanziierbar sein! Abstrakte Klassen oder Interfaces sind nicht zulaessig!
+ClassCastError=Cast-Fehler
+InstExpMess_1=Instanz von
+InstExpMess_2=erwartet!
+DataError=Daten-Fehler
+DuplXuluObjectNameMessIntro=Es gibt bereits ein Datenpool-Objekt
+DuplModelNameMessIntro=Es gibt bereits ein Modell
+ClassError=Klassen-Fehler
+ClassNotFoundErrMess=Die angegebene Klasse konnte nicht gefunden werden
+NoEvents=Keine Ereignisse für dieses Objekt verfügbar!
+NoHandler=Keine Handler für dieses Objekt verfügbar!

Added: trunk/resource/locales/XuluModel_Clue.properties
===================================================================
--- trunk/resource/locales/XuluModel_Clue.properties	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/resource/locales/XuluModel_Clue.properties	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,93 @@
+# ---------------------------------------------------------------
+# ------ English Translations for the xulu model ClueModel ------
+# ---------------------------------------------------------------
+
+# Descriptions of model resources
+MRDesc.ModelSteps=Number of time steps (${0}-${1})
+MRDesc.Tol.Type=Type of tolerance expressions [${0} = perc.; ${1} = abs.] (integer)
+MRDesc.Tol.Single=Demand tolerance for each single land use type (double)
+MRDesc.Tol.Avg=Average tolerance for land use demand (double)
+MRDesc.qmConvFactor=Conversion factor: demand unit to qm (double)
+MRDesc.LUC.Scenario=Base LUC scenatio (float-Grid)
+MRDesc.LUC.History=Land use history (float-Grid)
+MRDesc.LUC.ConvMatrix=Land use conversion matrix (integer-Matrix)
+MRDesc.LUC.ConvDev=Deviation of Land use conversion matrix (integer-Matrix)
+MRDesc.LUC.ConvElas=Conversion elasticity (double-List)
+MRDesc.AreaRestr=Area restrictions (float-Grid)
+MRDesc.Demand.Scenario=Demand scenario (integer-Matrix)
+MRDesc.DF.Static.Grids=Static driving forces (float-MultiGrid)
+MRDesc.DF.Dynamic.Grids=Dynamic driving forces (float-MultiGrid)
+MRDesc.DF.Dynamic.Types=Dynamic driving force types (int-List)
+MRDesc.Regression=Regression results (double-Matrix)
+MRDesc.Nbh.Weight=Weight of neighborhood (double-List)
+MRDesc.Nbh.Setting=Neighborhood settings (double-Matrix)
+MRDesc.Nbh.Regr=Regression results for neighborhood (double-Matrix)
+MRDesc.LSPA.Prob=Location specific preference addition (float-MultiGrid)
+MRDesc.LSPA.Fact=Factors for location specific pref. add. (double-List)
+MRDesc.Temp.LucHist=Temp-Raster for current land use history (float-Grid)
+MRDesc.Temp.LucProb=Temp-Raster for land use probabilities (float-MultiGrid)
+MRDesc.Temp.NbhProb=Temp-Raster for neighborhood probabilities (float-MultiGrid)
+MRDesc.Temp.IterVar=Temp-List for iteration variables (float-List)
+MRDesc.Temp.Luc=Temp-Raster for current land use (float-Grid)
+MRDesc.Temp.TotalProb=Temp-Raster for total probabilities (float-MultiGrid)
+MRDesc.Out.StepRes=Out-Rasters time step results (float-MultiGrid)
+
+# Model messages
+Model.InitCover=Initial coverage
+Model.TotalCover=Total coverage
+Model.LucTypes=List of all LUCC-Types in BaseScenario
+Model.Step.Started=Started step ${0}
+Model.Step.Started=Finished step ${0}
+Model.Step.Calc.done= done.
+Model.Step.Calc.LUCProb=Calculate LU-Probabilities for step ${0}...
+Model.Step.Calc.NbhProb=Calculate Neighborhood-Probabilities for step ${0}...
+Model.Step.Calc.Iter=Calculate Iterations for ${0}...
+Model.Step.Calc.Iter.done= done (${0} Iterations).
+Model.GUI.Single.Dev.Allowed=Allowed demand deviation per LUC type:
+Model.GUI.Avg.Dev.Allowed=Allowed average demand deviation:
+Model.GUI.AutoUpdate=Deviation update automatically
+Model.GUI.Total=Total
+Model.GUI.Avg=Average
+Model.GUI.LucType=LUC type
+Model.GUI.CurrDemandDev=Currend demand deviation
+Model.GUI.Iteration=Iteration
+Model.GUI.Type=Type
+Model.GUI.Divergence=Divergence
+Model.GUI.IterVar=Iter-Var.
+
+# Error messages
+Error.ModelSteps.Type=Long- or Integer-Property
+Error.LUC.ConvDev.Col=Matrix for LUC conversion deviation must have at least ${0} columns (one for each land use types)...
+Error.LUC.ConvDev.Row=Matrix for LUC conversion deviation must have at least ${0} rows (one for each land use types)...
+Error.LUC.ConvElas.Size=List for conversion elasticity must have at least ${0} entries (one for each land use types)...
+Error.LUC.ConvElas.Value=ListProperty with values between 0 and 1
+Error.Demand.Scenario.Col=Matrix for demand scenario must have ${0} column (one for each land use type)...
+Error.Demand.Scenario.Row=Matrix for demand scenario must have ${0} rows (one for each time step)...
+Error.DF.Static.Grids=MultiGrid for static driving forces must contain at least ${0} entries (one for each driving force)...
+Error.DF.Dynamic.Types.Size=List of dynamic driving forces must not have more than ${0} entries...
+Error.DF.Dynamic.Types.Value=Only values between ${0} and ${1} are allowed in list of dynamic driving forces...
+Error.DF.Dynamic.Grids.Null=Dynamic Driving Forces are uses! Resource '${0}' is not allowed to be null...
+Error.DF.Dynamic.Grids.Size1=MultiGrid for dynamic driving forces must contain at least ${0} entries (one for each driving force at every time step)...
+Error.DF.Dynamic.Grids.Size2=MultiGrid for dynamic driving forces must contain the same number of grids for all driving forces...
+Error.Regression.Col=Matrix for regression results must have ${0} columns (one for the constant and one for each driving force)...
+Error.Regression.Row=Matrix for regression results must have ${0} rows (one for each land use type)...
+Error.Nbh.Weight.Size=List of neighborhood weights must have at least ${0} entries (one for each land use type)...
+Error.Nbh.Setting.Null=Neighborhood settings must be specified...
+Error.Nbh.Setting.Size1=Neighborhood settings must be specified in matrix of uneven size in dimension 1 and 2 (the center is the considered cell)...
+Error.Nbh.Setting.Size2=${0} neighborhood settings must be specified in matrix (one for each land use type)...
+Error.Nbh.Regr.Null=Neighborhood regression must be specified...
+Error.Nbh.Regr.Col=Matrix for neighborhood regression results must have ${0} columns (one for the constant and one for each land use type)...
+Error.Nbh.Regr.Row=Matrix for neighborhood regression results must have ${0} rows (one for each land use type)...
+Error.Temp.LucProb.Size=MultiGrid for land use probabilities must contain at least ${0} grids (one for each land use type)...
+Error.Temp.NbhProb.Null=Temp. raster for neighborhood probabilities must be specified...
+Error.LSPA.Prob.Size=MultiGrid for location specific preference addition must contain at least ${0} entries (one for land use type)...
+Error.LSPA.Fact.Size=Factor-List for location specific preference addition must contain at least ${0} entries (one for land use type)...
+Error.RasterDim.GridWidth=Grid width
+Error.RasterDim.GridHeight=Grid height
+Error.RasterDim.CellWidth=Cell width
+Error.RasterDim.CellHeight=Cell height
+Error.RasterDim.SampleType=Grid sample type
+Error.RasterDim=${0} of '${1}' is incompatible to '${2}'...
+Error.Resource.Not.Allowed='${0}': value ${1} not allowed!
+Error.Expected.Matrix2=At least 2-dimensional Matrix
+Error.Expected.Matrix3=At least 3-dimensional Matrix

Added: trunk/resource/locales/XuluModel_Clue_de.properties
===================================================================
--- trunk/resource/locales/XuluModel_Clue_de.properties	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/resource/locales/XuluModel_Clue_de.properties	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,91 @@
+# ---------------------------------------------------------------
+# ------ German Translations for the xulu model ClueModel ------
+# ---------------------------------------------------------------
+
+# Descriptions of model resources
+MRDesc.ModelSteps=Modellierte Zeitschritte (${0}-${1})
+MRDesc.Tol.Type=Art der Toleranz-Angabe [${0} = Prozent; ${1} = Abs.] (integer)
+MRDesc.Tol.Single=Erlaubte Bedarfsabweichung pro LUC-Typ (double)
+MRDesc.Tol.Avg=Erlaubte durchschn. Bedarfsabweichung (double)
+MRDesc.qmConvFactor=Umrechnungsfaktor: Nachfrage-Eh. zu qm (double)
+MRDesc.LUC.Scenario=Ausgangsszenario LUC (float-Grid)
+MRDesc.LUC.History=LUC History (float-Grid)
+MRDesc.LUC.ConvMatrix=LUC-Conversion-Matrix (integer-Matrix)
+MRDesc.LUC.ConvDev=Abweichung der LUC-Conversion-Matrix (integer-Matrix)
+MRDesc.LUC.ConvElas=Conversion Elasticity (double-List)
+MRDesc.AreaRestr=Area Restrictions (float-Grid)
+MRDesc.Demand.Scenario=Nachfrage-Szenarion (integer-Matrix)
+MRDesc.DF.Static.Grids=Statische Driving Forces (float-MultiGrid)
+MRDesc.DF.Dynamic.Grids=Dynamische Driving Forces (float-MultiGrid)
+MRDesc.DF.Dynamic.Types=Dynamische LUC-Typen (int-List)
+MRDesc.Regression=Regression (double-Matrix)
+MRDesc.Nbh.Weight=Nachbarschafts-Gewichte (double-List)
+MRDesc.Nbh.Setting=Nachbarschafts-Einstellung (double-Matrix)
+MRDesc.Nbh.Regr=Nachbarschafts-Regression (double-Matrix)
+MRDesc.LSPA.Prob=Location specific preference addition (float-MultiGrid)
+MRDesc.LSPA.Fact=Faktoren der location specific pref. add. (double-List)
+MRDesc.Temp.LucHist=Temp-Raster fuer LUC-History (float-Grid)
+MRDesc.Temp.LucProb=Temp-Raster fuer LUC-W'keiten (float-MultiGrid)
+MRDesc.Temp.NbhProb=Temp-Raster fuer Nachbarschafts-W'keiten (float-MultiGrid)
+MRDesc.Temp.IterVar=Temp-List fuer Iterations-Variablen (float-List)
+MRDesc.Temp.Luc=Temp-Raster fuer aktuelle LUC (float-Grid)
+MRDesc.Temp.TotalProb=Temp-Raster fuer Gesamt-W'keiten (float-MultiGrid)
+MRDesc.Out.StepRes=Ausgabe-Raster fuer Schritt-Ergebnisse (float-MultiGrid)
+
+# Model messages
+Model.InitCover=Initiale LUC
+Model.TotalCover=Gesamt-Flaeche
+Model.LucTypes=Liste der LUC-Typen im Szenario
+Model.Step.Calc.done= erledigt.
+Model.Step.Calc.LUCProb=Berechne LUC-W'keiten fuer Schritt ${0}...
+Model.Step.Calc.NbhProb=Berechne Nachbarschafts-W'keiten fuer Schritt ${0}...
+Model.Step.Calc.Iter=Berechne Iterationen fuer Schritt ${0}...
+Model.Step.Calc.Iter.done= erledigt (${0} Iterationen).
+Model.GUI.Single.Dev.Allowed=Erlaubte Bedarfsabweichung pro LUC-Typ:
+Model.GUI.Avg.Dev.Allowed=Erlaubte durchschn. Bedarfsabweichung:
+Model.GUI.AutoUpdate=Abweichungen autom. aktualisieren
+Model.GUI.Total=Gesamt
+Model.GUI.Avg=Durchschn.
+Model.GUI.LucType=LUC-Typ
+Model.GUI.CurrDemandDev=Aktuelle Bedarfsabweichung
+Model.GUI.Iteration=Iteration
+Model.GUI.Type=Typ
+Model.GUI.Divergence=Abweichung
+Model.GUI.IterVar=Iter-Var.
+
+# Error messages
+Error.ModelSteps.Type=Long- oder Integer-Property
+Error.LUC.ConvDev.Col=Matrix fuer Abweichung der LUC-Conversion-Matrix muss mind. ${0} Spalten haben (eine pro LUC-Typ)...
+Error.LUC.ConvDev.Row=Matrix fuer Abweichung der LUC-Conversion-Matrix muss mind. ${0} Zeilen haben (eine pro LUC-Typ)...
+Error.LUC.ConvElas.Size=Liste fuer Conversion-Elasticity muss mind. ${0} Eintraege haben (einen pro LUC-Typ)...
+Error.LUC.ConvElas.Value=ListProperty mit Werten zwischen 0 und 1
+Error.Demand.Scenario.Col=Matrix fuer Nachfrage-Szenario muss mind. ${0} Spalten haben (eine pro LUC-Typ)...
+Error.Demand.Scenario.Row=Matrix fuer Nachfrage-Szenario muss mind. ${0} Zeilen haben (eine pro Zeitschritt)...
+Error.DF.Static.Grids=MultiGrid fuer statische DF muss mind. ${0} Eintraege haben (einen pro DF)...
+Error.DF.Dynamic.Types.Size=Liste der dyn. DF darf maximal ${0} Eintraege haben...
+Error.DF.Dynamic.Types.Value=Nur Werte zwischen ${0} und ${1} erlaubt in Liste der dynamischen DF...
+Error.DF.Dynamic.Grids.Null=Dynamische Driving Forces werden verwendet! Ressource '${0}' muss belegt werden...
+Error.DF.Dynamic.Grids.Size1=MultiGrid fuer dynamische DF muss mind. ${0} Eintraege haben (einen pro DF und Zeitschritt)...
+Error.DF.Dynamic.Grids.Size2=MultiGrid fuer dynamische DF muss die gleiche Anzahl an Rastern fuer jeden DF beinhalten...
+Error.Regression.Col=Matrix fuer Regression muss ${0} Spalten haben (eine fuer die Konstante und eine pro DF)...
+Error.Regression.Row=Matrix fuer Regression muss ${0} Zeilen haben (eine pro LUC-Typ)...
+Error.Nbh.Weight.Size=Liste der Nachbarschafts-Gewichte muss mind. ${0} Eintraege haben (eine pro LUC-Typ)...
+Error.Nbh.Setting.Null=Nachbarschafts-Einstellungen muessen angegeben werden...
+Error.Nbh.Setting.Size1=Nachbarschafts-Matrix muss von ungerader Groesse in jeder Dimension sein (das Zentrum ist die betr. Zelle)...
+Error.Nbh.Setting.Size2=${0} Nachbarschafts-Einst. muessen in der Matrix eingetragen sein (je eine pro LUC-Typ)...
+Error.Nbh.Regr.Null=Nachbarschafts-Regression muss angegeben werden...
+Error.Nbh.Regr.Col=Matrix fuer Nachbarschafts-Regression muss ${0} Spalten haben (eine fuer die Konstante und eine pro LUC-Typ)...
+Error.Nbh.Regr.Row=Matrix for Nachbarschafts-Regression muss ${0} Zeilen haben (eine pro LUC-Typ)...
+Error.Temp.LucProb.Size=MultiGrid LUC-W'keiten muss mind. ${0} Raster enthalten (eines pro LUC-Typ)...
+Error.Temp.NbhProb.Null=Temp-Raster fuer Nachbarschafts-W'keiten muss angegeben werden...
+Error.LSPA.Prob.Size=MultiGrid fuer Location Specific Preference Addition muss mind. ${0} Eintraege haben (einen pro LUC-Typ)...
+Error.LSPA.Fact.Size=Faktor-Liste fuer Location Specific Preference Addition muss mind ${0} Eintraege (einen pro LUC-Typ)...
+Error.RasterDim.GridWidth=Raster-Breite
+Error.RasterDim.GridHeight=Raster-Hoehe
+Error.RasterDim.CellWidth=Zellen-Breite
+Error.RasterDim.CellHeight=Zellen-Hoehe
+Error.RasterDim.SampleType=Raster-Datentyp
+Error.RasterDim=${0} von '${1}' ist nicht kompatibel zu '${2}'...
+Error.Resource.Not.Allowed='${0}': Wert ${1} nicht zulaessig!
+Error.Expected.Matrix2=Mindestens 2-dimensionale Matrix
+Error.Expected.Matrix3=Mindestens 3-dimensionale Matrix

Added: trunk/resource/locales/XuluModel_ImpetusFireCA.properties
===================================================================
--- trunk/resource/locales/XuluModel_ImpetusFireCA.properties	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/resource/locales/XuluModel_ImpetusFireCA.properties	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,45 @@
+# ---------------------------------------------------------------
+# ------ Default translations (english) for the xulu model ------
+# ------ ImpetusFireCA (iMABFIRE)                          ------
+# ---------------------------------------------------------------
+
+# Descriptions of model resources
+MRDesc.In.ModelParams=Common model parameters
+MRDesc.In.BurnSource=Fire source points [Point-FeatureCollection]
+MRDesc.In.BaseLUC=LUC classification [float-Raster]
+MRDesc.In.BurnSuit=Burn suitability (optional) [float-Raster]
+MRDesc.Out.LUC=Output raster for modelled LUC
+MRDesc.Out.BioMass=Output raster for burned biomass
+MRDesc.Temp.BurnTime=Temp raster for burn time
+
+# Model messages
+Model.ModelTime.Step=1 model step = 1 hour
+Model.ModelTime.Iter=1 iteration = ${0} seconds
+Model.GUI.WindDir.Dev=Deviation of wind direction [°]:
+Model.GUI.WindPower=Wind power [m/s]:
+Model.GUI.WindPower.Dev=Deviation of wind power [m/s]:
+Model.GUI.WindMatrix=Wind matrix:
+
+
+# Error messages
+Error.Global.Mess=Resource '${0}': ${1}
+Warn.In.ModelParams.Missing=Property '${0}' missing. Value ${0} used.
+Error.In.ModelParams.ModelTime=Must contain a property '${0}' with an greater zero int!
+Error.In.ModelParams.BurnLuc=Must contain a property '${0}' with an greater zero int!
+Error.In.ModelParams.BurnOutLuc=Must contain a property '${0}' with an greater zero int!
+Error.In.ModelParams.BurnSuit=Must contain a list-property '${0}' of number values!
+Error.In.ModelParams.BurnTime=Must contain a list-property '${0}' of positive number values!
+Error.In.ModelParams.WindDir=Must contain a property '${0}' with a not-negative value!
+Error.In.ModelParams.WindPower=Must contain a property '${0}' with a positive value!
+Error.In.ModelParams.WindDirDev=Must contain a property '${0}' with a not-negative value!
+Error.In.ModelParams.WindPowerDev=Must contain a property '${0}' with a not-negative value!
+Error.In.ModelParams.WindPowerMaxBW=Must contain a property '${0}' with a positive value!
+Error.In.ModelParams.WindMatrix=Must contain a 3x3-matrix-property '${0}' of number values!
+Error.In.ModelParams.WindMatrix_PowerConst=Property '${0}' must be scalar!
+Error.In.ModelParams.WindMatrix_PowerFact=Property '${0}' must be scalar with value not 0!
+Error.In.BurnSource.Data=Must contain at least one point feature!
+Error.In.BaseLUC.Grid=LUC-Classification-Raster
+Error.In.BurnSuit.Grid=Burn-Suitability-Raster
+Error.Out.LUC.Grid=LUC-Output-Raster
+Error.Out.BioMass.Grid=Biomass-Output-Raster
+Error.Temp.BurnTime.Grid=Burntime-Output-Raster
\ No newline at end of file

Added: trunk/resource/locales/XuluModel_ImpetusFireCA_de.properties
===================================================================
--- trunk/resource/locales/XuluModel_ImpetusFireCA_de.properties	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/resource/locales/XuluModel_ImpetusFireCA_de.properties	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,45 @@
+# ----------------------------------------------------
+# ------ German Translations for the xulu model ------
+# ------ ImpetusFireCA (iMABFIRE)               ------
+# ----------------------------------------------------
+
+# Descriptions of model resources
+MRDesc.In.ModelParams=Allgemeine Modell-Parameter
+MRDesc.In.BurnSource=Brandherde [Point-FeatureCollection]
+MRDesc.In.BaseLUC=LUC Klassifikation [float-Raster]
+MRDesc.In.BurnSuit=Brenn-Eignung (optional) [float-Raster]
+MRDesc.Out.LUC=Ausgabe-Raster für modellierte LUC
+MRDesc.Out.BioMass=Ausgabe-Raster für verbrannte Biomasse
+MRDesc.Temp.BurnTime=Temp-Raster für Brenn-Zeit
+
+# Model messages
+Model.ModelTime.Step=1 Modellschritt = 1 Stunde
+Model.ModelTime.Iter=1 Iteration = ${0} Sekunden
+Model.GUI.WindDir.Dev=Abweichung Windrichtung [°]:
+Model.GUI.WindPower=Windstaerke [m/s]:
+Model.GUI.WindPower.Dev=Abweichung Windstaerke [m/s]:
+Model.GUI.WindMatrix=Wind-Matrix:
+
+
+# Error messages
+Error.Global.Mess=Ressource '${0}': ${1}
+Warn.In.ModelParams.Missing=Property '${0}' nicht vorhanden. Wert ${0} angenommen.
+Error.In.ModelParams.ModelTime=Muss eine Property '${0}' mit int-Wert > 0 besitzen!
+Error.In.ModelParams.BurnLuc=Muss eine Property '${0}' mit int-Wert > 0 besitzen!
+Error.In.ModelParams.BurnOutLuc=Muss eine Property '${0}' mit int-Wert > 0 besitzen!
+Error.In.ModelParams.BurnSuit=Muss eine Listen-Property '${0}' mit numerischen Werten besitzen!
+Error.In.ModelParams.BurnTime=Muss eine Listen-Property '${0}' mit positiven numerischen Werten besitzen!
+Error.In.ModelParams.WindDir=Muss eine Property '${0}' mit Wert >= 0 besitzen!
+Error.In.ModelParams.WindPower=Muss eine Property '${0}' mit Wert > 0 besitzen!
+Error.In.ModelParams.WindDirDev=Muss eine Property '${0}' mit Wert >= 0 besitzen!
+Error.In.ModelParams.WindPowerDev=Must contain a property '${0}' with a not-negative value!
+Error.In.ModelParams.WindPowerMaxBW=Muss eine Property '${0}' mit Wert > 0 besitzen!
+Error.In.ModelParams.WindMatrix=Muss eine 3x3-Matrix-Property '${0}' mit numerischen Werten besitzen!
+Error.In.ModelParams.WindMatrix_PowerConst=Property '${0}' muss skalar sein!
+Error.In.ModelParams.WindMatrix_PowerFact=Property '${0}' muss skalar sein mit Wert <> 0!
+Error.In.BurnSource.Data=Muss mind. ein Punkt-Feature besitzen!
+Error.In.BaseLUC.Grid=LUC-Klassifikation-Raster
+Error.In.BurnSuit.Grid=Brenn-Eignungs-Raster
+Error.Out.LUC.Grid=LUC-Ausgabe-Raster
+Error.Out.BioMass.Grid=BioMasse-Ausgabe-Raster
+Error.Temp.BurnTime.Grid=Brennzeit-Ausgabe-Raster
\ No newline at end of file

Added: trunk/resource/locales/XuluModel_SmallReservoirModel.properties
===================================================================
--- trunk/resource/locales/XuluModel_SmallReservoirModel.properties	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/resource/locales/XuluModel_SmallReservoirModel.properties	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,37 @@
+# ---------------------------------------------------------------
+# ------ Default translations (english) for the xulu model ------
+# ------ SmallReservoirModel (SYMBA)                       ------
+# ---------------------------------------------------------------
+
+# Descriptions of model resources
+MRDesc.In.DHM=DHM (raster)
+MRDesc.In.Dam.Loc=Dam wall location (feature collection)
+MRDesc.In.Dam.Height=Dam wall height (double)
+MRDesc.In.Infilt=Infiltration in mm/day (double)
+MRDesc.In.Evapo=Evaporation in mm/day (double)
+MRDesc.In.StepSize=Model step size in days (int)
+MRDesc.Out.Area.Size=Calculated: size of flooded area in qm (double-List)
+MRDesc.Out.Area.Vol=Calculated: volume of flooded area in qqm (double-List)
+MRDesc.Out.Area.Grid=Calculated: flooded area (float-MultiGrid)
+MRDesc.Temp.DHM=Temp: dhm for wall (raster)
+
+# Model messages
+Model.Calc.Done= done.
+Model.Calc.Fill=Calculate filled reservoir...
+Model.Calc.Empty=Calculate reservoir after day ${0}...
+Model.Calc.Dam.DHM=Determining dam wall DHM and starting cells...
+Model.GUI.DamHeight=Dam height [m]
+Model.GUI.ModelSteps=Modelled step size [days]
+Model.GUI.Infilt=Infiltration [mm/day]
+Model.GUI.Evapo=Evaporation [mm/day]
+Model.GUI.Store.StepResults=Store step result raster
+Model.GUI.Calc.Area=Calculated area [m²]:
+Model.GUI.Calc.Vol=Calculated volume [m³]:
+
+# Error messages
+Error.Global.Mess=Resource '${0}': ${1}
+Error.In.Dam.Loc=Must contain at least one line string feature!
+Error.In.Dam.Loc.Type=Dam wall resource does not contain any (Multi)LineString!
+Error.In.DHM.Grid=DHM
+Error.Out.Area.Grid=Raster for flooded area
+Error.Temp.DHM.Grid=Temp-DHM for dam wall

Added: trunk/resource/locales/XuluModel_SmallReservoirModel_de.properties
===================================================================
--- trunk/resource/locales/XuluModel_SmallReservoirModel_de.properties	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/resource/locales/XuluModel_SmallReservoirModel_de.properties	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,37 @@
+# ----------------------------------------------------
+# ------ German translations for the xulu model ------
+# ------ SmallReservoirModel (SYMBA)            ------
+# ----------------------------------------------------
+
+# Descriptions of model resources
+MRDesc.In.DHM=DHM (raster)
+MRDesc.In.Dam.Loc=Staudamm-Lage (feature collection)
+MRDesc.In.Dam.Height=Staudamm-Hoehe ueber NN (double)
+MRDesc.In.Infilt=Versickerung in mm/tag (double)
+MRDesc.In.Evapo=Verdunstung in mm/tag (double)
+MRDesc.In.StepSize=Modellierte Schrittweite in Tagen (int)
+MRDesc.Out.Area.Size=Ausgabe: Groesse der ueberfluteten Flaeche in qm (double-List)
+MRDesc.Out.Area.Vol=Ausgabe: Volumen der ueberfluteten Flaeche in qqm (double-List)
+MRDesc.Out.Area.Grid=Ausgabe: Ueberflutete Flaeche (float-MultiGrid)
+MRDesc.Temp.DHM=Temp: DHM fuer Staumauer (raster)
+
+# Model messages
+Model.Calc.Done= fertig.
+Model.Calc.Fill=Berechne Befuellung des Stausees...
+Model.Calc.Empty=Berechne Inhalt des Stausees nach Tag ${0}...
+Model.Calc.Dam.DHM=Ermittle das Staumauer-DHM und die Start-Zellen...
+Model.GUI.DamHeight=Staumauer Hoehe [m]
+Model.GUI.ModelSteps=Modellierte Schrittweite [Tage]
+Model.GUI.Infilt=Versickerung [mm/Tag]
+Model.GUI.Evapo=Verdunstung [mm/Tag]
+Model.GUI.Store.StepResults=Speichere Raster fuer jeden Modellschritt
+Model.GUI.Calc.Area=Berechnete Stausee-Groesse [m²]:
+Model.GUI.Calc.Vol=Berechnetes Stausee-Volumen [m³]:
+
+# Error messages
+Error.Global.Mess=Resource '${0}': ${1}
+Error.In.Dam.Loc=Muss mindestens ein LineString-Feature enthalten!
+Error.In.Dam.Loc.Type=Staudamm-Ressource enthaelt keinen (Multi)LineString!
+Error.In.DHM.Grid=DHM
+Error.Out.Area.Grid=Raster fuer ueberflutete Flaeche
+Error.Temp.DHM.Grid=Temp-DHM fuer Staumauer

Added: trunk/resource/locales/XuluVisualisationTool.properties
===================================================================
--- trunk/resource/locales/XuluVisualisationTool.properties	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/resource/locales/XuluVisualisationTool.properties	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,15 @@
+# -------------------------------------------------------------------
+# ------ Default Translations (english) for Xulu Visualisation ------
+# ------ Plugins                                               ------
+# ------------------------------------------------------------------
+
+# ======== GTVisualisationTool ========
+GTVisualisationTool.FrameTitle=Geotools Visualisation
+
+# ======== GTEditorTool ========
+GTEditorTool.FrameTitle=Geotools Editor
+
+# ======== JFreeChartVisualisationTool ========
+JFreeChartVisualiationTool.FrameTitle=JFreeChart Visualisation
+JFreeChartVisualiationTool.RotateData=Rotate data
+JFreeChartVisualiationTool.ChartObjects=Chart objects

Added: trunk/resource/locales/XuluVisualisationTool_de.properties
===================================================================
--- trunk/resource/locales/XuluVisualisationTool_de.properties	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/resource/locales/XuluVisualisationTool_de.properties	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,14 @@
+# ----------------------------------------------------------------
+# ------ German Translations for Xulu Visualisation Plugins ------
+# ----------------------------------------------------------------
+
+# ======== GTVisualisationTool ========
+GTVisualisationTool.FrameTitle=Geotools Visualisierung
+
+# ======== GTEditorTool ========
+GTEditorTool.FrameTitle=Geotools Editor
+
+# ======== JFreeChartVisualisationTool ========
+JFreeChartVisualiationTool.FrameTitle=JFreeChart Visualisierung
+JFreeChartVisualiationTool.RotateData=Daten rotieren
+JFreeChartVisualiationTool.ChartObjects=Chart-Objekte

Added: trunk/resource/unused/edit_clear.gif
===================================================================
(Binary files differ)


Property changes on: trunk/resource/unused/edit_clear.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/resource/unused/edit_redo.gif
===================================================================
(Binary files differ)


Property changes on: trunk/resource/unused/edit_redo.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/resource/unused/edit_undo.gif
===================================================================
(Binary files differ)


Property changes on: trunk/resource/unused/edit_undo.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/resource/unused/layer_cancel3.png
===================================================================
(Binary files differ)


Property changes on: trunk/resource/unused/layer_cancel3.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/resource/unused/xulu_icon.gif
===================================================================
(Binary files differ)


Property changes on: trunk/resource/unused/xulu_icon.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/resource/unused/xulu_icon_green.gif
===================================================================
(Binary files differ)


Property changes on: trunk/resource/unused/xulu_icon_green.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/resource/unused/xulu_icon_red.gif
===================================================================
(Binary files differ)


Property changes on: trunk/resource/unused/xulu_icon_red.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/resource/unused/xulu_icon_yellow.gif
===================================================================
(Binary files differ)


Property changes on: trunk/resource/unused/xulu_icon_yellow.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/resource/unused/xuluv.png
===================================================================
(Binary files differ)


Property changes on: trunk/resource/unused/xuluv.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/META-INF/PREFERRED.LIST
===================================================================
--- trunk/src/META-INF/PREFERRED.LIST	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/META-INF/PREFERRED.LIST	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,8 @@
+PreferredResources-Version: 1.0
+Preferred: false
+
+Name: edu/bonn/xulu/plugin/model/*
+Preferred: true
+
+Name: edu/bonn/xulu/plugin/model/-
+Preferred: true

Added: trunk/src/appl/data/DataLoader.java
===================================================================
--- trunk/src/appl/data/DataLoader.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/data/DataLoader.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,31 @@
+package appl.data;
+
+import java.io.Serializable;
+
+/**
+ * A class that automatically loads a specified object and returns it, as soon
+ * as the {@link #load()} method is invoked. It is the counterpart of {@link DataUnloader}.
+ * 
+ * @author Dominik Appl
+ * @see DataUnloader
+ */
+public interface DataLoader extends Serializable {
+	
+	/**
+	 * On invocation the data is loaded and returned
+	 * 
+	 * @return the newly loaded object
+	 * 
+	 * @throws LoadingException if for some reason the data could not
+	 * be loaded
+	 */
+	public Object load() throws LoadingException;
+	
+	/**
+	 * @return some general information about the loading class 
+	 * (like what the class exactly loads)
+	 * 
+	 */
+	public String getLoadInfo();
+
+}

Added: trunk/src/appl/data/DataProxy.java
===================================================================
--- trunk/src/appl/data/DataProxy.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/data/DataProxy.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,12 @@
+package appl.data;
+
+/**
+ * A DataProxy class should forward calls to exactly one encapsulated object.
+ * 
+ * @author Dominik Appl
+ */
+public interface DataProxy {
+
+	/** get the encapsulated Object */
+	Object getProxiedObject();
+}

Added: trunk/src/appl/data/DataUnloader.java
===================================================================
--- trunk/src/appl/data/DataUnloader.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/data/DataUnloader.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,22 @@
+package appl.data;
+
+/**
+ * A instances of <code>DataUnloader</code> unloads a specified object to a
+ * location, as soon as the {@link #unload()} method is invoked. Counterpart of
+ * {@link DataLoader}.
+ * 
+ * @author Dominik Appl
+ */
+public interface DataUnloader {
+
+	/**
+	 * unloads the Data to a specific location
+	 */
+	public void unload();
+
+	/**
+	 * @return a short description of what the class exactly does
+	 */
+	public String getUnloadInfo();
+
+}

Added: trunk/src/appl/data/FactoryLoader.java
===================================================================
--- trunk/src/appl/data/FactoryLoader.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/data/FactoryLoader.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,56 @@
+package appl.data;
+
+import schmitzm.data.WritableGrid;
+import appl.util.RasterMetaData;
+import edu.bonn.xulu.plugin.io.grid.WritableGridFactory;
+
+/**
+ * This is an implementation of a loader class which loads data with a
+ * {@link WritableGridFactory}. It is used for Late Loading.
+ * 
+ * @author Dominik Appl
+ * @see WritableGridLLProxy
+ */
+public class FactoryLoader implements DataLoader {
+
+	private WritableGridFactory fac;
+
+	private RasterMetaData metaData;
+
+	private FactoryLoader() {
+	}
+
+	/**
+	 * @param factory
+	 *            the factory which is used for instantiation
+	 * @param metaData
+	 *            the meta data is required for grid instantiation
+	 */
+	public FactoryLoader(WritableGridFactory factory, RasterMetaData metaData) {
+		fac = factory;
+		this.metaData = metaData;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.data.DataLoader#load()
+	 */
+	public WritableGrid load() {
+		return fac.newInstance(metaData.getDataType(), metaData.getWidth(),
+				metaData.getHeight(), metaData.getMinX(), metaData.getMinY(),
+				metaData.getX(), metaData.getY(), metaData.getRealWidth(),
+				metaData.getRealHeight(), metaData
+						.getCoordinateReferenceSystem());
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.data.DataLoader#getLoadInfo()
+	 */
+	public String getLoadInfo() {
+		return "FactoryLoader|" + fac + "|" + metaData;
+	}
+
+}

Added: trunk/src/appl/data/ImportFactoryLoader.java
===================================================================
--- trunk/src/appl/data/ImportFactoryLoader.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/data/ImportFactoryLoader.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,68 @@
+package appl.data;
+
+import edu.bonn.xulu.appl.XuluRegistry;
+import edu.bonn.xulu.io.ImportFactory;
+
+/**
+ * This is an implementation of a loader class which loads data with an
+ * importer. It is for Late Loading.
+ * 
+ * @author Dominik Appl
+ * @see WritableGridLLProxy
+ * @author Dominik Appl
+ */
+public class ImportFactoryLoader implements DataLoader {
+
+	private ImportFactory fac;
+
+	private Object inputPara;
+
+	private XuluRegistry reg;
+
+	/**
+	 * not usable
+	 */
+	private ImportFactoryLoader() {
+	}
+
+	/**
+	 * @param importFac
+	 *            the import factory to be used for loading
+	 * @param inputPara
+	 *            the input object (usually a file)
+	 * @param reg
+	 *            the {@link XuluRegistry}
+	 */
+	public ImportFactoryLoader(ImportFactory importFac, Object inputPara,
+			XuluRegistry reg) {
+		fac = importFac;
+		this.inputPara = inputPara;
+		this.reg = reg;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.data.DataLoader#load()
+	 */
+	public Object load() throws LoadingException {
+		try {
+			return fac.importObject(inputPara, reg);
+		} catch (Exception e) {
+			throw new LoadingException(
+					"Could not load Grid with Importfactory <"
+							+ fac.getClass().getName() + ">" + " and "
+							+ inputPara, inputPara);
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.data.DataLoader#getLoadInfo()
+	 */
+	public String getLoadInfo() {
+		return "ImportFactoryLoader|" + fac + "|" + inputPara;
+	}
+
+}

Added: trunk/src/appl/data/LateLoadingProxy.java
===================================================================
--- trunk/src/appl/data/LateLoadingProxy.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/data/LateLoadingProxy.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,178 @@
+package appl.data;
+
+import java.io.File;
+import java.io.Serializable;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import appl.util.GeneralUtil;
+
+/**
+ * Loads an object on demand with the help of an <code>DataLoader</code>. The
+ * unload() method unloads a serializable {@link Object} into a temporary folder
+ * on the hard disk. Unloading can be disabled via the
+ * {@link #setUnloading(boolean)} method.
+ * 
+ * @see DataLoader
+ * @author Dominik Appl
+ */
+public class LateLoadingProxy implements DataProxy, Serializable {
+
+	private File unloadFile;
+
+	protected transient final Logger LOG = LogManager.getLogger(this.getClass()
+			.getName());
+
+	/** Object loaded? */
+	protected boolean loaded = false;
+
+	protected transient DataLoader dataLoader;
+
+	/**
+	 * The loader which constructs the object
+	 */
+	protected transient DataLoader intialDataLoader;
+
+	protected Object baseObject;
+
+	private boolean unloadingEnabled;
+
+	/**
+	 * Creates a new instance with the specified data loader
+	 * 
+	 * @param loader
+	 *            the load method of the {@link DataLoader} is called for
+	 *            loading
+	 */
+	public LateLoadingProxy(DataLoader loader) {
+		if (loader == null) {
+			throw new UnsupportedOperationException(
+					"Error: the dataloader may not be null");
+		}
+		setUnloadDir("Temp");
+		this.intialDataLoader = loader;
+		this.dataLoader = loader;
+	}
+
+	private LateLoadingProxy() {
+	};
+
+	/**
+	 * returns the File, in which the object is/will be unloaded
+	 */
+	protected File getUnloadFile() {
+		return unloadFile;
+	}
+
+	/**
+	 * Loads the data into memory (if not already loaded).<br>
+	 * This method is thread-safe
+	 * 
+	 * @throws LoadingException
+	 */
+	public synchronized void loadData() throws LoadingException {
+		if (loaded)
+			return;
+		try {
+			if (dataLoader == null)
+				throw new UnsupportedOperationException(
+						"A dataloader was found to be null!");
+			baseObject = dataLoader.load();
+			if (LOG.isDebugEnabled())
+				LOG.debug("Successfully loaded " + baseObject + " with "
+						+ dataLoader.getLoadInfo());
+			loaded = true;
+
+		} catch (LoadingException e) {
+			throw e;
+		}
+	}
+
+	/***************************************************************************
+	 * If no Data is loaded or unloading is disabled this method does nothing,
+	 * else it saves the Data into a temporary File. <br>
+	 * Warning: Should be Thread-Safe with loadData, but was not tested
+	 **************************************************************************/
+	public synchronized void unloadData() {
+		// only do something if the Data is loaded and unloading is enabled:
+		if (!loaded)
+			return;
+		if (!unloadingEnabled)
+			return;
+		// there is no way to save the Grid to a File, when its not serializible
+		if (!(baseObject instanceof java.io.Serializable)) {
+			LOG.warn("Could not unload the Data because the class "
+					+ baseObject.getClass().getName() + "is not serializable");
+			return;
+		}
+
+		// unload the Data
+		try {
+			GeneralUtil.SerializeToFile(baseObject, unloadFile);
+			loaded = false;
+			baseObject = null;
+			dataLoader = new SerializedDataLoader(unloadFile, true);
+			LOG.debug("Successfully unloaded Grid into File: "
+					+ unloadFile.getPath());
+		} catch (Exception e) {
+			LOG.error("Error while trying to unload a grid into file '"
+					+ unloadFile.getAbsolutePath() + "'");
+			e.printStackTrace();
+		}
+
+	}
+
+	/**
+	 * This class supports late loading, of course.
+	 * 
+	 * @see appl.data.LateLoadable#unloadData()
+	 * @return true;
+	 * @see appl.data.LateLoadable#isLateLoadable()
+	 */
+	public boolean isLateLoadable() {
+		return true;
+	}
+
+	/**
+	 * returns the baseObject
+	 * 
+	 * @see appl.data.DataProxy#getProxiedObject()
+	 */
+	public Object getProxiedObject() {
+		try {
+			loadData();
+		} catch (LoadingException e) {
+			System.err.println("Error while loading Griddata ... ");
+			e.printStackTrace();
+		}
+		return baseObject;
+	}
+
+	/** returns true, if the baseObject is loaded */
+	public boolean isLoaded() {
+		return loaded;
+	}
+
+	public void setUnloadDir(String newUnloadDirectory) {
+		unloadFile = new File(newUnloadDirectory + File.separatorChar
+				+ this.toString() + ".tmp");
+		// the unload file will be deleted after the JVM shuts down (only after
+		// "normal" shutdown)
+		unloadFile.deleteOnExit();
+	}
+
+	/**
+	 * Set to false, if you want to disable the unloading in a temporary file
+	 */
+	public void setUnloading(boolean unloadingEnabled) {
+		this.unloadingEnabled = unloadingEnabled;
+	}
+
+	/**
+	 * @return true, if unloading is enabled
+	 */
+	public boolean isUnloadingEnabled() {
+		return unloadingEnabled;
+	}
+}

Added: trunk/src/appl/data/SerializedDataLoader.java
===================================================================
--- trunk/src/appl/data/SerializedDataLoader.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/data/SerializedDataLoader.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,93 @@
+package appl.data;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import schmitzm.data.WritableGrid;
+
+/**
+ * @author Dominik Appl
+ */
+public class SerializedDataLoader implements DataLoader {
+
+	protected File loadFile;
+
+	private boolean del_after_loading;
+
+	private SerializedDataLoader() {
+	}
+
+	public SerializedDataLoader(File loadFile,
+			boolean DELETE_SOURCE_AFTER_LOADING) {
+		this.loadFile = loadFile;
+		del_after_loading = DELETE_SOURCE_AFTER_LOADING;
+	}
+
+	public SerializedDataLoader(File loadFile) {
+		this(loadFile, false);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.data.DataLoader#load()
+	 */
+	public Object load() throws LoadingException {
+		Object loadedObject = null;
+		try {
+			BufferedInputStream fis = new BufferedInputStream(
+					new FileInputStream(loadFile));
+			ObjectInputStream ois = new ObjectInputStream(fis);
+			loadedObject = ois.readObject();
+			ois.close();
+			fis.close();
+			// remove File from Filesystem
+			if (del_after_loading)
+				loadFile.delete();
+
+		} catch (FileNotFoundException e) {
+			throw new LoadingException("Could not find temporary unload-file:"
+					+ loadFile, loadFile);
+
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new LoadingException("Could not load from temporary file "
+					+ loadFile, loadFile);
+
+		}
+		return loadedObject;
+
+	}
+
+	public static void SerializeToFile(Object o, File destFile)
+			throws LoadingException {
+		try {
+			destFile.createNewFile();
+			BufferedOutputStream fos = new BufferedOutputStream(
+					new FileOutputStream(destFile));
+			ObjectOutputStream oos = new ObjectOutputStream(fos);
+			oos.writeObject(o);
+			oos.close();
+			fos.close();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.data.DataLoader#getLoadInfo()
+	 */
+	public String getLoadInfo() {
+		return "SerializedDataLoader|" + loadFile.getPath();
+	}
+
+}

Added: trunk/src/appl/data/WritableGridArrayLoader.java
===================================================================
--- trunk/src/appl/data/WritableGridArrayLoader.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/data/WritableGridArrayLoader.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,45 @@
+package appl.data;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.WritableGridArray;
+import appl.util.RasterMetaData;
+
+/**
+ * Simply loads an empty {@link WritableGridArray} with the specified meta data.
+ * 
+ * @author Dominik Appl
+ */
+public class WritableGridArrayLoader implements DataLoader {
+
+	private RasterMetaData metaData;
+
+	private WritableGridArrayLoader() {
+	}
+
+	/**
+	 * @param metaData
+	 *            the metadata with the exact dimensions/datatype
+	 */
+	public WritableGridArrayLoader(RasterMetaData metaData) {
+		this.metaData = metaData;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.data.DataLoader#load()
+	 */
+	public WritableGrid load() {
+		return WritableGridArray.createEmpty(metaData);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.data.DataLoader#getLoadInfo()
+	 */
+	public String getLoadInfo() {
+		return "WritableGridArrayLoader|" + metaData;
+	}
+
+}

Added: trunk/src/appl/data/WritableGridLLProxy.java
===================================================================
--- trunk/src/appl/data/WritableGridLLProxy.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/data/WritableGridLLProxy.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,251 @@
+package appl.data;
+
+import java.awt.Rectangle;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.WritableGridArray;
+import appl.util.RasterMetaData;
+import edu.bonn.xulu.appl.XuluRegistry;
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.plugin.io.grid.WritableGridFactory;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+/**
+ * This is an a late loading implementation for {@link WritableGrid WritableGrids}.
+ * 
+ * @author Dominik Appl
+ */
+public class WritableGridLLProxy extends LateLoadingProxy implements
+		WritableGrid {
+
+	protected RasterMetaData metaData;
+
+	public WritableGridLLProxy(ImportFactory importFac,
+			RasterMetaData metaData, Object inputPara, XuluRegistry reg) {
+		super(new ImportFactoryLoader(importFac, inputPara, reg));
+		this.metaData = metaData;
+	}
+
+	public WritableGridLLProxy(WritableGridFactory targetFactory,
+			RasterMetaData metaData) {
+		super(new FactoryLoader(targetFactory, metaData));
+		this.metaData = metaData;
+	}
+
+	public WritableGridLLProxy(RasterMetaData metaData) {
+		super(new WritableGridArrayLoader(metaData));
+		baseObject = null;
+		loaded = false;
+		this.metaData = metaData;
+	}
+
+	protected WritableGridLLProxy(RasterMetaData metaData, DataLoader loader) {
+		super(loader);
+		loaded = false;
+		this.metaData = metaData;
+	}
+
+	public double convertRasterToReal(int cell, int dim) {
+		if (!loaded)
+			tryLoadingGrid();
+		;
+		return ((WritableGrid) baseObject).convertRasterToReal(cell, dim);
+	}
+
+	public int convertRealToRaster(double coord, int dim) {
+		if (!loaded)
+			tryLoadingGrid();
+		return ((WritableGrid) baseObject).convertRealToRaster(coord, dim);
+	}
+
+	/** @see WritableGrid#dispose() */
+	public void dispose() {
+		if (baseObject != null)
+			((WritableGrid) baseObject).dispose();
+	}
+
+	public Object getGridSample(double... coord) {
+		if (!loaded)
+			tryLoadingGrid();
+		return ((WritableGrid) baseObject).getGridSample();
+	}
+
+	public byte getGridSampleAsByte(double... coord) {
+		if (!loaded)
+			tryLoadingGrid();
+		return ((WritableGrid) baseObject).getGridSampleAsByte(coord);
+	}
+
+	public double getGridSampleAsDouble(double... coord) {
+		if (!loaded)
+			tryLoadingGrid();
+		return ((WritableGrid) baseObject).getGridSampleAsDouble(coord);
+	}
+
+	public float getGridSampleAsFloat(double... coord) {
+		if (!loaded)
+			tryLoadingGrid();
+		return ((WritableGrid) baseObject).getGridSampleAsFloat(coord);
+	}
+
+	public int getGridSampleAsInt(double... coord) {
+		if (!loaded)
+			tryLoadingGrid();
+		return ((WritableGrid) baseObject).getGridSampleAsInt(coord);
+	}
+
+	public long getGridSampleAsLong(double... coord) {
+		if (!loaded)
+			tryLoadingGrid();
+		return ((WritableGrid) baseObject).getGridSampleAsLong(coord);
+	}
+
+	public short getGridSampleAsShort(double... coord) {
+		if (!loaded)
+			tryLoadingGrid();
+		return ((WritableGrid) baseObject).getGridSampleAsShort(coord);
+	}
+
+	public CoordinateReferenceSystem getCoordinateReferenceSystem() {
+		return metaData.getCoordinateReferenceSystem();
+	}
+
+	public int getHeight() {
+		return metaData.getHeight();
+	}
+
+	public int getMinX() {
+		return metaData.getMinX();
+
+	}
+
+	public int getMinY() {
+		return metaData.getMinY();
+	}
+
+	public Object getRasterSample(int... cell) {
+		if (!loaded)
+			tryLoadingGrid();
+		return ((WritableGrid) baseObject).getRasterSample(cell);
+	}
+
+	public byte getRasterSampleAsByte(int... cell) {
+		if (!loaded)
+			tryLoadingGrid();
+		return ((WritableGrid) baseObject).getRasterSampleAsByte(cell);
+	}
+
+	public double getRasterSampleAsDouble(int... cell) {
+		if (!loaded)
+			tryLoadingGrid();
+		return ((WritableGrid) baseObject).getRasterSampleAsDouble(cell);
+	}
+
+	public float getRasterSampleAsFloat(int... cell) {
+		if (!loaded)
+			tryLoadingGrid();
+		return ((WritableGrid) baseObject).getRasterSampleAsFloat(cell);
+	}
+
+	public int getRasterSampleAsInt(int... cell) {
+		if (!loaded)
+			tryLoadingGrid();
+		return ((WritableGrid) baseObject).getRasterSampleAsInt(cell);
+	}
+
+	public long getRasterSampleAsLong(int... cell) {
+		if (!loaded)
+			tryLoadingGrid();
+		return ((WritableGrid) baseObject).getRasterSampleAsLong(cell);
+	}
+
+	public short getRasterSampleAsShort(int... cell) {
+		if (!loaded)
+			tryLoadingGrid();
+		return ((WritableGrid) baseObject).getRasterSampleAsShort(cell);
+	}
+
+	public double getRealHeight() {
+		return metaData.getRealHeight();
+	}
+
+	public double getRealWidth() {
+		return metaData.getRealWidth();
+	}
+
+	public int getSampleType() {
+		return metaData.getDataType();
+	}
+
+	/** Returns the Width of the Grid */
+	public int getWidth() {
+		return metaData.getWidth();
+	}
+
+	public double getX() {
+		return metaData.getX();
+	}
+
+	public double getY() {
+		return metaData.getY();
+	}
+
+	public void setGridSample(Object value, double... coord) {
+		if (!loaded)
+			tryLoadingGrid();
+		((WritableGrid) baseObject).setGridSample(value, coord);
+	}
+
+	public void setRasterSample(Object value, int... cell) {
+		if (!loaded)
+			tryLoadingGrid();
+		((WritableGrid) baseObject).setRasterSample(value, cell);
+
+	}
+
+	/**
+	 * Trys to load the grid and gives out an error to the LOG, if the loading
+	 * fails.
+	 */
+	protected void tryLoadingGrid() {
+		try {
+			super.loadData();
+		} catch (LoadingException e) {
+			LOG.error("Error while Loading Grid " + this + " from Source "
+					+ e.getLoadSource());
+			e.printStackTrace();
+		}
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see schmitzm.data.WritableGrid#getCellHeight()
+	 */
+	public double getCellHeight() {
+		// TODO Auto-generated method stub
+		return metaData.getCellHeight();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see schmitzm.data.WritableGrid#getCellWidth()
+	 */
+	public double getCellWidth() {
+		// TODO Auto-generated method stub
+		return metaData.getCellWidth();
+	}
+
+	/**
+	 * This class supports late loading
+	 * 
+	 * @see appl.data.LateLoadable#unloadData()
+	 * @return true;
+	 * @see appl.data.LateLoadable#isLateLoadable()
+	 */
+	public boolean isLateLoadable() {
+		return true;
+	}
+}

Added: trunk/src/appl/data/package.html
===================================================================
--- trunk/src/appl/data/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/data/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,8 @@
+<html>
+<body>
+	This package contains files responsible for data handling. It contains several loader
+	and unloader classes. Important and frequently used classes are the WritableGridLLProxy
+	and the LateLoadingProxy. Thease classes are responsible for the late loading functionality
+	in Xulu.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/ext/ConfigurationEditor.java
===================================================================
--- trunk/src/appl/ext/ConfigurationEditor.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/ext/ConfigurationEditor.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,62 @@
+package appl.ext;
+
+import javax.swing.SwingUtilities;
+import java.awt.BorderLayout;
+import javax.swing.JPanel;
+import javax.swing.JFrame;
+import javax.swing.WindowConstants;
+import java.awt.Dimension;
+
+/**
+ * Displays the {@link XuluConfig} in a frame based using the
+ * {@link ConfigurationEditorEngine}. This class is independent of Xulu and may
+ * be used separately.
+ * 
+ * @author Dominik Appl
+ */
+public class ConfigurationEditor extends JFrame {
+
+	private static final long serialVersionUID = 1L;
+
+	private JPanel jContentPane = null;
+
+	/**
+	 * @param args
+	 */
+	public static void main(String[] args) {
+		// TODO Auto-generated method stub
+		SwingUtilities.invokeLater(new Runnable() {
+			public void run() {
+				ConfigurationEditor thisClass = new ConfigurationEditor();
+				thisClass.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+				thisClass.setVisible(true);
+			}
+		});
+	}
+
+	/**
+	 * This is the default constructor
+	 */
+	public ConfigurationEditor() {
+		super();
+		initialize();
+	}
+
+	/**
+	 * This method initializes this
+	 * 
+	 * @return void
+	 */
+	private void initialize() {
+		this.setSize(621, 445);
+		this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+		this.setContentPane(new ConfigurationEditorEngine().getGUI());
+		this.setTitle("Xulu Configuration Editor");
+	}
+
+	public void dispose() {
+		XuluConfig.getXuluConfig().store();
+		System.exit(0);
+	}
+
+} // @jve:decl-index=0:visual-constraint="10,10"

Added: trunk/src/appl/ext/ConfigurationEditorEngine.java
===================================================================
--- trunk/src/appl/ext/ConfigurationEditorEngine.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/ext/ConfigurationEditorEngine.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,215 @@
+package appl.ext;
+
+import java.awt.Component;
+import java.util.Set;
+import java.util.Vector;
+
+import javax.swing.DefaultListModel;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JTable;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.event.TableModelEvent;
+import javax.swing.event.TableModelListener;
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.DefaultTableModel;
+import javax.swing.table.TableCellRenderer;
+import javax.swing.table.TableModel;
+
+import appl.util.NonEditableTableModel;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.gui.XuluInternalFrame;
+import edu.bonn.xulu.plugin.appl.AbstractMenuPlugin;
+
+/**
+ * Handles the {@link ConfigurationEditorGUI}. The prefixes of the
+ * {@link XuluConfig} are added to the {@link JList} and the suffixes to the
+ * {@link JTable}. For the documentation column for every key with a name lets
+ * say 'key' the value of "key.doc" is looked up in the configuration. The
+ * prefixes which are values of the key "Filter.prefixes" in the
+ * configuration are ignored. Also all keys which show up in "Filter.keys"
+ * 
+ * @see XuluConfig
+ * @author Dominik Appl
+ */
+public class ConfigurationEditorEngine implements ListSelectionListener,
+		TableModelListener {
+
+	ConfigurationEditorGUI GUI = null;
+
+	private DefaultTableModel tableModel;
+
+	private JTable entryTable;
+
+	private JList categoryList;
+
+	private XuluConfig config;
+
+	private String currentCategory;
+
+	/**
+	 * creates a new Editor. Use {@link #getGUI()} to access the GUI.
+	 */
+	public ConfigurationEditorEngine() {
+		config = XuluConfig.getXuluConfig();
+		GUI = new ConfigurationEditorGUI();
+		initGUI();
+	}
+
+	/**
+	 * inits the GUI
+	 */
+	private void initGUI() {
+
+		entryTable = GUI.entryTable;
+		categoryList = GUI.keyList;
+		initList();
+		initTable();
+	}
+
+	/**
+	 * initializes the table
+	 */
+	private void initTable() {
+		// only the 2nd column is editable
+		tableModel = new NonEditableTableModel(
+				new Object[] { "Name", "Entry" },
+				new boolean[] { false, true }, 0);
+		entryTable.setModel(tableModel);
+		entryTable.setDefaultRenderer(Object.class, new ToolTipRenderer());
+		entryTable.getModel().addTableModelListener(this);
+		entryTable.getSelectionModel().addListSelectionListener(this);
+		String firstElement = (String) categoryList.getModel().getElementAt(0);
+		if (firstElement != null)
+			initTableData(firstElement);
+	}
+
+	/**
+	 * The table is initalized with the given category
+	 * 
+	 * @param firstElement
+	 */
+	private void initTableData(String categoryName) {
+		// get ignored keys
+		String[] filteredKeys = config.getMultiProperty("Filter.keys");
+		Vector<String> filter = new Vector<String>();
+		for (String string : filteredKeys) {
+			filter.add(string);
+		}
+		Set<String> suffixes = config.getSuffixesOfPrefix(categoryName);
+		// clear table
+		tableModel.setRowCount(0);
+		for (String suffix : suffixes) {
+			// do not enter the documentation as seperate entries
+			if (suffix.endsWith(".doc"))
+				continue;
+			String key = categoryName + "." + suffix;
+			// do not enter filtered keys
+			if (filter.contains(key))
+				continue;
+			String value = config.getProperty(key);
+			tableModel.addRow(new Object[] { suffix, value });
+		}
+		currentCategory = categoryName;
+	}
+
+	public ConfigurationEditorGUI getGUI() {
+		return GUI;
+	}
+
+	/**
+	 * 
+	 */
+	private void initList() {
+		// get ignored prefixes
+		String[] filteredPrefixes = config.getMultiProperty("Filter.prefixes");
+		Vector<String> filter = new Vector<String>();
+		for (String string : filteredPrefixes) {
+			filter.add(string);
+		}
+		DefaultListModel listModel = new DefaultListModel();
+		Object[] prefixes = config.getPrefixes().toArray();
+		for (Object object : prefixes) {
+			if (!filter.contains(object))
+				listModel.addElement(object);
+		}
+		this.GUI.keyList.setModel(listModel);
+		// select first element
+		categoryList.setSelectedIndex(0);
+		categoryList.addListSelectionListener(this);
+	}
+
+	/**
+	 * Listens for selection changes in list and table
+	 * 
+	 * @see javax.swing.event.ListSelectionListener#valueChanged(javax.swing.event.ListSelectionEvent)
+	 */
+	public void valueChanged(ListSelectionEvent e) {
+		if (e.getSource() == categoryList) {
+			String value = (String) categoryList.getSelectedValue();
+			if (value != null)
+				initTableData(value);
+			// clear documentation field
+			GUI.docArea
+					.setText("<select a table value to see its documentation>");
+		}
+		// update documentation
+		else if (e.getSource() == entryTable.getSelectionModel()) {
+			int selRow = entryTable.getSelectedRow();
+			// if a row is selected:
+			if (selRow >= 0) {
+				String value = (String) entryTable.getModel().getValueAt(
+						selRow, 0);
+				String docKey = currentCategory + "." + value + ".doc";
+				String doc = config.getProperty(docKey);
+				if (doc == null)
+					doc = "<no documentation found for this entry>";
+				GUI.docArea.setText(doc);
+			}
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see javax.swing.event.TableModelListener#tableChanged(javax.swing.event.TableModelEvent)
+	 */
+	public void tableChanged(TableModelEvent e) {
+		// handle the editing the user does
+		if (e.getType() == TableModelEvent.UPDATE) {
+			int changedRow = e.getFirstRow();
+			// only the 2nd col is editable
+			String value = tableModel.getValueAt(changedRow, 1).toString();
+			String suffix = tableModel.getValueAt(changedRow, 0).toString();
+			String prefix = categoryList.getSelectedValue().toString();
+			String key = prefix + "." + suffix;
+			config.setProperty(key, value);
+
+		}
+	}
+
+	/**
+	 * just for the tooltips
+	 * 
+	 * @author Dominik Appl
+	 */
+	private class ToolTipRenderer extends DefaultTableCellRenderer {
+
+		public ToolTipRenderer() {
+			setOpaque(true);
+		}
+
+		public Component getTableCellRendererComponent(JTable table,
+				Object color, boolean isSelected, boolean hasFocus, int row,
+				int column) {
+			Object value = table.getModel().getValueAt(row, column);
+			if (value != null)
+				setToolTipText(value.toString());
+			return super.getTableCellRendererComponent(table, color,
+					isSelected, hasFocus, row, column);
+		}
+
+	}
+}
\ No newline at end of file

Added: trunk/src/appl/ext/ConfigurationEditorGUI.java
===================================================================
--- trunk/src/appl/ext/ConfigurationEditorGUI.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/ext/ConfigurationEditorGUI.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,272 @@
+package appl.ext;
+
+import java.awt.BorderLayout;
+import javax.swing.JPanel;
+import javax.swing.JFrame;
+import java.awt.Dimension;
+import javax.swing.JList;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.BoxLayout;
+
+import edu.bonn.xulu.gui.XuluInternalFrame;
+
+import java.awt.FlowLayout;
+import java.awt.GridLayout;
+import java.awt.GridBagLayout;
+import java.awt.GridBagConstraints;
+import java.awt.Insets;
+import javax.swing.ListSelectionModel;
+import javax.swing.JLabel;
+import javax.swing.border.SoftBevelBorder;
+import javax.swing.BorderFactory;
+import javax.swing.border.BevelBorder;
+import javax.swing.JTextField;
+import javax.swing.JTextArea;
+import javax.swing.SwingConstants;
+
+/**
+ * Displays the properties of {@link XuluConfig}. The interesting stuff happens
+ * in {@link ConfigurationEditorEngine}.
+ * 
+ * @see XuluConfig
+ * @see ConfigurationEditorEngine
+ * @author Dominik Appl
+ */
+public class ConfigurationEditorGUI extends JPanel {
+
+	private static final long serialVersionUID = 1L;
+
+	JList keyList = null;
+
+	JScrollPane scrollPane = null;
+
+	JTable entryTable = null;
+
+	private JPanel jPanel = null;
+
+	private JPanel jPanel1 = null;
+
+	private JLabel jLabel = null;
+
+	private JScrollPane jScrollPane = null;
+
+	JTextArea docArea = null;
+
+	private JLabel jLabel1 = null;
+
+	private JPanel jPanel2 = null;
+
+	/**
+	 * This is the default constructor
+	 */
+	public ConfigurationEditorGUI() {
+		super();
+		initialize();
+	}
+
+	/**
+	 * This method initializes this
+	 * 
+	 * @return void
+	 */
+	private void initialize() {
+		GridBagConstraints gridBagConstraints4 = new GridBagConstraints();
+		gridBagConstraints4.insets = new Insets(0, 0, 0, 0);
+		gridBagConstraints4.gridy = 0;
+		gridBagConstraints4.ipady = 0;
+		gridBagConstraints4.gridwidth = 1;
+		gridBagConstraints4.weightx = 1.0;
+		gridBagConstraints4.weighty = 1.0;
+		gridBagConstraints4.fill = GridBagConstraints.BOTH;
+		gridBagConstraints4.ipadx = 0;
+		gridBagConstraints4.gridx = 1;
+		GridBagConstraints gridBagConstraints3 = new GridBagConstraints();
+		gridBagConstraints3.gridx = 0;
+		gridBagConstraints3.ipadx = 135;
+		gridBagConstraints3.ipady = 0;
+		gridBagConstraints3.anchor = GridBagConstraints.WEST;
+		gridBagConstraints3.fill = GridBagConstraints.VERTICAL;
+		gridBagConstraints3.gridheight = 1;
+		gridBagConstraints3.gridwidth = 1;
+		gridBagConstraints3.weightx = 0.0;
+		gridBagConstraints3.weighty = 1.0;
+		gridBagConstraints3.gridy = 0;
+		this.setLayout(new GridBagLayout());
+		this.setSize(682, 239);
+		this.add(getJPanel(), gridBagConstraints3);
+		this.add(getJPanel1(), gridBagConstraints4);
+	}
+
+	/**
+	 * This method initializes keyList
+	 * 
+	 * @return javax.swing.JList
+	 */
+	private JList getKeyList() {
+		if (keyList == null) {
+			keyList = new JList();
+			keyList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+		}
+		return keyList;
+	}
+
+	/**
+	 * This method initializes scrollPane
+	 * 
+	 * @return javax.swing.JScrollPane
+	 */
+	private JScrollPane getScrollPane() {
+		if (scrollPane == null) {
+			scrollPane = new JScrollPane();
+			scrollPane.setViewportView(getEntryTable());
+		}
+		return scrollPane;
+	}
+
+	/**
+	 * This method initializes entryTable
+	 * 
+	 * @return javax.swing.JTable
+	 */
+	private JTable getEntryTable() {
+		if (entryTable == null) {
+			entryTable = new JTable();
+		}
+		return entryTable;
+	}
+
+	/**
+	 * This method initializes jPanel
+	 * 
+	 * @return javax.swing.JPanel
+	 */
+	private JPanel getJPanel() {
+		if (jPanel == null) {
+			GridBagConstraints gridBagConstraints2 = new GridBagConstraints();
+			gridBagConstraints2.fill = GridBagConstraints.BOTH;
+			gridBagConstraints2.gridy = 1;
+			gridBagConstraints2.ipadx = 0;
+			gridBagConstraints2.ipady = 0;
+			gridBagConstraints2.weightx = 1.0;
+			gridBagConstraints2.weighty = 1.0;
+			gridBagConstraints2.insets = new Insets(0, 10, 10, 10);
+			gridBagConstraints2.gridx = 0;
+			GridBagConstraints gridBagConstraints = new GridBagConstraints();
+			gridBagConstraints.insets = new Insets(5, 0, 5, 0);
+			gridBagConstraints.gridy = 0;
+			gridBagConstraints.gridx = 0;
+			jLabel = new JLabel();
+			jLabel.setText("Category:");
+			jPanel = new JPanel();
+			jPanel.setLayout(new GridBagLayout());
+			jPanel.add(jLabel, gridBagConstraints);
+			jPanel.add(getJScrollPane(), gridBagConstraints2);
+		}
+		return jPanel;
+	}
+
+	/**
+	 * This method initializes jPanel1
+	 * 
+	 * @return javax.swing.JPanel
+	 */
+	private JPanel getJPanel1() {
+		if (jPanel1 == null) {
+			GridBagConstraints gridBagConstraints8 = new GridBagConstraints();
+			gridBagConstraints8.insets = new Insets(0, 0, 1, 0);
+			gridBagConstraints8.gridy = 1;
+			gridBagConstraints8.ipadx = 419;
+			gridBagConstraints8.ipady = 0;
+			gridBagConstraints8.fill = GridBagConstraints.NONE;
+			gridBagConstraints8.gridx = 0;
+			GridBagConstraints gridBagConstraints7 = new GridBagConstraints();
+			gridBagConstraints7.fill = GridBagConstraints.BOTH;
+			gridBagConstraints7.gridy = 0;
+			gridBagConstraints7.ipadx = 55;
+			gridBagConstraints7.ipady = 0;
+			gridBagConstraints7.weightx = 1.0;
+			gridBagConstraints7.weighty = 1.0;
+			gridBagConstraints7.insets = new Insets(25, 0, 0, 10);
+			gridBagConstraints7.gridx = 0;
+			jLabel1 = new JLabel();
+			jLabel1.setText("Documentation:");
+			jLabel1.setVerticalAlignment(SwingConstants.TOP);
+			GridBagConstraints gridBagConstraints1 = new GridBagConstraints();
+			gridBagConstraints1.anchor = GridBagConstraints.EAST;
+			gridBagConstraints1.insets = new Insets(0, 150, 0, 0);
+			gridBagConstraints1.gridx = -1;
+			gridBagConstraints1.gridy = -1;
+			gridBagConstraints1.ipady = 0;
+			gridBagConstraints1.weightx = 1.0;
+			gridBagConstraints1.weighty = 1.0;
+			gridBagConstraints1.fill = GridBagConstraints.BOTH;
+			jPanel1 = new JPanel();
+			jPanel1.setLayout(new GridBagLayout());
+			jPanel1.add(getScrollPane(), gridBagConstraints7);
+			jPanel1.add(getJPanel2(), gridBagConstraints8);
+		}
+		return jPanel1;
+	}
+
+	/**
+	 * This method initializes jScrollPane
+	 * 
+	 * @return javax.swing.JScrollPane
+	 */
+	private JScrollPane getJScrollPane() {
+		if (jScrollPane == null) {
+			jScrollPane = new JScrollPane();
+			jScrollPane.setPreferredSize(new Dimension(100, 100));
+			jScrollPane.setViewportView(getKeyList());
+		}
+		return jScrollPane;
+	}
+
+	/**
+	 * This method initializes docArea
+	 * 
+	 * @return javax.swing.JTextArea
+	 */
+	private JTextArea getDocArea() {
+		if (docArea == null) {
+			docArea = new JTextArea();
+			docArea.setPreferredSize(new Dimension(0, 50));
+			docArea.setText("<select a value to see its documentation>");
+			docArea.setRows(2);
+			docArea.setLineWrap(true);
+			docArea.setEditable(false);
+		}
+		return docArea;
+	}
+
+	/**
+	 * This method initializes jPanel2
+	 * 
+	 * @return javax.swing.JPanel
+	 */
+	private JPanel getJPanel2() {
+		if (jPanel2 == null) {
+			GridBagConstraints gridBagConstraints6 = new GridBagConstraints();
+			gridBagConstraints6.fill = GridBagConstraints.HORIZONTAL;
+			gridBagConstraints6.gridy = 1;
+			gridBagConstraints6.ipadx = 0;
+			gridBagConstraints6.ipady = 21;
+			gridBagConstraints6.weightx = 1.0;
+			gridBagConstraints6.weighty = 1.0;
+			gridBagConstraints6.insets = new Insets(0, 0, 10, 10);
+			gridBagConstraints6.gridx = 1;
+			GridBagConstraints gridBagConstraints5 = new GridBagConstraints();
+			gridBagConstraints5.insets = new Insets(0, 0, 0, 0);
+			gridBagConstraints5.gridy = 0;
+			gridBagConstraints5.anchor = GridBagConstraints.WEST;
+			gridBagConstraints5.gridx = 1;
+			jPanel2 = new JPanel();
+			jPanel2.setLayout(new GridBagLayout());
+			jPanel2.add(jLabel1, gridBagConstraints5);
+			jPanel2.add(getDocArea(), gridBagConstraints6);
+		}
+		return jPanel2;
+	}
+
+} // @jve:decl-index=0:visual-constraint="10,10"

Added: trunk/src/appl/ext/ConfigurationEditorPlugin.java
===================================================================
--- trunk/src/appl/ext/ConfigurationEditorPlugin.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/ext/ConfigurationEditorPlugin.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,41 @@
+package appl.ext;
+
+import java.util.ResourceBundle;
+
+import appl.util.XuluFrameAdapter;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.gui.XuluInternalFrame;
+import edu.bonn.xulu.plugin.appl.AbstractMenuPlugin;
+import static edu.bonn.xulu.appl.XuluConstants.XULUGUI_RES;
+/**
+ * The configuration plug-in.
+ *
+ * @see XuluConfig
+ * @see ConfigurationEditorGUI
+ * @see ConfigurationEditorEngine
+ * @author Dominik Appl
+ */
+public class ConfigurationEditorPlugin extends AbstractMenuPlugin {
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see edu.bonn.xulu.plugin.appl.AbstractMenuPlugin#createPluginApplication()
+	 */
+
+	@Override
+	protected XuluInternalFrame createPluginApplication() throws Exception {
+		ConfigurationEditorGUI GUI = new ConfigurationEditorEngine().getGUI();
+		return new XuluFrameAdapter(XULUGUI_RES
+				.getString("Menu_Advanced_Preferences"), GUI);
+	}
+
+	/**
+	 *
+	 */
+	public ConfigurationEditorPlugin() {
+		super(4, XULUGUI_RES.getString("Menu_Advanced_Preferences"));
+
+	}
+
+}

Added: trunk/src/appl/ext/XuluConfig.java
===================================================================
--- trunk/src/appl/ext/XuluConfig.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/ext/XuluConfig.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,446 @@
+package appl.ext;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.geotools.io.DefaultFileFilter;
+
+/**
+ * Simple Property store, which is loaded at each Xulu start and saved at each
+ * Xulu exit. Every class or plugin can store and retrieve configuration
+ * information easy through a static method. To keep the property file readable
+ * and to avoid conflicts with other plugins please prefix the key-name with a
+ * unique name, which identifies your class, followed by a dot and the property.
+ * This is important for correct display in a User-GUI (which could be
+ * implemented). <br>
+ * <br>
+ * Keyformat: <code>domain.property</code> <br>
+ * Example key: <code>DiscoveryService.className</code> <br>
+ * <br>
+ * There could be no double entries.But you can save multiple values to one key
+ * using the {@link #setMultiProperty(String, String[]) setMultiProperty}
+ * method. <br>
+ * <b>These values are internally separated with ';', so see that you don't use
+ * ';' in your values of {@link #setMultiProperty(String, String[]) Multi
+ * Properties}</b> <br>
+ * <br>
+ * First the settings of the file "DefaultProperties" are loaded. After that the
+ * values are possibly overwritten by the loading of the file "XuluProperties"
+ * in which is intended to store a actual user configuration.
+ * <b>"DefaultPropoerties" should never be modified by the user.</b> The
+ * programmer should store all default values there. <br>
+ * <br>
+ * The user may change values through the {@link ConfigurationEditorGUI}.
+ *
+ * @see ConfigurationEditorGUI
+ * @see ConfigurationEditorEngine
+ * @author Dominik Appl
+ */
+public class XuluConfig {
+
+	private final String delimiter = ";";
+
+	// File for default values
+	File defaultFile = new File("DefaultProperties");
+
+	// File in which the props are stored
+	File file = new File("XuluProperties");
+
+	Properties propStore = null;
+
+	private static XuluConfig instance = null;
+
+        private XuluConfig() {
+          this(null);
+        }
+
+	private XuluConfig(File rootDir) {
+                if ( rootDir != null && rootDir.isDirectory() ) {
+                  defaultFile = new File(rootDir, defaultFile.getName());
+                  file        = new File(rootDir, file.getName());
+                }
+		// try to read defaults
+		Properties defaults = new Properties();
+		try {
+			defaults.load(new FileInputStream(defaultFile));
+		} catch (Exception e) {
+			System.out
+					.println("Warning: defaults could not be loaded from file '"
+							+ defaultFile + "'");
+			System.out.println(e.getMessage());
+		}
+		propStore = new Properties(defaults);
+		if (file.exists())
+			load();
+		else
+			store();
+	}
+
+        public static XuluConfig getXuluConfig() {
+          return getXuluConfig(null);
+        }
+
+	public static XuluConfig getXuluConfig(File rootDir) {
+		if (instance == null)
+			instance = new XuluConfig(rootDir);
+		return instance;
+	}
+
+	/**
+	 * Saves the configuration to the file system
+	 */
+	public void store() {
+		try {
+			propStore.store(new FileOutputStream(file),
+					"Stored properties of the Xulu modelling platform");
+		} catch (FileNotFoundException e) {
+			System.err.println("Could not write PropertyStore!!!");
+			e.printStackTrace();
+		} catch (IOException e) {
+			System.err.println("Could not write PropertyStore!!!");
+			e.printStackTrace();
+		}
+
+	}
+
+	/**
+	 * Sets the Property file. Notice that this has only an effect if you call
+	 * load afterwards.
+	 *
+	 * @param file
+	 */
+	public void setPropertyFile(File file) {
+		this.file = file;
+	}
+
+	/**
+	 * loads the Properties from the Propertyfile. No loaded values are deleted -
+	 * only existing ones are overwritten;
+	 */
+	public void load() {
+		try {
+			propStore.load(new FileInputStream(file));
+		} catch (FileNotFoundException e) {
+			System.err.println("Property file with name '" + file
+					+ "' not found");
+		} catch (IOException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * inserts the property value with the specified key into the
+	 * {@link XuluConfig}
+	 *
+	 * @param key
+	 *            the key
+	 * @param value
+	 *            the value associated with the key
+	 */
+	public void setProperty(String key, String value) {
+		if (!key.contains("."))
+			System.out
+					.println("WARNING for key "
+							+ key
+							+ ": Propertykeys in XuluConfig should have at least one '.' ! ");
+		propStore.setProperty(key, value);
+	}
+
+	/***************************************************************************
+	 * @return the property associated with the provided key. If not found the
+	 *         defaults are searched. If still not found, null is returned.
+	 *         Gives out a warning to console if the key was not found
+	 **************************************************************************/
+	public String getProperty(String key) {
+		String value = propStore.getProperty(key);
+		if (value == null)
+			System.err.println("Warning! Value for property '" + key
+					+ "' was not found in property file!");
+		return value;
+	}
+
+	/***************************************************************************
+	 * Same as {@link #getProperty(String)}, but you can disable the warning
+	 * message
+	 *
+	 * @param giveWarning
+	 *            if true, a warning is given to the console if the specified
+	 *            entry was not found
+	 * @return the property associated with the provided key. If not found the
+	 *         defaults are searched. If still not found, null is returned.
+	 *         Gives out a warning to console if the key was not found
+	 **************************************************************************/
+	public String getProperty(String key, boolean giveWarning) {
+		String value = propStore.getProperty(key);
+		if (value == null && giveWarning)
+			System.err.println("Warning! Value for property '" + key
+					+ "' was not found in property file!");
+		return value;
+	}
+
+	/***************************************************************************
+	 *
+	 * @return the property associated with the provided key as integer value.
+	 *         If not found the defaults are searched. If not found or the value
+	 *         is in a wrong format 0 is returned and a warning is given to the
+	 *         console
+	 **************************************************************************/
+	public int getIntProperty(String key) {
+		String value = propStore.getProperty(key);
+		if (value == null) {
+			System.err.println("Error! Value for property '" + key
+					+ "' was not found in property file!");
+			return 0;
+		}
+		int returnvalue = 0;
+		try {
+			returnvalue = Integer.valueOf(value);
+		} catch (java.lang.NumberFormatException e) {
+			System.err
+					.println("Error! Value for property '"
+							+ key
+							+ "' was not in the right format. Should be a Integer value! - Returning 0");
+		}
+		return returnvalue;
+	}
+
+	/***************************************************************************
+	 * @return the property associated with the provided key as double value. If
+	 *         not found the defaults are searched. If not found or the value is
+	 *         in a wrong format 0 is returned and a warning is given to the
+	 *         console
+	 **************************************************************************/
+	public double getDoubleProperty(String key) {
+		String value = propStore.getProperty(key);
+		if (value == null) {
+			System.err.println("Error! Value for property '" + key
+					+ "' was not found in property file!");
+			return 0;
+		}
+		double returnvalue = 0;
+		try {
+			returnvalue = Double.valueOf(value);
+		} catch (java.lang.NumberFormatException e) {
+			System.err
+					.println("Error! Value for property '"
+							+ key
+							+ "' was not in the right format. Should be a Integer value! - Returning 0");
+		}
+		return returnvalue;
+	}
+
+	/**
+	 * inserts the property value with the specified key into the
+	 * {@link XuluConfig}
+	 *
+	 * @param key
+	 *            the key
+	 * @param value
+	 *            the value associated with the key
+	 */
+	public void setBooleanProperty(String key, boolean value) {
+		this.setProperty(key, String.valueOf(value));
+	}
+
+	/**
+	 * inserts the property value with the specified key into the
+	 * {@link XuluConfig}
+	 *
+	 * @param key
+	 *            the key
+	 * @param value
+	 *            the value associated with the key
+	 */
+	public void setIntProperty(String key, int value) {
+		this.setProperty(key, String.valueOf(value));
+	}
+
+	/***************************************************************************
+	 * @return the property associated with the provided key as boolean value.
+	 *         If not found the defaults are searched. If still not found or
+	 *         null then false is returned. Gives out a warning to console if
+	 *         the key was not found
+	 **************************************************************************/
+	public boolean getBooleanProperty(String key) {
+		String value = propStore.getProperty(key);
+		if (value == null) {
+			System.err.println("Error! Value for property '" + key
+					+ "' was not found in property file!");
+			return false;
+		}
+		if(value.equals("1"))
+			return true;
+		boolean bool = false;
+		try {
+			bool = Boolean.valueOf(value);
+		} catch (Exception e) {
+			System.err.println("Error! Value for property '" + key
+					+ "' was not a valid boolean value");
+		}
+		return bool;
+	}
+
+	/**
+	 * A multiproperty stores multiple values for one key. These values are
+	 * internaly seperated with spaces, so see that you dont use spaces in your
+	 * values.
+	 *
+	 * @param key
+	 *            the key
+	 * @param values
+	 *            array of the values which should be associated with the key
+	 */
+	public void setMultiProperty(String key, String values[]) {
+		if (!key.contains("."))
+			System.out
+					.println("WARNING for key "
+							+ key
+							+ ": Propertykeys in XuluConfig should have at least one '.' ! ");
+		String value = "";
+		if (values != null)
+			for (String string : values) {
+				value += (string + delimiter);
+			}
+		propStore.setProperty(key, value);
+	}
+
+	/***************************************************************************
+	 * A multiproperty stores multiple values for one key. These values are
+	 * internaly seperated with ';', so do not use ';' in your values. if the
+	 * key was not found it gives out a warning to console and a empty array is
+	 * retured.
+	 *
+	 * @return the multiProperty associated with the provided key, which is in
+	 *         this case just a String array
+	 **************************************************************************/
+
+	public String[] getMultiProperty(String key) {
+		String value = propStore.getProperty(key);
+		if (value != null)
+			return value.split(delimiter);
+		System.err.println("Error! Value for property '" + key
+				+ "' was not found in property file!");
+		return new String[0];
+	}
+
+	/**
+	 * removes the Property from the list
+	 *
+	 * @param key
+	 */
+	public void removeProperty(String key) {
+		propStore.remove(key);
+	}
+
+	/**
+	 * removes all keys starting with the value given. USE WITH CAUTION! If you
+	 * give a String "a" all entrys starting with "a" will be removed from the
+	 * registry
+	 *
+	 * @param key
+	 */
+	public void removeAll(String key) {
+		if (key == null)
+			return;
+
+		Enumeration keys = propStore.propertyNames();
+		while (keys.hasMoreElements()) {
+			String propKey = (String) keys.nextElement();
+			if (propKey == null)
+				continue;
+			if (propKey.startsWith(key))
+				propStore.remove(propKey);
+		}
+	}
+
+	/**
+	 * Gets all prefixes. A Prefix is the string of all characters up to the
+	 * first dot. A Suffix is the string of all characters following this dot.
+	 *
+	 * @return the prefixes
+	 *
+	 */
+	public Set<String> getPrefixes() {
+		TreeSet set = new TreeSet();
+		Enumeration keys = propStore.propertyNames();
+		while (keys.hasMoreElements()) {
+			String propKey = (String) keys.nextElement();
+			String[] strings = propKey.split("\\.");
+			set.add(strings[0]);
+		}
+		return set;
+	}
+
+	/**
+	 * Gets all suffixes for one prefix. A Prefix is the string of all
+	 * characters up to the first dot. A Suffix is the string of all characters
+	 * following this dot. The Strings are ordered alphabeticly
+	 *
+	 * @param prefix
+	 *            the prefix.
+	 */
+	public Set<String> getSuffixesOfPrefix(String prefix) {
+		TreeSet set = new TreeSet();
+		Enumeration keys = propStore.propertyNames();
+		while (keys.hasMoreElements()) {
+			String propKey = (String) keys.nextElement();
+			String[] strings = propKey.split("\\.");
+			if (strings.length > 1 && strings[0].equals(prefix))
+				set.add(propKey.substring(strings[0].length() + 1));
+		}
+		return set;
+	}
+
+	/**
+	 * Gets all entries starting with the given {@link String}
+	 *
+	 * @param startingString
+	 *            the prefixstring
+	 * @return all keys starting the given prefix
+	 */
+	public Set<String> getKeysStartingWith(String startingString) {
+		TreeSet set = new TreeSet();
+		Enumeration keys = propStore.propertyNames();
+		while (keys.hasMoreElements()) {
+			String propKey = (String) keys.nextElement();
+			if (propKey.startsWith(startingString))
+				set.add(propKey);
+		}
+		return set;
+	}
+
+	/**
+	 * Just for testing.
+	 *
+	 * @deprecated
+	 */
+	public static void main(String[] args) {
+		XuluConfig config = XuluConfig.getXuluConfig();
+		config.setProperty("atest2", "test3");
+		config.setProperty("test4.testproperty", "test");
+		String[] multiTest = { "value1", "value2", "value3" };
+		config.setMultiProperty("multiproperty.1", multiTest);
+		String[] multioutput = config.getMultiProperty("multiproperty.1");
+		for (String string : multioutput) {
+			System.out.println("Multivalue: " + string);
+		}
+		config.store();
+		config.setPropertyFile(new File("XuluTestfile"));
+		config.load();
+		String[] multiTest2 = { "value1", "value2", "value3" };
+		config.setMultiProperty("multiproperty.2", multiTest);
+		config.removeAll("multiproperty");
+		config.removeProperty("atest2");
+		config.store();
+	}
+}

Added: trunk/src/appl/ext/package.html
===================================================================
--- trunk/src/appl/ext/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/ext/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,6 @@
+<html>
+<body>
+	At the moment this classes contains only classes related to the Configuration Editor in Xulu. 
+	Beside the plugin functionality in the ConfigurationEditorPlugin-class it is independent of Xulu itself and may be used in other projects.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/package.html
===================================================================
--- trunk/src/appl/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,8 @@
+<html>
+<body>
+	In diesem Paket können sämtliche benutzerdefinierten Komponenten für die
+	Xulu-Modelling-Platform implementiert werden.
+	z.B. Benutzerdefinierte Datentypen in {@link edu.bonn.xulu.plugin.data edu.bonn.xulu.plugin.data}
+	und die dazugehörigen Factorys in {@link edu.bonn.xulu.plugin.data edu.bonn.xulu.plugin.io}.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/parallel/ComputingResource.java
===================================================================
--- trunk/src/appl/parallel/ComputingResource.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/ComputingResource.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,64 @@
+package appl.parallel;
+
+import java.rmi.RemoteException;
+import java.util.HashMap;
+import java.util.Vector;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.gui.ModelControlFrame;
+
+import appl.parallel.spmd.SPMDTask;
+import appl.parallel.spmd.split.SinglePartitionInfo;
+import appl.parallel.spmd.split.SplitMap;
+import appl.parallel.spmd.split.SplittableResource;
+
+/**
+ * This is the base class for remote computing resources, which could be
+ * displayed e.g. in the {@link ModelControlFrame} of the
+ * {@link XuluModellingPlatform}. It provides very basic functionality like
+ * connecting, disconnecting or pinging. Also it provides a flag saying if the
+ * resource is available for computation (or e.g. in use).
+ *
+ * @author Dominik Appl
+ */
+public interface ComputingResource extends java.rmi.Remote {
+
+	/**
+	 * Should return Information about the ComputingResource. This Information
+	 * is primary used to display infos to the user.
+	 */
+	public ComputingResourceProperties getResourceInformation()
+			throws RemoteException;
+
+	/**
+	 * Can be used to ping the object
+	 *
+	 * @param o
+	 *            the object to ping with
+	 * @return the same object
+	 * @throws RemoteException
+	 */
+	public Object ping(Object... o) throws RemoteException;
+
+	/**
+	 * tries to connect to the resource
+	 *
+	 * @return true for success
+	 * @throws RemoteException
+	 */
+	public boolean connect() throws RemoteException;
+
+	/**
+	 * disconnects from the resource
+	 *
+	 * @throws RemoteException
+	 */
+	public void disconnect() throws RemoteException;
+
+	/**
+	 * @return true, if the resource is available for computation (may return
+	 *         false, if the resource is used by another client)
+	 * @throws RemoteException
+	 */
+	public boolean isAvailable() throws RemoteException;
+}

Added: trunk/src/appl/parallel/ComputingResourceContainer.java
===================================================================
--- trunk/src/appl/parallel/ComputingResourceContainer.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/ComputingResourceContainer.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,53 @@
+package appl.parallel;
+
+
+/**
+ * Encapsulates {@link ComputingResource ComputingResources} and their meta
+ * Information (for fast access)
+ *
+ * @author Dominik Appl
+ */
+public class ComputingResourceContainer {
+
+	private final ComputingResource resource;
+
+	private final ComputingResourceProperties information;
+
+	private boolean supportsSimpleRemoteExecution = false;
+
+	/**
+	 * @param resource
+	 * @param information
+	 */
+	public ComputingResourceContainer(ComputingResource resource,
+			ComputingResourceProperties information) {
+		this.resource = resource;
+		this.information = information;
+	}
+
+	/**
+	 * @return the information
+	 */
+	public ComputingResourceProperties getInformation() {
+		return information;
+	}
+
+	/**
+	 * @return the resource
+	 */
+	public ComputingResource getResource() {
+		return resource;
+	}
+
+	public String toString() {
+		if (information != null)
+			return information.getProperty("Name");
+		else
+			return "Unknown Resource(No Information available)";
+	}
+
+	public boolean supportsSimpleRemoteExecution() {
+		return supportsSimpleRemoteExecution;
+	}
+
+}

Added: trunk/src/appl/parallel/ComputingResourceProperties.java
===================================================================
--- trunk/src/appl/parallel/ComputingResourceProperties.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/ComputingResourceProperties.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,62 @@
+package appl.parallel;
+
+import java.io.Serializable;
+import java.util.Properties;
+
+/**
+ * Information about a {@link ComputingResource}. All entries may return
+ * <code>null</code> if no information is available. Notice that the 
+ * information represents the state of the remote Object at the time it was
+ * created. So it may be outdated. The following Properties should be available
+ * on all systems <br>
+ * <ul>
+ * <li>ActiveModel</li>
+ * <li>isAvailable - says if the resource is currently available for use</li>
+ * <li>SystemInformation - Identifies the current System/OS</li>
+ * <li>Name - a name which will be displayed to the user</li>
+ * <li>IP - the IP address of the Object<br>
+ * </li>
+ * </ul>
+ * <br>
+ * 
+ * @author Dominik Appl
+ */
+public interface ComputingResourceProperties extends Serializable {
+
+	Properties getProperties();
+
+	/**
+	 * Sets a property
+	 * @param key the key
+	 * @param value the value
+	 */
+	public void setProperty(String key, String value);
+
+	/**
+	 * 
+	 * @param key the key
+	 * @return the property property associated with that key or null if not found
+	 */
+	public String getProperty(String key);
+
+	/**
+	 * @return the name of the resource (usually the hostname)
+	 */
+	public String getName();
+
+	/**
+	 * @return says if the resource is available for computation (of in use).
+	 */
+	public boolean isAvailable();
+
+	/**
+	 * @return the ip of the resource
+	 */
+	public String getIP();
+
+	/**
+	 * @return port the resouce is bound to
+	 */
+	public String getPort();
+
+}

Added: trunk/src/appl/parallel/SimpleResourceProperties.java
===================================================================
--- trunk/src/appl/parallel/SimpleResourceProperties.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/SimpleResourceProperties.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,134 @@
+package appl.parallel;
+
+import java.io.Serializable;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryPoolMXBean;
+import java.lang.management.MemoryUsage;
+import java.lang.management.ThreadMXBean;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * Sets the following properties: <br>
+ * <br>
+ * Maximum Java Memory <br>
+ * Free Java Memory<br>
+ * System Information<br>
+ * System Architecture<br>
+ * System Version<br>
+ * Hostname<br>
+ * IP<br>
+ * 
+ * @see ComputingResourceProperties
+ * @author Dominik Appl
+ */
+public class SimpleResourceProperties implements ComputingResourceProperties,
+		Serializable {
+
+	protected Properties properties = new Properties();
+
+	public SimpleResourceProperties() {
+		java.net.InetAddress i;
+		try {
+			i = java.net.InetAddress.getLocalHost();
+			properties.setProperty("Hostname", i.getHostName());
+
+			// also the DefaultName of the machine, if not specified
+			properties.setProperty("Name", i.getHostName());
+			properties.setProperty("IP", i.getHostAddress());
+		} catch (UnknownHostException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		properties.setProperty("Memory Maximum", ""
+				+ getFormatedMemoryString(Runtime.getRuntime().maxMemory()));
+		properties.setProperty("Memory Free", ""
+				+ getFormatedMemoryString(Runtime.getRuntime().freeMemory()));
+		properties.setProperty("Memory Used", ""
+				+ getFormatedMemoryString(getUsedMemory()));
+		properties.setProperty("Operating System", System
+				.getProperty("os.name"));
+		properties.setProperty("System Architecture", System
+				.getProperty("os.arch"));
+		properties.setProperty("System Version", System
+				.getProperty("os.version"));
+		properties.setProperty("Available Processors", Runtime.getRuntime()
+				.availableProcessors()
+				+ "");
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.ComputingResourceProperties#getProperties()
+	 */
+	public Properties getProperties() {
+		return properties;
+	}
+
+	protected long getUsedMemory() {
+		ThreadMXBean tb = ManagementFactory.getThreadMXBean();
+		List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans();
+		long sum = 0;
+		for (MemoryPoolMXBean pool : pools) {
+			MemoryUsage peak = pool.getPeakUsage();
+			sum += peak.getUsed();
+		}
+		return sum;
+	}
+
+	protected String getFormatedMemoryString(long bytes) {
+		long mb = bytes / (1024 * 1024);
+		long kb = bytes / 1024 - (mb * 1024);
+		// only the first char of kb
+		kb = kb / 100;
+		return mb + "." + kb + " MB";
+
+	}
+
+	/*
+	 * (non-Javadoc) only indirection
+	 * 
+	 * @see appl.parallel.ComputingResourceProperties#getProperty(java.lang.String)
+	 */
+	public String getProperty(String key) {
+		return properties.getProperty(key);
+	}
+
+	/*
+	 * (non-Javadoc) only indirection
+	 * 
+	 * @see appl.parallel.ComputingResourceProperties#setProperty(java.lang.String,
+	 *      java.lang.String)
+	 */
+	public void setProperty(String key, String value) {
+		properties.setProperty(key, value);
+	}
+
+	public String toString() {
+		return getProperty("Name");
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.ComputingResourceProperties#getName()
+	 */
+	public String getName() {
+		return getProperty("Name");
+	}
+
+	public boolean isAvailable() {
+		return getProperty("isAvailable").equals("true");
+	}
+
+	public String getIP() {
+		return getProperty("IP");
+	}
+
+	public String getPort() {
+		return getProperty("Port");
+	}
+}

Added: trunk/src/appl/parallel/client/ClientDataServer.java
===================================================================
--- trunk/src/appl/parallel/client/ClientDataServer.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/client/ClientDataServer.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,200 @@
+package appl.parallel.client;
+
+import java.awt.Rectangle;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.rmi.AccessException;
+import java.rmi.NotBoundException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.ServerNotActiveException;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.HashMap;
+import java.util.Hashtable;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import appl.ext.XuluConfig;
+import appl.parallel.event.CommEvent;
+import appl.parallel.event.CommEventSink;
+import appl.parallel.event.TransferEvent;
+import appl.parallel.event.CommEvent.CommType;
+import appl.parallel.spmd.split.DataPartition;
+import appl.parallel.util.Helper;
+// fuer Doku
+import javax.activation.DataHandler;
+import appl.parallel.server.PartitionDataServer;
+import appl.parallel.server.XuluServer;
+import appl.parallel.spmd.split.SplittableResource;
+
+/**
+ * This class is used for storing all data which is needed for parallelization
+ * and may be requested remotely. On {@link DataPartition DataPartitions} the
+ * request of partitions is supported. {@link PartitionDataServer}s running on
+ * {@link XuluServer}s will typically use {@link DataHandler DataHandlers} for
+ * retrieving the partitions.
+ *
+ * @see PartitionDataServer
+ * @author Dominik Appl
+ */
+public class ClientDataServer extends UnicastRemoteObject implements DataServer {
+
+	protected final Logger LOG = LogManager
+			.getLogger(this.getClass().getName());
+
+	private final String bindingName = "DataServer";
+
+	// for retrieval with the baseID
+	private Hashtable<Integer, DataPartition> dataByID;
+
+	HashMap<String, String> hostnames = new HashMap<String, String>(10);
+
+	private int registryPort = 1099;
+
+	private final CommEventSink eventSink;
+
+	/**
+	 * The standard Constructor (binds itself to the running registry)
+	 *
+	 * @param eventSink
+	 *            the sink is used for generating events
+	 * @throws RemoteException
+	 *             if the connection fails
+	 */
+	public ClientDataServer(CommEventSink eventSink) throws RemoteException {
+		this.eventSink = eventSink;
+		dataByID = new Hashtable<Integer, DataPartition>();
+
+		// bind to the registry - create a new reg, if no reg is found
+		try {
+			// try to get port from registry
+			int port = XuluConfig.getXuluConfig().getIntProperty(
+					"XuluClient.registryport");
+			if (port != 0)
+				registryPort = port;
+			Helper.bind(bindingName, this, registryPort);
+		} catch (Exception e) {
+			LOG.error("Error while binding SPMDClient to the registry."
+					+ e.getMessage());
+		}
+		LOG.info("DataServer up and running....");
+	}
+
+	/**
+	 * Returns the data identified by the given id
+	 *
+	 * @param baseID
+	 *            Id identifiying the data
+	 * @see SplittableResource#getRootID()
+	 */
+	public DataPartition getData(int baseID) throws RemoteException {
+		DataPartition result = dataByID.get(baseID);
+		if (LOG.isDebugEnabled())
+			LOG.debug("Data retrieved from SPMDClient: ID:" + baseID);
+
+		// generate transfer event. Notice that this is very slow and
+		// will therefore only be created if a listener has registered
+		if (eventSink.isTransferMonitoringEnabled()) {
+			try {
+				// try to get Hostname (for performance reasons this is done
+				// only one time)
+				String hostIP = getClientHost();
+				// check if already looked up;
+				String hostname = hostnames.get(hostIP);
+				if (hostname == null) {
+					hostname = InetAddress.getByName(hostIP).getHostName();
+					hostnames.put(hostIP, hostname);
+				}
+				eventSink.fireRemoteEvent(new TransferEvent("DataServer",
+						hostname, CommType.TRANSFER_DATA, result));
+			} catch (ServerNotActiveException e) {
+				// if this is a purely local call no event
+				// should be generated.
+			} catch (UnknownHostException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * DataPartitions can be added
+	 *
+	 * @see appl.parallel.client.DataServer#addData(appl.parallel.spmd.split.DataPartition)
+	 */
+	public void addData(DataPartition splittable) {
+		this.dataByID.put(splittable.getRootID(), splittable);
+	}
+
+	/**
+	 * stops the client and removes it from the registry
+	 */
+	public void close() {
+		Helper.unbind(bindingName);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.server.PartitionDataServer#getPartition(int,
+	 *      java.awt.Rectangle)
+	 */
+	public DataPartition getPartition(int id, Rectangle bounds)
+			throws RemoteException {
+		DataPartition data = (DataPartition) dataByID.get(id);
+		if (data == null && LOG.isDebugEnabled()) {
+			LOG.error("Partition with id " + id + " and bounds " + bounds
+					+ "was requested but not found on SPMDClient");
+			return null;
+		}
+		DataPartition result = data.getPartition(bounds);
+		if (eventSink.isTransferMonitoringEnabled()) {
+			try {
+				eventSink.fireRemoteEvent(new TransferEvent("DataServer",
+						getClientHost(), CommType.TRANSFER_DATA, result));
+			} catch (ServerNotActiveException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+		}
+		if (LOG.isDebugEnabled())
+			LOG.debug("Data retrieved from SPMDClient: ID:" + id
+					+ " partition: " + bounds);
+		return result;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.server.PartitionDataServer#setPartition(int,
+	 *      appl.parallel.spmd.split.DataPartition, java.awt.Rectangle)
+	 */
+	public void updatePartition(int id, DataPartition partition,
+			Rectangle bounds) throws RemoteException {
+		DataPartition data = (DataPartition) dataByID.get(id);
+		if (data == null && LOG.isDebugEnabled()) {
+			LOG.error("Partition of data with id " + id + " and bounds "
+					+ bounds + "should be set but was not found on SPMDClient");
+			return;
+		}
+		data.setPartition(partition, bounds);
+		if (LOG.isDebugEnabled())
+			LOG.debug("Partition set on SPMDClient with id " + id
+					+ " and partition bounds: " + bounds);
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.client.DataServer#removeData(int)
+	 */
+	public void removeData(int id) {
+		dataByID.remove(id);
+	}
+
+}

Added: trunk/src/appl/parallel/client/DataServer.java
===================================================================
--- trunk/src/appl/parallel/client/DataServer.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/client/DataServer.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,84 @@
+package appl.parallel.client;
+
+import java.awt.Rectangle;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+import appl.parallel.event.CommEvent;
+import appl.parallel.event.CommEventSink;
+import appl.parallel.server.PartitionDataServer;
+import appl.parallel.spmd.split.DataPartition;
+import appl.parallel.spmd.split.SplittableResource;
+
+/**
+ * A {@link DataServer} shares resources over a network. For
+ * {@link SplittableResource}s it allows also the retrieval of
+ * {@link DataPartition}s. The data is retrieved using a unique id identifying
+ * the resource.
+ *
+ * @author Dominik Appl
+ */
+public interface DataServer extends Remote {
+
+	/**
+	 * gets the data with the id of a SplittableRessource
+	 *
+	 * @param id
+	 *            the {@link SplittableResource#getRootID() ID} of a the base
+	 *            data
+	 * @param bounds
+	 *            the bounds of the partition to retrieve (using global
+	 *            coordinates)
+	 * @return the partition
+	 * @throws RemoteException
+	 */
+	public DataPartition getPartition(int id, Rectangle bounds)
+			throws RemoteException;
+
+	/**
+	 * sets the data with the id of a SplittableRessource
+	 *
+	 * @param id
+	 *            the {@link SplittableResource#getRootID() ID} of a the base
+	 *            data
+	 * @param bounds
+	 *            the location where the partition is to be updated (using
+	 *            global coordinates)
+	 * @param updateData
+	 *            the updateData (which may only a partitial update, depending
+	 *            on the bounds set with the last parameter)
+	 * @throws RemoteException
+	 */
+	public void updatePartition(int id, DataPartition updateData,
+			Rectangle bounds) throws RemoteException;
+
+	/**
+	 * Returns the whole Partition with the given ID
+	 *
+	 * @param id
+	 *            the id of the partition
+	 * @return the partition
+	 * @throws RemoteException
+	 *             if the connection to the server fails
+	 */
+	public DataPartition getData(int id) throws RemoteException;
+
+	/**
+	 * Adds a Partition to the server
+	 *
+	 * @param partition
+	 *            the partition to add
+	 * @throws RemoteException
+	 */
+	public void addData(DataPartition partition) throws RemoteException;
+
+	/**
+	 * Removes the partition with the specified id.
+	 *
+	 * @param id
+	 *            id of the partition to remove
+	 * @throws RemoteException
+	 */
+	public void removeData(int id) throws RemoteException;
+
+}

Added: trunk/src/appl/parallel/client/RemoteEventHandler.java
===================================================================
--- trunk/src/appl/parallel/client/RemoteEventHandler.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/client/RemoteEventHandler.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,225 @@
+package appl.parallel.client;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.Vector;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import appl.ext.XuluConfig;
+import appl.parallel.event.CommEvent;
+import appl.parallel.event.CommEventSink;
+import appl.parallel.event.RemoteEvent;
+import appl.parallel.event.RemoteEventSink;
+import appl.parallel.event.TimeEvent;
+import appl.parallel.event.TimeMonitor;
+import appl.parallel.event.TransferEvent;
+import appl.parallel.event.TransferMonitor;
+import appl.parallel.services.Service;
+import appl.parallel.util.Helper;
+
+/**
+ * Starts a Service for receiving local and remote events. Monitors can register
+ * to this service. All events are forwarded the registered listeners. The
+ * service tries to get info for registry port from property
+ * <code>XuluClient.registryport</code> in {@link XuluConfig}.
+ * 
+ * @author Dominik Appl
+ */
+public class RemoteEventHandler extends UnicastRemoteObject implements Service,
+		CommEventSink {
+
+	private final Logger LOG = LogManager.getLogger(this.getClass().getName());
+
+	// defaults
+	private String bindingName = "RemoteEventReceiver";
+
+	private int registryPort = 1099;
+
+	private Vector<TimeMonitor> timeMonitors = new Vector<TimeMonitor>();
+
+	private Vector<TransferMonitor> transferMonitors = new Vector<TransferMonitor>();
+
+	private boolean timeMonitoring = false;
+
+	private boolean transferMonitoring = false;
+
+	private boolean isRunning;
+
+	/**
+	 * @throws RemoteException
+	 * @throws RemoteException
+	 *             if binding fails
+	 */
+	public RemoteEventHandler() throws RemoteException {
+		super();
+		isRunning = false;
+	}
+
+	/**
+	 * tries to bind to a running registry or creates one.
+	 * 
+	 * @throws RemoteException
+	 *             if binding fails
+	 */
+	private void bind() throws RemoteException {
+		// try to get port from registry
+		int port = XuluConfig.getXuluConfig().getIntProperty(
+				"XuluClient.registryport");
+		if (port != 0)
+			registryPort = port;
+		// bind it
+		CommEventSink sink = this;
+		Helper.bind(bindingName, sink, registryPort);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.services.Service#isRunning()
+	 */
+	public boolean isRunning() {
+		return isRunning;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.services.Service#startService()
+	 */
+	public void startService() {
+		try {
+			bind();
+		} catch (RemoteException e) {
+			LOG.error("Could not bind " + bindingName
+					+ " to the registry! Eventsystem will fail.");
+		}
+		isRunning = true;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.services.Service#stopService()
+	 */
+	public void stopService() {
+		unbind();
+		isRunning = false;
+	}
+
+	/**
+	 * unbinds the Service
+	 */
+	private void unbind() {
+		Helper.unbind(bindingName);
+	}
+
+	public void fireRemoteEvent(TimeEvent t) throws RemoteException {
+		for (TimeMonitor timeMonitor : timeMonitors) {
+			timeMonitor.receiveTimeEvent(t);
+		}
+	}
+
+
+	public void fireRemoteEvent(TransferEvent t) throws RemoteException {
+		for (TransferMonitor transferMonitor : transferMonitors) {
+			transferMonitor.receiveTransferEvent(t);
+		}
+	}
+
+	
+
+	/**
+	 * Adds a new time monitor
+	 * 
+	 * @param monitor
+	 *            a time monitor
+	 */
+	public void addTimeEventListener(TimeMonitor monitor) {
+		if (monitor != null) {
+			timeMonitors.add(monitor);
+			timeMonitoring = true;
+		}
+	}
+
+	/**
+	 * Adds a new {@link TransferMonitor}
+	 * 
+	 * @param monitor
+	 *            a time monitor
+	 */
+	public void addTransferEventListener(TransferMonitor monitor) {
+		if (monitor != null) {
+			transferMonitors.add(monitor);
+			transferMonitoring = true;
+		}
+	}
+
+	/**
+	 * removes the given monitor
+	 * 
+	 * @param monitor
+	 */
+	public void removeTimeMonitor(TimeMonitor monitor) {
+		timeMonitors.remove(monitor);
+		if (timeMonitors.size() == 0)
+			timeMonitoring = false;
+	}
+
+	/**
+	 * adds the given Monitor
+	 * 
+	 * @param monitor
+	 */
+	public void removeTransferMonitor(TransferMonitor monitor) {
+		transferMonitors.remove(monitor);
+		if (transferMonitors.size() == 0)
+			transferMonitoring = false;
+
+	}
+
+	/**
+	 * @return true if the service is running and time monitoring is enabled
+	 */
+	public boolean isTimeMonitoringEnabled() throws RemoteException {
+		return timeMonitoring;
+	}
+
+	/**
+	 * @return true if the service is running and transfer monitoring is enabled
+	 */
+	public boolean isTransferMonitoringEnabled() throws RemoteException {
+		return transferMonitoring;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.event.RemoteEventSink#fireRemoteEvent(appl.parallel.event.RemoteEvent)
+	 */
+	public void fireRemoteEvent(RemoteEvent e) throws RemoteException {
+		if (e instanceof TimeEvent)
+			fireRemoteEvent((TimeEvent) e);
+		else if (e instanceof TransferEvent)
+			fireRemoteEvent((TransferEvent) e);
+		else
+			// All events should be handled properly
+			System.err.println("Received unknown event of class "
+					+ e.getClass().getName());
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.event.RemoteEventSink#fireRemoteEvents(appl.parallel.event.RemoteEvent[])
+	 */
+	public void fireRemoteEvents(RemoteEvent[] e) throws RemoteException {
+		for (RemoteEvent event : e) {
+			fireRemoteEvent(event);
+		}
+	}
+
+}

Added: trunk/src/appl/parallel/client/RemoteExecutionController.java
===================================================================
--- trunk/src/appl/parallel/client/RemoteExecutionController.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/client/RemoteExecutionController.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,370 @@
+package appl.parallel.client;
+
+import java.io.IOException;
+import java.rmi.RemoteException;
+import java.util.Iterator;
+import java.util.Vector;
+
+import javax.swing.JOptionPane;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+import org.apache.log4j.lf5.StartLogFactor5;
+
+import com.sun.jini.tool.ClassServer;
+
+import appl.ext.XuluConfig;
+import appl.parallel.ComputingResource;
+import appl.parallel.ComputingResourceContainer;
+import appl.parallel.ComputingResourceProperties;
+import appl.parallel.model.ParallelStepModel;
+import appl.parallel.server.XuluServer;
+import appl.parallel.services.DiscoveryService;
+import appl.parallel.services.GlobalDiscoveryService;
+import appl.parallel.spmd.AdvancedSPMDClientController;
+import appl.parallel.spmd.SPMDClientController;
+import appl.parallel.spmd.SPMDClientInterface;
+import appl.parallel.spmd.split.SplitMap;
+import appl.parallel.util.Helper;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.XuluPlugin;
+import edu.bonn.xulu.model.AbstractStepModel;
+import edu.bonn.xulu.model.XuluModel;
+import schmitzm.lang.AbstractNamedObject;
+
+/**
+ * This plugin is responsible that all services required for remote
+ * execution are properly started. It first starts the
+ * {@link GlobalDiscoveryService}. Then it uses the following entries of
+ * {@link XuluConfig} for configuration: <br>
+ * <br>
+ * <code>RemoteExecutionController.spmd.start</code> - if, <code>true</code>
+ * the {@link ClientDataServer} is started. <br><br>
+ * <code>RemoteExecutionController.http.start</code> - if, <code>true</code>
+ * the {@link ClassServer HTTP-Class server} is started. <br><br>
+ * <code>RemoteExecutionController.startLocalXuluServer</code> - if,
+ * <code>true</code> a local {@link XuluServer} is started. <br>.
+ * 
+ * @author Dominik Appl
+ */
+public class RemoteExecutionController extends AbstractNamedObject implements
+		XuluPlugin {
+
+	private final Logger LOG = LogManager.getLogger(this.getClass().getName());
+
+	private ClientDataServer spmdClient;
+
+	private boolean started = false;
+
+	private XuluServer localServer;
+
+	private ClassServer httpServer;
+
+	private RemoteEventHandler eventHandlerProxy;
+
+	private GlobalDiscoveryService discoveryService;
+
+	private boolean startHTTP = false;
+
+	private boolean startSPMD = false;
+
+	private boolean startXuluServer = false;
+
+	private boolean httpVerbose = false;
+
+	private int httpPort = 80;
+
+	private String httpBaseDir = ".\\classes"; //default: will be overwritten with the configuration
+	
+	private Vector<ResourceChangeListener> activeChangeListeners = new Vector<ResourceChangeListener>();
+
+	private Vector<ComputingResourceContainer> lastKnownResources;
+	
+	public RemoteExecutionController() {
+		startDiscovery();
+	}
+
+	/**
+	 * Starts the Plugin
+	 * 
+	 * @see edu.bonn.xulu.appl.XuluPlugin#execute(edu.bonn.xulu.XuluModellingPlatform)
+	 */
+	public void execute(XuluModellingPlatform appl) {
+		started = true;
+		loadConfig();
+		startEventSystem();
+		startSPMDClient();
+		startXuluServer();
+		startDiscovery();
+		startHTTPServer();
+		//discover own server
+		refreshResources();
+	}
+
+	private void startEventSystem() {
+		// start EventProxy
+		try {
+			eventHandlerProxy = new RemoteEventHandler();
+			eventHandlerProxy.startService();
+		} catch (RemoteException e1) {
+			// TODO Auto-generated catch block
+			e1.printStackTrace();
+		}
+	}
+
+	private void startDiscovery() {
+		if (discoveryService != null)
+			discoveryService.stopService();
+		discoveryService = new GlobalDiscoveryService();
+	}
+
+	/**
+	 * Load the configuration form the {@link XuluConfig}
+	 */
+	private void loadConfig() {
+		XuluConfig config = XuluConfig.getXuluConfig();
+		startSPMD = config
+				.getBooleanProperty("RemoteExecutionController.spmd.start");
+		startXuluServer = config
+				.getBooleanProperty("RemoteExecutionController.startlocalxuluserver");
+		startHTTP = config
+				.getBooleanProperty("RemoteExecutionController.http.start");
+		httpVerbose = config
+				.getBooleanProperty("RemoteExecutionController.http.verbose");
+		if (config.getIntProperty("RemoteExecutionController.http.port") != 0)
+			httpPort = config
+					.getIntProperty("RemoteExecutionController.http.port");
+		if (config.getProperty("RemoteExecutionController.http.basedir") != null)
+			httpBaseDir = config
+					.getProperty("RemoteExecutionController.http.basedir");
+	}
+
+	private void startHTTPServer() {
+		// start the http server
+		if (startHTTP) {
+			try {
+				httpServer = new ClassServer(httpPort, httpBaseDir, true,
+						httpVerbose);
+				httpServer.start();
+			} catch (IOException e) {
+				LOG.error("Could not create HTTP-Server!", e);
+				e.printStackTrace();
+			}
+		}
+	}
+
+	private void startSPMDClient() {
+		try {
+			if (startSPMD)
+				spmdClient = new ClientDataServer(eventHandlerProxy);
+		} catch (RemoteException e) {
+			LOG.error("SPMD Client could NOT be started. " + e.getMessage());
+			e.printStackTrace();
+		}
+	}
+
+	private void startXuluServer() {
+		try {
+			if (startXuluServer)
+				localServer = new XuluServer(false, spmdClient);
+		} catch (RemoteException e) {
+			LOG.error("XuluServer could NOT be started. " + e.getMessage());
+			e.printStackTrace();
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see edu.bonn.xulu.appl.XuluPlugin#isStarted()
+	 */
+	public boolean isStarted() {
+		return started;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see edu.bonn.xulu.appl.XuluPlugin#isVisible()
+	 */
+	public boolean isVisible() {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see edu.bonn.xulu.appl.XuluPlugin#setVisible(boolean)
+	 */
+	public void setVisible(boolean visible) {
+		// TODO Auto-generated method stub
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see edu.bonn.xulu.appl.XuluPlugin#stop()
+	 */
+	public void stop() {
+		started = false;
+		if (httpServer != null)
+			httpServer.stop();
+		if (spmdClient != null)
+			spmdClient.close();
+		spmdClient = null;
+		if (localServer != null)
+			localServer.stopServer();
+		spmdClient = null;
+		eventHandlerProxy.stopService();
+	}
+
+	/**
+	 * Gets active Resources and triggers the discovery-process. After
+	 * the resources are found an update is called on all registered 
+	 * {@link ResourceChangeListener}s.
+	 * 	 * 
+	 */
+	public void refreshResources() {
+		Vector<ComputingResourceContainer> remoteResources = discoveryService
+				.getRemoteResources();
+		
+		lastKnownResources = remoteResources;
+		//notify listeners about the resource update
+		for (ResourceChangeListener listener : activeChangeListeners) {
+			listener.updateResources(remoteResources);
+		}
+
+		// The advanced Server still makes some problems and therefore is here
+		// deactivated. May be fixed later.
+		// try {
+		// if(localServer!=null){
+		// ComputingResourceProperties localInfo =
+		// localServer.getResourceInformation();
+		// localInfo.setProperty("Name", "Advanced Internal Server");
+		// remoteResources.add(new ComputingResourceContainer(localServer,
+		// localInfo));
+		// }
+		//				
+		// } catch (RemoteException e) {
+		// // TODO Auto-generated catch block
+		// e.printStackTrace();
+		// }
+	}
+	
+	
+	/**
+	 * adds the change lister
+	 * 
+	 * @param r the change listener
+	 */
+	public void addResourceChangeListener(ResourceChangeListener r){
+		activeChangeListeners.add(r);
+	}
+	
+	/**
+	 * Removes the change listener
+	 * @param r the change listener to remove
+	 */
+	public void removeResourceChangeListener(ResourceChangeListener r){
+		activeChangeListeners.remove(r);
+	}
+
+	
+
+	/**
+	 * Calculates weight for the given resources for the use in {@link SplitMap}
+	 * splitmaps. For this the PerfomanceRating read out of the
+	 * {@link XuluConfig} property <br>
+	 * "PerformanceRating." + name of the machine <br>
+	 * If the rating is 0 an average rating is assumed.
+	 * 
+	 * @param computingResources
+	 * @return the weights
+	 */
+	private double[] calculateWeights(
+			Vector<ComputingResourceContainer> computingResources) {
+		// first get the rating. Try to find the value in the
+		// (user defined)configuration first, if not there try resource info.
+		int ratings[] = new int[computingResources.size()];
+		for (int i = 0; i < ratings.length; i++) {
+			ComputingResourceContainer container = computingResources.get(i);
+			String resName = container.getInformation().getName();
+			String rating = XuluConfig.getXuluConfig().getProperty(
+					"PerformanceRating." + resName, false);
+			// if not found take the benchmark value
+			if (rating == null) {
+				rating = container.getInformation().getProperty("Rating");
+			}
+			if (rating == null)
+				rating = "0";
+			ratings[i] = Integer.valueOf(rating);
+		}
+		return Helper.calculateWeights(ratings);
+	}
+
+	/**
+	 * Gives a new {@link SPMDClientController}.
+	 * 
+	 * @param computingResources
+	 *            the resources to be used by the new controller
+	 * @return a new {@link SPMDClientController} for the given resources
+	 */
+	public SPMDClientController getNewSPMDClientController(
+			ComputingResourceContainer[] computingResources) {
+		Vector<ComputingResourceContainer> resvec = new Vector<ComputingResourceContainer>(
+				computingResources.length);
+		for (ComputingResourceContainer container : computingResources) {
+			resvec.add(container);
+		}
+		return getNewSPMDClientController(resvec);
+	}
+
+	/**
+	 * Gives a new {@link SPMDClientController}.
+	 * 
+	 * @param computingResources
+	 *            the resources to be used by the new controller
+	 * @return a new {@link SPMDClientController} for the given resources
+	 */
+	public SPMDClientController getNewSPMDClientController(
+			Vector<ComputingResourceContainer> computingResources) {
+		double[] weights = calculateWeights(computingResources);
+		return new AdvancedSPMDClientController(computingResources, weights,
+				spmdClient, eventHandlerProxy);
+	}
+
+	/**
+	 * @return the execution controller of the given
+	 *         {@link XuluModellingPlatform} or null, if not found
+	 */
+	public static RemoteExecutionController getRemoteExecutionController(
+			XuluModellingPlatform modellingPlatform) {
+		XuluPlugin[] plugins = modellingPlatform.getRegistry().getPlugins();
+		for (XuluPlugin plugin : plugins) {
+			if (plugin instanceof RemoteExecutionController)
+				return (RemoteExecutionController) plugin;
+		}
+		return null;
+	}
+
+	public RemoteEventHandler getEventProxy() {
+		return eventHandlerProxy;
+	}
+
+	/**
+	 * Prepares a Model for execution, which means it creates a
+	 * {@link SPMDClientController} with the given Resources
+	 * 
+	 * @param model
+	 *            the model which is to be executed parallel
+	 * @param selectedResourceContainers
+	 *            the resources on which the model is executed
+	 */
+	public void prepareModelForSPMDExecution(ParallelStepModel model,
+			ComputingResourceContainer[] selectedResourceContainers) {
+		SPMDClientInterface controller = getNewSPMDClientController(selectedResourceContainers);
+		model.setSPMDController(controller);
+	}
+}

Added: trunk/src/appl/parallel/client/ResourceChangeListener.java
===================================================================
--- trunk/src/appl/parallel/client/ResourceChangeListener.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/client/ResourceChangeListener.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,22 @@
+package appl.parallel.client;
+
+import java.util.Vector;
+
+import appl.parallel.ComputingResourceContainer;
+
+/**
+ * Listeners which implement this interface can react on changes on the availability of
+ * remote resources. GUI classes use the interface to keep their resource list up to date.
+ *  
+ * @see RemoteExecutionController for a handler
+ * 
+ * @author Dominik Appl
+ */
+public interface ResourceChangeListener {
+	
+	/**
+	 * @param currentResources the current active remote resources
+	 */
+	public void updateResources(Vector<ComputingResourceContainer> currentResources);  
+
+}

Added: trunk/src/appl/parallel/client/package.html
===================================================================
--- trunk/src/appl/parallel/client/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/client/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,5 @@
+<html>
+<body>
+	Contains some classes for parallelization which are especially important on client side.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/parallel/data/AbstractDataHandler.java
===================================================================
--- trunk/src/appl/parallel/data/AbstractDataHandler.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/AbstractDataHandler.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,186 @@
+package appl.parallel.data;
+
+import java.awt.Rectangle;
+import java.io.IOException;
+import java.io.Serializable;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.rmi.Naming;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import appl.data.LoadingException;
+import appl.parallel.client.DataServer;
+import appl.parallel.client.ClientDataServer;
+import appl.parallel.spmd.split.DataPartition;
+import appl.parallel.spmd.split.SplittableResource;
+
+/**
+ * This class is used as a base class for loaders. It is especially intended for
+ * use with the SPMD-Paradigm, but may be used with other loaders, too. It
+ * implements the reusable stuff of the {@link PartitionDataHandler} Interface.
+ * Notice that each loader is responsible for exactly one data element. It must
+ * be {@link Cloneable}, so that multi-data elements can add another element.
+ * 
+ * @author Dominik Appl
+ */
+public abstract class AbstractDataHandler implements PartitionDataHandler {
+
+	protected transient Logger LOG = LogManager.getLogger(this.getClass()
+			.getName());
+
+	/**
+	 * The id of the currently handled {@link SplittableResource}
+	 */
+	protected int rootID;
+
+	/**
+	 * The partition bounds (the whole bounds) of the current
+	 * {@link SplittableResource}
+	 */
+	protected Rectangle partitionBounds;
+
+	/**
+	 * the currently handled data (must be initialized before calling
+	 * {@link #unload()}
+	 */
+	protected transient DataPartition data;
+
+	/**
+	 * The unload bounds differ may differ from the partitionBounds. If there is
+	 * a neighborhood region it is important, that only the core-region (without
+	 * the neighborhood) is unloaded.
+	 */
+	protected Rectangle unloadBounds;
+
+	/**
+	 * A {@link ClientDataServer} may be used locally for faster access.
+	 */
+	protected transient ClientDataServer spmdClient;
+
+	/**
+	 * Constructs a new {@link AbstractDataHandler}. The local IP address at
+	 * the time of construction is later used on serverside for communication
+	 * (e.g. unloading).
+	 * 
+	 * @param rootID
+	 *            the id of the data
+	 * @param client
+	 *            a {@link ClientDataServer} which may be used to get meta
+	 *            information on client side before transferring the loader to
+	 *            its destination
+	 * @param partitionBounds
+	 *            the bounds of the partition to be retrieved on server side
+	 * @param unloadBounds
+	 *            the bounds of the partition which is to be uploaded to the
+	 *            client after calculation (may only be the calculation area)
+	 */
+	public AbstractDataHandler(int rootID, ClientDataServer client,
+			Rectangle partitionBounds, Rectangle unloadBounds) {
+		this.spmdClient = client;
+		this.rootID = rootID;
+		this.partitionBounds = partitionBounds;
+		this.unloadBounds = unloadBounds;
+	}
+
+	/**
+	 * sets a local {@link ClientDataServer} which MAY be used by the handler
+	 * for local access
+	 * 
+	 * @param localSPMDClient
+	 */
+	public void setSPMDClient(ClientDataServer localSPMDClient) {
+		this.spmdClient = localSPMDClient;
+	}
+
+	/**
+	 * (empty constructors are important for deserialization)
+	 * 
+	 * @see #AbstractDataHandler(int, ClientDataServer, Rectangle, Rectangle)
+	 */
+	public AbstractDataHandler() {
+		this(-1, null, new Rectangle(0, 0, 0, 0), new Rectangle(0, 0, 0, 0));
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.data.DataLoader#getLoadInfo()
+	 */
+	public abstract String getLoadInfo();
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.data.DataLoader#getLoadInfo()
+	 */
+	public abstract String getUnloadInfo();
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.data.DataLoader#load()
+	 */
+	public abstract DataPartition load() throws LoadingException;
+
+	/**
+	 * Initializes the {@link Logger} after deserialization (used by
+	 * {@link java.io.Serializable})
+	 * 
+	 * @throws IOException
+	 * @see Serializable
+	 */
+	private synchronized void readObject(java.io.ObjectInputStream s)
+			throws IOException, ClassNotFoundException {
+		// reading standard fields
+		s.defaultReadObject();
+		// initialize Logger
+		LOG = LogManager.getLogger(this.getClass().getName());
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.data.PartitionDataHandler#setUnloadPartition(java.awt.Rectangle)
+	 */
+	public void setUnloadBounds(Rectangle unloadBounds) {
+		this.unloadBounds = unloadBounds;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.data.PartitionDataHandler#setBasePartition(appl.parallel.spmd.split.DataPartition)
+	 */
+	public void setBasePartition(DataPartition data) {
+		this.data = data;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.data.DataUnloader#unload()
+	 */
+	public abstract void unload();
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.data.PartitionDataHandler#setRootID(int)
+	 */
+	public void setRootID(int rootID) {
+		this.rootID = rootID;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.lang.Object#clone()
+	 */
+	public PartitionDataHandler clone() {
+		return newInstance(rootID, spmdClient, this.unloadBounds,
+				this.partitionBounds);
+	}
+
+}

Added: trunk/src/appl/parallel/data/DataLoadHandler.java
===================================================================
--- trunk/src/appl/parallel/data/DataLoadHandler.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/DataLoadHandler.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,14 @@
+package appl.parallel.data;
+
+import appl.data.DataLoader;
+import appl.data.DataUnloader;
+
+/**
+ * Instances of this interface are both {@link DataLoader} and
+ * {@link DataUnloader}.
+ * 
+ * @author Dominik Appl
+ */
+public interface DataLoadHandler extends DataLoader, DataUnloader {
+
+}

Added: trunk/src/appl/parallel/data/PartitionDataHandler.java
===================================================================
--- trunk/src/appl/parallel/data/PartitionDataHandler.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/PartitionDataHandler.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,55 @@
+package appl.parallel.data;
+
+import java.awt.Rectangle;
+
+import appl.data.LoadingException;
+import appl.parallel.client.ClientDataServer;
+import appl.parallel.spmd.split.DataPartition;
+
+/**
+ * Responsible for loading and unloading data partitions
+ * 
+ * @author Dominik Appl
+ */
+public interface PartitionDataHandler extends DataLoadHandler, Cloneable {
+
+	/**
+	 * sets the bounds of the data to be unloaded so that not all data is
+	 * unloaded to the destination. This is for example useful if there is a
+	 * neighborhood region which should not be uploaded to the destination.
+	 * 
+	 * @param bounds
+	 */
+	public void setUnloadBounds(Rectangle bounds);
+
+	public void setBasePartition(DataPartition data);
+
+	public void setRootID(int rootID);
+
+	/**
+	 * @param rootID
+	 *            the id of the data
+	 * @param partitionBounds
+	 *            the bounds of the partition to be retrieved on server side
+	 * @param unloadBounds
+	 *            the bounds of the partition which is to be uploaded to the
+	 *            client after calculation
+	 * @return the new instance
+	 */
+	public PartitionDataHandler newInstance(int rootID,
+			ClientDataServer spmdClient, Rectangle partitionBounds,
+			Rectangle unloadBounds);
+
+	public DataPartition load() throws LoadingException;
+
+	public PartitionDataHandler clone();
+
+	/**
+	 * sets a local spmd client which MAY be used by the handler for local
+	 * access
+	 * 
+	 * @param localSPMDClient
+	 */
+	public void setSPMDClient(ClientDataServer localSPMDClient);
+
+}

Added: trunk/src/appl/parallel/data/PartitionHandlerFactory.java
===================================================================
--- trunk/src/appl/parallel/data/PartitionHandlerFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/PartitionHandlerFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,65 @@
+package appl.parallel.data;
+
+import java.awt.Rectangle;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import appl.ext.XuluConfig;
+import appl.parallel.client.ClientDataServer;
+
+/**
+ * Reads out of {@link XuluConfig} which {@link PartitionDataHandler} needs to
+ * be used for data loading/unloading and constructs an instance of this class.
+ * The classname is read out of the property <br>
+ * <br>
+ * Parallel.partitionhandlerfactory.classname
+ * 
+ * @author Dominik Appl
+ */
+public class PartitionHandlerFactory {
+
+	private static Logger LOG = LogManager
+			.getLogger("appl.data.PartitionHandlerFactory");
+
+	/**
+	 * @param rootID
+	 *            the id of the data
+	 * @param partitionBounds
+	 *            the bounds of the partition to be retrieved on server side
+	 * @param unloadBounds
+	 *            the bounds of the partition which is to be uploaded to the
+	 *            client after calculation
+	 * @return a new {@link PartitionDataHandler} instance
+	 */
+	public static PartitionDataHandler newInstance(int rootID,
+			ClientDataServer client, Rectangle partitionBounds,
+			Rectangle unloadBounds) {
+		PartitionDataHandler returnhandler = null;
+		// try to get info from xulu config
+		String classname = XuluConfig.getXuluConfig().getProperty(
+				"Parallel.partitionhandlerfactory.classname");
+		if (classname != null) {
+			try {
+				returnhandler = (PartitionDataHandler) Class.forName(classname)
+						.newInstance();
+			} catch (InstantiationException e) {
+				LOG.error(e);
+				e.printStackTrace();
+			} catch (IllegalAccessException e) {
+				LOG.error(e);
+				e.printStackTrace();
+			} catch (ClassNotFoundException e) {
+				e.printStackTrace();
+				LOG.error("Could not find PartitionHandler class '" + classname
+						+ "'", e);
+			}
+		}
+		if (returnhandler != null) {
+			return returnhandler.newInstance(rootID, client, partitionBounds,
+					unloadBounds);
+		}
+		return null;
+	}
+
+}

Added: trunk/src/appl/parallel/data/WritableGridArrayPartition.java
===================================================================
--- trunk/src/appl/parallel/data/WritableGridArrayPartition.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/WritableGridArrayPartition.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,276 @@
+package appl.parallel.data;
+
+import java.awt.Rectangle;
+import java.awt.image.DataBuffer;
+
+import appl.data.DataProxy;
+import appl.parallel.server.XuluServer;
+import appl.parallel.spmd.split.DataPartition;
+import appl.parallel.spmd.split.WritableGridPartition;
+import appl.parallel.util.PartitionUtil;
+import appl.util.RasterMetaData;
+import schmitzm.data.WritableGrid;
+import schmitzm.data.WritableGridArray;
+
+/** 
+ * A WritableGridArrayPartition extends the {@link WritableGridArray} so that
+ * it can be used in parallel computation. Every partition represents a 
+ * rectangle-shaped part of a father-grid. It has information about its bounds
+ * and about its father-grid. The partition may be used for data transfer
+ * between computing resources. It is very fast, because it is not proxyied
+ * by a {@link DataProxy}, but uses the {@link WritableGridArray} directly. 
+ * 
+ * @see WritableGridArrayPartition
+ * 
+ * @author Dominik Appl
+ */
+public abstract class WritableGridArrayPartition {
+
+	/**
+	 * For Float data types
+	 * 
+	 * @see WritableGridArray.Float
+	 * @author Dominik Appl
+	 */
+	public static class Float extends WritableGridArray.Float implements
+			WritableGridPartition {
+
+		private final int rootID;
+
+		private final Rectangle thisPartition;
+
+		private final RasterMetaData metaData;
+
+		public Float(RasterMetaData metaData, int rootID,
+				Rectangle thisPartition) {
+			super(metaData.getMinX(), metaData.getMinY(), metaData.getWidth(),
+					metaData.getHeight(), metaData.getX(), metaData.getY(),
+					metaData.getRealWidth(), metaData.getRealHeight(), metaData
+							.getCoordinateReferenceSystem(), null);
+			this.metaData = metaData;
+			this.rootID = rootID;
+			this.thisPartition = thisPartition;
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.parallel.spmd.split.DataPartition#getBounds(java.awt.Rectangle)
+		 */
+		public Rectangle getPartitionBounds() {
+			return thisPartition;
+
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.parallel.spmd.split.DataPartition#getPartition(java.awt.Rectangle)
+		 */
+		public DataPartition getPartition(Rectangle partitionBounds) {
+			return PartitionUtil.getPartitialGrid2D(this, partitionBounds,
+					rootID);
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.parallel.spmd.split.DataPartition#getRootID()
+		 */
+		public int getRootID() {
+			return rootID;
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.parallel.spmd.split.DataPartition#setPartition(appl.parallel.spmd.split.DataPartition,
+		 *      java.awt.Rectangle)
+		 */
+		public void setPartition(DataPartition partition,
+				Rectangle partitionBounds) {
+			if (!(partition instanceof WritableGrid))
+				throw new UnsupportedOperationException(
+						"The partition must be an instance of WritableGrid!");
+			PartitionUtil.setPartition(this, (WritableGrid) partition,
+					partitionBounds);
+
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.parallel.spmd.split.DataPartition#getEmpty(int id)
+		 */
+		public DataPartition getEmpty(int id) {
+			return new WritableGridArrayPartition.Float(this.metaData, id,
+					thisPartition);
+		}
+	}
+	
+	/**
+	 * For Double data types
+	 * 
+	 * @see WritableGridArray.Double
+	 * @author Dominik Appl
+	 */
+	public static class Double extends WritableGridArray.Float implements
+			WritableGridPartition {
+
+		private final int rootID;
+
+		private final Rectangle thisPartition;
+
+		private final RasterMetaData metaData;
+
+		
+		public Double(RasterMetaData metaData, int rootID,
+				Rectangle thisPartition) {
+			super(metaData.getMinX(), metaData.getMinY(), metaData.getWidth(),
+					metaData.getHeight(), metaData.getX(), metaData.getY(),
+					metaData.getRealWidth(), metaData.getRealHeight(), metaData
+							.getCoordinateReferenceSystem(), null);
+			this.metaData = metaData;
+			this.rootID = rootID;
+			this.thisPartition = thisPartition;
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.parallel.spmd.split.DataPartition#getBounds(java.awt.Rectangle)
+		 */
+		public Rectangle getPartitionBounds() {
+			return thisPartition;
+
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.parallel.spmd.split.DataPartition#getPartition(java.awt.Rectangle)
+		 */
+		public DataPartition getPartition(Rectangle partitionBounds) {
+			return PartitionUtil.getPartitialGrid2D(this, partitionBounds,
+					rootID);
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.parallel.spmd.split.DataPartition#getRootID()
+		 */
+		public int getRootID() {
+			return rootID;
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.parallel.spmd.split.DataPartition#setPartition(appl.parallel.spmd.split.DataPartition,
+		 *      java.awt.Rectangle)
+		 */
+		public void setPartition(DataPartition partition,
+				Rectangle partitionBounds) {
+			if (!(partition instanceof WritableGrid))
+				throw new UnsupportedOperationException(
+						"The partition must be an instance of WritableGrid!");
+			PartitionUtil.setPartition(this, (WritableGrid) partition,
+					partitionBounds);
+
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.parallel.spmd.split.DataPartition#getEmpty(int id)
+		 */
+		public DataPartition getEmpty(int id) {
+			return new WritableGridArrayPartition.Double(this.metaData, id,
+					thisPartition);
+		}
+	}
+	
+	/**
+	 * For Integer data types
+	 * 
+	 * @see WritableGridArray.Integer
+	 * @author Dominik Appl
+	 */
+	public static class Integer extends WritableGridArray.Integer implements
+			WritableGridPartition {
+
+		private final int rootID;
+
+		private final Rectangle thisPartition;
+
+		private final RasterMetaData metaData;
+
+		public Integer(RasterMetaData metaData, int rootID,
+				Rectangle thisPartition) {
+			super(metaData.getMinX(), metaData.getMinY(), metaData.getWidth(),
+					metaData.getHeight(), metaData.getX(), metaData.getY(),
+					metaData.getRealWidth(), metaData.getRealHeight(), metaData
+							.getCoordinateReferenceSystem(), null);
+			this.metaData = metaData;
+			this.rootID = rootID;
+			this.thisPartition = thisPartition;
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.parallel.spmd.split.DataPartition#getBounds(java.awt.Rectangle)
+		 */
+		public Rectangle getPartitionBounds() {
+			return thisPartition;
+
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.parallel.spmd.split.DataPartition#getPartition(java.awt.Rectangle)
+		 */
+		public DataPartition getPartition(Rectangle partitionBounds) {
+			return PartitionUtil.getPartitialGrid2D(this, partitionBounds,
+					rootID);
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.parallel.spmd.split.DataPartition#getRootID()
+		 */
+		public int getRootID() {
+			return rootID;
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.parallel.spmd.split.DataPartition#setPartition(appl.parallel.spmd.split.DataPartition,
+		 *      java.awt.Rectangle)
+		 */
+		public void setPartition(DataPartition partition,
+				Rectangle partitionBounds) {
+			if (!(partition instanceof WritableGrid))
+				throw new UnsupportedOperationException(
+						"The partition must be an instance of WritableGrid!");
+			PartitionUtil.setPartition(this, (WritableGrid) partition,
+					partitionBounds);
+
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.parallel.spmd.split.DataPartition#getEmpty(int id)
+		 */
+		public DataPartition getEmpty(int id) {
+			return new WritableGridArrayPartition.Integer(this.metaData, id,
+					thisPartition);
+		}
+	}
+
+}

Added: trunk/src/appl/parallel/data/XuluClientLoader.java
===================================================================
--- trunk/src/appl/parallel/data/XuluClientLoader.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/XuluClientLoader.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,207 @@
+package appl.parallel.data;
+
+import java.awt.Rectangle;
+import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+import java.io.Serializable;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.UnknownHostException;
+import java.rmi.Naming;
+import java.rmi.NotBoundException;
+import java.rmi.RemoteException;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import appl.data.LoadingException;
+import appl.parallel.client.ClientDataServer;
+import appl.parallel.client.DataServer;
+import appl.parallel.server.XuluServer;
+import appl.parallel.spmd.split.DataPartition;
+
+import schmitzm.data.WritableGrid;
+
+/**
+ * Loads partitioned data from a {@link ClientDataServer}. And unloads the data
+ * 
+ * @author Dominik Appl
+ */
+public class XuluClientLoader extends AbstractDataHandler implements
+		PartitionDataHandler {
+
+	protected InetAddress address;
+
+	protected String namingString;
+
+	private String unloadTarget = null;
+
+	/**
+	 * constructs a new {@link XuluClientLoader}. The local IP adress at the
+	 * time of construction is later used on serverside for communication (e.g.
+	 * unloading).
+	 * 
+	 * @param rootID
+	 *            the id of the data
+	 * @param partitionBounds
+	 *            the bounds of the partition to be retrieved on server side
+	 * @param unloadBounds
+	 *            the bounds of the partition which is to be uploaded to the
+	 *            client after calculation
+	 */
+	public XuluClientLoader(int rootID, ClientDataServer client,
+			Rectangle partitionBounds, Rectangle unloadBounds) {
+		super(rootID, client, partitionBounds, unloadBounds);
+		address = null;
+		namingString = null;
+		try {
+			this.address = InetAddress.getLocalHost();
+			unloadTarget = address.getHostAddress();
+			namingString = "rmi://" + unloadTarget + "/DataServer";
+		} catch (UnknownHostException e) {
+			LOG.error("The client IP could not be determined!!", e);
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * constructs a new {@link XuluClientLoader}. The unloading is done to the
+	 * {@link DataServer} at the machine given with the parameter unloadTarget
+	 * (IP/Adress or Hostname).
+	 * 
+	 * @param rootID
+	 *            the id of the data
+	 * @param partitionBounds
+	 *            the bounds of the partition to be retrieved on server side
+	 * @param unloadBounds
+	 *            the bounds of the partition which is to be uploaded to the
+	 *            client after calculation
+	 */
+	public XuluClientLoader(int rootID, ClientDataServer client,
+			Rectangle partitionBounds, Rectangle unloadBounds,
+			String unloadTarget) {
+		spmdClient = client;
+		this.unloadTarget = unloadTarget;
+		address = null;
+		namingString = null;
+		try {
+			this.address = InetAddress.getLocalHost();
+			namingString = "rmi://" + unloadTarget + "/DataServer";
+		} catch (UnknownHostException e) {
+			LOG.error("The client IP could not be determined!!", e);
+			e.printStackTrace();
+		}
+		this.rootID = rootID;
+		this.partitionBounds = partitionBounds;
+		this.unloadBounds = unloadBounds;
+	}
+
+	public XuluClientLoader newInstance(int rootID, ClientDataServer client,
+			Rectangle partitionBounds, Rectangle unloadBounds) {
+		return new XuluClientLoader(rootID, client, partitionBounds,
+				unloadBounds);
+	}
+
+	/**
+	 * Used for deserialization. Do not use for other purposes
+	 */
+	public XuluClientLoader() {
+		super();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.data.DataLoader#getLoadInfo()
+	 */
+	public String getLoadInfo() {
+		return "XuluClientLoader tries to load data with rootID " + rootID
+				+ " from IP: " + address.getHostAddress() + " with naming: "
+				+ namingString;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.data.DataLoader#getLoadInfo()
+	 */
+	public String getUnloadInfo() {
+		return "XuluClientLoader tries to unload data with rootID " + rootID
+				+ " to IP: " + address.getHostAddress() + " with naming: "
+				+ namingString;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.data.DataLoader#load()
+	 */
+	public DataPartition load() throws LoadingException {
+		try {
+			LOG.debug(getLoadInfo());
+			DataServer client = (DataServer) Naming.lookup(namingString);
+			data = client.getPartition(rootID, partitionBounds);
+			LOG.debug("Partition with id  " + rootID
+					+ " successfully retrieved from client");
+			return data;
+		} catch (Exception e) {
+			LOG.error("Partition retrieval failed: " + e.getMessage());
+		}
+		return null;
+	}
+
+	/**
+	 * Initializes the {@link Logger} after deserialization (used by
+	 * {@link java.io.Serializable}
+	 * 
+	 * @author Dominik Appl
+	 * @param s
+	 * @throws IOException
+	 * @see Serializable
+	 */
+	private synchronized void readObject(java.io.ObjectInputStream s)
+			throws IOException, ClassNotFoundException {
+		// reading standard fields
+		s.defaultReadObject();
+		// initialize Logger
+		LOG = LogManager.getLogger(this.getClass().getName());
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.data.DataUnloader#unload()
+	 */
+	public void unload() {
+		try {
+			if (LOG.isDebugEnabled())
+				LOG.debug(getUnloadInfo());
+			if (data == null) {
+				if (LOG.isDebugEnabled())
+					LOG.debug("No data loaded -> nothing to unload");
+				return;
+			}
+			// construct return grid only if necessary
+			DataPartition returnPartition = null;
+			if (unloadBounds.equals(data.getPartitionBounds()))
+				returnPartition = data;
+			else
+				returnPartition = data.getPartition(unloadBounds);
+			// if there is a local spmdClient try to use it
+			if (spmdClient != null)
+				spmdClient.updatePartition(rootID, returnPartition,
+						unloadBounds);
+			// else connect remotely to client
+			else {
+				DataServer client = (DataServer) Naming.lookup(namingString);
+				client.updatePartition(rootID, returnPartition, unloadBounds);
+			}
+
+			LOG.debug("Partition with id  " + rootID
+					+ " was transfered back to client!");
+		} catch (Exception e) {
+			LOG.error("Backtransfer of data to client failed!", e);
+		}
+	}
+
+}

Added: trunk/src/appl/parallel/data/package.html
===================================================================
--- trunk/src/appl/parallel/data/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,5 @@
+<html>
+<body>
+	Contains data related parallelization classes. 
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/parallel/data/splittable/GridListFactory.java
===================================================================
--- trunk/src/appl/parallel/data/splittable/GridListFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/splittable/GridListFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,27 @@
+package appl.parallel.data.splittable;
+
+import edu.bonn.xulu.io.InstantiationFactory;
+
+// nur fuer Doku
+import schmitzm.data.WritableGrid;
+import edu.bonn.xulu.plugin.data.grid.GridList;
+
+/**
+ * Diese Factory erzeugt Standard-Instanzen von {@link GridList} mit
+ * durch die Factory {@link SplittableGridLLFactory} erzeugten (auf Standard-Arrays
+ * basierenden) {@link WritableGrid}-Instanzen als Inhalt.
+ * 
+ * @author Dominik Appl
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class GridListFactory extends edu.bonn.xulu.plugin.io.grid.awt.GridListFactory {
+  /**
+   * Liefert eine Instanz von {@link SplittableGridLLFactory}, die auf
+   * Standard-Arrays basierende Instanzen von {@link WritableGrid} erzeugt. Mit diesen
+   * Instanzen wird die GridList gefuellt.
+   */
+  protected InstantiationFactory getWritableGridFactory() {
+    return new SplittableGridLLFactory();
+  }
+}

Added: trunk/src/appl/parallel/data/splittable/GridListFactory_ArcInfoAsciiGrid.java
===================================================================
--- trunk/src/appl/parallel/data/splittable/GridListFactory_ArcInfoAsciiGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/splittable/GridListFactory_ArcInfoAsciiGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,162 @@
+package appl.parallel.data.splittable;
+
+import java.io.File;
+
+import appl.data.DataProxy;
+import appl.data.WritableGridLLProxy;
+import appl.ext.XuluConfig;
+import appl.util.RasterUtil;
+
+import schmitzm.io.IOUtil;
+import schmitzm.data.WritableGridArray;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyReadAccess;
+
+import edu.bonn.xulu.io.Factory;
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+import edu.bonn.xulu.plugin.data.grid.GridList;
+import edu.bonn.xulu.plugin.io.grid.array.WritableGridArrayFactory_ArcInfoAsciiGrid;
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link GridList} aus/in Dateien im ArcInfo-ASCII-Grid-Format.
+ * Beim Import liefert die Factory eine Standard-Arrays basierendes Raster-Liste
+ * ({@link WritableGridArray}).
+ * 
+ * 
+ * @author Dominik Appl
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class GridListFactory_ArcInfoAsciiGrid extends AbstractFactory implements ImportFactory,ExportFactory {
+ private static final ImportFactory importFac = new WritableGridArrayFactory_ArcInfoAsciiGrid();
+ private static final ExportFactory exportFac = new WritableGridArrayFactory_ArcInfoAsciiGrid();
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link GridList GridList.class}
+   */
+  public Class getImportType() {
+    return GridList.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File[].class}
+   */
+  public Class getImportSourceType() {
+     return File[].class;
+  }
+
+  /**
+   * Importiert Raster aus Dateien im ArcInfoAsciiGrid-Format
+   * und fuegt diese in einer {@link GridList} zusammen.
+   * @param input Eingabe-Quelle (muss ein {@link File File[]} sein!)
+   * @param reg   Instanz der Xulu-Registry, ueber die eine Factory ermittelt
+   *              wird, die eine Standard-Instanz von {@link GridList} erzeugt, in
+   *              die das Objekt importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Dateien angegeben werden
+   */
+  public GridList importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+    InstantiationFactory instFac = AbstractFactory.getInstantiationFactoryFromRegistry(reg,getImportType(),true);
+    GridList sg = (GridList)instFac.newInstance(false);
+    // Raster importieren und in GridList einfuegen
+    for (int i=0; i<((Object[])input).length; i++){
+    	SplittableLLProxyGrid grid =  new SplittableLLProxyGrid(importFac,
+        		RasterUtil.getRasterMetaData_from_ArcGridASCII_File(((File[])input)[i]), 
+        		((File[])input)[i], 
+        		reg );
+    	//read and apply settings from the registry
+        String unloadFolder = XuluConfig.getXuluConfig().getProperty("Datatypes.proxy.unloadFolder");
+        boolean unloading = XuluConfig.getXuluConfig().getBooleanProperty("Datatypes.proxy.enableUnloading");
+        if(unloadFolder!=null)
+        	grid.setUnloadDir(unloadFolder);
+        grid.setUnloading(unloading);
+    	sg.addGrid(  grid  );
+    }
+//    // Dateinamen in die Bezeichnung aufnehmen
+//    sg.setDescription(sg.getDescription().concat(" [").concat(((File)input).getName()).concat("]"));
+    return sg;
+  }
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um eine {@link GridList} handelt, die nur Instanzen
+   * von {@link WritableGridArray} als Elemente enthaelt.
+   * @param obj zu pruefendes Objekt
+   */
+  public boolean isExportable(Object obj) {
+    if ( obj==null || !(obj instanceof GridList) )
+      return false;
+    GridList list = (GridList)obj;
+    for (int i=0; i<list.getGridCount(); i++)
+      if ( !(list.getGrid(i) instanceof SplittableLLProxyGrid) )
+        return false;
+    return true;
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link GridList} (oder eine Unterklasse)
+   * handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return GridList.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt. Dabei handelt es sich um eine <b>einzelne Datei</b>, da
+   * die die letztendlichen Export-Dateien automatisch durchnummeriert werden!!
+   * @return immer {@link File File.class}
+   */
+  public Class getExportDestinationType() {
+    return File.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link GridList} in Dateien des
+   * ArcInfoAsciiGrid-Formats.<br>
+   * <b>Beachte:</b><br>
+   * Als Ausgabe-Objekt ist eine <b>einzelne</b> Datei anzugeben, kein
+   * Array! Die Dateien werden ausgehend von dem angegebenen Dateinamen
+   * durchnummeriert!!
+   * @param object zu exportiertende Raster (muss eine {@link GridList} sein
+   * @param output Export-Ziel (muss ein einzelner {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel keine
+   *            einzelne Datei angegeben wird
+   * @exception IllegalArgumentException falls es sich bei dem angegeben Objekt
+   *            nicht um eine {@link GridList} handelt
+   */
+  public void exportObject(Object object, Object output) throws Exception {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(object) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(object.getClass().getName()));
+
+    // Dateinamen-Teile ermitteln
+    String fileName = IOUtil.getBaseFileName((File)output);
+    String fileExt  = IOUtil.getFileExt((File)output);
+
+    // Grids in der Liste einzeln exportieren
+    ListPropertyReadAccess listAccess = ((ListProperty) (((GridList)object).getProperty(GridList.PROP_GRIDS))).getReadAccess(this);
+    for (int i=0; i<listAccess.getCount(); i++) {
+      File outFile = new File( fileName.concat("_"+i).concat(fileExt) );
+      exportFac.exportObject( ((DataProxy)listAccess.getValue(i)).getProxiedObject() ,outFile );
+    }
+    listAccess.release();
+
+  }
+}

Added: trunk/src/appl/parallel/data/splittable/MultiGridFactory.java
===================================================================
--- trunk/src/appl/parallel/data/splittable/MultiGridFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/splittable/MultiGridFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,26 @@
+package appl.parallel.data.splittable;
+
+import edu.bonn.xulu.plugin.io.grid.WritableGridFactory;
+// nur fuer Doku
+import schmitzm.data.WritableGrid;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+
+/**
+ * Diese Factory erzeugt Standard-Instanzen von {@link MultiGrid} mit
+ * durch die Factory {@link SplittableGridLLFactory} erzeugten (auf Standard-Arrays
+ * basierenden) {@link WritableGrid}-Instanzen als Inhalt.
+ * @author Dominik Appl
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class MultiGridFactory extends edu.bonn.xulu.plugin.io.grid.awt.MultiGridFactory {
+  /**
+   * Liefert eine Instanz von {@link SplittableGridLLFactory}, die auf Standard-Arrays
+   * basierende Instanzen von {@link WritableGrid} erzeugt. Mit diesen
+   * Instanzen wird die GridList gefuellt.
+   */
+  protected WritableGridFactory getWritableGridFactory() {
+    return new SplittableGridLLFactory();
+  }
+
+}

Added: trunk/src/appl/parallel/data/splittable/MultiGridFactory_ArcInfoAsciiGrid.java
===================================================================
--- trunk/src/appl/parallel/data/splittable/MultiGridFactory_ArcInfoAsciiGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/splittable/MultiGridFactory_ArcInfoAsciiGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,94 @@
+package appl.parallel.data.splittable;
+
+import java.io.File;
+
+import appl.data.WritableGridLLProxy;
+import appl.ext.XuluConfig;
+import appl.util.RasterUtil;
+
+import schmitzm.data.WritableGrid;
+
+import edu.bonn.xulu.appl.XuluRegistry;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.io.ImportFactory;
+
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+import edu.bonn.xulu.plugin.data.grid.GridList;
+import edu.bonn.xulu.plugin.io.grid.WritableGridFactory;
+import edu.bonn.xulu.plugin.io.grid.array.WritableGridArrayFactory_ArcInfoAsciiGrid;
+//import edu.bonn.xulu.plugin.io.grid.gt.GridListFactory_ArcInfoAsciiGrid;
+
+// nur fuer Doku
+import schmitzm.data.WritableGridArray;
+import edu.bonn.xulu.io.InstantiationFactory;
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link MultiGrid} aus/in Dateien im ArcInfo-ASCII-Grid-Format.
+ * Beim Import liefert die Factory eine Standard-Arrays basierendes Raster-Liste
+ * 
+ * 
+ * @author Dominik Appl
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class MultiGridFactory_ArcInfoAsciiGrid extends GridListFactory_ArcInfoAsciiGrid {
+  private static final ImportFactory importFac = new WritableGridArrayFactory_ArcInfoAsciiGrid();
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link MultiGrid MultiGrid.class}
+   */
+  public Class getImportType() {
+    return MultiGrid.class;
+  }
+
+  /**
+   * Importiert Raster aus Dateien im ArcInfoAsciiGrid-Format
+   * und fuegt diese in einem {@link MultiGrid} zusammen.
+   * @param input Eingabe-Quelle (muss ein {@link File File[]} sein!)
+   * @param reg   Instanz der Xulu-Registry, ueber die eine Factory ermittelt
+   *              wird, die eine Standard-Instanz von {@link MultiGrid} erzeugt, in
+   *              die das Objekt importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Dateien angegeben werden
+   */
+  public MultiGrid importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+
+    // MultiGrid erst erzeugen, wenn ein Beispiel-Raster vorliegt
+    MultiGrid mg = null;
+    // Raster importieren und in GridList einfuegen
+    for (int i=0; i<((Object[])input).length; i++) {
+    	SplittableLLProxyGrid grid = new SplittableLLProxyGrid
+                                (importFac,
+                                 RasterUtil.getRasterMetaData_from_ArcGridASCII_File(((File[])input)[i]), 
+                                 ((File[])input)[i], reg );
+      //read and apply settings from the registry
+      String unloadFolder = XuluConfig.getXuluConfig().getProperty("Datatypes.proxy.unloadFolder");
+      boolean unloading = XuluConfig.getXuluConfig().getBooleanProperty("Datatypes.proxy.enableUnloading");
+      if(unloadFolder!=null)
+      	grid.setUnloadDir(unloadFolder);
+      grid.setUnloading(unloading);
+      // das erste Grid dient dem MultiGrid als Vorlage
+      if ( mg == null )
+        mg = new MultiGrid(grid,getWritableGridFactory());
+
+      mg.addGrid(grid);
+    }
+    return mg;
+  }
+
+  /**
+   * Liefert eine Instanz von {@link SplittableGridLLFactory}, die auf Standard-Arrays
+   * basierende Instanzen von {@link WritableGrid} erzeugt. Mit diesen
+   * Instanzen wird das SingleGrid gefuellt.
+   */
+  protected WritableGridFactory getWritableGridFactory() {
+    return new SplittableGridLLFactory();
+  }
+
+}

Added: trunk/src/appl/parallel/data/splittable/SingleGridFactory.java
===================================================================
--- trunk/src/appl/parallel/data/splittable/SingleGridFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/splittable/SingleGridFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,27 @@
+package appl.parallel.data.splittable;
+
+import edu.bonn.xulu.io.InstantiationFactory;
+// nur fuer Doku
+import schmitzm.data.WritableGrid;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+import edu.bonn.xulu.plugin.io.grid.array.WritableGridArrayFactory;
+
+/**
+ * Diese Factory erzeugt Standard-Instanzen von {@link SingleGrid} mit einem
+ * durch die Factory {@link SplittableGridLLFactory} erzeugten (auf Standard-Arrays basierenden)
+ * {@link WritableGrid}.
+ * @author Dominik Appl
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class SingleGridFactory  extends edu.bonn.xulu.plugin.io.grid.awt.SingleGridFactory{
+
+  /**
+   * Liefert eine Instanz von {@link WritableGridArrayFactory}, die auf Standard-Arrays
+   * basierende Instanzen von {@link WritableGrid} erzeugt. Mit diesen
+   * Instanzen wird das SingleGrid gefuellt.
+   */
+  protected InstantiationFactory getWritableGridFactory() {
+    return new SplittableGridLLFactory();
+  }
+}

Added: trunk/src/appl/parallel/data/splittable/SingleGridFactory_ArcInfoAsciiGrid.java
===================================================================
--- trunk/src/appl/parallel/data/splittable/SingleGridFactory_ArcInfoAsciiGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/splittable/SingleGridFactory_ArcInfoAsciiGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,137 @@
+package appl.parallel.data.splittable;
+
+import java.io.File;
+
+import appl.data.DataProxy;
+import appl.data.WritableGridLLProxy;
+import appl.ext.XuluConfig;
+import appl.util.RasterMetaData;
+import appl.util.RasterUtil;
+
+import schmitzm.data.WritableGridArray;
+
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+import edu.bonn.xulu.plugin.io.grid.array.WritableGridArrayFactory_ArcInfoAsciiGrid;
+
+// nur fuer Doku
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link SingleGrid} aus/in das ArcInfo-ASCII-Grid-Format.
+ * Beim Import liefert die Factory ein auf Standard-Arrays basierendes Raster
+ * ({@link WritableGridArray}).
+ 
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @author Dominik Appl
+ * @version 1.0
+ */
+public class SingleGridFactory_ArcInfoAsciiGrid extends AbstractFactory implements ImportFactory, ExportFactory {
+  private static final ImportFactory importFac = new WritableGridArrayFactory_ArcInfoAsciiGrid();
+  private static final ExportFactory exportFac = new WritableGridArrayFactory_ArcInfoAsciiGrid();
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link SingleGrid SingleGrid.class}
+   */
+  public Class getImportType() {
+    return SingleGrid.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getImportSourceType() {
+    return File.class;
+  }
+
+  /**
+   * Importiert eine Instanz von {@link SingleGrid} aus einer Datei im
+   * ArcInfoAsciiGrid-Format.
+   * @param input Eingabe-Quelle (muss ein {@link File} sein!)
+   * @param reg   Instanz der Xulu-Registry, ueber die eine Factory ermittelt
+   *              wird, die eine Standard-Instanz von {@link SingleGrid} erzeugt, in
+   *              die das Raster importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Datei angegeben wird
+   */
+  public SingleGrid importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+    // Aus Registry die passende Factory fuer SingleGrid suchen
+    InstantiationFactory instFac = AbstractFactory.getInstantiationFactoryFromRegistry(reg,getImportType(),true);
+    // Raster importieren und in ein SingleGrid einfuegen
+    SingleGrid sg = (SingleGrid)instFac.newInstance(false);
+    SplittableLLProxyGrid newGrid = new SplittableLLProxyGrid(importFac, 
+            RasterUtil.getRasterMetaData_from_ArcGridASCII_File((File) input),
+            (File)input,reg);
+    //read and apply settings from the registry
+    String unloadFolder = XuluConfig.getXuluConfig().getProperty("Datatypes.proxy.unloadFolder");
+    boolean unloading = XuluConfig.getXuluConfig().getBooleanProperty("Datatypes.proxy.enableUnloading");
+    if(unloadFolder!=null)
+    	newGrid.setUnloadDir(unloadFolder);
+    newGrid.setUnloading(unloading);
+    sg.setGrid(newGrid);
+    // Dateinamen in die Bezeichnung aufnehmen
+    sg.setDescription(sg.getDescription().concat(" [").concat(((File)input).getName()).concat("]"));
+    return sg;
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um ein {@link SingleGrid} handelt, das ein
+   * {@link WritableGridArray} in seiner Raster-Eigenschaft besitzt.
+   * @param obj zu pruefendes Objekt
+   */
+  public boolean isExportable(Object obj) {
+    return obj!=null &&
+           obj instanceof SingleGrid &&
+           ((SingleGrid)obj).getGrid() instanceof SplittableLLProxyGrid;
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link SingleGrid} (oder eine Unterklasse)
+   * handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return SingleGrid.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getExportDestinationType() {
+    return File.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link SingleGrid} in eine ArcInfoAsciiGrid-Datei.
+   * @param grid zu exportiertendes Raster (muss ein {@link SingleGrid} sein
+   * @param output Export-Ziel (muss ein {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel keine
+   *            Datei angegeben wird
+   * @exception IllegalArgumentException falls es sich bei dem angegeben Raster
+   *            nicht um ein {@link SingleGrid} handelt
+   */
+  public void exportObject(Object grid, Object output) throws Exception {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(grid) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(grid.getClass().getName()));
+    exportFac.exportObject( ((DataProxy)((SingleGrid)grid).getGrid()).getProxiedObject(),(File)output );
+  }
+
+}

Added: trunk/src/appl/parallel/data/splittable/SingleGridFactory_GeoTiff.java
===================================================================
--- trunk/src/appl/parallel/data/splittable/SingleGridFactory_GeoTiff.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/splittable/SingleGridFactory_GeoTiff.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,129 @@
+package appl.parallel.data.splittable;
+
+import java.io.File;
+
+import appl.data.DataProxy;
+
+
+import schmitzm.data.WritableGridArray;
+
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+import edu.bonn.xulu.plugin.io.grid.array.WritableGridArrayFactory_GeoTiff;
+
+// nur fuer Doku
+import appl.data.WritableGridLLProxy;
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link SingleGrid} aus/in das GeoTiff-Format.
+ * Beim Import liefert die Factory ein auf Standard-Arrays basierendes Raster
+ * ({@link WritableGridArray}).
+ *
+ * @author Dominik Appl
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class SingleGridFactory_GeoTiff extends AbstractFactory implements ImportFactory, ExportFactory {
+  private static final WritableGridArrayFactory_GeoTiff GRID_FAC = new WritableGridArrayFactory_GeoTiff();
+  private static final WritableGridArrayFactory_GeoTiff importFac = new WritableGridArrayFactory_GeoTiff();
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link SingleGrid SingleGrid.class}
+   */
+  public Class getImportType() {
+    return SingleGrid.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getImportSourceType() {
+    return File.class;
+  }
+
+  /**
+   * Importiert eine Instanz von {@link SingleGrid} aus einer Datei im
+   * GeoTiff-Format.
+   * @param input Eingabe-Quelle (muss ein {@link File} sein!)
+   * @param reg   Instanz der Xulu-Registry, ueber die eine Factory ermittelt
+   *              wird, die eine Standard-Instanz von {@link SingleGrid} erzeugt, in
+   *              die das Raster importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Datei angegeben wird
+   */
+  public SingleGrid importObject(Object input, XuluRegistry reg) throws Exception {
+	  throw new UnsupportedOperationException("currently this import type is not supported for Proxy Grids. Use the standard data type");
+//    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+//    // Aus Registry die passende Factory fuer SingleGrid suchen
+//    InstantiationFactory instFac = AbstractFactory.getInstantiationFactoryFromRegistry(reg,getImportType(),true);
+//    // Raster importieren und in ein SingleGrid einfuegen
+//    SingleGrid sg = (SingleGrid)instFac.newInstance(false);
+//    //new WritableGridLLProxy(importFac, new FileInputStream((File)input),reg)
+//    ;
+//    // Dateinamen in die Bezeichnung aufnehmen
+//    sg.setDescription(sg.getDescription().concat(" [").concat(((File)input).getName()).concat("]"));
+
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um ein {@link SingleGrid} handelt, das ein
+   * {@link WritableGridLLProxy} in seiner Raster-Eigenschaft besitzt.
+   * @param obj zu pruefendes Objekt
+   */
+  public boolean isExportable(Object obj) {
+    return obj!=null &&
+           obj instanceof SingleGrid &&
+           ((SingleGrid)obj).getGrid() instanceof SplittableLLProxyGrid;
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link SingleGrid} (oder eine Unterklasse)
+   * handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return SingleGrid.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getExportDestinationType() {
+    return File.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link SingleGrid} in eine GeoTiff-Datei.
+   * @param grid zu exportiertendes Raster (muss ein {@link SingleGrid} sein
+   * @param output Export-Ziel (muss ein {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel keine
+   *            Datei angegeben wird
+   * @exception IllegalArgumentException falls es sich bei dem angegeben Raster
+   *            nicht um ein {@link SingleGrid} handelt
+   */
+  public void exportObject(Object grid, Object output) throws Exception {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(grid) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(grid.getClass().getName()));
+    GRID_FAC.exportObject( ((DataProxy)((SingleGrid)grid).getGrid()).getProxiedObject(), (File)output );
+  }
+
+}

Added: trunk/src/appl/parallel/data/splittable/SplittableGridLLFactory.java
===================================================================
--- trunk/src/appl/parallel/data/splittable/SplittableGridLLFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/splittable/SplittableGridLLFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,65 @@
+package appl.parallel.data.splittable;
+
+import java.awt.geom.Rectangle2D;
+import java.awt.image.DataBuffer;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+import appl.data.WritableGridLLProxy;
+import appl.util.RasterMetaData;
+import schmitzm.data.WritableGrid;
+import edu.bonn.xulu.plugin.io.grid.WritableGridFactory;
+import edu.bonn.xulu.plugin.io.grid.array.WritableGridArrayFactory;
+
+// nur fuer Doku
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.io.Factory;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+
+/**
+ * Diese Factory erzeugt Standard-Instanzen des Datentyps {@link SplittableLLProxyGrid}.<br>
+ * <b>Bemerke:</b><br>
+ * Dieser stellt <b>kein</b> {@linkplain XuluObject Xulu-Objekt} dar, kann also
+ * nicht direkt im Xulu-Datenpool gespeichert werden. Hierzu ist der Datentyp
+ * {@link SingleGrid} (bzw. eine entsprechende Factory) zu verwenden!
+ * @author Dominik Appl
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class SplittableGridLLFactory extends WritableGridFactory {
+
+
+    WritableGridFactory  targetFactory = new WritableGridArrayFactory();
+
+
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link SplittableLLProxyGrid SplittableLLProxyGrid.class}
+   */
+  public Class getInstanceType() {
+    return SplittableLLProxyGrid.class;
+  }
+
+  /**
+   * Erzeugt ein neues Grid.
+   * @param type    Datentyp der gespeicherten Objekte
+   * @param widthc  Breite in Zellen
+   * @param heightc Hoehe in Zellen
+   * @param minX    Index der ersten Zelle in X-Richtung
+   * @param minY    Index der ersten Zelle in Y-Richtung
+   * @param x       Georeferenz Latitude (Suedliche/Untere Kante)
+   * @param y       Georeferenz Longitute (Westliche/Linke Kante)
+   * @param width   Breite
+   * @param height  Hoehe
+   */
+  public SplittableLLProxyGrid newInstance(int type, int widthc, int heightc, int minX, int minY, double x, double y, double width, double height, CoordinateReferenceSystem crs) {
+
+
+	  return new SplittableLLProxyGrid(targetFactory,new RasterMetaData(
+			  											type,widthc,heightc,
+			  											minX,minY,x,y,width,
+			  											height, crs));
+    }
+}

Added: trunk/src/appl/parallel/data/splittable/SplittableLLProxyGrid.java
===================================================================
--- trunk/src/appl/parallel/data/splittable/SplittableLLProxyGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/splittable/SplittableLLProxyGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,132 @@
+package appl.parallel.data.splittable;
+
+import java.awt.Rectangle;
+import java.io.Serializable;
+
+import schmitzm.data.WritableGrid;
+import appl.data.DataLoader;
+import appl.data.WritableGridLLProxy;
+import appl.parallel.spmd.split.DataPartition;
+import appl.parallel.spmd.split.SplittableGrid;
+import appl.parallel.spmd.split.SplittableResource;
+import appl.parallel.spmd.split.WritableGridPartition;
+import appl.parallel.util.PartitionUtil;
+import appl.util.RasterMetaData;
+import edu.bonn.xulu.appl.XuluRegistry;
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.plugin.io.grid.WritableGridFactory;
+
+/**
+ * @version 1.0
+ */
+public class SplittableLLProxyGrid extends WritableGridLLProxy implements
+		SplittableGrid, Serializable {
+
+	private final int id;
+
+	public SplittableLLProxyGrid(ImportFactory importFac,
+			RasterMetaData metaData, Object inputPara, XuluRegistry reg) {
+		super(importFac, metaData, inputPara, reg);
+		id = this.hashCode();
+	}
+
+	public SplittableLLProxyGrid(WritableGridFactory targetFactory,
+			RasterMetaData metaData) {
+		super(targetFactory, metaData);
+		id = this.hashCode();
+	}
+
+	public SplittableLLProxyGrid(RasterMetaData metaData, int id) {
+		super(metaData);
+		this.id = id;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.spmd.split.SplittableResource#getFileSystemLoader()
+	 */
+	public DataLoader getLocalLoader() {
+		return this.intialDataLoader;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.spmd.split.SplittableResource#getID()
+	 */
+	public int getRootID() {
+		return this.id;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.spmd.split.SplittableResource#getPartition(java.awt.Rectangle)
+	 */
+	public WritableGridPartition getPartition(Rectangle partitionBounds) {
+		if (!loaded)
+			tryLoadingGrid();
+		return PartitionUtil.getPartitialGrid2D(this, partitionBounds,
+				getRootID());
+	}
+
+	/**
+	 * Overwrites the data at the location specified by the {@link Rectangle}
+	 * with the given partition-data.
+	 *
+	 * @param partition
+	 *            the grid to be inserted which MUST be an instance of
+	 *            {@link WritableGrid}!
+	 * @param partitionBounds
+	 *            the target location of the data
+	 * @see appl.parallel.spmd.split.DataPartition#setPartition(DataPartition,
+	 *      java.awt.Rectangle)
+	 */
+	public void setPartition(DataPartition partition, Rectangle partitionBounds) {
+		if (!loaded)
+			tryLoadingGrid();
+		if (!(partition instanceof WritableGrid))
+			throw new UnsupportedOperationException(
+					"The partition must be an instance of WritableGrid!");
+		PartitionUtil.setPartition(this, (WritableGrid) partition,
+				partitionBounds);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.spmd.split.SplittableResource#getSplitHeight()
+	 */
+	public int getSplitHeight() {
+		return this.getHeight();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.spmd.split.SplittableResource#getSplitWidth()
+	 */
+	public int getSplitWidth() {
+		return this.getWidth();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.spmd.split.DataPartition#getPartitionBounds()
+	 */
+	public Rectangle getPartitionBounds() {
+		return new Rectangle(0, 0, this.getWidth(), this.getHeight());
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.spmd.split.DataPartition#getEmpty()
+	 */
+	public DataPartition getEmpty(int id) {
+		return new SplittableLLProxyGrid(this.metaData, id);
+	}
+
+}

Added: trunk/src/appl/parallel/data/splittable/package.html
===================================================================
--- trunk/src/appl/parallel/data/splittable/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/splittable/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,7 @@
+<html>
+<body>
+	The SplittableLLProxyGrid is an extension to the WritableGridLLProxyGrid for use with parallelization.
+	The new class can handle partition of itself properly. The other classes are all xulu-specific factory classes
+	required for all data types which should be used in the Xulu-Application.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/parallel/data/xulugridfile/BufferedHelper.java
===================================================================
--- trunk/src/appl/parallel/data/xulugridfile/BufferedHelper.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/xulugridfile/BufferedHelper.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,91 @@
+package appl.parallel.data.xulugridfile;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+// fuer Doku
+import java.io.RandomAccessFile;
+
+/**
+ * The methods of this class can be used to efficiently read or write values
+ * into a Bytestream (it is e.g. used by the {@link XuluGridFile}).
+ *
+ * @author Dominik Appl
+ *
+ */
+public class BufferedHelper {
+
+	/**
+	 * Reads a long value out of the given bytestream Used for buffered reading.
+	 * Used the code of {@link RandomAccessFile#readInt()}
+	 *
+	 * @exception IOException
+	 *                if an I/O error occurs.
+	 */
+	public static final int readIntFromStream(ByteArrayInputStream input)
+			throws IOException {
+		int ch1 = input.read();
+		int ch2 = input.read();
+		int ch3 = input.read();
+		int ch4 = input.read();
+		if ((ch1 | ch2 | ch3 | ch4) < 0)
+			throw new EOFException();
+		return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
+	}
+
+	/**
+	 * Writes a int value in the the given bytestream Used for buffered writing.
+	 * Used the code of {@link RandomAccessFile#writeInt(int)}
+	 *
+	 * @exception IOException
+	 *                if an I/O error occurs.
+	 *
+	 */
+	public static final void writeInt(int v, ByteArrayOutputStream output)
+			throws IOException {
+		output.write((v >>> 24) & 0xFF);
+		output.write((v >>> 16) & 0xFF);
+		output.write((v >>> 8) & 0xFF);
+		output.write((v >>> 0) & 0xFF);
+		// written += 4;
+	}
+
+	/**
+	 * Writes a <code>long</code> to the stream as eight bytes, high byte
+	 * first. The write starts at the current position of the file pointer. Used
+	 * for buffered writing. Used the code of
+	 * {@link RandomAccessFile#writeLong(long)}
+	 *
+	 * @param output the stream to be written to
+	 * @param v
+	 *            a <code>long</code> to be written.
+	 * @exception IOException
+	 *                if an I/O error occurs.
+	 */
+	public static final void writeLong(long v, ByteArrayOutputStream output)
+			throws IOException {
+		output.write((int) (v >>> 56) & 0xFF);
+		output.write((int) (v >>> 48) & 0xFF);
+		output.write((int) (v >>> 40) & 0xFF);
+		output.write((int) (v >>> 32) & 0xFF);
+		output.write((int) (v >>> 24) & 0xFF);
+		output.write((int) (v >>> 16) & 0xFF);
+		output.write((int) (v >>> 8) & 0xFF);
+		output.write((int) (v >>> 0) & 0xFF);
+		// written += 8;
+	}
+
+	/**
+	 * Reads a long value out of the given {@link ByteArrayInputStream}. Used for buffered
+	 * reading. Used the code of {@link RandomAccessFile#readLong()} *
+	 *
+	 * @exception IOException
+	 *                if an I/O error occurs.
+	 */
+	public static final long readLongFromStream(ByteArrayInputStream input)
+			throws IOException {
+		return ((long) (readIntFromStream(input) << 32) + (readIntFromStream(input) & 0xFFFFFFFFL));
+	}
+
+}

Added: trunk/src/appl/parallel/data/xulugridfile/BufferedRandomAccessFile.java
===================================================================
--- trunk/src/appl/parallel/data/xulugridfile/BufferedRandomAccessFile.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/xulugridfile/BufferedRandomAccessFile.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,130 @@
+package appl.parallel.data.xulugridfile;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+/**
+ * Copied from java world.
+ * 
+ * See http://www.javaworld.com/javaworld/javatips/jw-javatip26.html
+ * 
+ * @author Nick Zhang
+ * 
+ */
+public class BufferedRandomAccessFile extends RandomAccessFile {
+
+	byte buffer[];
+
+	int buf_end = 0;
+
+	int buf_pos = 0;
+
+	long real_pos = 0;
+
+	private int BUF_SIZE;
+
+	public BufferedRandomAccessFile(String filename, String mode, int bufsize)
+			throws IOException {
+		super(filename, mode);
+		invalidate();
+		BUF_SIZE = bufsize;
+		buffer = new byte[BUF_SIZE];
+	}
+
+	public final int read() throws IOException {
+		if (buf_pos >= buf_end) {
+			if (fillBuffer() < 0)
+				return -1;
+		}
+		if (buf_end == 0) {
+			return -1;
+		} else {
+			return buffer[buf_pos++];
+		}
+	}
+
+	private int fillBuffer() throws IOException {
+		int n = super.read(buffer, 0, BUF_SIZE);
+		if (n >= 0) {
+			real_pos += n;
+			buf_end = n;
+			buf_pos = 0;
+		}
+		return n;
+	}
+
+	private void invalidate() throws IOException {
+		buf_end = 0;
+		buf_pos = 0;
+		real_pos = super.getFilePointer();
+	}
+
+	public int read(byte b[], int off, int len) throws IOException {
+		int leftover = buf_end - buf_pos;
+		if (len <= leftover) {
+			System.arraycopy(buffer, buf_pos, b, off, len);
+			buf_pos += len;
+			return len;
+		}
+		for (int i = 0; i < len; i++) {
+			int c = this.read();
+			if (c != -1)
+				b[off + i] = (byte) c;
+			else {
+				return i;
+			}
+		}
+		return len;
+	}
+
+	public long getFilePointer() throws IOException {
+		long l = real_pos;
+		return (l - buf_end + buf_pos);
+	}
+
+	public void seek(long pos) throws IOException {
+		int n = (int) (real_pos - pos);
+		if (n >= 0 && n <= buf_end) {
+			buf_pos = buf_end - n;
+		} else {
+			super.seek(pos);
+			invalidate();
+		}
+	}
+
+	/**
+	 * return a next line in String 
+	 */
+	public final String getNextLine() throws IOException {
+		String str = null;
+		if (buf_end - buf_pos <= 0) {
+			if (fillBuffer() < 0) {
+				throw new IOException("error in filling buffer!");
+			}
+		}
+		int lineend = -1;
+		for (int i = buf_pos; i < buf_end; i++) {
+			if (buffer[i] == '\n') {
+				lineend = i;
+				break;
+			}
+		}
+		if (lineend < 0) {
+			StringBuffer input = new StringBuffer(256);
+			int c;
+			while (((c = read()) != -1) && (c != '\n')) {
+				input.append((char) c);
+			}
+			if ((c == -1) && (input.length() == 0)) {
+				return null;
+			}
+			return input.toString();
+		}
+		if (lineend > 0 && buffer[lineend - 1] == '\r')
+			str = new String(buffer, 0, buf_pos, lineend - buf_pos - 1);
+		else
+			str = new String(buffer, 0, buf_pos, lineend - buf_pos);
+		buf_pos = lineend + 1;
+		return str;
+	}
+}

Added: trunk/src/appl/parallel/data/xulugridfile/GridFileDataLoader.java
===================================================================
--- trunk/src/appl/parallel/data/xulugridfile/GridFileDataLoader.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/xulugridfile/GridFileDataLoader.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,46 @@
+package appl.parallel.data.xulugridfile;
+
+import schmitzm.data.WritableGrid;
+import appl.data.DataLoader;
+import appl.data.LoadingException;
+
+/**
+ * This {@link DataLoader} is responsible to load data from a
+ * {@link XuluGridFile}. When {@link #load()} is called it tries to load the
+ * whole(!) grid into the memory. Notice that using this loader will destroy all
+ * memory advantages of the {@link XuluGridFile}. It is intended as standard loader in
+ * the xulu application. The user can therefore force the loading of the grid
+ * into the local memory e.g. for visualization.
+ * 
+ * @author Dominik Appl
+ */
+public class GridFileDataLoader implements DataLoader {
+
+	private final XuluGridFile gridFile;
+
+	public GridFileDataLoader(XuluGridFile gridFile) {
+		this.gridFile = gridFile;
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.data.DataLoader#getLoadInfo()
+	 */
+	public String getLoadInfo() {
+		// TODO Auto-generated method stub
+		return "Loading gridfile " + gridFile.getOutputFile().getPath() + ". ";
+	}
+
+	/** loads the whole grid into memory and returns it
+	 * @see appl.data.DataLoader#load()
+	 */
+	public WritableGrid load() throws LoadingException {
+		try {
+			return gridFile.getWholeGrid();
+		} catch (XuluGridFileException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+}

Added: trunk/src/appl/parallel/data/xulugridfile/XuluGridFile.java
===================================================================
--- trunk/src/appl/parallel/data/xulugridfile/XuluGridFile.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/xulugridfile/XuluGridFile.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,670 @@
+package appl.parallel.data.xulugridfile;
+
+import java.awt.Rectangle;
+import java.awt.image.DataBuffer;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.RandomAccessFile;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.WritableGridArray;
+import appl.parallel.data.WritableGridArrayPartition;
+import appl.parallel.spmd.split.SplittableResource;
+import appl.parallel.spmd.split.WritableGridPartition;
+import appl.util.RasterMetaData;
+
+/**
+ * A XuluGridfile is a memory- and 2D-access optimized file format
+ * which can be used for parallel programming. All data is accessed
+ * on disk only (and not loaded into memory).
+ * For this the data is stored in a special uncompressed format.<p/>
+ *
+ * The values are stored line by line in the GridFile. The result is, that
+ * every value is stored at a well known position in the file,
+ * so that the position of the value in the file can be calculated.
+ * Because of this it is not necessary to search the file for a value
+ * of a given coordinate.<br>
+ * If a partition is requested it is possible to read the data directly from
+ * the file.<p/>
+ *
+ * The filename of the XuluGridFile must end with ".xgrid"
+ * The metadata of the gird is stored in a separate file with the same name in
+ * the same directory ending with ".xworld".<p/>
+ *
+ * The XuluGridFile is buffered, it can handle Float, Double and Int values.
+ * To create a XuluGridFile you can use {@link #XuluGridFile(File, RasterMetaData) this} constructor, or
+ * you can convert an existing Grid into the {@link XuluGridFile} format using
+ * the {@link XuluGridFileConverter}.<p/>
+ *
+ * A monitor is used to guarantee that only one XuluGridFile is accessed at a time.
+ * This guarantees a high disk performance.<p/>
+ *
+ * For use in the XuluPlatform you can use the {@link XuluWritableGridFile}, which
+ * implements the {@link WritableGrid} interface.<p/>
+ *
+ *
+ * @author Dominik Appl
+ *
+ */
+public class XuluGridFile {
+
+	protected RandomAccessFile gridFile = null;
+
+	protected RasterMetaData metaData = null;
+
+	//length of one datavalue in bytes
+	private int dataValueSize = 4;
+
+	//buffer of 256 kb
+	private int buffersize = 262144;
+
+	private final File outputFile;
+
+	//the monitor is used to guarantee that only one XuluGridFile is accessed at a time
+	private static Object monitor = new Object();
+
+	/**
+	 * Opens an <b>existing</b> Xulu Grid File. The File must have the ending ".xgrid" and there
+	 * must be a xuluGrid world file in the same directory with the ending ".xworld"
+	 *
+	 * @param file the filename to read from and write to
+	 * @param mode the input mode as specified at {@link RandomAccessFile#RandomAccessFile(java.lang.String, java.lang.String)}
+	 * <blockquote><table summary="Access mode permitted values and meanings">
+	 *<tr><th><p align="left">Value</p></th><th><p align="left">Meaning</p></th></tr>
+	 *<tr><td valign="top"><tt>"r"</tt></td>
+	 *    <td> Open for reading only.  Invoking any of the <tt>write</tt>
+	 *    methods of the resulting object will cause an <A HREF="../../java/io/IOException.html" title="class in java.io"><CODE>IOException</CODE></A> to be thrown. </td></tr>
+	 *
+	 *<tr><td valign="top"><tt>"rw"</tt></td>
+	 *    <td> Open for reading and writing.  If the file does not already
+	 *    exist then an attempt will be made to create it. </td></tr>
+	 *<tr><td valign="top"><tt>"rws"</tt></td>
+	 *    <td> Open for reading and writing, as with <tt>"rw"</tt>, and also
+	 *    require that every update to the file's content or metadata be
+	 *    written synchronously to the underlying storage device.  </td></tr>
+	 *<tr><td valign="top"><tt>"rwd"&nbsp;&nbsp;</tt></td>
+	 *     <td> Open for reading and writing, as with <tt>"rw"</tt>, and also
+	 *    require that every update to the file's content be written
+	 *    synchronously to the underlying storage device. </td></tr>
+	 *</table></blockquote>
+	 *
+	 * @throws FileNotFoundException
+	 * @see RandomAccessFile
+	 * */
+	public XuluGridFile(File file, String mode) throws FileNotFoundException,
+			XuluGridFileException {
+		outputFile = file;
+		checkFileName(file);
+		try {
+			//gridFile = new BufferedRandomAccessFile(file.getAbsolutePath(), mode, buffersize);
+			gridFile = new RandomAccessFile(file.getAbsolutePath(), mode);
+		} catch (IOException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		String worldFileName = file.getAbsolutePath().replaceAll(".xgrid$",
+				".xworld");
+		this.metaData = readXuluGridWorldFile(new File(worldFileName));
+	}
+
+	/**
+	 * Opens an<b> existing</b> gridfile in read/write mode.
+	 *
+	 * @param file the existing XuluGridFile to be opened
+	 * @throws FileNotFoundException
+	 * @throws XuluGridFileException
+	 */
+	public XuluGridFile(File file) throws FileNotFoundException,
+			XuluGridFileException {
+		this(file, "rw");
+	}
+
+	/**
+	 * Creates a <b>NEW</b> File with the sample given as {@link RasterMetaData}
+	 * @param targetFile the file the new grid will be written to. <b>Has to end with ".xgrid"!</b>
+	 * @param metaData the metadata of the new grid. Width and height are used to allocate the space for the new XGrid.
+	 * @throws XuluGridFileException
+	 */
+	public XuluGridFile(File targetFile, RasterMetaData metaData)
+			throws XuluGridFileException {
+		outputFile = targetFile;
+		this.metaData = metaData;
+		checkFileName(targetFile);
+		writeWorldFileForMetaData(targetFile, metaData);
+		setByteLength(metaData);
+		try {
+			//gridFile = new BufferedRandomAccessFile(targetFile.getAbsolutePath(), "rw",buffersize );
+			gridFile = new RandomAccessFile(targetFile.getAbsolutePath(), "rw");
+			//allocate space by extending the file
+			gridFile.setLength(metaData.getWidth() * metaData.getHeight()
+					* dataValueSize);
+		} catch (FileNotFoundException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		} catch (IOException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+
+	}
+
+	/**
+	 * Sets the bytelength (4 bytes for float/int, 8 for double)
+	 *
+	 * @param meta the metadata object of the grid
+	 * @throws XuluGridFileException
+	 */
+	private void setByteLength(RasterMetaData meta)
+			throws XuluGridFileException {
+		switch (metaData.getDataType()) {
+		case DataBuffer.TYPE_DOUBLE:
+			dataValueSize = 8;
+			break;
+		case DataBuffer.TYPE_FLOAT:
+		case DataBuffer.TYPE_INT:
+			dataValueSize = 4;
+			break;
+		default:
+			throw new XuluGridFileException(
+					"XuluGridFile supports only float,double and int Datatypes!");
+		}
+	}
+
+	/**
+	 * Creates a new XuluGridFile out of an existing Writable Grid and opens it in read-write mode. The {@link WritableGrid}-Method
+	 * {@link WritableGrid#getSampleType() getSampleType} is used to determine the type and
+	 * the bytelength (4 bytes for Float/Int and 8 bytes for doubleValues);
+	 * @param grid
+	 * @param output
+	 * @throws XuluGridFileException
+	 */
+	public XuluGridFile(WritableGrid grid, File output)
+			throws XuluGridFileException {
+		this.outputFile = output;
+		//make a new MetaData object out of the grid
+		RasterMetaData metaData = new RasterMetaData(grid);
+
+		setByteLength(metaData);
+
+		//write the metadata file
+		writeWorldFileForMetaData(output, metaData);
+
+		// Write out the GridFile (32Bit and float only until now)
+		// for this go through the Grid line by line upwards
+
+		try {
+			output.createNewFile();
+			gridFile = new BufferedRandomAccessFile(output.getAbsolutePath(),
+					"rw", buffersize);
+
+		    for (int y = metaData.getMinY(); y < metaData.getHeight()
+					- metaData.getMinY(); y++)
+				for (int x = metaData.getMinY(); x < metaData.getWidth()
+						- metaData.getMinX(); x++)
+					gridFile.writeFloat(grid.getRasterSampleAsFloat(x, y));
+
+		    gridFile.close();
+
+		} catch (FileNotFoundException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		} catch (IOException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * Returns a partition of a {@link WritableGrid} as a
+	 * {@link WritableGridArray}. Notice, that the minX and minY values are
+	 * ignored and will be set to 0 (see {@link WritableGrid} for more
+	 * information about minX and minY). If the given {@link WritableGrid} is
+	 * not an instance of {@link WritableGridPartition} it is assumed that the
+	 * topLeft corner of the source grid is (0,0). If it is a
+	 * {@link WritableGridPartition} it is assumed that the the bounds of the
+	 * two Partition refer to the same coordinate system. Real coordinates are
+	 * supposed to reference the South(!)-West Corner.
+	 *
+	 * @param partitionBounds
+	 *            the rectangle describing the partition
+	 *
+	 * @return the new partition including the given corners
+	 * @throws XuluGridFileException
+	 *             if the reading goes wrong
+	 */
+	public WritableGridPartition getPartitialGrid2D(
+			Rectangle partitionBounds) throws XuluGridFileException {
+		synchronized (monitor){
+
+		// get Metadata of the big Grid
+		RasterMetaData bigMeta = this.metaData;
+
+		// create MetaData for the new partitial Grid
+		// Height an width of the partitial Grid
+		int pHeight = (int) partitionBounds.getHeight();
+		int pWidth = (int) partitionBounds.getWidth();
+
+		// real coordinates of the partitial Grid (which are referenced by the
+		// SW Corner)
+		double pX = partitionBounds.getX() * bigMeta.getCellWidth()
+				+ bigMeta.getX();
+		double pY = (partitionBounds.getY() + partitionBounds.getHeight() - 1)
+				* bigMeta.getCellHeight() + bigMeta.getY();
+		double pRealWidth = pWidth * bigMeta.getCellWidth();
+		double pRealHeight = pHeight * bigMeta.getCellHeight();
+
+		// the MetaData of the new Grid
+		RasterMetaData pMetaData = new RasterMetaData(bigMeta.getDataType(),
+				pWidth, pHeight, 0, 0, pX, pY, pRealWidth, pRealHeight, bigMeta.getCoordinateReferenceSystem());
+
+		// if the sourceGrid is a partition itself then we do not want to to
+		// start reading from (0,0)
+		// but shifted relative to the global coordinate system. So we calculate
+		// now the start values:
+
+		// for standard WritableGrids these are simply the bounds of the new
+		// partition...
+		int startX = (int) partitionBounds.getX();
+		int startY = (int) partitionBounds.getY();
+
+		try {
+			//seek to starting Position offset (= datavalues until startx)
+			long offset = ((startY) * metaData.getWidth() // number of rows to skip
+			+ startX) // number of Colums to skip
+					* dataValueSize; // length of one value in bytes
+			gridFile.seek(offset);
+			//the read-buffer is as wide as the grid (because we read line by line)
+			byte[] buffer = new byte[pWidth * dataValueSize];
+
+			// create empty return Grid
+			WritableGridPartition pGrid;
+
+			//switch structures are a bad smell, but necessary here because of the
+			//implementation of WritableGridArray
+			switch (bigMeta.getDataType()) {
+			case DataBuffer.TYPE_INT:
+				pGrid = new WritableGridArrayPartition.Integer(pMetaData,
+						getRootID(), partitionBounds);
+
+				// read the data into the raster from left to right and upwards
+				for (int y = 0; y < pHeight; y++) {
+					//for buffered reading read first into a bytearray
+					gridFile.read(buffer);
+					ByteArrayInputStream stream = new ByteArrayInputStream(
+							buffer);
+					for (int x = 0; x < pWidth; x++) {
+						int data = BufferedHelper.readIntFromStream(stream);
+						pGrid.setRasterSample(data, x, y);
+					}
+					//seek to the next input position (if not last row)
+					int seek = (metaData.getWidth() - pWidth) * dataValueSize;
+					if (!(y == pHeight - 1))
+						gridFile.skipBytes(seek);
+				}
+				break;
+
+			case DataBuffer.TYPE_DOUBLE:
+				pGrid = new WritableGridArrayPartition.Double(pMetaData,
+						getRootID(), partitionBounds);
+
+				// read the data into the raster from left to right and upwards
+				for (int y = 0; y < pHeight; y++) {
+					//for buffered reading read first into a bytearray
+					gridFile.read(buffer);
+					ByteArrayInputStream stream = new ByteArrayInputStream(
+							buffer);
+
+					for (int x = 0; x < pWidth; x++) {
+						double data = Double.longBitsToDouble(BufferedHelper
+								.readLongFromStream(stream));
+						pGrid.setRasterSample(data, x, y);
+					}
+					//seek to the next input position (if not last row)
+					int seek = (metaData.getWidth() - pWidth) * dataValueSize;
+					if (!(y == pHeight - 1))
+						gridFile.skipBytes(seek);
+				}
+				break;
+
+			case DataBuffer.TYPE_FLOAT:
+				pGrid = new WritableGridArrayPartition.Float(pMetaData,
+						getRootID(), partitionBounds);
+
+				// read the data into the raster from left to right and downwards
+				System.out.print("[getX]");
+				for (int y = 0; y < pHeight; y++) {
+					//for buffered reading read first into a bytearray
+					gridFile.read(buffer);
+					ByteArrayInputStream stream = new ByteArrayInputStream(
+							buffer);
+
+					for (int x = 0; x < pWidth; x++) {
+						float data = Float.intBitsToFloat(BufferedHelper
+								.readIntFromStream(stream));
+						pGrid.setRasterSample(data, x, y);
+					}
+
+					// seek to the next input position (if not last row)
+					int seek = (metaData.getWidth() - pWidth) * dataValueSize;
+					if (!(y == pHeight - 1)) {
+						long currentOffset = gridFile.getFilePointer();
+						if (currentOffset + seek > gridFile.length())
+							System.err.println("Error: offset was "
+									+ gridFile.getFilePointer()
+									+ " and seek was " + seek
+									+ " but file has only " + gridFile.length()
+									+ " bytes");
+						gridFile.skipBytes(seek);
+					}
+				}
+				break;
+			default:
+				throw new UnsupportedOperationException("No value found");
+			}
+			return pGrid;
+
+		} catch (IOException e) {
+
+			throw new XuluGridFileException(
+					"IOException while operating on XuluGridFile. Reason was: \n"
+							+ e.getCause());
+		}
+		}
+	}
+
+	/**
+	 *  @return the hashcode of this object
+	 *  @see SplittableResource#getRootID()
+	 */
+	public int getRootID() {
+		return this.hashCode();
+	}
+
+	/**
+	 * Overwrites the data at the location specified by the {@link Rectangle} with
+	 * the given partition-data. It is assumed that the topLeft corner is (0,0).
+	 * The method is synchronized over a static variable to ensure that only
+	 * one XuluGridFile is read/write at a time. This reduces (hopefully) harddisk
+	 * seek times and increases the overall performance.
+	 *
+	 * @param gridPartition the grid to be inserted
+	 * @param partitionBounds the excact location in coordinates of the baseGrid
+	 * @throws XuluGridFileException if the writing goes wrong
+	 */
+	public void setPartition(WritableGrid gridPartition,
+			Rectangle partitionBounds) throws XuluGridFileException {
+		synchronized (monitor){
+		//Check if partition and the rectangle fit
+		if ((gridPartition.getWidth() != partitionBounds.getWidth())
+				|| (gridPartition.getHeight() != partitionBounds.getHeight()))
+			throw new UnsupportedOperationException(
+					"The partition width/height does not match the rectangle width/height");
+
+		if (this.metaData.getDataType() != gridPartition.getSampleType())
+			throw new UnsupportedOperationException("Datatypes incompatible: "
+					+ this.metaData.getDataType() + "!="
+					+ gridPartition.getSampleType());
+		//the start coodinates
+		int startX = (int) partitionBounds.getX();
+		int startY = (int) partitionBounds.getY();
+		int pHeight = (int) partitionBounds.getHeight();
+		int pWidth = (int) partitionBounds.getWidth();
+
+		try {
+			//			seek to starting Position offset = datavalues until startx
+			long offset = ((startY) * metaData.getWidth() // number of rows to skip
+			+ startX) // number of Colums to skip
+					* dataValueSize; // length of one value in bytes
+			gridFile.seek(offset);
+			//the buffer is exactly as wide as the grid
+			ByteArrayOutputStream bos = new ByteArrayOutputStream(dataValueSize
+					* pWidth);
+
+			switch (this.metaData.getDataType()) {
+			case DataBuffer.TYPE_FLOAT:
+				System.out.print("[setX]");
+				for (int y = 0; y < pHeight; y++) {
+					for (int x = 0; x < pWidth; x++) {
+						float data = gridPartition.getRasterSampleAsFloat(x, y);
+						BufferedHelper
+								.writeInt(Float.floatToIntBits(data), bos);
+					}
+					//write buffered bytes to file
+					gridFile.write(bos.toByteArray());
+					//clear the bos
+					bos.reset();
+					// seek to the next input position
+					gridFile.skipBytes((metaData.getWidth() - pWidth)
+							* dataValueSize);
+				}
+				break;
+			case DataBuffer.TYPE_INT:
+				for (int y = 0; y < pHeight; y++) {
+					for (int x = 0; x < pWidth; x++) {
+						int data = gridPartition.getRasterSampleAsInt(x, y);
+						this.gridFile.writeInt(data);
+					}
+					// seek to the next input position
+					gridFile.skipBytes((metaData.getWidth() - pWidth)
+							* dataValueSize);
+				}
+				break;
+			case DataBuffer.TYPE_DOUBLE:
+				for (int y = 0; y < pHeight; y++) {
+					for (int x = 0; x < pWidth; x++) {
+						double data = gridPartition.getRasterSampleAsDouble(x,
+								y);
+						this.gridFile.writeDouble(data);
+					}
+					// seek to the next input position
+					gridFile.skipBytes((metaData.getWidth() - pWidth)
+							* dataValueSize);
+				}
+			}
+
+		} catch (Exception e) {
+			throw new XuluGridFileException(
+					"Error while writing in XuluGridFile");
+		}
+		}
+	}
+
+	/**
+	 * Closes all used Filehandles. Should be called before destroying the
+	 * object.
+	 */
+	public void close() {
+		try {
+			gridFile.close();
+		} catch (IOException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+	}
+
+
+	/**
+	 * @return the metadata for this object
+	 */
+	public RasterMetaData getMetaData() {
+		return metaData;
+	}
+
+	/**
+	 * The Xulu world file ist just a serialized RasterMetaData-Object!
+	 *
+	 * @param worldFile the world file
+	 * @return a {@link RasterMetaData} Object, that contains all the raster meta data
+	 * @throws XuluGridFileException if an error occures
+	 */
+	public RasterMetaData readXuluGridWorldFile(File worldFile)
+			throws XuluGridFileException {
+		try {
+			FileInputStream fis = new FileInputStream(worldFile);
+			ObjectInputStream ois = new ObjectInputStream(fis);
+			RasterMetaData meta = (RasterMetaData) ois.readObject();
+			ois.close();
+			fis.close();
+			return meta;
+
+		} catch (IOException e) {
+			throw new XuluGridFileException(
+					"IOException while reading Worldfile"
+							+ worldFile.toString());
+		} catch (ClassNotFoundException e) {
+			throw new XuluGridFileException(
+					"ClassNotFoundException while reading Worldfile"
+							+ worldFile.toString());
+		}
+	}
+
+	/**
+	 * Writes the given Grid to a XuluGridFile. Warning: unbuffered write.
+	 *
+	 * @param grid the input grid
+	 * @param output the output file
+	 * @throws XuluGridFileException if something goes wrong
+	 */
+	public static void writeToXuluGridFile(WritableGrid grid, File output)
+			throws XuluGridFileException {
+		RasterMetaData metaData = new RasterMetaData(grid);
+
+		writeWorldFileForMetaData(output, metaData);
+
+		// Write out the GridFile (32Bit and float only until now)
+		// for this go through the Grid line by line upwards
+
+		try {
+			output.createNewFile();
+			RandomAccessFile randomFile = new RandomAccessFile(output, "rw");
+			//              fos = new FileOutputStream(output);
+			//            BufferedOutputStream bos = new BufferedOutputStream(fos);
+			//            ObjectOutputStream oos = new ObjectOutputStream(bos);
+			for (int y = metaData.getMinY(); y < metaData.getHeight()
+					- metaData.getMinY(); y++)
+				for (int x = metaData.getMinY(); x < metaData.getWidth()
+						- metaData.getMinX(); x++)
+					randomFile.writeFloat(grid.getRasterSampleAsFloat(x, y));
+			//            oos.close();
+			//            bos.close();
+			//            fos.close();
+			randomFile.close();
+
+		} catch (FileNotFoundException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		} catch (IOException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * Writes data out of a XuluGridFile into a {@link WritableGrid}. Warning: unbuffered. May be slow.
+	 * For buffered read use {@link #getWholeGrid()} instead.
+	 * @param grid the Grid in which the data should be written
+	 * @param input the File with the XuluGridFile
+	 *
+	 * */
+	public static void readIntoGridFromXuluGridFile(WritableGrid grid,
+			File input) throws XuluGridFileException {
+		synchronized (monitor) {
+
+		RasterMetaData metaData = new RasterMetaData(grid);
+
+		// Read from File into the given grid
+
+		try {
+			RandomAccessFile randomFile = new RandomAccessFile(input, "r");
+			for (int y = metaData.getMinY(); y < metaData.getHeight()
+					- metaData.getMinY(); y++)
+				for (int x = metaData.getMinY(); x < metaData.getWidth()
+						- metaData.getMinX(); x++)
+					grid.setRasterSample(randomFile.readFloat(), x, y);
+
+		} catch (FileNotFoundException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		} catch (IOException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		}
+	}
+
+	/**
+	 * This File simply serializes the given {@link appl.util.RasterMetaData}
+	 * Object to the given file.
+	 */
+	public static void writeWorldFileForMetaData(File XuluGridFile,
+			RasterMetaData meta) throws XuluGridFileException {
+		try {
+			File xuluWorldFile = getWorldFileNameForGridFile(XuluGridFile);
+			xuluWorldFile.createNewFile();
+			FileOutputStream fos = new FileOutputStream(xuluWorldFile);
+			ObjectOutputStream oos = new ObjectOutputStream(fos);
+			oos.writeObject(meta);
+			oos.close();
+			fos.close();
+		} catch (FileNotFoundException e) {
+			throw new XuluGridFileException(
+					"Exception while processing WorldFile of XuluGridFile "
+							+ XuluGridFile);
+		} catch (IOException e) {
+			throw new XuluGridFileException(
+					"Exception while processing WorldFile of XuluGridFile "
+							+ XuluGridFile);
+		}
+	}
+
+
+	/**
+	 * Returns a worldfilename. For this the extension xgrid is replaced by xworld
+	 */
+	private static File getWorldFileNameForGridFile(File xuluGridFile)
+			throws XuluGridFileException {
+		checkFileName(xuluGridFile);
+		// create worldfilename by exchanging the file extension
+		File worldFile = new File(xuluGridFile.getAbsolutePath().replaceAll(
+				".xgrid$", ".xworld"));
+		return worldFile;
+	}
+
+	/**
+	 * Checks if the given filename is a valid grid file name. To be valid the name must end with .xgrid
+	 * @param xuluGridFile the file to be checked
+	 * @throws XuluGridFileException if this is not the case
+	 *
+	 */
+	static void checkFileName(File xuluGridFile) throws XuluGridFileException {
+		if (!xuluGridFile.getAbsolutePath().endsWith(".xgrid"))
+			throw new XuluGridFileException(
+					"XuluGridFiles must have the extension \".xgrid\"");
+
+	}
+
+	/**
+	 * gives back the whole grid as a {@link WritableGridArray} in memory! Notice
+	 * that this destroys all memory advantages of the GridFile. Is used e.g. by visualisation classes
+	 *
+	 */
+	public WritableGrid getWholeGrid() throws XuluGridFileException {
+		return getPartitialGrid2D(new Rectangle(0, 0, metaData.getWidth(),
+				metaData.getHeight()));
+	}
+
+	/**
+	 * @return the underlying file
+	 */
+	public File getOutputFile() {
+		return outputFile;
+	}
+
+}

Added: trunk/src/appl/parallel/data/xulugridfile/XuluGridFileConverter.java
===================================================================
--- trunk/src/appl/parallel/data/xulugridfile/XuluGridFileConverter.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/xulugridfile/XuluGridFileConverter.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,264 @@
+/*
+ *    Geotools2 - OpenSource mapping toolkit
+ *    http://geotools.org
+ *    (C) 2002, Geotools Project Managment Committee (PMC)
+ *
+ *    This library is free software; you can redistribute it and/or
+ *    modify it under the terms of the GNU Lesser General Public
+ *    License as published by the Free Software Foundation;
+ *    version 2.1 of the License.
+ *
+ *    This library is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *    Lesser General Public License for more details.
+ *
+ */
+package appl.parallel.data.xulugridfile;
+import org.geotools.gce.arcgrid.ArcGridRaster;
+import org.geotools.resources.NIOUtilities;
+
+import appl.util.RasterMetaData;
+
+import java.awt.image.DataBuffer;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.RandomAccessFile;
+import java.io.Reader;
+import java.io.StreamTokenizer;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import javax.media.jai.RasterFactory;
+
+
+/**
+ * This class converts a ArcGridInfo_ASCII file to a {@link XuluGridFile}. It directly writes from
+ * the the ArcGridInfo to the given file. It does not use the memory!
+ *
+ * It is a modified geotools import class. Buffering was added.
+ *
+ * @author Dominik Appl <br>
+ * For reading this class is based partly on the Geotools class {@link ArcGridRaster}. This was
+ * done to make sure that EVERY ArcInfoASCII can be read. The used {@link ArcGridRaster} was created by <br>
+ * @author <a href="mailto:ckl at dacelo.nl">Christiaan ten Klooster</a>
+ * @author <a href="mailto:aaime at users.sf.net">Andrea Aime</a>
+ * @author <a href="mailto:simboss_ml at tiscali.it">Simone Giannecchini
+ *         (simboss)</a>
+ * @see XuluGridFile
+ * @see http://svn.geotools.org/geotools/tags/2.2.0/plugin/arcgrid/src/org/geotools/gce/arcgrid/ArcGridRaster.java
+ */
+
+public class XuluGridFileConverter extends ArcGridRaster {
+
+    protected final File inputArcInfoGrid;
+	protected final File outputXuluGridFile;
+
+	/**
+	 * @throws FileNotFoundException
+	 */
+	public XuluGridFileConverter(File inputArcInfoGrid, File outputXuluGridFile) throws FileNotFoundException {
+		super(new BufferedReader(new InputStreamReader(new FileInputStream(inputArcInfoGrid))), false);
+		this.inputArcInfoGrid = inputArcInfoGrid;
+		this.outputXuluGridFile = outputXuluGridFile;
+	}
+
+
+   /**
+     * partly copied from Geotools. www.geotools.org.
+     *
+     * @param type the type of the values. Use the
+     * {@link DataBuffer} constants to identify the type
+     *
+     * @return the new XuluGridFile
+     *
+     * @throws IOException
+     * @throws XuluGridFileException
+     */
+    public XuluGridFile convertArcInfoToXuluGridFile(int type) throws IOException, XuluGridFileException {
+
+
+
+    	// open reader and make tokenizer
+        Reader reader = openReader();
+        StreamTokenizer st = new StreamTokenizer(reader);
+
+        // parse header
+        parseHeader(st);
+
+        //create metadata and outputFile
+        RasterMetaData meta = new RasterMetaData(type,getNCols(),getNRows(),0,0,getXlCorner(),getYlCorner(),getCellSize(),null);
+        RandomAccessFile outputFile = new RandomAccessFile(outputXuluGridFile,"rw");
+
+        // reconfigure tokenizer
+        st.resetSyntax();
+        st.parseNumbers();
+        st.whitespaceChars(' ', ' ');
+        st.whitespaceChars(' ', '\t');
+        st.whitespaceChars('\n', '\n');
+        st.whitespaceChars('\r', '\r'); //linefeed (on windows only?)
+        st.whitespaceChars('\f', '\f'); //form feed (on printers????)
+        st.eolIsSignificant(false);
+        st.ordinaryChars('E', 'E');
+
+
+
+        // Read values from grid and put into raster.
+        // Values must be numbers, which may be simple <num>, or expressed
+        // in scientific notation <num>E<exp>.
+        // The following loop can read both, even if mixed.
+        // The loop expects a token to be read already
+        st.nextToken();
+
+
+        for (int y = 0; y < getNRows(); y++) {
+        	ByteArrayOutputStream baos;
+        	if(type == DataBuffer.TYPE_DOUBLE)
+        		baos = new ByteArrayOutputStream(getNCols()*8);
+        	else
+        		baos = new ByteArrayOutputStream(getNCols()*4);
+
+        	for (int x = 0; x < getNCols(); x++) {
+                // this call always reads the next token
+                double d = readCell(st, x, y);
+
+                // mask no data values with NaN
+                if (d == getNoData()) {
+                    d = Double.NaN;
+                } else {
+                    minValue = Math.min(minValue, d);
+                    maxValue = Math.max(maxValue, d);
+                }
+                switch(type){
+                case DataBuffer.TYPE_FLOAT:
+                	BufferedHelper.writeInt(Float.floatToIntBits((float)d),baos);
+                break;
+                case DataBuffer.TYPE_DOUBLE:
+                	BufferedHelper.writeLong(Double.doubleToLongBits(d),baos);
+                case DataBuffer.TYPE_INT:
+                	BufferedHelper.writeInt((int)d,baos);
+                break;
+                default:
+                	throw new UnsupportedOperationException("Unsupported datatype");
+            }
+                outputFile.write(baos.toByteArray());
+                baos.reset();
+        }
+        }
+        reader.close();
+        try {
+			XuluGridFile.writeWorldFileForMetaData(outputXuluGridFile, meta);
+		} catch (XuluGridFileException e) {
+			throw new IOException ("Could not write WorldFile");
+		}
+        return new XuluGridFile(outputXuluGridFile,"rw");
+    }
+
+    /**
+     *copied unmodified form superclass (had to be copied, because the geotools method was private)
+     */
+    private double readCell(StreamTokenizer st, int x, int y)
+        throws IOException {
+        double d = 0;
+
+        // read a token, expected: a number
+        switch (st.ttype) {
+        case StreamTokenizer.TT_NUMBER:
+            d = (float) st.nval;
+
+            break;
+
+        case StreamTokenizer.TT_EOF:
+            throw new IOException("Unexpected EOF at " + x + "," + y);
+
+        default:
+            throw new IOException("Unknown token " + st.ttype);
+        }
+
+        // read another. May be an exponent of this number.
+        // If its not an exponent, its the next number. Fall through
+        // and token is prefetched for next loop...
+        switch (st.nextToken()) {
+        case 'e':
+        case 'E':
+
+            // now read the exponent
+            st.nextToken();
+
+            if (st.ttype != StreamTokenizer.TT_NUMBER) {
+                throw new IOException("Expected exponent at " + x + "," + y);
+            }
+
+            // calculate
+            d = d * Math.pow(10.0, st.nval);
+
+            // prefetch for next loop
+            st.nextToken();
+
+            break;
+
+        case StreamTokenizer.TT_NUMBER:
+        case StreamTokenizer.TT_EOF:
+            break;
+
+        default:
+            throw new IOException("Expected Number or EOF");
+        }
+
+        return d;
+    }
+
+   /** You can use this method to manually convert datatypes
+ * @param args
+ */
+public static void main(String[] args) {
+	   int type=DataBuffer.TYPE_FLOAT;
+	   if((args.length!=2 && args.length!=3)){
+		   parameterMessage();
+	   return;
+	   }
+	   if(!args[1].endsWith(".xgrid")){
+		   parameterMessage();
+		   return;
+	   }
+	   if(args.length==3){
+			if(args[2].equals("INT"))
+				type=DataBuffer.TYPE_INT;
+	   		if(args[2].equals("DOUBLE"))
+	   			type = DataBuffer.TYPE_DOUBLE;
+   		}
+		XuluGridFileConverter converter;
+		try {
+			converter = new XuluGridFileConverter(new File(args[0]),new File(args[1]));
+			converter.convertArcInfoToXuluGridFile(type);
+		} catch (FileNotFoundException e) {
+			System.out.println("Could not find file " + args[0]);
+		} catch (IOException e) {
+			System.out.println("IOException while converting: " + e.getMessage());
+		} catch (XuluGridFileException e) {
+			System.out.println("XuluGridFileException while converting: " + e.getMessage());
+		}
+
+
+   }
+   public static void parameterMessage(){
+   System.out.println("Syntax: XuluGridFileConverter Source Target [type], where \n" +
+   		"Source = a raster in the ArcInfo_ASCII format \n" +
+   		"Target = the new XuluGridFile with the extension .xgrid \n" +
+   		"[type] = (optional) the type of the XuluGridFile. Possible Values: INT,FLOAT,DOUBLE\n" +
+   		" default type is FLOAT");
+   }
+}
+

Added: trunk/src/appl/parallel/data/xulugridfile/XuluGridFileException.java
===================================================================
--- trunk/src/appl/parallel/data/xulugridfile/XuluGridFileException.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/xulugridfile/XuluGridFileException.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,14 @@
+package appl.parallel.data.xulugridfile;
+
+/**
+ * Is thrown if an error inside the XuluGridFile occours.
+ * 
+ * @author Dominik Appl
+ */
+public class XuluGridFileException extends Exception {
+
+    public XuluGridFileException(String message) {
+       super(message);// TODO Auto-generated constructor stub
+    }
+
+}

Added: trunk/src/appl/parallel/data/xulugridfile/XuluGridSharedFileSystemLoader.java
===================================================================
--- trunk/src/appl/parallel/data/xulugridfile/XuluGridSharedFileSystemLoader.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/xulugridfile/XuluGridSharedFileSystemLoader.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,133 @@
+package appl.parallel.data.xulugridfile;
+
+import java.awt.Rectangle;
+import java.io.File;
+import java.rmi.RemoteException;
+
+import appl.data.LoadingException;
+import appl.parallel.client.ClientDataServer;
+import appl.parallel.data.AbstractDataHandler;
+import appl.parallel.data.PartitionDataHandler;
+import appl.parallel.spmd.split.DataPartition;
+
+/**
+ * This is a loader for use with shared file systems like ocfs2 or gfs. It only
+ * works in conjunction with the {@link XuluWritableGridFile} and supports
+ * loading data from and into this file format. That means reading and writing
+ * is done directly into the file. The Xulu GUI won't notice changes if you do not
+ * reload the XuluWritableGrid!
+ * 
+ * @see XuluGridFile
+ * @see XuluWritableGridFile
+ * @see PartitionDataHandler
+ * 
+ * @author Dominik Appl
+ */
+public class XuluGridSharedFileSystemLoader extends AbstractDataHandler{
+	
+	private String gridFileName;
+	private transient XuluWritableGridFile xuluWritableGridFile;
+	
+	/**
+	 * constructs a new {@link XuluGridSharedFileSystemLoader}. 
+	 * 
+	 * @param rootID
+	 *            the id of the data
+	 * @param client
+	 *            a spmd client which may be used to get metainformation on
+	 *            client side before transfering the loader to its destination
+	 * @param partitionBounds
+	 *            the bounds of the partition to be retrieved on server side
+	 * @param unloadBounds
+	 *            the bounds of the partition which is to be uploaded to the
+	 *            client after calculation (may only be the calculation area)
+	 */
+	public XuluGridSharedFileSystemLoader(int rootID, ClientDataServer client, Rectangle partitionBounds, Rectangle unloadBounds) {
+		super(rootID, client, partitionBounds, unloadBounds);
+		DataPartition partition;
+		try {
+			partition = client.getData(rootID);
+			if (partition instanceof XuluWritableGridFile) {
+				XuluWritableGridFile xwg = (XuluWritableGridFile) partition;
+				gridFileName = xwg.getGridFileName();
+			}
+			else throw new UnsupportedOperationException("This Dataloader can only be used XuluGridFiles");
+		} catch (RemoteException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+	}
+	
+	
+	/**
+	 * only used by {@link #clone()}
+	 */
+	private XuluGridSharedFileSystemLoader(int rootID, ClientDataServer spmdClient, Rectangle partitionBounds, Rectangle unloadBounds, String gridFileName) {
+		super(rootID, null, partitionBounds, unloadBounds);
+		this.gridFileName=gridFileName;
+	}
+
+	/**
+	 * Used for deserialization. Do not use for other purposes
+	 */
+	public XuluGridSharedFileSystemLoader() {
+		super();
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.data.AbstractDataHandler#newInstance(int, appl.parallel.client.SPMDClient, java.awt.Rectangle, java.awt.Rectangle)
+	 */
+	public PartitionDataHandler newInstance(int rootID, ClientDataServer client, Rectangle partitionBounds, Rectangle unloadBounds) {
+		// TODO Auto-generated method stub
+		return new XuluGridSharedFileSystemLoader(rootID, client, partitionBounds, unloadBounds);
+	}
+	
+	/* (non-Javadoc)
+	 * @see appl.data.AbstractDataHandler#getLoadInfo()
+	 */
+	@Override
+	public String getLoadInfo() {
+		return "Trying to load " + gridFileName;
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.data.AbstractDataHandler#getUnloadInfo()
+	 */
+	@Override
+	public String getUnloadInfo() {
+		return "Trying to unload " + gridFileName;
+	}
+
+	/** loads the data directly from the gridfile 
+	 * @see appl.parallel.data.AbstractDataHandler#load()
+	 */
+	@Override
+	public DataPartition load() throws LoadingException {
+		//load from the gridfile
+		if(xuluWritableGridFile==null)
+			xuluWritableGridFile = new XuluWritableGridFile(new File(gridFileName));
+		data =  xuluWritableGridFile.getPartition(partitionBounds);
+		return data;
+	}
+
+	/** unloads into the file! not into the Xulu-Client or anything!
+	 */
+	@Override
+	public void unload() {
+		//unload to the local file
+		if(xuluWritableGridFile==null)
+			xuluWritableGridFile = new XuluWritableGridFile(new File(gridFileName));
+//		 construct return grid only if necessary
+		DataPartition returnPartition = null;
+		if (unloadBounds.equals(data.getPartitionBounds()))
+			returnPartition = data;
+		else
+			returnPartition = data.getPartition(unloadBounds);
+		xuluWritableGridFile.setPartition(returnPartition, unloadBounds);
+	}
+	
+	public PartitionDataHandler clone() {
+		return new XuluGridSharedFileSystemLoader(rootID, spmdClient, this.partitionBounds,
+				this.unloadBounds, this.gridFileName);
+	}
+}

Added: trunk/src/appl/parallel/data/xulugridfile/XuluWritableGridFile.java
===================================================================
--- trunk/src/appl/parallel/data/xulugridfile/XuluWritableGridFile.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/xulugridfile/XuluWritableGridFile.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,271 @@
+package appl.parallel.data.xulugridfile;
+
+import java.awt.Rectangle;
+import java.io.File;
+import java.io.FileNotFoundException;
+
+import schmitzm.data.WritableGrid;
+
+import edu.bonn.xulu.appl.XuluRegistry;
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.plugin.io.grid.WritableGridFactory;
+import appl.data.DataLoader;
+import appl.data.WritableGridArrayLoader;
+import appl.data.WritableGridLLProxy;
+import appl.parallel.spmd.split.DataPartition;
+import appl.parallel.spmd.split.SplittableGrid;
+import appl.parallel.spmd.split.SplittableResource;
+import appl.util.RasterMetaData;
+
+/**
+ * An implementation of a WritableGrid based on a {@link XuluGridFile}.
+ * 
+ * @author Dominik Appl
+ */
+public class XuluWritableGridFile extends WritableGridLLProxy implements SplittableGrid{
+	
+	private XuluGridFile gridFile;
+	private boolean wasWriteAccessed = false;
+	private final String directory;
+	private int rootID = this.hashCode();
+	private final File baseFile;
+
+	/**
+	 * Opens the GridFile at the given destination
+	 * @param gridfileName the filename of the XuluGridfile
+	 * 
+	 */
+	public XuluWritableGridFile(File gridfileName) {
+		super(null);
+		this.baseFile = gridfileName;
+		try {
+			gridFile = new XuluGridFile(gridfileName);
+		} catch (FileNotFoundException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		} catch (XuluGridFileException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		this.metaData = gridFile.metaData;
+		this.intialDataLoader = new GridFileDataLoader(gridFile);
+		this.dataLoader = new GridFileDataLoader(gridFile);
+		directory = null;
+	}
+	
+	
+	/**
+	 * Creates NEW a GridFile in the given directory with the given metadata-sample
+	 * 
+	 * @param metaData the metadata
+	 */
+	public XuluWritableGridFile(RasterMetaData metaData, String directory) {
+		super(metaData);
+		this.directory = directory;
+		baseFile = new File(directory + File.separatorChar + "xulugridFile"+ this.hashCode() + ".xgrid");
+		try {
+			gridFile = new XuluGridFile(baseFile,metaData);
+			this.intialDataLoader = new GridFileDataLoader(gridFile);
+			this.dataLoader = new GridFileDataLoader(gridFile);
+		} catch (XuluGridFileException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+			LOG.error(e);
+		
+		}
+		
+	}
+	
+	/** creates a instance out of a {@link XuluGridFile} */
+	public XuluWritableGridFile(XuluGridFile xuluGridFile) {
+		super(xuluGridFile.getMetaData());
+		baseFile = xuluGridFile.getOutputFile();
+		gridFile = xuluGridFile;
+		this.metaData = xuluGridFile.getMetaData();
+		this.intialDataLoader = new GridFileDataLoader(gridFile);
+		this.dataLoader = new GridFileDataLoader(gridFile);
+		// TODO Auto-generated constructor stub
+		this.directory=null;
+	}
+
+
+	/**
+	 * Creates a new XuluWritableGridFile in the specified directory, with the given metadata. 
+	 * The ID given in this constuctor will be the RootID of this Grid (used e.g. for 
+	 * identification in remoteComputing) 
+	 * 
+	 * @param newID the to be set as the new RootID (permanent)
+	 * @param metaData the metadata is used for creation of the bounds and the type of the new {@link XuluGridFile}
+	 * @param directory the directory in which the file should be created
+	 * @see SplittableResource#getRootID()
+	 */
+	public XuluWritableGridFile(int newID, RasterMetaData metaData, String directory) {
+		this(metaData,directory);
+		this.rootID  = newID;
+	}
+
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.SplittableResource#getLocalLoader()
+	 */
+	public DataLoader getLocalLoader() {
+		throw new UnsupportedOperationException("Feature not yet supported!");
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.SplittableResource#getRootID()
+	 */
+	public int getRootID() {
+		return rootID;
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.SplittableResource#getSplitHeight()
+	 */
+	public int getSplitHeight() {
+		return metaData.getHeight();
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.SplittableResource#getSplitWidth()
+	 */
+	public int getSplitWidth() {
+		return metaData.getWidth();
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.DataPartition#getEmpty(int)
+	 */
+	public DataPartition getEmpty(int newID) {
+		if(directory==null)
+		   throw new UnsupportedOperationException("Directory == null. Cant create a empty grid!");
+		return new XuluWritableGridFile(newID,this.metaData,this.directory);
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.DataPartition#getPartition(java.awt.Rectangle)
+	 */
+	public DataPartition getPartition(Rectangle partitionBounds) {
+		try {
+			return gridFile.getPartitialGrid2D(partitionBounds);
+		} catch (XuluGridFileException e) {
+			e.printStackTrace();
+			LOG.error("Could not retrieve partition from underlaying gridfile");
+		}
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.DataPartition#getPartitionBounds()
+	 */
+	public Rectangle getPartitionBounds() {
+		return new Rectangle(0,0,getWidth(),getHeight());
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.DataPartition#setPartition(appl.parallel.spmd.split.DataPartition, java.awt.Rectangle)
+	 */
+	public void setPartition(DataPartition partition, Rectangle partitionBounds) {
+		try {
+			gridFile.setPartition((WritableGrid) partition, partitionBounds);
+		} catch (XuluGridFileException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.data.WritableGridLLProxy#setGridSample(java.lang.Object, double[])
+	 */
+	@Override
+	public void setGridSample(Object value, double... coord) {
+		throw new UnsupportedOperationException("Writing on cell level is not yet supported. Use setPartition(..) to write to the Grid");
+		//wasWriteAccessed =true;
+//		super.setGridSample(value, coord);
+	}
+	
+	 /* (non-Javadoc)
+	 * @see appl.data.WritableGridLLProxy#setRasterSample(java.lang.Object, int[])
+	 */
+	public void setRasterSample(Object value, int... cell) {
+		 throw new UnsupportedOperationException("Writing on cell level is not yet supported. Use setPartition(..) to write to the Grid");
+
+	 }
+
+
+	/* (non-Javadoc)
+	 * @see appl.data.WritableGridLLProxy#getGridSample(double[])
+	 */
+	@Override
+	public Object getGridSample(double... coord) {
+		 throw new UnsupportedOperationException("Reading on cell level is not yet supported. Use getPartition(..) to read from the to the Grid");
+	}
+
+
+	/* (non-Javadoc)
+	 * @see appl.data.WritableGridLLProxy#getGridSampleAsByte(double[])
+	 */
+	@Override
+	public byte getGridSampleAsByte(double... coord) {
+		throw new UnsupportedOperationException("Reading on cell level is not yet supported. Use getPartition(..) to read from the to the Grid");
+	}
+
+
+	/* (non-Javadoc)
+	 * @see appl.data.WritableGridLLProxy#getGridSampleAsDouble(double[])
+	 */
+	@Override
+	public double getGridSampleAsDouble(double... coord) {
+		throw new UnsupportedOperationException("Reading on cell level is not yet supported. Use getPartition(..) to read from the to the Grid");
+	}
+
+
+	/* (non-Javadoc)
+	 * @see appl.data.WritableGridLLProxy#getGridSampleAsFloat(double[])
+	 */
+	@Override
+	public float getGridSampleAsFloat(double... coord) {
+		throw new UnsupportedOperationException("Reading on cell level is not yet supported. Use getPartition(..) to read from the to the Grid");
+	}
+
+
+	/* (non-Javadoc)
+	 * @see appl.data.WritableGridLLProxy#getGridSampleAsInt(double[])
+	 */
+	@Override
+	public int getGridSampleAsInt(double... coord) {
+		throw new UnsupportedOperationException("Reading on cell level is not yet supported. Use getPartition(..) to read from the to the Grid");
+	}
+
+
+	/* (non-Javadoc)
+	 * @see appl.data.WritableGridLLProxy#getGridSampleAsLong(double[])
+	 */
+	@Override
+	public long getGridSampleAsLong(double... coord) {
+		throw new UnsupportedOperationException("Reading on cell level is not yet supported. Use getPartition(..) to read from the to the Grid");
+	}
+
+
+	/* (non-Javadoc)
+	 * @see appl.data.WritableGridLLProxy#getGridSampleAsShort(double[])
+	 */
+	@Override
+	public short getGridSampleAsShort(double... coord) {
+		throw new UnsupportedOperationException("Reading on cell level is not yet supported. Use getPartition(..) to read from the to the Grid");
+	}
+	/**
+	 * unloading is not necessary (method does nothing
+	 * 
+	 * @see appl.data.LateLoadingProxy#unloadData()
+	 */
+	@Override
+	public synchronized void unloadData() {
+	}
+
+
+	public String getGridFileName() {
+		return baseFile.getPath();
+	}
+}

Added: trunk/src/appl/parallel/data/xulugridfile/factories/GridListFactory.java
===================================================================
--- trunk/src/appl/parallel/data/xulugridfile/factories/GridListFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/xulugridfile/factories/GridListFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,25 @@
+package appl.parallel.data.xulugridfile.factories;
+
+import edu.bonn.xulu.io.InstantiationFactory;
+
+// nur fuer Doku
+import schmitzm.data.WritableGrid;
+import edu.bonn.xulu.plugin.data.grid.GridList;
+
+/**
+ * Diese Factory erzeugt Standard-Instanzen von {@link GridList} mit
+ * durch die Factory {@link XuluGridFactory} erzeugten (auf Standard-Arrays
+ * basierenden) {@link WritableGrid}-Instanzen als Inhalt.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class GridListFactory extends edu.bonn.xulu.plugin.io.grid.awt.GridListFactory {
+  /**
+   * Liefert eine Instanz von {@link XuluGridFactory}, die auf
+   * Standard-Arrays basierende Instanzen von {@link WritableGrid} erzeugt. Mit diesen
+   * Instanzen wird die GridList gefuellt.
+   */
+  protected InstantiationFactory getWritableGridFactory() {
+    return new XuluGridFactory();
+  }
+}

Added: trunk/src/appl/parallel/data/xulugridfile/factories/GridListFactory_ArcInfoAsciiGrid.java
===================================================================
--- trunk/src/appl/parallel/data/xulugridfile/factories/GridListFactory_ArcInfoAsciiGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/xulugridfile/factories/GridListFactory_ArcInfoAsciiGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,180 @@
+package appl.parallel.data.xulugridfile.factories;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+
+import appl.data.DataProxy;
+import appl.data.WritableGridLLProxy;
+import appl.ext.XuluConfig;
+import appl.parallel.data.xulugridfile.XuluGridFile;
+import appl.parallel.data.xulugridfile.XuluGridFileConverter;
+import appl.parallel.data.xulugridfile.XuluWritableGridFile;
+import appl.util.RasterUtil;
+
+import schmitzm.io.IOUtil;
+import schmitzm.data.WritableGrid;
+import schmitzm.data.WritableGridArray;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyReadAccess;
+
+import edu.bonn.xulu.io.Factory;
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+import edu.bonn.xulu.plugin.data.grid.GridList;
+import edu.bonn.xulu.plugin.io.grid.array.WritableGridArrayFactory_ArcInfoAsciiGrid;
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link GridList} aus/in Dateien im ArcInfo-ASCII-Grid-Format.
+ * Beim Import liefert die Factory eine Standard-Arrays basierendes Raster-Liste
+ * ({@link WritableGridArray}).
+ * Entsprechend koennen beim Export nur {@link GridList GridLists}
+ * verarbeitet werden, die {@link WritableGridArray}-Instanzen in ihrer
+ * Raster-Property besitzen.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class GridListFactory_ArcInfoAsciiGrid extends AbstractFactory implements ImportFactory,ExportFactory {
+ private static final ImportFactory importFac = new WritableGridArrayFactory_ArcInfoAsciiGrid();
+ private static final ExportFactory exportFac = new WritableGridArrayFactory_ArcInfoAsciiGrid();
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link GridList GridList.class}
+   */
+  public Class getImportType() {
+    return GridList.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File[].class}
+   */
+  public Class getImportSourceType() {
+     return File[].class;
+  }
+
+  /**
+   * Importiert Raster aus Dateien im ArcInfoAsciiGrid-Format
+   * und fuegt diese in einer {@link GridList} zusammen.
+   * @param input Eingabe-Quelle (muss ein {@link File File[]} sein!)
+   * @param reg   Instanz der Xulu-Registry, ueber die eine Factory ermittelt
+   *              wird, die eine Standard-Instanz von {@link GridList} erzeugt, in
+   *              die das Objekt importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Dateien angegeben werden
+   */
+  public GridList importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+    InstantiationFactory instFac = AbstractFactory.getInstantiationFactoryFromRegistry(reg,getImportType(),true);
+    GridList sg = (GridList)instFac.newInstance(false);
+    // Raster importieren und in GridList einfuegen
+    for (int i=0; i<((Object[])input).length; i++){
+    	//take the first File
+    	File inputFile = (File) ((Object[]) input)[i];
+        File outputFile = new File(inputFile.getAbsoluteFile()+".xgrid");
+        //check if already a gridFile (should not be..)
+        XuluGridFile xuluGridFile;
+        if(inputFile.getAbsolutePath().endsWith(".xgrid"))
+        	xuluGridFile = new XuluGridFile(inputFile);
+        else
+        {	
+        //check if a the import should be converted even if a xulugridfile with the same name exists
+        boolean alwaysreload = XuluConfig.getXuluConfig().getBooleanProperty("Datatypes.xulugrid.alwaysconvert");		
+        //only convert if nessecary
+        if(alwaysreload || (!outputFile.exists())){
+        	 //the ArcInfoGrid must be converted to XuluGridFile
+            XuluGridFileConverter converter = new XuluGridFileConverter(inputFile,outputFile);
+            int dataType = RasterUtil.getRasterMetaData_from_ArcGridASCII_File(inputFile).getDataType();
+            xuluGridFile = converter.convertArcInfoToXuluGridFile(dataType);
+        }
+        else
+        	xuluGridFile = new XuluGridFile(outputFile);
+        }
+        WritableGrid grid = new XuluWritableGridFile(xuluGridFile);
+    sg.addGrid(grid);
+    }
+    //    // Dateinamen in die Bezeichnung aufnehmen
+//    sg.setDescription(sg.getDescription().concat(" [").concat(((File)input).getName()).concat("]"));
+    return sg;
+  }
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um eine {@link GridList} handelt, die nur Instanzen
+   * von {@link WritableGridArray} als Elemente enthaelt.
+   * @param obj zu pruefendes Objekt
+   */
+  public boolean isExportable(Object obj) {
+    if ( obj==null || !(obj instanceof GridList) )
+      return false;
+    GridList list = (GridList)obj;
+    for (int i=0; i<list.getGridCount(); i++)
+      if ( !(list.getGrid(i) instanceof WritableGridLLProxy) )
+        return false;
+    return true;
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link GridList} (oder eine Unterklasse)
+   * handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return GridList.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt. Dabei handelt es sich um eine <b>einzelne Datei</b>, da
+   * die die letztendlichen Export-Dateien automatisch durchnummeriert werden!!
+   * @return immer {@link File File.class}
+   */
+  public Class getExportDestinationType() {
+    return File.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link GridList} in Dateien des
+   * ArcInfoAsciiGrid-Formats.<br>
+   * <b>Beachte:</b><br>
+   * Als Ausgabe-Objekt ist eine <b>einzelne</b> Datei anzugeben, kein
+   * Array! Die Dateien werden ausgehend von dem angegebenen Dateinamen
+   * durchnummeriert!!
+   * @param object zu exportiertende Raster (muss eine {@link GridList} sein
+   * @param output Export-Ziel (muss ein einzelner {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel keine
+   *            einzelne Datei angegeben wird
+   * @exception IllegalArgumentException falls es sich bei dem angegeben Objekt
+   *            nicht um eine {@link GridList} handelt
+   */
+  public void exportObject(Object object, Object output) throws Exception {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(object) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(object.getClass().getName()));
+
+    // Dateinamen-Teile ermitteln
+    String fileName = IOUtil.getBaseFileName((File)output);
+    String fileExt  = IOUtil.getFileExt((File)output);
+
+    // Grids in der Liste einzeln exportieren
+    ListPropertyReadAccess listAccess = ((ListProperty) (((GridList)object).getProperty(GridList.PROP_GRIDS))).getReadAccess(this);
+    for (int i=0; i<listAccess.getCount(); i++) {
+      File outFile = new File( fileName.concat("_"+i).concat(fileExt) );
+      exportFac.exportObject( ((DataProxy)listAccess.getValue(i)).getProxiedObject() ,new FileOutputStream(outFile) );
+    }
+    listAccess.release();
+
+  }
+}

Added: trunk/src/appl/parallel/data/xulugridfile/factories/MultiGridFactory.java
===================================================================
--- trunk/src/appl/parallel/data/xulugridfile/factories/MultiGridFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/xulugridfile/factories/MultiGridFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,25 @@
+package appl.parallel.data.xulugridfile.factories;
+
+import edu.bonn.xulu.plugin.io.grid.WritableGridFactory;
+// nur fuer Doku
+import schmitzm.data.WritableGrid;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+
+/**
+ * Diese Factory erzeugt Standard-Instanzen von {@link MultiGrid} mit
+ * durch die Factory {@link XuluGridFactory} erzeugten (auf Standard-Arrays
+ * basierenden) {@link WritableGrid}-Instanzen als Inhalt.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class MultiGridFactory extends edu.bonn.xulu.plugin.io.grid.awt.MultiGridFactory {
+  /**
+   * Liefert eine Instanz von {@link XuluGridFactory}, die auf Standard-Arrays
+   * basierende Instanzen von {@link WritableGrid} erzeugt. Mit diesen
+   * Instanzen wird die GridList gefuellt.
+   */
+  protected WritableGridFactory getWritableGridFactory() {
+    return new XuluGridFactory();
+  }
+
+}

Added: trunk/src/appl/parallel/data/xulugridfile/factories/MultiGridFactory_ArcInfoAsciiGrid.java
===================================================================
--- trunk/src/appl/parallel/data/xulugridfile/factories/MultiGridFactory_ArcInfoAsciiGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/xulugridfile/factories/MultiGridFactory_ArcInfoAsciiGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,114 @@
+package appl.parallel.data.xulugridfile.factories;
+
+import java.io.File;
+import java.io.FileInputStream;
+
+import appl.data.WritableGridLLProxy;
+import appl.ext.XuluConfig;
+import appl.parallel.data.xulugridfile.XuluGridFile;
+import appl.parallel.data.xulugridfile.XuluGridFileConverter;
+import appl.parallel.data.xulugridfile.XuluWritableGridFile;
+import appl.util.RasterUtil;
+
+import schmitzm.data.WritableGrid;
+
+import edu.bonn.xulu.appl.XuluRegistry;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.io.ImportFactory;
+
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+import edu.bonn.xulu.plugin.data.grid.GridList;
+import edu.bonn.xulu.plugin.io.grid.WritableGridFactory;
+import edu.bonn.xulu.plugin.io.grid.array.WritableGridArrayFactory_ArcInfoAsciiGrid;
+//import edu.bonn.xulu.plugin.io.grid.gt.GridListFactory_ArcInfoAsciiGrid;
+
+// nur fuer Doku
+import schmitzm.data.WritableGridArray;
+import edu.bonn.xulu.io.InstantiationFactory;
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link MultiGrid} aus/in Dateien im ArcInfo-ASCII-Grid-Format.
+ * Beim Import liefert die Factory eine Standard-Arrays basierendes Raster-Liste
+ * ({@link WritableGridArray}).
+ * Entsprechend koennen beim Export nur {@link MultiGrid MultiGrids}
+ * verarbeitet werden, die {@link WritableGridArray}-Instanzen in ihrer
+ * Raster-Property besitzen.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class MultiGridFactory_ArcInfoAsciiGrid extends GridListFactory_ArcInfoAsciiGrid {
+  private static final ImportFactory importFac = new WritableGridArrayFactory_ArcInfoAsciiGrid();
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link MultiGrid MultiGrid.class}
+   */
+  public Class getImportType() {
+    return MultiGrid.class;
+  }
+
+  /**
+   * Importiert Raster aus Dateien im ArcInfoAsciiGrid-Format
+   * und fuegt diese in einem {@link MultiGrid} zusammen.
+   * @param input Eingabe-Quelle (muss ein {@link File File[]} sein!)
+   * @param reg   Instanz der Xulu-Registry, ueber die eine Factory ermittelt
+   *              wird, die eine Standard-Instanz von {@link MultiGrid} erzeugt, in
+   *              die das Objekt importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Dateien angegeben werden
+   */
+  public MultiGrid importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+
+    // MultiGrid erst erzeugen, wenn ein Beispiel-Raster vorliegt
+    MultiGrid mg = null;
+    // Raster importieren und in GridList einfuegen
+    for (int i=0; i<((Object[])input).length; i++) {
+    	File inputFile = (File) ((Object[]) input)[i];
+        File outputFile = new File(inputFile.getAbsoluteFile()+".xgrid");
+        //check if already a gridFile (should not be..)
+        XuluGridFile xuluGridFile;
+        if(inputFile.getAbsolutePath().endsWith(".xgrid"))
+        	xuluGridFile = new XuluGridFile(inputFile);
+        else
+        {	
+        //check if a the import should be converted even if a xulugridfile with the same name exists
+        boolean alwaysreload = XuluConfig.getXuluConfig().getBooleanProperty("Datatypes.xulugrid.alwaysconvert");		
+        //only convert if nessecary
+        if(alwaysreload || (!outputFile.exists())){
+        	 //the ArcInfoGrid must be converted to XuluGridFile
+            XuluGridFileConverter converter = new XuluGridFileConverter(inputFile,outputFile);
+            int dataType = RasterUtil.getRasterMetaData_from_ArcGridASCII_File(inputFile).getDataType();
+            xuluGridFile = converter.convertArcInfoToXuluGridFile(dataType);
+        }
+        else
+        	xuluGridFile = new XuluGridFile(outputFile);
+        }
+        WritableGrid grid = new XuluWritableGridFile(xuluGridFile);
+    	
+    	
+    	
+    	
+      // das erste Grid dient dem MultiGrid als Vorlage
+      if ( mg == null )
+        mg = new MultiGrid(grid,getWritableGridFactory());
+
+      mg.addGrid(grid);
+    }
+    return mg;
+  }
+
+  /**
+   * Liefert eine Instanz von {@link XuluGridFactory}, die auf Standard-Arrays
+   * basierende Instanzen von {@link WritableGrid} erzeugt. Mit diesen
+   * Instanzen wird das SingleGrid gefuellt.
+   */
+  protected WritableGridFactory getWritableGridFactory() {
+    return new XuluGridFactory();
+  }
+
+}

Added: trunk/src/appl/parallel/data/xulugridfile/factories/SingleGridFactory.java
===================================================================
--- trunk/src/appl/parallel/data/xulugridfile/factories/SingleGridFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/xulugridfile/factories/SingleGridFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,23 @@
+package appl.parallel.data.xulugridfile.factories;
+
+import edu.bonn.xulu.io.InstantiationFactory;
+// nur fuer Doku
+import schmitzm.data.WritableGrid;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+
+/**
+ * Diese Factory erzeugt Standard-Instanzen von {@link SingleGrid} mit einem
+ * durch die Factory {@link XuluGridFactory} erzeugten {@link WritableGrid}.
+ * @author Dominik Appl
+ * @version 1.0
+ */
+public class SingleGridFactory extends edu.bonn.xulu.plugin.io.grid.awt.SingleGridFactory{
+
+  /**
+   * Liefert eine Instanz von {@link XuluGridFactory}. Mit diesen
+   * Instanzen wird das SingleGrid gefuellt.
+   */
+  protected InstantiationFactory getWritableGridFactory() {
+    return new XuluGridFactory();
+  }
+}

Added: trunk/src/appl/parallel/data/xulugridfile/factories/SingleGridFactory_ArcInfoAsciiGrid.java
===================================================================
--- trunk/src/appl/parallel/data/xulugridfile/factories/SingleGridFactory_ArcInfoAsciiGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/xulugridfile/factories/SingleGridFactory_ArcInfoAsciiGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,152 @@
+package appl.parallel.data.xulugridfile.factories;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+
+import appl.data.DataProxy;
+import appl.data.WritableGridLLProxy;
+import appl.ext.XuluConfig;
+import appl.parallel.data.xulugridfile.XuluGridFile;
+import appl.parallel.data.xulugridfile.XuluGridFileConverter;
+import appl.parallel.data.xulugridfile.XuluWritableGridFile;
+import appl.util.RasterMetaData;
+import appl.util.RasterUtil;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.WritableGridArray;
+
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+import edu.bonn.xulu.plugin.io.grid.array.WritableGridArrayFactory_ArcInfoAsciiGrid;
+
+// nur fuer Doku
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link SingleGrid} aus/in das ArcInfo-ASCII-Grid-Format.
+
+ * @author Dominik Appl
+ * @version 1.0
+ */
+public class SingleGridFactory_ArcInfoAsciiGrid extends AbstractFactory implements ImportFactory, ExportFactory {
+  private static final ImportFactory importFac = new WritableGridArrayFactory_ArcInfoAsciiGrid();
+  private static final ExportFactory exportFac = new WritableGridArrayFactory_ArcInfoAsciiGrid();
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link SingleGrid SingleGrid.class}
+   */
+  public Class getImportType() {
+    return SingleGrid.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getImportSourceType() {
+    return File.class;
+  }
+
+  /**
+   * Importiert eine Instanz von {@link SingleGrid} aus einer Datei im
+   * ArcInfoAsciiGrid-Format.
+   * @param input Eingabe-Quelle (muss ein {@link File} sein!)
+   * @param reg   Instanz der Xulu-Registry, ueber die eine Factory ermittelt
+   *              wird, die eine Standard-Instanz von {@link SingleGrid} erzeugt, in
+   *              die das Raster importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Datei angegeben wird
+   */
+  public SingleGrid importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+    // Aus Registry die passende Factory fuer SingleGrid suchen
+    InstantiationFactory instFac = AbstractFactory.getInstantiationFactoryFromRegistry(reg,getImportType(),true);
+    // Raster importieren und in ein SingleGrid einfuegen
+    SingleGrid sg = (SingleGrid)instFac.newInstance(false);
+    File inputFile = (File) input;
+    File outputFile = new File(inputFile.getAbsoluteFile()+".xgrid");
+    //check if already a gridFile (should not be..)
+    XuluGridFile xuluGridFile;
+    if(((File)input).getAbsolutePath().endsWith(".xgrid"))
+    	xuluGridFile = new XuluGridFile((File)input);
+    else
+    {	
+    //check if a the import should be converted even if a xulugridfile with the same name exists
+    boolean alwaysreload = XuluConfig.getXuluConfig().getBooleanProperty("Datatypes.xulugrid.alwaysconvert");		
+    //only convert if nessecary
+    if(alwaysreload || (!outputFile.exists())){
+    	 //the ArcInfoGrid must be converted to XuluGridFile
+        XuluGridFileConverter converter = new XuluGridFileConverter(inputFile,outputFile);
+        int dataType = RasterUtil.getRasterMetaData_from_ArcGridASCII_File((File) input).getDataType();
+        xuluGridFile = converter.convertArcInfoToXuluGridFile(dataType);
+    }
+    else
+    	xuluGridFile = new XuluGridFile(outputFile);
+    }
+    WritableGrid grid = new XuluWritableGridFile(xuluGridFile);
+    sg.setGrid(grid);
+    // Dateinamen in die Bezeichnung aufnehmen
+    sg.setDescription(sg.getDescription().concat(" [").concat(((File)input).getName()).concat("]"));
+    return sg;
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um ein {@link SingleGrid} handelt, das ein
+   * {@link WritableGridArray} in seiner Raster-Eigenschaft besitzt.
+   * @param obj zu pruefendes Objekt
+   */
+  public boolean isExportable(Object obj) {
+    return obj!=null &&
+           obj instanceof SingleGrid &&
+           ((SingleGrid)obj).getGrid() instanceof XuluWritableGridFile;
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link SingleGrid} (oder eine Unterklasse)
+   * handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return SingleGrid.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getExportDestinationType() {
+    return File.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link SingleGrid} in eine ArcInfoAsciiGrid-Datei.
+   * @param grid zu exportiertendes Raster (muss ein {@link SingleGrid} sein
+   * @param output Export-Ziel (muss ein {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel keine
+   *            Datei angegeben wird
+   * @exception IllegalArgumentException falls es sich bei dem angegeben Raster
+   *            nicht um ein {@link SingleGrid} handelt
+   */
+  public void exportObject(Object grid, Object output) throws Exception {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(grid) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(grid.getClass().getName()));
+    exportFac.exportObject( ((DataProxy)((SingleGrid)grid).getGrid()).getProxiedObject(), new FileOutputStream((File)output) );
+  }
+
+}

Added: trunk/src/appl/parallel/data/xulugridfile/factories/XuluGridFactory.java
===================================================================
--- trunk/src/appl/parallel/data/xulugridfile/factories/XuluGridFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/xulugridfile/factories/XuluGridFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,65 @@
+package appl.parallel.data.xulugridfile.factories;
+
+import java.awt.geom.Rectangle2D;
+import java.awt.image.DataBuffer;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+import appl.data.WritableGridLLProxy;
+import appl.ext.XuluConfig;
+import appl.parallel.data.xulugridfile.XuluGridFile;
+import appl.parallel.data.xulugridfile.XuluWritableGridFile;
+import appl.util.RasterMetaData;
+import schmitzm.data.WritableGrid;
+import edu.bonn.xulu.plugin.io.grid.WritableGridFactory;
+import edu.bonn.xulu.plugin.io.grid.array.WritableGridArrayFactory;
+
+// nur fuer Doku
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.io.Factory;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+
+/**
+ *Creates instances of the memory saving data type {@link XuluGridFile} for the use in the Xulu
+ *Plattform.
+ *
+ * @author Dominik Appl
+ * @version 1.0
+ */
+public class XuluGridFactory extends WritableGridFactory {
+
+	/**
+	 * Liefert den Datentyp, den die Factory erzeugt.
+	 * @return immer {@link XuluWritableGridFile XuluWritableGridFile.class}
+	 */
+	public Class getInstanceType() {
+		return XuluWritableGridFile.class;
+	}
+
+	/**
+	 * Creates a new grid under the directory given under
+	 * @param type    Datentyp der gespeicherten Objekte
+	 * @param widthc  Breite in Zellen
+	 * @param heightc Hoehe in Zellen
+	 * @param minX    Index der ersten Zelle in X-Richtung
+	 * @param minY    Index der ersten Zelle in Y-Richtung
+	 * @param x       Georeferenz Latitude (Suedliche/Untere Kante)
+	 * @param y       Georeferenz Longitute (Westliche/Linke Kante)
+	 * @param width   Breite
+	 * @param height  Hoehe
+	 */
+	public WritableGridLLProxy newInstance(int type, int widthc, int heightc,
+			int minX, int minY, double x, double y, double width,
+			double height, CoordinateReferenceSystem crs) {
+
+		String directory = XuluConfig.getXuluConfig().getProperty(
+				"Datatypes.xulugrid.creationFolder");
+		if (directory == null)
+			directory = "Temp";
+
+		return new XuluWritableGridFile(new RasterMetaData(type, widthc,
+				heightc, minX, minY, x, y, width, height, crs), directory);
+	}
+}

Added: trunk/src/appl/parallel/data/xulugridfile/factories/package.html
===================================================================
--- trunk/src/appl/parallel/data/xulugridfile/factories/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/xulugridfile/factories/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,5 @@
+<html>
+<body>
+	The factories needed for loading the xuluWritableGridFile-Datatype into the xulu-plattform.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/parallel/data/xulugridfile/package.html
===================================================================
--- trunk/src/appl/parallel/data/xulugridfile/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/data/xulugridfile/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,8 @@
+<html>
+<body>
+	Contains classes related to the xulugridfile format. The XuluGridFile format is a special
+	file format which stores all values of a grid in a binary format that allows random access.
+	It allows the retrieval of partitions of itself without loading the whole file
+	into memory.  
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/parallel/event/CommEvent.java
===================================================================
--- trunk/src/appl/parallel/event/CommEvent.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/event/CommEvent.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,117 @@
+package appl.parallel.event;
+
+/**
+ * A {@link CommEvent} is a {@link RemoteEvent}. It gives Information about
+ * Events related to Communication.
+ * 
+ * @author Dominik Appl
+ */
+public class CommEvent extends RemoteEvent {
+
+	/**
+	 * The target of the event
+	 */
+	protected final String target;
+
+	/**
+	 * The source of the event
+	 */
+	protected final String src;
+
+	/**
+	 * the type of the event
+	 */
+	protected final CommType type;
+
+	/**
+	 * @author Dominik Appl
+	 */
+	public enum CommType {
+		/**
+		 * A not further specified type
+		 */
+		UNDEFINED,
+		/**
+		 * A Server has made an update from a source (possibly another server)
+		 */
+		REMOTE_UPDATE,
+		/**
+		 * A Server has executed a task (without client-server communication)
+		 */
+		REMOTE_EXECUTION,
+		/**
+		 * A Client has executed a Task (including communication)
+		 */
+		CLIENT_EXECUTION,
+		/**
+		 * A client has invoked an update
+		 */
+		CLIENT_UPDATE,
+		/**
+		 * A client has invoked a merge
+		 */
+		CLIENT_MERGE,
+		/**
+		 * Parameters were transfered
+		 */
+		TRANSFER_PARAMETERS,
+		/**
+		 * meta data was transfered
+		 */
+		TRANSFER_METADATA,
+		/**
+		 * data was transfered
+		 */
+		TRANSFER_DATA,
+		/**
+		 * Connection to servers were made
+		 */
+		CONNECT,
+		/**
+		 * The client disconnects from the servers
+		 */
+		DISCONNECT,
+	}
+
+	/**
+	 * A new CommEvent
+	 * 
+	 * @param src
+	 *            the source of the event
+	 * @param target
+	 *            the target
+	 * @param type
+	 *            the type
+	 */
+	CommEvent(String src, String target, CommType type) {
+		this.target = (target == null) ? "" : target;
+		this.src = (src == null) ? "" : src;
+		this.type = (type == null) ? CommType.UNDEFINED : type;
+	}
+
+	/**
+	 * @return the target
+	 */
+	public String getTarget() {
+		return target;
+	}
+
+	/**
+	 * @return the source
+	 */
+	public String getSrc() {
+		return src;
+	}
+
+	/**
+	 * @return the type
+	 */
+	public CommType getType() {
+		return type;
+	}
+
+	public String typeName() {
+		return type.toString();
+	}
+
+}
\ No newline at end of file

Added: trunk/src/appl/parallel/event/CommEventSink.java
===================================================================
--- trunk/src/appl/parallel/event/CommEventSink.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/event/CommEventSink.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,32 @@
+package appl.parallel.event;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+//doc
+import appl.parallel.client.RemoteEventHandler;
+import appl.parallel.services.RemoteEventProxy;
+
+
+/**
+ * A event sink for communication events receives {@link TimeEvent}s and {@link TransferEvent}s 
+ * and processes them. 
+ * 
+ * @see RemoteEventHandler
+ * @see RemoteEventProxy
+ * @author Dominik Appl
+ */
+public interface CommEventSink extends Remote, RemoteEventSink {
+
+	
+	/**
+	 * @return true if the service is running and time monitoring is enabled
+	 */
+	public boolean isTimeMonitoringEnabled() throws RemoteException;
+
+	/**
+	 * @return true if the service is running and transfer monitoring is enabled
+	 */
+	public boolean isTransferMonitoringEnabled() throws RemoteException;
+	
+}

Added: trunk/src/appl/parallel/event/RemoteEvent.java
===================================================================
--- trunk/src/appl/parallel/event/RemoteEvent.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/event/RemoteEvent.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,12 @@
+package appl.parallel.event;
+
+import java.io.Serializable;
+
+/**
+ * A event which may be thrown over a network
+ * 
+ * @author Dominik Appl
+ */
+public class RemoteEvent implements Serializable {
+
+}

Added: trunk/src/appl/parallel/event/RemoteEventSink.java
===================================================================
--- trunk/src/appl/parallel/event/RemoteEventSink.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/event/RemoteEventSink.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,18 @@
+package appl.parallel.event;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+/**
+ * A EventSink fires {@link RemoteEvent}s from a possibly remote source and
+ * processes them. May be an EventHandler.
+ * 
+ * @author Dominik Appl
+ */
+public interface RemoteEventSink extends Remote {
+
+	public void fireRemoteEvent(RemoteEvent e) throws RemoteException;
+
+	public void fireRemoteEvents(RemoteEvent[] e) throws RemoteException;
+
+}

Added: trunk/src/appl/parallel/event/SimpleConsoleMonitor.java
===================================================================
--- trunk/src/appl/parallel/event/SimpleConsoleMonitor.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/event/SimpleConsoleMonitor.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,80 @@
+package appl.parallel.event;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import appl.parallel.client.RemoteEventHandler;
+import appl.parallel.client.RemoteExecutionController;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.AbstractXuluPlugin;
+import edu.bonn.xulu.appl.XuluPlugin;
+
+/**
+ * A simple {@link XuluPlugin} that outputs received {@link TimeEvent}s 
+ * and {@link TransferEvent}s to the console.
+ * 
+ * @author Dominik Appl
+ */
+public class SimpleConsoleMonitor extends AbstractXuluPlugin implements
+		TimeMonitor, TransferMonitor {
+
+	protected final Logger LOG = LogManager
+			.getLogger(this.getClass().getName());
+
+	RemoteEventHandler eventProxy;
+
+	public SimpleConsoleMonitor() {
+		super(false);
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.event.TimeMonitor#receiveTimeEvent(appl.parallel.event.TimeEvent)
+	 */
+	public void receiveTimeEvent(TimeEvent t) {
+		System.out.println(t);
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.event.TransferMonitor#receiveTransferEvent(appl.parallel.event.TransferEvent)
+	 */
+	public void receiveTransferEvent(TransferEvent t) {
+		System.out.println(t);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see edu.bonn.xulu.appl.XuluPlugin#execute(edu.bonn.xulu.XuluModellingPlatform)
+	 */
+	public void execute(XuluModellingPlatform appl) {
+		super.execute(appl);
+		RemoteExecutionController controller = RemoteExecutionController
+				.getRemoteExecutionController(appl);
+		if (controller == null) {
+			LOG
+					.error("Could not find RemoteExecutionController! -> Could not start SimpleConsoleMonitor");
+			return;
+		}
+		eventProxy = controller.getEventProxy();
+		eventProxy.addTimeEventListener(this);
+		eventProxy.addTransferEventListener(this);
+		started = true;
+	}
+
+	@Override
+	public void stop() {
+		eventProxy.removeTimeMonitor(this);
+		eventProxy.removeTransferMonitor(this);
+		// TODO Auto-generated method stub
+		super.stop();
+	}
+}

Added: trunk/src/appl/parallel/event/TimeEvent.java
===================================================================
--- trunk/src/appl/parallel/event/TimeEvent.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/event/TimeEvent.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,50 @@
+package appl.parallel.event;
+
+/**
+ * A {@link TimeEvent} is a {@link CommEvent} which is associated with a 
+ * execution time of a operation. 
+ * 
+ * @author Dominik Appl
+ */
+public class TimeEvent extends CommEvent {
+
+	private final long time;
+
+	/**
+	 * @param timeNanos
+	 *            the execution time to be associated with this event in nano
+	 *            seconds
+	 * @param src
+	 *            the source of the event
+	 * @param target
+	 *            the target of the event
+	 * @param type
+	 *            the type of the event
+	 * @see System#nanoTime()
+	 */
+	public TimeEvent(long timeNanos, String src, String target, CommType type) {
+		super(src, target, type);
+		this.time = timeNanos;
+	}
+
+	/**
+	 * @return the execution time
+	 */
+	public long getTime() {
+		return time;
+	}
+
+	public String toString() {
+		StringBuffer returnString = new StringBuffer();
+		returnString.append(type.toString());
+		returnString.append(" execution time: ").append((time) / 1000000f)
+				.append(" ms");
+		if (!src.equals(""))
+			returnString.append(" source: ").append(src);
+		if (!target.equals(""))
+			returnString.append(" target: ").append(target);
+
+		return returnString.toString();
+	}
+
+}

Added: trunk/src/appl/parallel/event/TimeMonitor.java
===================================================================
--- trunk/src/appl/parallel/event/TimeMonitor.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/event/TimeMonitor.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,17 @@
+package appl.parallel.event;
+
+/**
+ * A monitor, that receives {@link TimeEvent}s
+ * @author Dominik Appl
+ */
+public interface TimeMonitor{
+	
+	/**
+	 * Receive a event
+	 * 
+	 * @param t
+	 *            the event
+	 */
+	public void receiveTimeEvent(TimeEvent t);
+
+}

Added: trunk/src/appl/parallel/event/TransferEvent.java
===================================================================
--- trunk/src/appl/parallel/event/TransferEvent.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/event/TransferEvent.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,89 @@
+/**
+ * 
+ */
+package appl.parallel.event;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+/**
+ * A TransferEvent is event which is associated with the size of a data transfer
+ * in bytes. It is measured by serializing the data into byte stream. This is
+ * very slow! So use this events carefully. You should check if monitoring for
+ * this event type is enabled, before generating it! See {@link CommEventSink}
+ * for details.
+ * 
+ * @author Dominik Appl
+ */
+public class TransferEvent extends CommEvent {
+
+	int size = 0;
+
+	/**
+	 * @param src
+	 *            the source of the event
+	 * @param target
+	 *            the target of the event
+	 * @param type
+	 *            the type of the event
+	 * @param toTransferObjects
+	 *            the objects transfered (Warning: the size will be measured by
+	 *            serializing the object. This is slow!)
+	 * @see #getObjectSize(Object)
+	 */
+	public TransferEvent(String src, String target, CommType type,
+			Object... toTransferObjects) {
+		super(src, target, type);
+		for (Object object : toTransferObjects) {
+			size += getObjectSize(object);
+		}
+	}
+
+	/**
+	 * Determines the object size in a very primitive way (serializing to a byte
+	 * array and returning the byteSize) I do not have to mention here
+	 * explicitly that this is slow, do I? There is no real alternative, because
+	 * in java exists. no function like <code>sizeOf</code> in C++
+	 * 
+	 * @param object
+	 *            a {@link Serializable} object
+	 * @return the size in bytes
+	 */
+	protected int getObjectSize(Object object) {
+		if (object == null)
+			return 0;
+
+		byte[] byteArray = null;
+		try {
+			ByteArrayOutputStream baos = new ByteArrayOutputStream();
+			ObjectOutputStream oos = new ObjectOutputStream(baos);
+			oos.writeObject(object);
+			oos.close();
+			byteArray = baos.toByteArray();
+			baos.close();
+		} catch (IOException e) {
+			e.printStackTrace();
+			return 0;
+		}
+		return byteArray.length;
+	}
+
+	public int getSize() {
+		return size;
+	}
+
+	public String toString() {
+		StringBuffer returnString = new StringBuffer();
+		returnString.append(type.toString());
+		returnString.append(" Transfer size: ").append(size).append(" bytes");
+		if (!src.equals(""))
+			returnString.append(" source: ").append(src);
+		if (!target.equals(""))
+			returnString.append(" target: ").append(target);
+
+		return returnString.toString();
+	}
+
+}

Added: trunk/src/appl/parallel/event/TransferMonitor.java
===================================================================
--- trunk/src/appl/parallel/event/TransferMonitor.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/event/TransferMonitor.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,15 @@
+package appl.parallel.event;
+
+/**
+ * A Monitor that receives {@link TransferEvent}s
+ * @author Dominik Appl
+ */
+public interface TransferMonitor {
+
+	/**
+	 * Receive a event
+	 * @param t the event
+	 */
+	public void receiveTransferEvent(TransferEvent t);
+
+}

Added: trunk/src/appl/parallel/event/package.html
===================================================================
--- trunk/src/appl/parallel/event/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/event/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,5 @@
+<html>
+<body>
+	Contains classes related event handling. Especially remote events are progressed with this classes.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/parallel/gui/ModelControlContainer_parallel.java
===================================================================
--- trunk/src/appl/parallel/gui/ModelControlContainer_parallel.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/gui/ModelControlContainer_parallel.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,56 @@
+package appl.parallel.gui;
+
+import appl.parallel.ComputingResourceContainer;
+import appl.parallel.client.RemoteExecutionController;
+import appl.parallel.model.AbstractParallelStepModel;
+import appl.parallel.model.ParallelStepModel;
+import appl.parallel.spmd.SPMDClientInterface;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.model.AbstractStepModel;
+import edu.bonn.xulu.model.XuluModel;
+import edu.bonn.xulu.plugin.gui.ModelControlContainer;
+
+/**
+ * This class extends the functionality of the container to support the execution
+ * of a {@link ParallelStepModel}. It retrieves the {@link RemoteExecutionController}
+ * and uses it to prepare the model for parallel execution.
+ * 
+ * @author Dominik Appl
+ */
+public class ModelControlContainer_parallel extends ModelControlContainer {
+
+	private final XuluModellingPlatform appl;
+
+	private final ParallelControlPanelEngine pcpEngine;
+
+	/**
+	 * A new instance
+	 * @param model the XuluModel which should be executed
+	 * @param pcpEngine the controlling engine for parallel execution
+	 * @param appl the Xulu application
+	 */
+	public ModelControlContainer_parallel(XuluModel model,
+			ParallelControlPanelEngine pcpEngine, XuluModellingPlatform appl) {
+		super(model);
+		this.pcpEngine = pcpEngine;
+		// TODO Auto-generated constructor stub
+		this.appl = appl;
+	}
+
+	@Override
+	protected void createNewThread() {
+		if (model instanceof ParallelStepModel) {
+			// create the ClientController
+			RemoteExecutionController remoteController = RemoteExecutionController
+					.getRemoteExecutionController(appl);
+			if (remoteController == null)
+				throw new UnsupportedOperationException(
+						"You must load the RemoteExecutionController-Plugin to execute parallel Models!");
+			remoteController.prepareModelForSPMDExecution(
+					(ParallelStepModel) model, pcpEngine
+							.getSelectedResourceContainers());
+
+		}
+		super.createNewThread();
+	}
+}

Added: trunk/src/appl/parallel/gui/ModelControlFrame_Tabbed.java
===================================================================
--- trunk/src/appl/parallel/gui/ModelControlFrame_Tabbed.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/gui/ModelControlFrame_Tabbed.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,75 @@
+package appl.parallel.gui;
+
+import java.awt.CardLayout;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+
+import javax.swing.BoxLayout;
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.XuluConstants;
+
+import edu.bonn.xulu.model.XuluModel;
+import edu.bonn.xulu.plugin.gui.ModelControlFrame_Basic;
+import edu.bonn.xulu.gui.ModelContentManagerContainer;
+
+/**
+ * This class introduces tab functionality into the ModelControlFrame
+ * 
+ * @author Dominik Appl
+ * @version 1.0
+ */
+public class ModelControlFrame_Tabbed extends ModelControlFrame_Basic implements
+		XuluConstants {
+
+	protected JTabbedPane tabbedPane;
+
+	/**
+	 * Creates a new controlling window
+	 * 
+	 * @param appl
+	 *            application in which the model is executed
+	 * @param model
+	 *            the model to be controlled through the frame
+	 */
+	public ModelControlFrame_Tabbed(XuluModellingPlatform appl, XuluModel model) {
+		super(appl, model);
+		this.pack();
+	}
+
+	/**
+	 * inits the content pane as tabbed pane with one tab (the resource mapping)
+	 * 
+	 * @see edu.bonn.xulu.plugin.gui.ModelControlFrame_Basic#initContentPane()
+	 */
+	@Override
+	protected void initContentPane() {
+
+		// ####### Daten-Komponente #######
+		contentContainer = new ModelContentManagerContainer(model
+				.getContentManager(), appl.getDataPool());
+		tabbedPane = new JTabbedPane(JTabbedPane.TOP);
+		tabbedPane.setPreferredSize(new Dimension((int) contentContainer
+				.getPreferredSize().getWidth() + 5, (int) contentContainer
+				.getPreferredSize().getHeight() + 25));
+		JPanel panel = new JPanel(new GridBagLayout());
+
+		panel.add(contentContainer, new GridBagConstraints(0, 1, 2, 1, 1.0,
+				0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+				new Insets(5, 5, 5, 5), 0, 25));
+
+		tabbedPane.addTab("Resource Mapping", panel);
+		contentPane.add(tabbedPane, new GridBagConstraints(0, 1, 2, 1, 1.0,
+				0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+				new Insets(0, 0, 0, 0), 0, 0));
+	}
+
+	@Override
+	protected ModelControlFrame_Tabbed newInstance(XuluModel newModel) {
+		return new ModelControlFrame_Tabbed(appl, newModel);
+	}
+
+}

Added: trunk/src/appl/parallel/gui/ModelControlFrame_parallel.java
===================================================================
--- trunk/src/appl/parallel/gui/ModelControlFrame_parallel.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/gui/ModelControlFrame_parallel.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,123 @@
+package appl.parallel.gui;
+
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JPanel;
+
+import schmitzm.lang.WorkingThread;
+import schmitzm.lang.WorkingThreadAdapter;
+
+import appl.parallel.client.RemoteExecutionController;
+import appl.parallel.model.AbstractParallelStepModel;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.model.XuluModel;
+import edu.bonn.xulu.plugin.gui.ModelControlContainer;
+import edu.bonn.xulu.plugin.gui.ModelControlFrame_Basic;
+
+/**
+ * Introduces a new TAB into the {@link ModelControlFrame_Basic}
+ * for controlling the parallel execution
+ *
+ * @author Dominik Appl
+ */
+public class ModelControlFrame_parallel extends ModelControlFrame_Tabbed {
+
+	protected ParallelControlPanelEngine spcEngine;
+
+	private boolean parallelPaneInitalized;
+
+	/**
+	 * @param appl
+	 * @param model
+	 */
+	public ModelControlFrame_parallel(XuluModellingPlatform appl,
+			XuluModel model) {
+		super(appl, model);
+		this.pack();
+	}
+
+	/**
+	 * does basically the same as
+	 * {@link ModelControlFrame_Basic#initControlContainer()}
+	 */
+	protected void initControlContainer() {
+		spcEngine = new ParallelControlPanelEngine(appl);
+		// ####### Initialize controlcomponent #######
+		controlContainer = new ModelControlContainer_parallel(model, spcEngine,
+				appl);
+
+		// ******************** COPIED FROM SUPERCLASS
+		// **************************
+
+		// Bei Init-Aktion muessen zunaechst die Modell-Ressourcen mit den
+		// ausgewaehlten
+		// Datenpool-Objekten verknuepft werden; bevor das Modell initialisiert
+		// wird
+		controlContainer.addButtonActionListener(
+				ModelControlContainer.BUTTON_INIT, new ActionListener() {
+					public void actionPerformed(ActionEvent e) {
+						setModelResources();
+					}
+				});
+		// Waehrend das Modell laeuft, soll nichts an den Ressourcen veraendet
+		// werden
+		controlContainer.addThreadListener(new WorkingThreadAdapter() {
+			public void threadStarted(WorkingThread thread) {
+				contentContainer.setEnabled(false);
+				reloadButton.setEnabled(false);
+			}
+
+			public void threadStopped(WorkingThread thread) {
+				contentContainer.setEnabled(true);
+				reloadButton.setEnabled(true);
+			}
+		});
+		contentPane.add(controlContainer, new GridBagConstraints(0, 0, 1, 1,
+				1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+				new Insets(5, 5, 5, 5), 0, 0));
+	}
+
+	@Override
+	protected void initContentPane() {
+		super.initContentPane();
+//		System.out.println(model.getClass().getName());
+		if (model instanceof AbstractParallelStepModel) {
+			initializeParallelPane();
+		} else
+			parallelPaneInitalized = false;
+	}
+
+	private boolean isParallelPaneInitalized() {
+		return parallelPaneInitalized;
+	}
+
+	@Override
+	protected ModelControlFrame_parallel newInstance(XuluModel newModel) {
+		ModelControlFrame_parallel frame_parallel = new ModelControlFrame_parallel(
+				appl, newModel);
+		// initialize the parallel pane if it was initialized before
+		if (this.isParallelPaneInitalized()
+				&& !frame_parallel.isParallelPaneInitalized()) {
+			if (newModel.getClass().getName()
+					.equals(model.getClass().getName())) {
+				frame_parallel.initializeParallelPane();
+			}
+		}
+		return frame_parallel;
+	}
+
+	private void initializeParallelPane() {
+		super.tabbedPane.addTab("Parallel Control", spcEngine.getPanel());
+		// The boolean parallelPaneInitalized is required because after
+		// reloading
+		// with a custom classloader, like the preferred classloader, the
+		// 'instanceof' will no longer work properly with the reloaded class.
+		// (instanceof will return false)
+		parallelPaneInitalized = true;
+	}
+
+}

Added: trunk/src/appl/parallel/gui/ParallelControlPanel.java
===================================================================
--- trunk/src/appl/parallel/gui/ParallelControlPanel.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/gui/ParallelControlPanel.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,246 @@
+package appl.parallel.gui;
+
+import javax.swing.JPanel;
+import java.awt.GridBagLayout;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.BoxLayout;
+import javax.swing.ListSelectionModel;
+import java.awt.Insets;
+import javax.swing.border.SoftBevelBorder;
+import javax.swing.table.DefaultTableModel;
+import edu.bonn.xulu.XuluModellingPlatform;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+
+import java.awt.Rectangle;
+
+/**
+ * The GUI for the ParallelControlPanel . All the interesting 
+ * stuff happens in the {@link ParallelControlPanelEngine}.
+ * This GUI was created with the Visual Editor plugin for eclipse. 
+ * Editing with another VE may be a bad idea.
+ *  
+ * @author Dominik Appl
+ */
+public class ParallelControlPanel extends JPanel {
+
+	static final long serialVersionUID = 1L;
+
+	JPanel executionPanel = null;
+
+	JLabel Steps = null;
+
+	JTable computingResourcesList = null;
+
+	JScrollPane jScrollPane1 = null;
+
+	JPanel jPanel = null;
+
+	JScrollPane jScrollPane = null;
+
+	SimplePropertyTable propertyTable = null;
+
+	JButton refreshButton = null;
+
+	JButton selectAllButton = null;
+
+	JPanel buttonPanel = null;
+
+	/**
+	 * This is the default constructor. It should be only used be the eclipse VE
+	 */
+	public ParallelControlPanel() {
+		super();
+		initialize();
+	}
+
+	/**
+	 * This method initializes this
+	 * 
+	 * @return void
+	 */
+	private void initialize() {
+		this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
+		this.setSize(578, 268);
+		this.add(getExecutionPanel(), null);
+		this.add(getJPanel(), null);
+	}
+
+	/**
+	 * This method initializes executionPanel	
+	 * 	
+	 * @return javax.swing.JPanel	
+	 */
+	private JPanel getExecutionPanel() {
+		if (executionPanel == null) {
+			GridBagConstraints gridBagConstraints12 = new GridBagConstraints();
+			gridBagConstraints12.gridx = 1;
+			gridBagConstraints12.gridy = 2;
+			GridBagConstraints gridBagConstraints11 = new GridBagConstraints();
+			gridBagConstraints11.fill = GridBagConstraints.BOTH;
+			gridBagConstraints11.weighty = 1.0;
+			gridBagConstraints11.gridx = 0;
+			gridBagConstraints11.gridy = 1;
+			gridBagConstraints11.ipadx = 0;
+			gridBagConstraints11.insets = new Insets(5, 5, 5, 5);
+			gridBagConstraints11.gridwidth = 2;
+			gridBagConstraints11.weightx = 1.0;
+			GridBagConstraints gridBagConstraints = new GridBagConstraints();
+			gridBagConstraints.insets = new Insets(0, 0, 0, 0);
+			gridBagConstraints.gridy = 0;
+			gridBagConstraints.anchor = GridBagConstraints.NORTH;
+			gridBagConstraints.gridheight = 1;
+			gridBagConstraints.gridwidth = 2;
+			gridBagConstraints.gridx = 0;
+			Steps = new JLabel();
+			Steps.setText("Computing resources:");
+			Steps.setName("Steps");
+			executionPanel = new JPanel();
+			executionPanel.setLayout(new GridBagLayout());
+			executionPanel.setBorder(new SoftBevelBorder(
+					SoftBevelBorder.LOWERED));
+			executionPanel.setVisible(true);
+			executionPanel.add(Steps, gridBagConstraints);
+			executionPanel.add(getJScrollPane1(), gridBagConstraints11);
+			executionPanel.add(getButtonPanel(), gridBagConstraints12);
+		}
+		return executionPanel;
+	}
+
+	/**
+	 * This method initializes computingResourcesList	
+	 * 	
+	 * @return javax.swing.JList	
+	 */
+	private JTable getComputingResourcesList() {
+		if (computingResourcesList == null) {
+			computingResourcesList = new JTable();
+			computingResourcesList.setShowHorizontalLines(false);
+			computingResourcesList
+					.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+		}
+		return computingResourcesList;
+	}
+
+	/**
+	 * This method initializes jScrollPane1	
+	 * 	
+	 * @return javax.swing.JScrollPane	
+	 */
+	private JScrollPane getJScrollPane1() {
+		if (jScrollPane1 == null) {
+			jScrollPane1 = new JScrollPane();
+			jScrollPane1.setName("jScrollPane1");
+			jScrollPane1.setViewportView(getComputingResourcesList());
+			jScrollPane1.setPreferredSize(new Dimension(200, 250));
+		}
+		return jScrollPane1;
+	}
+
+	/**
+	 * This method initializes jPanel	
+	 * 	
+	 * @return javax.swing.JPanel	
+	 */
+	private JPanel getJPanel() {
+		if (jPanel == null) {
+			GridBagConstraints gridBagConstraints1 = new GridBagConstraints();
+			gridBagConstraints1.fill = GridBagConstraints.BOTH;
+			gridBagConstraints1.gridy = 0;
+			gridBagConstraints1.weightx = 1.0;
+			gridBagConstraints1.weighty = 1.0;
+			gridBagConstraints1.gridx = 0;
+			jPanel = new JPanel();
+			jPanel.setLayout(new GridBagLayout());
+			jPanel.add(getJScrollPane(), gridBagConstraints1);
+		}
+		return jPanel;
+	}
+
+	/**
+	 * This method initializes jScrollPane	
+	 * 	
+	 * @return javax.swing.JScrollPane	
+	 */
+	private JScrollPane getJScrollPane() {
+		if (jScrollPane == null) {
+			jScrollPane = new JScrollPane();
+			jScrollPane.setViewportView(getPropertyTable());
+		}
+		return jScrollPane;
+	}
+
+	/**
+	 * This method initializes propertyTable	
+	 * 	
+	 * @return javax.swing.JTable	
+	 */
+	private JTable getPropertyTable() {
+		if (propertyTable == null) {
+			propertyTable = new SimplePropertyTable();
+		}
+		return propertyTable;
+	}
+
+	/**
+	 * This method initializes refreshButton	
+	 * 	
+	 * @return javax.swing.JButton	
+	 */
+	private JButton getRefreshButton() {
+		if (refreshButton == null) {
+			refreshButton = new JButton();
+			refreshButton.setName("refreshButton");
+			refreshButton.setText("Refresh");
+		}
+		return refreshButton;
+	}
+
+	/**
+	 * This method initializes selectAllButton	
+	 * 	
+	 * @return javax.swing.JButton	
+	 */
+	private JButton getSelectAllButton() {
+		if (selectAllButton == null) {
+			selectAllButton = new JButton();
+			selectAllButton.setText("Select available");
+		}
+		return selectAllButton;
+	}
+
+	/**
+	 * This method initializes buttonPanel	
+	 * 	
+	 * @return javax.swing.JPanel	
+	 */
+	protected JPanel getButtonPanel() {
+		if (buttonPanel == null) {
+			GridBagConstraints gridBagConstraints3 = new GridBagConstraints();
+			gridBagConstraints3.anchor = GridBagConstraints.SOUTHEAST;
+			gridBagConstraints3.gridy = -1;
+			gridBagConstraints3.gridx = -1;
+			GridBagConstraints gridBagConstraints2 = new GridBagConstraints();
+			gridBagConstraints2.anchor = GridBagConstraints.CENTER;
+			gridBagConstraints2.insets = new Insets(0, 0, 0, 0);
+			gridBagConstraints2.gridheight = 1;
+			gridBagConstraints2.gridwidth = 1;
+			gridBagConstraints2.gridx = -1;
+			gridBagConstraints2.gridy = -1;
+			gridBagConstraints2.ipadx = 0;
+			gridBagConstraints2.ipady = 0;
+			gridBagConstraints2.weightx = 0.5;
+			gridBagConstraints2.fill = GridBagConstraints.HORIZONTAL;
+			buttonPanel = new JPanel();
+			buttonPanel.setLayout(new GridBagLayout());
+			buttonPanel.add(getRefreshButton(), gridBagConstraints2);
+			buttonPanel.add(getSelectAllButton(), gridBagConstraints3);
+		}
+		return buttonPanel;
+	}
+
+} //  @jve:decl-index=0:visual-constraint="10,10"

Added: trunk/src/appl/parallel/gui/ParallelControlPanelEngine.java
===================================================================
--- trunk/src/appl/parallel/gui/ParallelControlPanelEngine.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/gui/ParallelControlPanelEngine.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,304 @@
+package appl.parallel.gui;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Iterator;
+import java.util.Vector;
+
+import javax.swing.JOptionPane;
+import javax.swing.JTable;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.event.TableModelEvent;
+import javax.swing.event.TableModelListener;
+import javax.swing.table.DefaultTableModel;
+import javax.swing.table.TableModel;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import appl.ext.XuluConfig;
+import appl.parallel.ComputingResource;
+import appl.parallel.ComputingResourceContainer;
+import appl.parallel.ComputingResourceProperties;
+import appl.parallel.client.RemoteExecutionController;
+import appl.parallel.client.ResourceChangeListener;
+import appl.util.NonEditableTableModel;
+import schmitzm.data.event.ObjectEvent;
+import schmitzm.data.event.ObjectListener;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.ModelControlManager;
+import edu.bonn.xulu.appl.XuluPlugin;
+import edu.bonn.xulu.data.XuluDataException;
+import edu.bonn.xulu.gui.ModelContentManagerContainer;
+import edu.bonn.xulu.gui.ModelControlFrame;
+import edu.bonn.xulu.gui.XuluGUIMessages;
+import edu.bonn.xulu.model.ModelContentManager;
+import edu.bonn.xulu.model.XuluModel;
+import edu.bonn.xulu.plugin.gui.ModelControlContainer;
+import edu.bonn.xulu.plugin.gui.ModelControlFrame_Basic;
+
+/**
+ * This class controls the {@link ParallelControlPanel}.
+ *
+ * @author Dominik Appl
+ */
+public class ParallelControlPanelEngine implements ActionListener,
+		ListSelectionListener, TableModelListener, ResourceChangeListener {
+
+	ParallelControlPanel panel;
+
+	XuluModellingPlatform xulu;
+
+	// get logger for this class
+	protected final Logger LOG = LogManager
+			.getLogger(this.getClass().getName());
+
+	private DefaultTableModel resTableModel;
+
+	private JTable resTable;
+
+	private Vector<ComputingResourceContainer> resources;
+
+	private RemoteExecutionController remoteExecutionController;
+
+	/**
+	 * @param xulu
+	 *            the active modeling platform
+	 */
+	public ParallelControlPanelEngine(XuluModellingPlatform xulu) {
+		this.xulu = xulu;
+		this.panel = new ParallelControlPanel();
+		init();
+	}
+
+	/**
+	 * @param xulu
+	 *            the active modeling platform
+	 * @param panel
+	 *            the panel to integrate
+	 */
+	public ParallelControlPanelEngine(XuluModellingPlatform xulu,
+			ParallelControlPanel panel) {
+		this.xulu = xulu;
+		this.panel = panel;
+		init();
+	}
+
+	/**
+	 * The init method must be called after all Components of the GUI are
+	 * initialized.
+	 */
+	void init() {
+		remoteExecutionController = RemoteExecutionController
+				.getRemoteExecutionController(xulu);
+		if (remoteExecutionController != null)
+			remoteExecutionController.addResourceChangeListener(this);
+		resTable = panel.computingResourcesList;
+
+		// add listeners
+		resTable.getSelectionModel().addListSelectionListener(this);
+		panel.refreshButton.addActionListener(this);
+		panel.selectAllButton.addActionListener(this);
+
+		resTableModel = new NonEditableTableModel(new Object[] { "Name",
+				"Rating" }, new boolean[] { false, true }, 1);
+		resTable.setModel(resTableModel);
+		resTable.getModel().addTableModelListener(this);
+		selectAvailableResources();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
+	 */
+	public void actionPerformed(ActionEvent e) {
+		// the source of the event.
+		Object src = e.getSource();
+		if (src == panel.refreshButton) {
+			handleRefresh();
+		} else if (src == panel.selectAllButton) {
+			selectAvailableResources();
+		}
+
+	}
+
+	/**
+	 * handles the refresh button
+	 */
+	private void handleRefresh() {
+		if (remoteExecutionController != null)
+			remoteExecutionController.refreshResources();
+		else
+			JOptionPane
+					.showMessageDialog(
+							getPanel(),
+							"Error: no discovery possible. The RemoteExecutionController-Plugin can " +
+							"not be found. The plugin is required for parallel " +
+							"computation","Error",JOptionPane.ERROR_MESSAGE);
+	}
+
+	private Vector<String> getVectorOfSelectedNames() {
+
+		Object[] selectedComputingResources = getSelectedResourceContainers();
+
+		// write selected names in vector
+		Vector<String> names = new Vector<String>();
+		for (int i = 0; i < selectedComputingResources.length; i++) {
+			names
+					.add(((ComputingResourceContainer) selectedComputingResources[i])
+							.getInformation().getName());
+		}
+		return names;
+	}
+
+	private void setSelectedElements(Vector<String> names) {
+		for (int i = 0; i < resTableModel.getRowCount(); i++) {
+			ComputingResourceContainer container = (ComputingResourceContainer) resTableModel
+					.getValueAt(i, 0);
+			if (container == null)
+				return;
+			String name = ((ComputingResourceContainer) resTableModel
+					.getValueAt(i, 0)).getInformation().getName();
+			if (names.contains(name))
+				resTable.getSelectionModel().addSelectionInterval(i, i);
+		}
+	}
+
+	private void selectAvailableResources() {
+		// write available selected names in vector
+		Vector<String> names = new Vector<String>();
+		for (int i = 0; i < resTableModel.getRowCount(); i++) {
+			ComputingResourceContainer container = ((ComputingResourceContainer) resTableModel
+					.getValueAt(i, 0));
+			if (container == null)
+				return;
+			ComputingResourceProperties info = container.getInformation();
+			if (info.isAvailable())
+				names.add(info.getName());
+
+		}
+		setSelectedElements(names);
+	}
+
+	/**
+	 * @returns the first current selected ComputingResourceContainer from the
+	 *          resouce list
+	 */
+	private ComputingResourceContainer getSelectedResourceContainer() {
+		int selectedRow = resTable.getSelectedRow();
+		if (selectedRow == -1)
+			return null;
+		return (ComputingResourceContainer) resTableModel.getValueAt(
+				selectedRow, 0);
+	}
+
+	/**
+	 * @return all current selected ComputingResourceContainer from the resouce
+	 *         list
+	 */
+	ComputingResourceContainer[] getSelectedResourceContainers() {
+		int[] selRows = panel.computingResourcesList.getSelectedRows();
+		Object[] selectedValues = new Object[selRows.length];
+		for (int i = 0; i < selRows.length; i++) {
+			selectedValues[i] = resTableModel.getValueAt(selRows[i], 0);
+			if (selectedValues[i] == null)
+				return new ComputingResourceContainer[0];
+		}
+		ComputingResourceContainer[] selectedContainers = new ComputingResourceContainer[selectedValues.length];
+		for (int i = 0; i < selectedValues.length; i++)
+			selectedContainers[i] = (ComputingResourceContainer) selectedValues[i];
+		return selectedContainers;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see javax.swing.event.ListSelectionListener#valueChanged(javax.swing.event.ListSelectionEvent)
+	 */
+	public void valueChanged(ListSelectionEvent e) {
+		Object src = e.getSource();
+		if (src == resTable.getSelectionModel()) {
+			ComputingResourceContainer selValue = getSelectedResourceContainer();
+			if (selValue == null)
+				return;
+			panel.propertyTable.setPropertyData(selValue.getInformation()
+					.getProperties());
+		}
+	}
+
+	/**
+	 * Listens for user changes of the rating
+	 *
+	 * @see javax.swing.event.TableModelListener#tableChanged(javax.swing.event.TableModelEvent)
+	 */
+	public void tableChanged(TableModelEvent e) {
+		// enter the new rating information to the configuration
+		XuluConfig config = XuluConfig.getXuluConfig();
+		if (e.getType() == TableModelEvent.UPDATE) {
+			int changedRow = e.getFirstRow();
+			// only the 2nd col is editable
+			String newRating = resTableModel.getValueAt(changedRow, 1)
+					.toString();
+			try {
+				int rating = Integer.valueOf(newRating);
+				if (rating < 0) {
+					resTableModel.setValueAt(0, changedRow, 1);
+					throw new UnsupportedOperationException(
+							"Rating must be > 0");
+				}
+
+			} catch (Exception f) {
+				resTableModel.setValueAt(0, changedRow, 1);
+				throw new UnsupportedOperationException(
+						"Rating must be an integer!");
+			}
+			String computerName = resTableModel.getValueAt(changedRow, 0)
+					.toString();
+			String prefix = "PerformanceRating";
+			String key = prefix + "." + computerName;
+			config.setProperty(key, newRating);
+		}
+	}
+
+	/**
+	 * @return the panel
+	 */
+	public ParallelControlPanel getPanel() {
+		return this.panel;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.client.ResourceChangeListener#updateResources(java.util.Vector)
+	 */
+	public void updateResources(
+			Vector<ComputingResourceContainer> currentResources) {
+		// get the selected values (and restore the selection after list
+		// initializing)
+		Vector names = getVectorOfSelectedNames();
+
+		// clear list
+		resTableModel.setRowCount(0);
+		for (ComputingResourceContainer res : currentResources) {
+			// init the rating from the configuration
+			XuluConfig config = XuluConfig.getXuluConfig();
+			String computerName = res.getInformation().getName();
+			String prefix = "PerformanceRating";
+			String key = prefix + "." + computerName;
+			String rating = config.getProperty(key, false);
+			// if no rating found use the selfrating of the machine
+			if (rating == null || rating.equals("0"))
+				rating = res.getInformation().getProperty("Rating");
+			if (rating == null)
+				rating = "0"; // '0' means average
+			resTableModel.addRow(new Object[] { res, rating });
+		}
+
+		// restore selection
+		this.setSelectedElements(names);
+	}
+}

Added: trunk/src/appl/parallel/gui/SimplePropertyTable.java
===================================================================
--- trunk/src/appl/parallel/gui/SimplePropertyTable.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/gui/SimplePropertyTable.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,46 @@
+package appl.parallel.gui;
+
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Properties;
+
+import javax.swing.JTable;
+import javax.swing.table.DefaultTableModel;
+
+/**
+ * Just a simple 2 column Property Table
+ * 
+ * @author Dominik Appl
+ */
+public class SimplePropertyTable extends JTable {
+
+	private final String colname1;
+
+	private final String colname2;
+
+	public SimplePropertyTable(String colname1, String colname2) {
+		super(1, 2);
+		this.colname1 = colname1;
+		this.colname2 = colname2;
+
+	}
+
+	public SimplePropertyTable() {
+		this("Property", "Value");
+	}
+
+	public void setPropertyData(Properties propdata) {
+		Enumeration keys = propdata.keys();
+		// Create array
+		String[][] data = new String[propdata.size()][2];
+		int i = 0;
+		while (keys.hasMoreElements()) {
+			data[i][0] = (String) keys.nextElement();
+			data[i][1] = (String) propdata.getProperty(data[i][0]);
+			i++;
+		}
+		setModel(new DefaultTableModel(data,
+				new String[] { colname1, colname2 }));
+	}
+
+}

Added: trunk/src/appl/parallel/gui/package.html
===================================================================
--- trunk/src/appl/parallel/gui/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/gui/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,5 @@
+<html>
+<body>
+	Contains classes related to the GUI for the parallelization functionality of XULU.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/parallel/model/AbstractParallelStepModel.java
===================================================================
--- trunk/src/appl/parallel/model/AbstractParallelStepModel.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/model/AbstractParallelStepModel.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,57 @@
+package appl.parallel.model;
+
+import appl.parallel.spmd.AdvancedSPMDClientController;
+import appl.parallel.spmd.AdvancedSPMDClientInterface;
+import appl.parallel.spmd.SPMDClientInterface;
+import edu.bonn.xulu.model.AbstractStepModel;
+import edu.bonn.xulu.model.ModelContentManager;
+import edu.bonn.xulu.model.event.ModelStepFinishedEvent;
+import edu.bonn.xulu.model.event.ModelStepStartedEvent;
+
+/**
+ * This class is used instead of the {@link AbstractStepModel} for implementation
+ * of parallel algorithms. It provides access to the {@link SPMDClientInterface}.
+ * 
+ * @author Dominik Appl
+ */
+public abstract class AbstractParallelStepModel extends AbstractStepModel
+		implements ParallelStepModel {
+
+	SPMDClientInterface SPMDController;
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.model.ParallelStepModel#getSPMDController()
+	 */
+	public SPMDClientInterface getSPMDController() {
+		if (SPMDController == null) {
+			throw new UnsupportedOperationException(
+					"SPMDController is null!"
+							+ "You cannot use the SPMDController before the performInit-method");
+		}
+		return SPMDController;
+	}
+
+	/**
+	 * @return the Advanced SPMD controller which provides access to advanced parallel functionality
+	 * like preloading or multithreading
+	 */
+	public AdvancedSPMDClientInterface getAdvancedSPMDController() {
+		return (AdvancedSPMDClientController) getSPMDController();
+	}
+
+	/**
+	 * A new instance. See {@link AbstractStepModel#AbstractStepModel(ModelContentManager)} for details
+	 * 
+	 */
+	public AbstractParallelStepModel(ModelContentManager contentManager) {
+		super(contentManager);
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.model.ParallelStepModel#setSPMDController(appl.parallel.spmd.SPMDClientController)
+	 */
+	public void setSPMDController(SPMDClientInterface controller) {
+		this.SPMDController = controller;
+	}
+
+}

Added: trunk/src/appl/parallel/model/ParallelStepModel.java
===================================================================
--- trunk/src/appl/parallel/model/ParallelStepModel.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/model/ParallelStepModel.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,30 @@
+package appl.parallel.model;
+
+import java.io.Serializable;
+
+import edu.bonn.xulu.model.StepModel;
+import appl.parallel.spmd.SPMDClientInterface;
+
+/**
+ * This class extends the functionality of a Xulu-StepModel. It provides
+ * access to the {@link SPMDClientInterface} for parallel access. For implementation
+ * it is recommended to subclass {@link AbstractParallelStepModel}.
+ * 
+ * @see AbstractParallelStepModel
+ * 
+ * @author Dominik Appl
+ */
+public interface ParallelStepModel extends StepModel, Serializable {
+
+	/**
+	 * @return the SPMD client controller which provides access to the parallelization control
+	 */
+	public SPMDClientInterface getSPMDController();
+
+	/**
+	 * Sets the SPMD Controller
+	 * @param controller the controller to set
+	 */
+	public void setSPMDController(SPMDClientInterface controller);
+
+}
\ No newline at end of file

Added: trunk/src/appl/parallel/model/package.html
===================================================================
--- trunk/src/appl/parallel/model/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/model/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,5 @@
+<html>
+<body>
+	Contains classes which are used for integration of parallel models into the XuluModelling-Platform.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/parallel/package.html
===================================================================
--- trunk/src/appl/parallel/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,5 @@
+<html>
+<body>
+	Contains some general classes used for parallelization.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/parallel/plugin/event/SimpleCommEventMonitor.java
===================================================================
--- trunk/src/appl/parallel/plugin/event/SimpleCommEventMonitor.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/plugin/event/SimpleCommEventMonitor.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,289 @@
+package appl.parallel.plugin.event;
+
+import javax.swing.SwingUtilities;
+import java.awt.BorderLayout;
+import javax.swing.JPanel;
+import javax.swing.JFrame;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.JToggleButton;
+import java.awt.GridBagLayout;
+import java.awt.GridBagConstraints;
+import javax.swing.JCheckBox;
+import javax.swing.BoxLayout;
+
+import edu.bonn.xulu.gui.XuluInternalFrame;
+
+import java.awt.FlowLayout;
+import java.awt.GridLayout;
+import javax.swing.JTabbedPane;
+import java.awt.Dimension;
+import java.awt.Button;
+import java.awt.CardLayout;
+import javax.swing.JLabel;
+import java.awt.Insets;
+import javax.swing.JTextPane;
+import javax.swing.text.html.HTMLDocument;
+import javax.swing.text.DefaultStyledDocument;
+
+/**
+ * Provides a GUI for the {@link SimpleCommEventMonitorEngine}
+ * 
+ * @author Dominik Appl
+ */
+public class SimpleCommEventMonitor extends XuluInternalFrame {
+
+	private static final long serialVersionUID = 1L;
+
+	JPanel jContentPane = null;
+
+	JScrollPane jScrollPane = null;
+
+	JTable timeEventTable = null;
+
+	JPanel optionsPanel = null;
+
+	JCheckBox timeEventEnabled = null;
+
+	JCheckBox transferEventEnabled = null;
+
+	SimpleCommEventMonitorEngine engine;
+
+	JTabbedPane jTabbedPane = null;
+
+	Button clearButton = null;
+
+	JScrollPane jScrollPane1 = null;
+
+	JTable transferEventTable = null;
+
+	private JTextPane jTextPane = null;
+
+	/**
+	 * This method initializes jScrollPane	
+	 * 	
+	 * @return javax.swing.JScrollPane	
+	 */
+	private JScrollPane getJScrollPane() {
+		if (jScrollPane == null) {
+			jScrollPane = new JScrollPane();
+			jScrollPane.setViewportView(getTimeEventTable());
+		}
+		return jScrollPane;
+	}
+
+	/**
+	 * This method initializes timeEventTable	
+	 * 	
+	 * @return javax.swing.JTable	
+	 */
+	private JTable getTimeEventTable() {
+		if (timeEventTable == null) {
+			timeEventTable = new JTable();
+			timeEventTable.setDoubleBuffered(true);
+		}
+		return timeEventTable;
+	}
+
+	/**
+	 * This method initializes optionsPanel	
+	 * 	
+	 * @return javax.swing.JPanel	
+	 */
+	private JPanel getOptionsPanel() {
+		if (optionsPanel == null) {
+			GridBagConstraints gridBagConstraints8 = new GridBagConstraints();
+			gridBagConstraints8.fill = GridBagConstraints.BOTH;
+			gridBagConstraints8.gridy = 0;
+			gridBagConstraints8.weightx = 1.0;
+			gridBagConstraints8.weighty = 0.0;
+			gridBagConstraints8.gridwidth = 1;
+			gridBagConstraints8.gridheight = 1;
+			gridBagConstraints8.anchor = GridBagConstraints.EAST;
+			gridBagConstraints8.insets = new Insets(0, 0, 0, 0);
+			gridBagConstraints8.ipadx = 1;
+			gridBagConstraints8.ipady = 0;
+			gridBagConstraints8.gridx = 9;
+			GridBagConstraints gridBagConstraints6 = new GridBagConstraints();
+			gridBagConstraints6.insets = new Insets(5, 5, 5, 5);
+			gridBagConstraints6.gridy = 0;
+			gridBagConstraints6.anchor = GridBagConstraints.WEST;
+			gridBagConstraints6.fill = GridBagConstraints.HORIZONTAL;
+			gridBagConstraints6.gridx = 8;
+			GridBagConstraints gridBagConstraints5 = new GridBagConstraints();
+			gridBagConstraints5.insets = new Insets(5, 5, 5, 2);
+			gridBagConstraints5.gridy = 0;
+			gridBagConstraints5.anchor = GridBagConstraints.WEST;
+			gridBagConstraints5.fill = GridBagConstraints.NONE;
+			gridBagConstraints5.gridwidth = 1;
+			gridBagConstraints5.gridx = 7;
+			GridBagConstraints gridBagConstraints4 = new GridBagConstraints();
+			gridBagConstraints4.insets = new Insets(5, 5, 5, 5);
+			gridBagConstraints4.gridy = 0;
+			gridBagConstraints4.anchor = GridBagConstraints.WEST;
+			gridBagConstraints4.gridwidth = 1;
+			gridBagConstraints4.gridheight = 1;
+			gridBagConstraints4.gridx = 1;
+			GridBagConstraints gridBagConstraints = new GridBagConstraints();
+			gridBagConstraints.gridx = 0;
+			gridBagConstraints.gridy = 0;
+			optionsPanel = new JPanel();
+			optionsPanel.setLayout(new GridBagLayout());
+			optionsPanel.add(getTimeEventEnabled(), gridBagConstraints4);
+			optionsPanel.add(getTransferEventEnabled(), gridBagConstraints5);
+			optionsPanel.add(getClearButton(), gridBagConstraints6);
+			optionsPanel.add(getJTextPane(), gridBagConstraints8);
+		}
+		return optionsPanel;
+	}
+
+	/**
+	 * This method initializes timeEventEnabled	
+	 * 	
+	 * @return javax.swing.JCheckBox	
+	 */
+	private JCheckBox getTimeEventEnabled() {
+		if (timeEventEnabled == null) {
+			timeEventEnabled = new JCheckBox();
+			timeEventEnabled.setText("log time events");
+			timeEventEnabled.setName("timeEventEnabled");
+			timeEventEnabled.addActionListener(engine);
+		}
+		return timeEventEnabled;
+	}
+
+	/**
+	 * This method initializes transferEventEnabled	
+	 * 	
+	 * @return javax.swing.JCheckBox	
+	 */
+	private JCheckBox getTransferEventEnabled() {
+		if (transferEventEnabled == null) {
+			transferEventEnabled = new JCheckBox();
+			transferEventEnabled.setText("log transferEvents");
+			transferEventEnabled.setName("transferEventEnabled");
+			transferEventEnabled.addActionListener(engine);
+		}
+		return transferEventEnabled;
+	}
+
+	/**
+	 * This is the default constructor
+	 * @param engine the engine responsible for event handling
+	 */
+	public SimpleCommEventMonitor(SimpleCommEventMonitorEngine engine) {
+		super("Simple Communication Event Monitor");
+		this.setClosable(true);
+		this.setDefaultCloseOperation(HIDE_ON_CLOSE);
+		this.engine = engine;
+		initialize();
+	}
+
+	/**
+	 * This method initializes this class
+	 * 
+	 */
+	private void initialize() {
+		this.setSize(608, 326);
+		this.setContentPane(getJContentPane());
+		this.setTitle("Communication Monitor");
+	}
+
+	/**
+	 * This method initializes jContentPane
+	 * 
+	 * @return javax.swing.JPanel
+	 */
+	private JPanel getJContentPane() {
+		if (jContentPane == null) {
+			jContentPane = new JPanel();
+			jContentPane.setLayout(new BoxLayout(getJContentPane(),
+					BoxLayout.Y_AXIS));
+			jContentPane.add(getJTabbedPane(), null);
+			jContentPane.add(getOptionsPanel(), null);
+		}
+		return jContentPane;
+	}
+
+	/* (non-Javadoc)
+	 * @see edu.bonn.xulu.gui.XuluInternalFrame#refresh()
+	 */
+	@Override
+	public void refresh() {
+		// TODO Auto-generated method stub
+
+	}
+
+	/**
+	 * This method initializes jTabbedPane	
+	 * 	
+	 * @return javax.swing.JTabbedPane	
+	 */
+	private JTabbedPane getJTabbedPane() {
+		if (jTabbedPane == null) {
+			jTabbedPane = new JTabbedPane();
+			jTabbedPane.addTab("Time Events", null, getJScrollPane(), null);
+			jTabbedPane
+					.addTab("Transfer Events", null, getJScrollPane1(), null);
+		}
+		return jTabbedPane;
+	}
+
+	/**
+	 * This method initializes clearButton	
+	 * 	
+	 * @return java.awt.Button	
+	 */
+	private Button getClearButton() {
+		if (clearButton == null) {
+			clearButton = new Button();
+			clearButton.setLabel("Clear all");
+			clearButton.setMinimumSize(new Dimension(100, 20));
+			clearButton.setName("clearButton");
+			clearButton.addActionListener(engine);
+		}
+		return clearButton;
+	}
+
+	/**
+	 * This method initializes jScrollPane1	
+	 * 	
+	 * @return javax.swing.JScrollPane	
+	 */
+	private JScrollPane getJScrollPane1() {
+		if (jScrollPane1 == null) {
+			jScrollPane1 = new JScrollPane();
+			jScrollPane1.setViewportView(getTransferEventTable());
+		}
+		return jScrollPane1;
+	}
+
+	/**
+	 * This method initializes transferEventTable	
+	 * 	
+	 * @return javax.swing.JTable	
+	 */
+	private JTable getTransferEventTable() {
+		if (transferEventTable == null) {
+			transferEventTable = new JTable();
+			transferEventTable.setDoubleBuffered(true);
+		}
+		return transferEventTable;
+	}
+
+	/**
+	 * This method initializes jTextPane	
+	 * 	
+	 * @return javax.swing.JTextPane	
+	 */
+	private JTextPane getJTextPane() {
+		if (jTextPane == null) {
+			jTextPane = new JTextPane();
+			jTextPane
+					.setText("Hint: Hold CTRL while clicking on a table header for secondary sorting");
+			jTextPane.setMaximumSize(new Dimension(100, 50));
+		}
+		return jTextPane;
+	}
+
+} //  @jve:decl-index=0:visual-constraint="10,10"

Added: trunk/src/appl/parallel/plugin/event/SimpleCommEventMonitorEngine.java
===================================================================
--- trunk/src/appl/parallel/plugin/event/SimpleCommEventMonitorEngine.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/plugin/event/SimpleCommEventMonitorEngine.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,197 @@
+package appl.parallel.plugin.event;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Calendar;
+import java.util.Comparator;
+import java.util.GregorianCalendar;
+
+import javax.swing.JTable;
+import javax.swing.table.DefaultTableModel;
+import javax.swing.table.TableModel;
+import javax.swing.table.TableRowSorter;
+
+import appl.ext.XuluConfig;
+import appl.parallel.client.RemoteEventHandler;
+import appl.parallel.event.TimeEvent;
+import appl.parallel.event.TimeMonitor;
+import appl.parallel.event.TransferEvent;
+import appl.parallel.event.TransferMonitor;
+
+/**
+ * Controls the {@link SimpleCommEventMonitorPlugin}
+ * 
+ * @author Dominik Appl
+ */
+public class SimpleCommEventMonitorEngine implements TimeMonitor,
+		TransferMonitor, ActionListener {
+
+	private XuluConfig config;
+
+	private boolean timeMonitoring;
+
+	private boolean transferMonitoring;
+
+	private SimpleCommEventMonitor monitor;
+
+	private final RemoteEventHandler eventProxy;
+
+	private DefaultTableModel timeEventModel;
+
+	private DefaultTableModel transferEventModel;
+
+	public SimpleCommEventMonitorEngine(RemoteEventHandler eventProxy) {
+		this.eventProxy = eventProxy;
+		config = XuluConfig.getXuluConfig();
+
+	}
+
+	/**
+	 * @return the GUI for the monitor
+	 */
+	public SimpleCommEventMonitor getMonitor() {
+		if (monitor == null) {
+			monitor = new SimpleCommEventMonitor(this);
+			initGUI();
+		}
+		return monitor;
+	}
+
+	/**
+	 * inits the {@link SimpleCommEventMonitor}
+	 */
+	public void initGUI() {
+		// get Data from XuluConfig:
+		timeMonitoring = config
+				.getBooleanProperty("SimpleCommEventMonitor.timemonitoring");
+		transferMonitoring = config
+				.getBooleanProperty("SimpleCommEventMonitor.transfermonitoring");
+		// registers itself as timeEvent receiver
+		if (timeMonitoring)
+			eventProxy.addTimeEventListener(this);
+		if (transferMonitoring)
+			eventProxy.addTransferEventListener(this);
+		initTimeEventTable();
+		initTransferEventTable();
+		monitor.timeEventEnabled.setSelected(timeMonitoring);
+		monitor.transferEventEnabled.setSelected(transferMonitoring);
+	}
+
+	/**
+	 * 
+	 */
+	private void initTimeEventTable() {
+		JTable table = monitor.timeEventTable;
+
+		timeEventModel = new DefaultTableModel(
+				new Object[] { "Receive Time", "Event type", "Event Source",
+						"Event target", "Exec time (ms)" }, 0);
+		TableRowSorter sorter = new TableRowSorter<TableModel>(timeEventModel);
+		sorter.setComparator(4, LONG_COMPARATOR);
+		table.setModel(timeEventModel);
+		table.setRowSorter(sorter);
+
+	}
+
+	private void initTransferEventTable() {
+		JTable table = monitor.transferEventTable;
+		transferEventModel = new DefaultTableModel(new Object[] {
+				"Receive Time", "Event type", "Event Source", "Event target",
+				"Size (kb)" }, 0);
+		TableRowSorter sorter = new TableRowSorter(transferEventModel);
+		sorter.setComparator(4, LONG_COMPARATOR);
+		table.setModel(transferEventModel);
+		table.setRowSorter(sorter);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.event.TimeMonitor#receiveTimeEvent(appl.parallel.event.TimeEvent)
+	 */
+	public synchronized void receiveTimeEvent(TimeEvent t) {
+		timeEventModel.addRow(new Object[] { getCurrentTimeString(),
+				t.getType(), t.getSrc(), t.getTarget(),
+				(long) (t.getTime() / 1000000) });
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.event.TransferMonitor#receiveTransferEvent(appl.parallel.event.TransferEvent)
+	 */
+	public void receiveTransferEvent(TransferEvent t) {
+		transferEventModel.addRow(new Object[] { getCurrentTimeString(),
+				t.getType(), t.getSrc(), t.getTarget(),
+				(long) (t.getSize() / 1024) });
+	}
+
+	public String getCurrentTimeString() {
+		Calendar cal = new GregorianCalendar();
+		String hour = String.valueOf(cal.get(Calendar.HOUR_OF_DAY));
+		while (hour.length() < 2)
+			hour = "0" + hour;
+		String min = String.valueOf(cal.get(Calendar.MINUTE));
+		while (min.length() < 2)
+			min = "0" + min;
+		String sec = String.valueOf(cal.get(Calendar.SECOND));
+		while (sec.length() < 2)
+			sec = "0" + sec;
+		String ms = String.valueOf(cal.get(Calendar.MILLISECOND));
+		while (ms.length() < 3)
+			ms = "0" + ms;
+		String time = hour + ":" + min + ":" + sec + ":" + ms;
+		return time;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
+	 */
+	public void actionPerformed(ActionEvent e) {
+		Object src = e.getSource();
+		if (src == monitor.transferEventEnabled) {
+			eventProxy.removeTransferMonitor(this);
+			if (monitor.transferEventEnabled.isSelected()) {
+				eventProxy.addTransferEventListener(this);
+				config.setBooleanProperty(
+						"SimpleCommEventMonitor.transfermonitoring", true);
+			} else
+				config.setBooleanProperty(
+						"SimpleCommEventMonitor.transfermonitoring", false);
+		}
+		if (src == monitor.timeEventEnabled) {
+			eventProxy.removeTimeMonitor(this);
+			if (monitor.timeEventEnabled.isSelected()) {
+				eventProxy.addTimeEventListener(this);
+				config.setBooleanProperty(
+						"SimpleCommEventMonitor.timemonitoring", true);
+			} else
+				config.setBooleanProperty(
+						"SimpleCommEventMonitor.timemonitoring", false);
+		}
+		if (src == monitor.clearButton) {
+			initTimeEventTable();
+			initTransferEventTable();
+		}
+	}
+
+	/**
+	 * stops the execution
+	 */
+	public void stop() {
+		eventProxy.removeTimeMonitor(this);
+		eventProxy.removeTransferMonitor(this);
+	}
+
+	/**
+	 * The comparator is used for sorting the values in the {@link JTable}
+	 */
+	public static final Comparator LONG_COMPARATOR = new Comparator() {
+		public int compare(Object o1, Object o2) {
+			return ((Long) o1).compareTo((Long) o2);
+		}
+	};
+
+}

Added: trunk/src/appl/parallel/plugin/event/SimpleCommEventMonitorPlugin.java
===================================================================
--- trunk/src/appl/parallel/plugin/event/SimpleCommEventMonitorPlugin.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/plugin/event/SimpleCommEventMonitorPlugin.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,73 @@
+package appl.parallel.plugin.event;
+
+import javax.swing.JMenuItem;
+import javax.swing.JTable;
+
+import appl.parallel.client.RemoteExecutionController;
+import appl.parallel.event.TimeEvent;
+import appl.parallel.event.TransferEvent;
+
+import edu.bonn.xulu.appl.XuluPlugin;
+import edu.bonn.xulu.gui.XuluInternalFrame;
+import edu.bonn.xulu.plugin.appl.AbstractMenuPlugin;
+
+/**
+ * The {@link XuluPlugin} logs {@link TransferEvent}s and {@link TimeEvent}s.
+ * The Events are displayed in a sortable {@link JTable}.
+ * 
+ * @author Dominik Appl
+ */
+public class SimpleCommEventMonitorPlugin extends AbstractMenuPlugin {
+
+	/**
+	 * Creates a new plugin
+	 */
+	public SimpleCommEventMonitorPlugin() {
+		super(4, "Xulu/V Communication Monitor");
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * Creates a new plugin
+	 * 
+	 * @param xuluMenuNo
+	 *            the position of the menu in the menubar
+	 * @param menuItem
+	 *            the menu to insert
+	 */
+	public SimpleCommEventMonitorPlugin(int xuluMenuNo, JMenuItem menuItem) {
+		super(xuluMenuNo, menuItem);
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * Creates a new plugin
+	 * 
+	 * @param xuluMenuNo
+	 *            the position of the menu in the menubar
+	 * @param menuItemName
+	 *            the name of the entry to insert
+	 */
+	public SimpleCommEventMonitorPlugin(int xuluMenuNo, String menuItemName) {
+		super(xuluMenuNo, menuItemName);
+		// TODO Auto-generated constructor stub
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see edu.bonn.xulu.plugin.appl.AbstractMenuPlugin#createPluginApplication()
+	 */
+	@Override
+	protected XuluInternalFrame createPluginApplication() throws Exception {
+		RemoteExecutionController controller = RemoteExecutionController
+				.getRemoteExecutionController(appl);
+		if (controller == null)
+			throw new UnsupportedOperationException(
+					"Remote Execution Monitor plugin not found!");
+		SimpleCommEventMonitorEngine engine = new SimpleCommEventMonitorEngine(
+				controller.getEventProxy());
+		return engine.getMonitor();
+	}
+
+}

Added: trunk/src/appl/parallel/plugin/event/package.html
===================================================================
--- trunk/src/appl/parallel/plugin/event/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/plugin/event/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,6 @@
+<html>
+<body>
+	The Plugin can monitor the parallelization, especially the execution time of remote commands
+	and the size of transfered data.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/parallel/server/MasterSlaveResource.java
===================================================================
--- trunk/src/appl/parallel/server/MasterSlaveResource.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/server/MasterSlaveResource.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,10 @@
+package appl.parallel.server;
+
+/**
+ * A resource for Master / Slave Computing (indicator for now)
+ * 
+ * @author Dominik Appl
+ */
+public interface MasterSlaveResource {
+
+}

Added: trunk/src/appl/parallel/server/PartitionDataManager.java
===================================================================
--- trunk/src/appl/parallel/server/PartitionDataManager.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/server/PartitionDataManager.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,696 @@
+package appl.parallel.server;
+
+import java.awt.Rectangle;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.rmi.Naming;
+import java.rmi.NotBoundException;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Vector;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import appl.data.LoadingException;
+import appl.parallel.client.DataServer;
+import appl.parallel.client.ClientDataServer;
+import appl.parallel.data.PartitionDataHandler;
+import appl.parallel.event.CommEventSink;
+import appl.parallel.event.TimeEvent;
+import appl.parallel.event.TransferEvent;
+import appl.parallel.event.CommEvent.CommType;
+import appl.parallel.services.RemoteEventProxy;
+import appl.parallel.spmd.MultiDataInfo;
+import appl.parallel.spmd.MultiDataPartitionObject;
+import appl.parallel.spmd.SPMDClientController;
+import appl.parallel.spmd.split.DataPartition;
+import appl.parallel.spmd.split.PartitionInfo;
+import appl.parallel.spmd.split.SinglePartitionInfo;
+import appl.parallel.spmd.split.SplitMap;
+import appl.parallel.thread.DataServerThread;
+
+/**
+ * Manages the all data for the {@link XuluServer}. This includes retrieval of
+ * partitions from connected resources like the {@link DataServer} or, as part
+ * of the update of neighborhood regions, from other
+ * {@link XuluServer XuluServers}.
+ *
+ * @author Dominik Appl
+ */
+public class PartitionDataManager extends UnicastRemoteObject implements
+		PartitionDataServer {
+
+	/**
+	 * The Thread is used for updating the partitions neighborhood region from
+	 * the other servers.
+	 *
+	 * @author Dominik Appl
+	 */
+	class UpdateThread extends DataServerThread {
+
+		private final DataPartition thisPartition;
+
+		private final Rectangle updateBounds;
+
+		private final int id;
+
+		private final String hostname;
+
+		public UpdateThread(PartitionDataServer dataServer,
+				String ipOrHostname, DataPartition thisPartition,
+				Rectangle updateBounds, int id, CommEventSink sink) {
+			super(dataServer, null, null, CommType.REMOTE_UPDATE, sink);
+			hostname = ipOrHostname;
+			// TODO Auto-generated constructor stub
+			this.thisPartition = thisPartition;
+			this.updateBounds = updateBounds;
+			this.id = id;
+		}
+
+		/*
+		 * (non-Javadoc)
+		 *
+		 * @see appl.parallel.thread.ExecutionThread#fireTimeEvents(long,
+		 *      java.lang.Object)
+		 */
+		@Override
+		protected void fireTimeEvents(long execTime, Object result) {
+			try {
+				eventSink.fireRemoteEvent(new TimeEvent(execTime,
+						dataServerName, hostname, commType));
+			} catch (RemoteException e) {
+				e.printStackTrace();
+			}
+		}
+
+		/*
+		 * (non-Javadoc)
+		 *
+		 * @see appl.parallel.thread.ExecutionThread#fireTransferEvent(java.lang.Object)
+		 */
+		@Override
+		protected void fireTransferEvent(Object result) {
+			try {
+				eventSink.fireRemoteEvent(new TransferEvent(dataServerName,
+						hostname, commType, new Object[] { result }));
+			} catch (RemoteException e) {
+				e.printStackTrace();
+			}
+		}
+
+		/*
+		 * (non-Javadoc)
+		 *
+		 * @see appl.parallel.thread.ExecutionThread#run()
+		 */
+		@Override
+		protected Object run() throws Exception {
+			try {
+				DataPartition updateData = getServer().getPartition(id,
+						updateBounds);
+				// apply update:
+				this.thisPartition.setPartition(updateData, updateBounds);
+				return updateData;
+			} catch (Exception e) {
+				LOG.error("Error while retrieving partition " + updateBounds
+						+ "from PartitionDataServer with ip " + hostname);
+			}
+			return null;
+		}
+	}
+
+	private final String bindingName = "PartitionDataServer";
+
+	private final Logger LOG = LogManager.getLogger(this.getClass().getName());
+
+	/**
+	 * all partition data. The key is the id. Is an Hashtable instead of
+	 * HashMasp for thread-safty.
+	 */
+	private Hashtable<Integer, DataPartition> data = new Hashtable<Integer, DataPartition>(
+			15);
+
+	/**
+	 * the names of the data objects
+	 */
+	private HashMap<String, Integer> NameToIDMapping = new HashMap<String, Integer>(
+			15);
+
+	private HashMap<Integer, SinglePartitionInfo> infos = new HashMap<Integer, SinglePartitionInfo>(
+			10);
+
+	private HashMap<String, Object> baseParameters = new HashMap<String, Object>(
+			10);
+
+	private final PartitionDataServer[] dataServers;
+
+	private final ExecutorService executor;
+
+	private final String[] IPs;
+
+	private boolean dataServersInitialized = false;
+
+	private HashMap<String, MultiDataInfo> multiDataInfos = new HashMap<String, MultiDataInfo>(
+			10);
+
+	private final String dataServerName;
+
+	private final CommEventSink remoteEventReceiver;
+
+	private String[] hostnames;
+
+	private ClientDataServer localSPMDClient;
+
+	private final int registryPort;
+
+	/**
+	 * Creates and inits a new PartitionDataserver.
+	 *
+	 * @param IPs
+	 *            the IPs of participating Servers for neighborhood updates(may
+	 *            include port specification)
+	 * @param remoteEventReceiver
+	 *            generated events are forwarded to the receiver
+	 * @param registryPort
+	 *            port of the registry to which the {@link PartitionDataManager}
+	 *            should be bound
+	 * @throws RemoteException
+	 *             if a connection to a participating server fails
+	 */
+	public PartitionDataManager(String[] IPs,
+			CommEventSink remoteEventReceiver, int registryPort)
+			throws RemoteException {
+		// create NameToID and IdToInfo-Mapping
+		this.IPs = IPs;
+		this.remoteEventReceiver = remoteEventReceiver;
+		this.registryPort = registryPort;
+
+		dataServers = new PartitionDataServer[IPs.length];
+		startTheServer();
+
+		// start Thread service
+		executor = Executors.newCachedThreadPool();
+		String name = "unknown PartitionDataServer";
+		try {
+			name = InetAddress.getLocalHost().getHostName();
+		} catch (UnknownHostException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		dataServerName = name;
+		// try to get the hostnames
+		hostnames = new String[IPs.length];
+		for (int i = 0; i < IPs.length; i++) {
+			// try {
+			hostnames[i] = IPs[i];
+			// hostnames[i] = InetAddress.getByName(IPs[i]).getHostName();
+			// } catch (UnknownHostException e) {
+			// LOG.warn("Exception while retrivieving hostname of address: " +
+			// IPs[i]);
+			// }
+		}
+	}
+
+	/**
+	 * Same as {@link #PartitionDataManager(String[], CommEventSink, int)}, but uses
+	 * a local SPMDClient. <br>
+	 * This is used when a Server is running inside the Xulu-Client. It has
+	 * performance advantages (direct access - no TCP/IP)
+	 *
+	 * @param IPs
+	 *            the IPs of participating Servers for neighborhood updates(may
+	 *            include port specification)
+	 * @param remoteEventReceiver
+	 *            generated events are forwarded to the receiver
+	 * @param registryport
+	 *            port of the registry to which the {@link PartitionDataManager}
+	 *            should be bound
+	 * @param localSPMDClient
+	 *            a {@link ClientDataServer} for fast local access
+	 * @throws RemoteException
+	 */
+	public PartitionDataManager(String[] IPs,
+			RemoteEventProxy remoteEventReceiver, int registryport,
+			ClientDataServer localSPMDClient) throws RemoteException {
+		this(IPs, remoteEventReceiver, registryport);
+		this.localSPMDClient = localSPMDClient;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.client.DataServer#addData(appl.parallel.spmd.split.DataPartition)
+	 */
+	public void addData(DataPartition partition) throws RemoteException {
+		if (partition == null) {
+			LOG.warn("To add partition was null - no data added");
+			return;
+		}
+		data.put(partition.getRootID(), partition);
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.server.PartitionDataServer#addMultiDataInfos(java.util.HashMap)
+	 */
+	public void addMultiDataInfos(
+			HashMap<String, MultiDataInfo> newMultiDataInfos)
+			throws RemoteException {
+		this.multiDataInfos.putAll(newMultiDataInfos);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.server.PartitionDataServer#addPartitionInfos(java.util.Vector)
+	 */
+	public void addPartitionInfos(
+			Vector<SinglePartitionInfo> singlePartitionInfos)
+			throws RemoteException {
+		for (SinglePartitionInfo singlePartitionInfo : singlePartitionInfos) {
+			NameToIDMapping.put(singlePartitionInfo.getBaseResourceName(),
+					singlePartitionInfo.getBaseResourceID());
+			infos.put(singlePartitionInfo.getBaseResourceID(),
+					singlePartitionInfo);
+		}
+	}
+
+	/**
+	 * @param name
+	 * @param idx
+	 */
+	public void destroyMultiPartition(String name, int idx) {
+
+	}
+
+	/**
+	 * returns the baseParameter by name
+	 *
+	 * @param name
+	 *            the name of the parameter
+	 * @return the parameter
+	 */
+	public Object getBaseParameter(String name) {
+		return baseParameters.get(name);
+	}
+
+	/**
+	 * Returns a a (remote) PartitionDataServer for an IP-Address. Looks up the
+	 * PartitionDataServer in the registry
+	 */
+	private PartitionDataServer getConnection(String ip) {
+		PartitionDataServer server;
+		// lookup server
+		try {
+			server = (PartitionDataServer) Naming.lookup("rmi://" + ip + "/"
+					+ bindingName);
+		} catch (Exception e) {
+			LOG.error("bindig of " + ip + " failed" + e.getMessage(), e);
+			e.printStackTrace();
+			return null;
+		}
+		return server;
+	}
+
+	/**
+	 * Returns the {@link DataPartition} associated with the given ID
+	 *
+	 * @param id
+	 *            the id of the data
+	 * @return the data
+	 */
+	public synchronized DataPartition getData(int id) throws RemoteException {
+		// check if in hashtable already
+		DataPartition partition = data.get(id);
+		if (partition != null)
+			return partition;
+		// if not in hashtable:
+		// load the data and put it into hash
+		// find the element with the ID:
+		SinglePartitionInfo info = infos.get(id);
+
+		if (info == null) {
+			LOG.warn("No partition with id " + id + " found!");
+			return null;
+		}
+		// retrieve data from client or other location
+		try {
+			// if there is a local server try to get the local partition
+			PartitionDataHandler partitionDataHandler = info
+					.getPartitionDataHandler();
+			if (localSPMDClient != null)
+				partitionDataHandler.setSPMDClient(localSPMDClient);
+			partition = partitionDataHandler.load();
+		} catch (LoadingException e) {
+			// TODO Auto-generated catch block
+			LOG.error("Loading of partition with id '" + id
+					+ "' failed. Null returned!");
+			e.printStackTrace();
+			return null;
+		}
+		if (partition == null) {
+			LOG.error("Loading of partition with id '" + id
+					+ "' failed. Null returned!");
+			return null;
+		}
+
+		// enter data in partition table
+		data.put(id, partition);
+		return partition;
+	}
+
+	/**
+	 * Gets a partition by name
+	 *
+	 * @param name
+	 *            the name of the resource (probably given by the programmer)
+	 * @return the partition or null if not found
+	 */
+	public DataPartition getData(String name) {
+		Integer id = NameToIDMapping.get(name);
+		if (id == null) {
+			LOG.warn("No data for name " + name + " found! Returning null");
+			return null;
+		}
+		try {
+			return getData(id);
+		} catch (RemoteException e) {
+			// should never be reached (because the method call is local
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	/**
+	 * Returns the partition info with the specified id
+	 *
+	 * @param id
+	 *            the id of the partition
+	 * @return the info
+	 */
+	public PartitionInfo getInfo(int id) {
+		return infos.get(id);
+	}
+
+	/**
+	 * Gets a partition of a multi-data element. NOTE THAT ALL PARTITIONS OF THE
+	 * MULTIGRID WILL BE LOADED (watch out for loading performance!).
+	 *
+	 * @param name
+	 *            the name of the resource (probably given by the programmer)
+	 * @return the partition
+	 * @see SPMDClientController#addToMultiDataSplitControl(Object[], String)
+	 */
+	public DataPartition[] getMultiData(String name) {
+		// fill an array with the partitions
+		DataPartition[] partitions = new DataPartition[multiDataInfos.get(name)
+				.getCount()];
+		for (int i = 0; i < partitions.length; i++) {
+			partitions[i] = getMultiData(name, i);
+		}
+		return partitions;
+	}
+
+	/**
+	 * Gets a partition of a multi-data element. Only the resource at the given
+	 * position will be loaded.
+	 *
+	 * @param name
+	 *            the name of the resource (probably given by the programmer)
+	 * @param pos
+	 *            the index of the requested element
+	 * @return the partition
+	 * @see SPMDClientController#addToMultiDataSplitControl(Object[], String)
+	 */
+	public DataPartition getMultiData(String name, int pos) {
+		try {
+			return getData(multiDataInfos.get(name).getMultiID(pos));
+		} catch (RemoteException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.server.PartitionDataServer#getMultiDataInfo(java.lang.String)
+	 */
+	public MultiDataInfo getMultiDataInfo(String name) throws RemoteException {
+		return multiDataInfos.get(name);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.server.PartitionDataServer#getMultiDataObject(java.lang.String)
+	 */
+	public MultiDataPartitionObject getMultiDataObject(String name)
+			throws RemoteException {
+		return new MultiDataPartitionObject(multiDataInfos.get(name), this);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.server.PartitionDataServer#getPartition(int,
+	 *      java.awt.Rectangle)
+	 */
+	public synchronized DataPartition getPartition(int id, Rectangle bounds)
+			throws RemoteException {
+		DataPartition thisPartition = (DataPartition) data.get(id);
+		if (thisPartition == null && LOG.isDebugEnabled()) {
+			LOG.error("Partition with id " + id + " and bounds " + bounds
+					+ "was requested but not found on DataManager");
+			return null;
+		}
+
+		if (LOG.isDebugEnabled())
+			LOG.debug("Data retrieved from DataManager: ID:" + id
+					+ " partition: " + bounds);
+		return thisPartition.getPartition(bounds);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.server.PartitionDataServer#getPartitionInfo(int)
+	 */
+	public SinglePartitionInfo getPartitionInfo(int rootID)
+			throws RemoteException {
+		return infos.get(rootID);
+	}
+
+	/**
+	 * other dataservers may not be initialized on creation of this object.
+	 * Therefore the dataServers must be looked up later
+	 */
+	private void initializeDataServers() {
+		if (dataServersInitialized == true)
+			return;
+		for (int i = 0; i < dataServers.length; i++) {
+			dataServers[i] = getConnection(IPs[i]);
+		}
+		dataServersInitialized = true;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.client.DataServer#removeData(int)
+	 */
+	public void removeData(int id) {
+		data.remove(id);
+
+	}
+
+	/**
+	 * Removes the partition from the database
+	 *
+	 * @param name
+	 *            the name of the partition to remove
+	 */
+	public void removeData(String name) {
+		data.remove(NameToIDMapping.get(name));
+	}
+
+	/**
+	 * Removes the partition from the database
+	 *
+	 * @param partition
+	 *            the Partition to remove
+	 */
+	public void removePartition(DataPartition partition) {
+		data.remove(partition.getRootID());
+	}
+
+	/**
+	 * binds the server to the registry
+	 */
+	private void startTheServer() throws RemoteException {
+		Registry registry = LocateRegistry.getRegistry(registryPort);
+		registry.rebind(bindingName, (PartitionDataServer) this);
+		LOG.info("PartitionDataServer bound to port " + registryPort
+				+ " and running....");
+	}
+
+	/**
+	 * unbinds the server from the registry, removes all data and runs the
+	 * garbage collector
+	 */
+	public void stop() {
+		data.clear();
+		NameToIDMapping.clear();
+		infos.clear();
+
+		Registry registry;
+		try {
+			registry = LocateRegistry.getRegistry();
+			registry.unbind(bindingName);
+			LOG.debug("Sucessfully removed " + bindingName + " from reggie");
+		} catch (RemoteException e) {
+			LOG.warn("tried to unbind " + bindingName
+					+ " from reggie, but an exception occured: "
+					+ e.getMessage());
+		} catch (NotBoundException e) {
+			LOG.warn("tried to unbind " + bindingName
+					+ " from reggie, but the name was not bound "
+					+ e.getMessage());
+		}
+		System.gc();
+	}
+
+	/**
+	 * @param rootID
+	 */
+	public void unloadToSource(int rootID) throws RemoteException {
+		SinglePartitionInfo info = infos.get(rootID);
+		if (info == null) {
+			LOG.error("Could not unload partition with id " + rootID
+					+ ". The partitioninfo was not found!");
+			return;
+		}
+		// start unloading
+		info.getPartitionDataHandler().setBasePartition(this.getData(rootID));
+		info.getPartitionDataHandler().unload();
+		// // remove data from memory and run garbage collection
+		// data.remove(rootID);
+		// System.gc();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.server.PartitionDataServer#updateBaseParameter(java.lang.Object[],
+	 *      java.lang.String[])
+	 */
+	public void updateBaseParameter(HashMap<String, Object> newParameters)
+			throws RemoteException {
+		// update the mapping. Old values are replaced automaticly
+		baseParameters.putAll(newParameters);
+	}
+
+	/**
+	 * Updates the specified partition. For this the the neighborhood partitions
+	 * are updated from remote DataServers using the {@link SplitMap} of the
+	 * {@link SinglePartitionInfo}.
+	 *
+	 * @param id
+	 */
+	public void updateFromNeighbors(int id) {
+		initializeDataServers();
+		// get the data to be updated:
+		DataPartition thisPartition = data.get(id);
+		PartitionInfo info = infos.get(id);
+		if (thisPartition == null || info == null) {
+			LOG.error("Update with id " + id
+					+ " failed, because no data was found with this id");
+			return;
+		}
+
+		// get some other needed infos
+		SplitMap map = info.getSplitMap();
+		int mapPosition = info.getSplitMapPos();
+		// check if something to do
+		if (map.getNeighborhoodRange() == 0) {
+			LOG.debug("Update has nothing to do (neighborhoodrange is 0)");
+			return;
+		}
+
+		// calculate (for each neighbor) the needed partitions and get
+		// the updates (implemented using Threads)
+		int[] neighbors = map.getNeighborsForPosition(mapPosition);
+		Future futures[] = new Future[neighbors.length];
+		for (int j = 0; j < neighbors.length; j++) {
+			int neighborIdx = neighbors[j];
+			// get the overlap of the neighborhood area of the current partion
+			// with the calcultation area of the remote partition
+			Rectangle updateBounds = map.getPartitionNeighborhoodBounds(
+					mapPosition).intersection(
+					map.getPartitionCalculationBounds(neighborIdx));
+			// Get the partition from remote server:
+			DataPartition updateData;
+			futures[j] = executor.submit(new UpdateThread(
+					dataServers[neighborIdx], hostnames[neighborIdx],
+					thisPartition, updateBounds, id, remoteEventReceiver));
+		}
+
+		for (Future future : futures) {
+			try {
+				future.get();
+			} catch (InterruptedException e) {
+				e.printStackTrace();
+			} catch (ExecutionException e) {
+				LOG.error("The Remote update of a partition failed", e);
+			}
+		}
+
+	}
+
+	/**
+	 * Does the same as {@link #updateFromNeighbors(int)}
+	 *
+	 * @param name
+	 *            the name of the resource
+	 */
+	public void updateFromNeighbors(String name) {
+		// get by ID
+		updateFromNeighbors(NameToIDMapping.get(name));
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.server.PartitionDataServer#setPartition(int,
+	 *      appl.parallel.spmd.split.DataPartition, java.awt.Rectangle)
+	 */
+	public synchronized void updatePartition(int id, DataPartition partition,
+			Rectangle bounds) throws RemoteException {
+		DataPartition thisPartition = (DataPartition) data.get(id);
+		if (thisPartition == null && LOG.isDebugEnabled()) {
+			LOG
+					.error("Partition of data with id " + id + " and bounds "
+							+ bounds
+							+ "should be set but was not found in DataManager");
+			return;
+		}
+		thisPartition.setPartition(partition, bounds);
+		if (LOG.isDebugEnabled())
+			LOG.debug("Partition of data set on DataManager with id " + id
+					+ " and partition bounds: " + bounds);
+
+	}
+
+}

Added: trunk/src/appl/parallel/server/PartitionDataServer.java
===================================================================
--- trunk/src/appl/parallel/server/PartitionDataServer.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/server/PartitionDataServer.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,123 @@
+package appl.parallel.server;
+
+import java.awt.Rectangle;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.util.HashMap;
+import java.util.Vector;
+
+import appl.parallel.client.DataServer;
+import appl.parallel.spmd.MultiDataInfo;
+import appl.parallel.spmd.MultiDataObject;
+import appl.parallel.spmd.split.DataPartition;
+import appl.parallel.spmd.split.PartitionInfo;
+import appl.parallel.spmd.split.SinglePartitionInfo;
+import appl.parallel.spmd.split.SplittableResource;
+
+/**
+ * Manages data and partitions on servers. The method descriptions for details.
+ * 
+ * @see PartitionDataManager
+ *
+ * @author Dominik Appl
+ */
+public interface PartitionDataServer extends Remote, DataServer {
+
+	/**
+	 * gets the data with the id of a SplittableRessource
+	 *
+	 * @param id
+	 *            the {@link SplittableResource#getRootID() ID} of a the base data
+	 * @param bounds
+	 *            the bounds of the partition to retrieve (using global
+	 *            coordinates)
+	 * @return the partition
+	 * @throws RemoteException
+	 */
+	public DataPartition getPartition(int id, Rectangle bounds)
+			throws RemoteException;
+
+	/**
+	 * sets the data with the id of a SplittableRessource
+	 *
+	 * @param id
+	 *            the {@link SplittableResource#getRootID() ID} of a the base data
+	 * @param bounds
+	 *            the locatition where the partition is to be updated (using
+	 *            global coordinates)
+	 * @param updateData
+	 *            the updateData (which may only a partitial update, depending
+	 *            on the bounds set with the last parameter)
+	 * @throws RemoteException
+	 */
+	public void updatePartition(int id, DataPartition updateData,
+			Rectangle bounds) throws RemoteException;
+
+	/**
+	 * Unloads the specified resource to the source it was loaded from
+	 *
+	 * @param rootID
+	 *            the id of the resource
+	 */
+	public void unloadToSource(int rootID) throws RemoteException;
+
+	/**
+	 * requests an update for the neighborhood region for the given resource
+	 *
+	 * @param rootID
+	 */
+	public void updateFromNeighbors(int rootID) throws RemoteException;
+
+	/**
+	 * Adds or updates BaseParameters
+	 */
+	public void updateBaseParameter(HashMap<String, Object> newParameters)
+			throws RemoteException;
+
+	/**
+	 * Adds {@link PartitionInfo}s to the server. They are submitted in a
+	 * vector to avoid multiple remote calls.
+	 *
+	 * @param singlePartitionInfos
+	 * @throws RemoteException
+	 */
+	public void addPartitionInfos(
+			Vector<SinglePartitionInfo> singlePartitionInfos)
+			throws RemoteException;
+
+	/**
+	 * Adds {@link MultiDataInfo}s to the server.
+	 *
+	 * @param toTransferMultiDataObjects
+	 */
+	public void addMultiDataInfos(
+			HashMap<String, MultiDataInfo> toTransferMultiDataObjects)
+			throws RemoteException;
+
+	/**
+	 * @param name
+	 *            the name of the associated multi data
+	 * @return the {@link MultiDataInfo} info
+	 * @throws RemoteException
+	 */
+	public MultiDataInfo getMultiDataInfo(String name) throws RemoteException;
+
+	/**
+	 * @param name
+	 *            the name of the multiDataObject
+	 * @return the MultiDataObject associated with that name
+	 * @throws RemoteException
+	 */
+	public MultiDataObject getMultiDataObject(String name)
+			throws RemoteException;
+
+	/**
+	 * @param rootID
+	 *            the id of the according partition
+	 * @return the the {@link PartitionInfo}
+	 * @throws RemoteException
+	 */
+	public SinglePartitionInfo getPartitionInfo(int rootID)
+			throws RemoteException;
+
+}

Added: trunk/src/appl/parallel/server/SPMDResource.java
===================================================================
--- trunk/src/appl/parallel/server/SPMDResource.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/server/SPMDResource.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,51 @@
+package appl.parallel.server;
+
+import java.rmi.RemoteException;
+import java.util.HashMap;
+import java.util.Vector;
+
+import appl.parallel.ComputingResource;
+import appl.parallel.spmd.SPMDClientController;
+import appl.parallel.spmd.SPMDTask;
+import appl.parallel.spmd.split.SinglePartitionInfo;
+import appl.parallel.spmd.split.SplitMap;
+
+/**
+ * The resources participating in a SPMD computation need to implement this
+ * interface.
+ * 
+ * @author Dominik Appl
+ */
+public interface SPMDResource extends ComputingResource {
+
+	/**
+	 * Executes the given Task.
+	 * 
+	 * @param SPMDTaskName
+	 *            name of the taskclass to be executed
+	 * @param referenceID
+	 *            the ID of the Grid which should be the reference resource
+	 * @param parameters
+	 *            parameters for the given Task
+	 * @return an object array containing the results for possibly multiple
+	 *         executions (when using multithreading with multi-core cpus)
+	 * @throws RemoteException
+	 *             if the connection fails
+	 * @see SPMDClientController#setReferenceResource(Object)
+	 */
+
+	public Object[] runSPMDModelTask(String SPMDTaskName, int referenceID,
+			Object... parameters) throws RemoteException;
+
+	/**
+	 * @param IPs
+	 *            the IP addresses of all other participating servers. They MUST
+	 *            have the same index as their according partition in the
+	 *            {@link SplitMap} has.
+	 * @return creates a new {@link PartitionDataServer} on this resource and
+	 *         returns it
+	 */
+	public PartitionDataServer createDataServer(String[] IPs)
+			throws RemoteException;
+
+}

Added: trunk/src/appl/parallel/server/ServerMulticastReceiver.java
===================================================================
--- trunk/src/appl/parallel/server/ServerMulticastReceiver.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/server/ServerMulticastReceiver.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,99 @@
+package appl.parallel.server;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.InetAddress;
+import java.net.MulticastSocket;
+import java.net.SocketException;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import appl.ext.XuluConfig;
+import appl.parallel.services.MulticastDiscoveryService;
+
+/**
+ * Waits for multicast messages from clients and responds properly.
+ * 
+ * @see MulticastDiscoveryService
+ * @author Dominik Appl
+ */
+public class ServerMulticastReceiver extends Thread {
+
+	private final Logger LOG = LogManager.getLogger(this.getClass().getName());
+
+	private static final String helloFromXuluMessage = "Hello Servers";
+
+	private static final String helloFromServerMessage = "Hello Xulu from XuluServer";
+
+	boolean exit = false;
+
+	MulticastSocket socket;
+
+	int multicastPort = XuluConfig.getXuluConfig().getIntProperty(
+			"XuluServer.multicastport");
+
+	/**
+	 * @param socket
+	 *            Socket which is used for listening. Set a timeout for the
+	 *            socket via {@link MulticastSocket#setSoTimeout(int)} so that
+	 *            the thread can be stopped (because of the blocked reading)
+	 */
+	public ServerMulticastReceiver(MulticastSocket socket) {
+		this.socket = socket;
+		// try {
+		// socket.setSoTimeout(5000);
+		// } catch (SocketException e) {
+		// //do not printout the timeout
+		// }
+	}
+
+	/**
+	 * Safe method to stop the Thread. Use this method instead of {@link Thread}
+	 */
+	public void stopThread() {
+		exit = true;
+	}
+
+	public void run() {
+		System.out.println("Listening on port " + socket.getLocalPort()
+				+ " for Xulu hello messages!");
+		while (!exit) {
+			try {
+				// receive buffer
+				byte[] buffer = new byte[256];
+				DatagramPacket datagram = new DatagramPacket(buffer,
+						buffer.length);
+				socket.receive(datagram);
+
+				// get right message format (cut out null bytes)
+				byte[] result = new byte[datagram.getLength()];
+				System.arraycopy(datagram.getData(), 0, result, 0, datagram
+						.getLength());
+
+				// check message:
+				if (new String(result).equals(helloFromXuluMessage)) {
+					// LOG.info("received hello from Client " +
+					// datagram.getAddress());
+					LOG.info("received hello from Client "
+							+ datagram.getAddress());
+
+					// get the IP again and send the answer
+					String IP = XuluConfig.getXuluConfig().getProperty(
+							"XuluServer.multicastgroup");
+					DatagramPacket answer = new DatagramPacket(
+							helloFromServerMessage.getBytes(),
+							helloFromServerMessage.length(), InetAddress
+									.getByName(IP), multicastPort);
+					socket.send(answer);
+				}
+			} catch (IOException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			} catch (Exception e) {
+				if (!(e instanceof InterruptedException))
+					e.printStackTrace();
+			}
+		}
+	}
+}

Added: trunk/src/appl/parallel/server/XuluServer.java
===================================================================
--- trunk/src/appl/parallel/server/XuluServer.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/server/XuluServer.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,1034 @@
+package appl.parallel.server;
+
+import java.awt.Rectangle;
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.MulticastSocket;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.rmi.MarshalledObject;
+import java.rmi.Naming;
+import java.rmi.NotBoundException;
+import java.rmi.RMISecurityManager;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.activation.Activatable;
+import java.rmi.activation.ActivationID;
+import java.rmi.server.ServerNotActiveException;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.HashMap;
+import java.util.Vector;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import net.jini.loader.pref.PreferredClassLoader;
+
+import org.apache.log4j.BasicConfigurator;
+import org.apache.log4j.Level;
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+import org.apache.log4j.PropertyConfigurator;
+import org.apache.log4j.net.SocketAppender;
+
+import appl.ext.XuluConfig;
+import appl.parallel.ComputingResourceProperties;
+import appl.parallel.client.DataServer;
+import appl.parallel.client.ClientDataServer;
+import appl.parallel.event.CommEventSink;
+import appl.parallel.event.TimeEvent;
+import appl.parallel.event.CommEvent.CommType;
+import appl.parallel.services.RemoteEventProxy;
+import appl.parallel.spmd.AdvancedSPMDServerController;
+import appl.parallel.spmd.AdvancedSPMDServerInterface;
+import appl.parallel.spmd.SPMDServerController;
+import appl.parallel.spmd.SPMDServerInterface;
+import appl.parallel.spmd.SPMDTask;
+import appl.parallel.spmd.split.SinglePartitionInfo;
+import appl.parallel.spmd.split.SplitMap;
+import appl.parallel.spmd.split.SplitMap1DVertical;
+import appl.parallel.spmd.split.AbstractSplitMap.NeighborhoodBoxingMode;
+import appl.parallel.thread.OneMethodThread;
+import appl.parallel.util.Helper;
+import appl.util.benchmark.Benchmark;
+
+/**
+ * The Server manages the remote execution of program code. It may be started
+ * using the {@link #main(String[])} method.<br>
+ * The Server reads the following properties from {@link XuluConfig} - the
+ * values given should be the defaults.<br>
+ * <table border="1">
+ * <tr>
+ * <th>Property</th>
+ * <th>Default</th>
+ * <th>Desc</th>
+ * </tr>
+ * <tr>
+ * <td>XuluServer.useCodeDownloading</td>
+ * <td>false</td>
+ * <td>if true, the server tries to download task class files from a
+ * HTTP-server at the client-url</td>
+ * </tr>
+ * <tr>
+ * <td>XuluServer.registryPort</td>
+ * <td>1099</td>
+ * <td>The port at which a new registry is created, if no running registry was
+ * found</td>
+ * </tr>
+ * <tr>
+ * <td>XuluServer.multicastgroup</td>
+ * <td>239.1.1.1</td>
+ * <td>The default multicast group</td>
+ * </tr>
+ * <tr>
+ * <td> XuluServer.multicastport</td>
+ * <td>10000</td>
+ * <td>The default multicast port</td>
+ * </tr>
+ * <tr>
+ * <td>XuluServer.eventDelay</td>
+ * <td>50</td>
+ * <td>Events generated on server side may be delayed to collect multiple
+ * Events and send them at once (this saves communication time).Time is given in
+ * milliseconds</td>
+ * </tr>
+ * <tr>
+ * <td>XuluServer.log4j.logLevel</td>
+ * <td>info</td>
+ * <td>the level can be '<i>debug</i>','<i>info</i>','<i>warn</i>','<i>error</i>'
+ * or '<i>fatal</i>' and can be overridden by commandline - Parameters<br>
+ * <br>
+ * </td>
+ * </tr>
+ * <td>XuluServer.log4j.mode</td>
+ * <td>console</td>
+ * <td>the mode can be '<i>file</i>','<i>chainsaw</i>' or '<i>console</i>'.
+ * File means that the configurationfile xuluserverlog4j.cfg is read. <br>
+ * <i>'chainsaw'</i> means that the server tries to configure the logger each
+ * time a new client for a chainsaw instance running at the client ip
+ * (standardports) <br>
+ * </td>
+ * </tr>
+ * <td>XuluServer.benchmarkclass</td>
+ * <td>appl.util.benchmark.SimpleBenchmark</td>
+ * <td>The Benchmark to get a rating for this machine. Notice that you can
+ * override the rating with the -rating parameter</td>
+ * </tr>
+ * <tr>
+ * <td>XuluServer.useThreads</td>
+ * <td>max</td>
+ * <td>The number of threads to be used by the server for tasks that support
+ * multi-threading. Per default one thread is created for every available
+ * Processors (value='max'). More threads than processors may be useful for
+ * testing tasks which support multihreading or for processors which support
+ * hyperthreading.</td>
+ * </tr>
+ * <tr>
+ * <td>XuluServer.runbench</td>
+ * <td>true</td>
+ * <td>the benchmark is run automatically</td>
+ * </tr>
+ * </table> <br>
+ * <b>Multicasting:</b> <br>
+ * If multicasting does not work, try to disable your firewall or configure it
+ * to allow multicast UDP packages. Notice also, that multicasting may not work
+ * in virtual machines like VMWare or MS Virtual PC 2004/7. <br>
+ * <br>
+ * <b>Assumptions</b> 
+ * Only one client is connected to the server (and can run Tasks) <br>
+  *<br>
+  * See {@link #main(String[])} for details about command line parameters
+ * @see ServerMulticastReceiver
+ * @author Dominik Appl
+ */
+public class XuluServer extends UnicastRemoteObject implements SPMDResource {
+
+	/**
+	 * This Thread is used when multiple threads should be executed simultaneous during multithreading
+	 *
+	 * @author Dominik Appl
+	 */
+	class SimpleCallThread implements Callable {
+
+		private final SPMDTask task;
+
+		private final Object[] parameters;
+
+		/**
+		 * @param task the task to be executed
+		 * @param parameters the parameters for the run method of the task
+		 */
+		public SimpleCallThread(SPMDTask task, Object... parameters) {
+			this.task = task;
+			this.parameters = parameters;
+		}
+
+		/*
+		 * (non-Javadoc)
+		 *
+		 * @see java.util.concurrent.Callable#call()
+		 */
+		public Object call() throws Exception {
+			return task.run(parameters);
+		}
+	}
+
+	private static final Logger LOG = LogManager
+			.getLogger("appl.parallel.server.XuluServer");
+
+	private static String bindingName = "XuluServer";
+
+	private static final String helloFromServerMessage = "Hello Xulu from XuluServer";
+
+	private static String log4jfilename = "xuluserverlog4j.cfg";
+
+	private static boolean chainsaw = false;
+
+	private static SocketAppender chainsawAppender;
+
+	/**
+	 * @param mode the mode of the execution
+	 */
+	private static void log4jConfig(String mode) {
+		if (mode.equals("chainsaw")) {
+			BasicConfigurator.resetConfiguration();
+			chainsawAppender = new SocketAppender();
+			BasicConfigurator.configure(chainsawAppender);
+			System.out.println("Server configured for chainsaw.");
+			chainsaw = true;
+		} else if (mode.equals("file")) {
+			BasicConfigurator.resetConfiguration();
+			PropertyConfigurator.configure(log4jfilename);
+		} else if (mode.equals("console")) {
+			BasicConfigurator.resetConfiguration();
+			BasicConfigurator.configure();
+		} else {
+			System.err.println("Invalid log4j-Config parameter found: " + mode);
+			printInfoMessage();
+			System.exit(0);
+		}
+	}
+
+	/**
+	 * configures the log4j level
+	 *
+	 * @see #main(String[])
+	 */
+	private static void log4jLevel(String level) {
+		if (level.equals("info")) {
+			LOG.setLevel(Level.INFO);
+		} else if (level.equals("debug")) {
+			LOG.setLevel(Level.DEBUG);
+		} else if (level.equals("error")) {
+			LOG.setLevel(Level.ERROR);
+		} else if (level.equals("fatal")) {
+			LOG.setLevel(Level.FATAL);
+		} else if (level.equals("warn")) {
+			LOG.setLevel(Level.WARN);
+		} else if (level.equals("off")) {
+			LOG.setLevel(Level.OFF);
+		} else {
+			System.err.println("Invalid log4j-Level found: " + level);
+			printInfoMessage();
+			System.exit(0);
+		}
+		System.out.println("Setting logLevel to " + level);
+	}
+
+	/**
+	 * Starts the server.
+	 *
+	 * @param args
+	 * The following parameters are valid: <br>
+	 * <br>
+	 * -loglevel:<code>LEVEL</code> - where <code>LEVEL</code> is '<i>debug</i>','<i>info</i>'
+	 * (DEFAULT),'<i>warn</i>','<i>error</i>' or '<i>fatal</i>' <br>
+	 * <br>
+	 * -logconfig:<code>CONFIG</code> - where <code>CONFIG</code> is '<i>file</i>','<i>chainsaw</i>' or '<i>console</i>'
+	 * <li>'chainsaw' means that the server tries to configure the logger each time a
+	 * new client for a chainsaw instance running at the client ip
+	 * (standardports) </li><br>
+	 * <li>'<i>file</i>' means that the file '<i>xuluserverlog4j.cfg</i>'
+	 * in the home-directory is used for configuration <br> </li>
+	 * <li>'<i>console</i>'
+	 * means of course, that the console is used for output <br> </li>
+	 * <br>
+	 * -port:PORTNUMBER - binds the server to the specified port (default 1099)
+	 *
+
+	 */
+	public static void main(String[] args) {
+		// parse arguments
+		int serverPort = 0;
+		for (String arg : args) {
+			if (arg.toLowerCase().startsWith("-loglevel:"))
+				log4jLevel(arg.substring(10).toLowerCase());
+			else if (arg.toLowerCase().startsWith("-logconfig:"))
+				log4jConfig(arg.substring(11).toLowerCase());
+			else if (arg.toLowerCase().startsWith("-port:"))
+				serverPort = Integer.valueOf(arg.substring(6));
+			else {
+				System.err.println("Invalid Argument found: " + arg);
+				printInfoMessage();
+				System.exit(0);
+			}
+		}
+
+		if (System.getSecurityManager() == null) {
+			System.setSecurityManager(new RMISecurityManager());
+		}
+		Remote server;
+		try {
+			server = new XuluServer(serverPort);
+			System.out.println("Xulu Server is up and running!");
+		} catch (RemoteException e) {
+			System.err.println("Xulu Server could not start!");
+			e.printStackTrace();
+		}
+	}
+
+	private static void printInfoMessage() {
+		System.out
+				.println("The following arguments are valid: \n"
+						+ "-loglevel:<LEVEL> \n"
+						+ "   where <LEVEL> is 'off','debug','info' (DEFAULT),'warn','error' or 'fatal'\n\n"
+						+ "-logconfig:<CONFIG> \n"
+						+ "   where <CONFIG> is 'file','chainsaw' or 'console'(DEFAULT) \n"
+						+ "   'chainsaw' means that the server tries to configure the logger each\n"
+						+ "   time a new client for a chainsaw instance running at the client ip\n"
+						+ "   (standardports) \n"
+						+ "   'file' means that the file 'xuluserverlog4j.cfg' in the home-directory "
+						+ "         is used for configuration \n"
+						+ "   'console' means of course, that the console is used for output"
+						+ "-port:<portnumber> \n"
+						+ "   The Server is bound to the specified port");
+	}
+
+	private static void unbind() {
+		Helper.unbind(bindingName);
+	}
+
+	/**
+	 * The {@link Class} objects of the currently active connection. Every time
+	 * {@link #runSPMDModelTask(String, int, Object[])} is called the
+	 * newest class is loaded from the client. For performance reasons this will
+	 * happen only one time per connection. In this map the current active
+	 * classes are stored.
+	 */
+	private HashMap<String, SPMDTask[]> spmdTaskInstances;
+
+	/* standard is should be 1099 */
+	private int registryPort = 1099;
+
+	private int multicastPort;
+
+	private String multiCastIP;
+
+	ServerMulticastReceiver multicastThread;
+
+	InetAddress multiCastGroup;
+
+	// says whether a client is connected
+	private boolean connected = false;
+
+	private long starttime = System.currentTimeMillis();
+
+	private String connectedClient;
+
+	private PartitionDataManager dataManager;
+
+	private RemoteEventProxy remoteEventReceiver;
+
+	// User specified name of the Server or hostname
+	private String serverName;
+
+	private int machineRating = 0;
+
+	private final boolean loggingEnabled;
+
+	private int taskPriority = Thread.NORM_PRIORITY;
+
+	private int availableProcessors = 1;
+
+	private int toUseThreads = 1;
+
+	private final boolean isInternalServer;
+
+	private ClientDataServer localSPMDClient;
+
+	private boolean useCodeDownloading;
+
+	private ExecutorService executor;
+
+	// used for execution results
+	private Future[] resultCalls;
+
+	/**
+	 * Creates a new instance at the standard port
+	 *
+	 * @throws RemoteException
+	 */
+	public XuluServer() throws RemoteException {
+		this(true, false, 0);
+	}
+
+	/**
+	 * @param configLogging
+	 *            enable or disable logging
+	 * @param isInternalServer
+	 *            set to true if you want to make method calls purely local.
+	 *            This is for performance reasons (see
+	 *            {@link UnicastRemoteObject#getClientHost()}
+	 * @param port
+	 *            port the server is bound to (0 for default)
+	 * @throws RemoteException
+	 */
+	public XuluServer(boolean configLogging, boolean isInternalServer, int port)
+			throws RemoteException {
+		super();
+		loggingEnabled = configLogging;
+		this.isInternalServer = isInternalServer;
+		initConfiguration();
+		//the executor is used for multithreading
+		executor = Executors.newCachedThreadPool();
+		spmdTaskInstances = new HashMap<String, SPMDTask[]>(10);
+		if (port != 0)
+			this.registryPort = port;
+		bind();
+
+		initializeMultiCasting();
+		serverName = "unknown server";
+		try {
+			if (isInternalServer)
+				serverName = "internal Server";
+			else
+				serverName = InetAddress.getLocalHost().getHostName();
+		} catch (UnknownHostException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		if (port != 0)
+			serverName = serverName + " (port " + registryPort + ")";
+		runBenchmark();
+	}
+
+	/**
+	 * <br>
+	 * This is used when a Server is running inside the Xulu-Client. It has
+	 * performance advantages (direct access - no TCP/IP)
+	 *
+	 * @param configLogging
+	 *            enable or disable logging
+	 * @param clientDataServer a local client for faster access
+	 * @throws RemoteException
+	 */
+	public XuluServer(boolean configLogging, ClientDataServer clientDataServer)
+			throws RemoteException {
+		this(configLogging, true, 0);
+		this.localSPMDClient = clientDataServer;
+	}
+
+	/**
+	 * @param port
+	 *            the port to which the Server is bound
+	 * @throws RemoteException
+	 */
+	public XuluServer(int port) throws RemoteException {
+		this(true, false, port);
+	}
+
+	/**
+	 * Bind the remote object's stub in the registry. Creates a registry if no
+	 * running registry is found.
+	 */
+	private void bind() throws RemoteException {
+		String name = bindingName;
+		Helper.bind(name, this, registryPort);
+	}
+
+	private boolean checkConnected(String callingHost) {
+
+		if (callingHost.equals(connectedClient))
+			return true;
+		LOG
+				.warn(callingHost
+						+ " has tried to execute a critical operation, but was not connected "
+						+ ". Actual connected client: " + connectedClient);
+		return false;
+	}
+
+	/**
+	 * Only a connected client has access to all functionality. When connecting
+	 * or reconnecting, all data of the server and the corresponding
+	 * {@link PartitionDataServer} is reset!
+	 *
+	 * @see appl.parallel.ComputingResource#connect()
+	 */
+	public synchronized boolean connect() throws RemoteException {
+		/**
+		 * determine the calling host. Internal Server requires special
+		 * handling: notice that this happens very often in this class, but can
+		 * not externalized due to the behavior of #getClientHost();
+		 */
+		String callingHost = "error";
+		try {
+			callingHost = isInternalServer ? "localhost" : getClientHost();
+		} catch (ServerNotActiveException e) {
+			e.printStackTrace();
+		}
+		/** ********************************************************************** */
+
+		if (connectedClient == null || callingHost.equals(connectedClient)) {
+			if (connectedClient == null)
+				LOG.info("Client " + callingHost + " connected!");
+			else
+				LOG.info("Client " + connectedClient + " reconnected! ");
+			// reset data
+			reset();
+			connectedClient = callingHost;
+			// initalize event system & chainsaw
+			initEventSystem();
+			initChainsaw(connectedClient);
+			return true;
+		} else if (connectedClient != null) {
+			LOG.warn(callingHost + " has tried to "
+					+ "connect to server, but was not connected, "
+					+ "because this server is in use by " + connectedClient);
+		}
+
+		return false;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.server.ComputingResource#createDataServer()
+	 */
+	public PartitionDataServer createDataServer(String[] IPs)
+			throws RemoteException {
+		/**
+		 * determine the calling host. Internal Server requires special
+		 * handling: notice that this happens very often in this class, but can
+		 * not externalized due to the behavior of #getClientHost();
+		 */
+		String callingHost = "localhost";
+		try {
+			callingHost = isInternalServer ? "localhost" : getClientHost();
+		} catch (ServerNotActiveException e) {
+			e.printStackTrace();
+		}
+		/** ********************************************************************** */
+		if (checkConnected(callingHost)) {
+			if (isInternalServer)
+				dataManager = new PartitionDataManager(IPs,
+						remoteEventReceiver, getRegistryPort(), localSPMDClient);
+			else
+				dataManager = new PartitionDataManager(IPs,
+						remoteEventReceiver, getRegistryPort());
+			return dataManager;
+		}
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.server.ComputingResource#disconnect()
+	 */
+	public synchronized void disconnect() throws RemoteException {
+		/**
+		 * determine the calling host. Internal Server requires special
+		 * handling: notice that this happens very often in this class, but can
+		 * not externalized due to the behavior of #getClientHost();
+		 */
+		String callingHost = "localhost";
+		try {
+			callingHost = isInternalServer ? "localhost" : getClientHost();
+		} catch (ServerNotActiveException e) {
+			e.printStackTrace();
+		}
+		/** ********************************************************************** */
+		if (checkConnected(callingHost)) {
+			reset();
+			LOG.info("Client " + connectedClient
+					+ " successfully disconnected from Server");
+		}
+	}
+
+	/**
+	 * @return a rating for the machine as discovered by the benchmark
+	 */
+	public int getRating() {
+		return machineRating;
+	}
+
+	/**
+	 * @return the registry port the server is bound to
+	 */
+	public int getRegistryPort() {
+		return registryPort;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.server.XuluServer#getResourceInformation()
+	 */
+	public ComputingResourceProperties getResourceInformation()
+			throws RemoteException {
+		return new XuluServerProperties(this, serverName);
+	}
+
+	/**
+	 * @return the time in s the server is running
+	 */
+	int getUptime() {
+		return (int) (System.currentTimeMillis() - starttime);
+	}
+
+	private void initChainsaw(String connectedClient) {
+		if (chainsaw && connectedClient != null) {
+			chainsawAppender = new SocketAppender(connectedClient, 4445);
+			BasicConfigurator.resetConfiguration();
+			BasicConfigurator.configure(chainsawAppender);
+		}
+	}
+
+	/**
+	 * inits task priority, ports and loglevel
+	 */
+	private void initConfiguration() {
+		XuluConfig config = XuluConfig.getXuluConfig();
+		// a lower priority will run the server more in the background
+		taskPriority = config.getIntProperty("XuluServer.priority");
+
+		switch (taskPriority) {
+		default:
+			taskPriority = Thread.NORM_PRIORITY;
+			break;
+		case 1:
+			taskPriority = Thread.MIN_PRIORITY;
+			break;
+		case 2:
+			taskPriority = Thread.NORM_PRIORITY - 1;
+			break;
+		case 4:
+			taskPriority = Thread.NORM_PRIORITY + 1;
+			break;
+		case 5:
+			taskPriority = Thread.MAX_PRIORITY;
+			break;
+		}
+
+		availableProcessors = Runtime.getRuntime().availableProcessors();
+		// default: try to use one thread per processor
+		toUseThreads = availableProcessors;
+		// check if there is an entry in the XuluConfig saying how many threads
+		// should be created.
+		// (more threads than processors may be useful for the use of
+		// hyperthreading)
+		String configProz = config.getProperty("XuluServer.useThreads");
+		if ((configProz != null) && !configProz.equals("max")) {
+			toUseThreads = config.getIntProperty("XuluServer.useThreads");
+			// error checking:
+			if (toUseThreads < 1 || toUseThreads > 128){
+				toUseThreads = availableProcessors;
+			System.out
+					.println("Error: Number of threads must be between 1 and 128!");
+			}
+		}
+		// init correspondig arrays
+		resultCalls = new Future[toUseThreads];
+
+		int port = config.getIntProperty("XuluServer.registryport");
+		if (port != 0)
+			registryPort = port;
+
+		useCodeDownloading = config
+				.getBooleanProperty("XuluServer.useCodeDownloading");
+		if (useCodeDownloading)
+			System.out.println("Code downloading is enabled");
+		else
+			System.out.println("Code downloading is disabled");
+
+		int multicastport = config.getIntProperty("XuluServer.multicastport");
+		if (multicastport != 0)
+			multicastPort = multicastport;
+		String IP = config.getProperty("XuluServer.multicastgroup");
+		if (IP != null)
+			multiCastIP = IP;
+		try {
+			multiCastGroup = InetAddress.getByName(multiCastIP);
+		} catch (UnknownHostException e) {
+			e.printStackTrace();
+		}
+		if (loggingEnabled) {
+
+			String mode = config.getProperty("XuluServer.log4j.mode");
+			if (mode != null)
+				log4jConfig(mode);
+		}
+		String level = config.getProperty("XuluServer.log4j.logLevel");
+		if (level != null)
+			log4jLevel(level.toLowerCase());
+		else
+			log4jLevel("info");
+	}
+
+	/**
+	 * Connects to the RemoteEventReceiver at the calling client
+	 */
+	private void initEventSystem() throws RemoteException {
+		String lookupName = "rmi://" + connectedClient + "/RemoteEventReceiver";
+		try {
+			int delay = XuluConfig.getXuluConfig().getIntProperty(
+					"XuluServer.eventDelay");
+			System.out.println("looking up " + lookupName);
+			CommEventSink eventSink = (CommEventSink) Naming.lookup(lookupName);
+			if (remoteEventReceiver != null)
+				remoteEventReceiver.stopService();
+			remoteEventReceiver = new RemoteEventProxy(eventSink, delay);
+			remoteEventReceiver.startService();
+		} catch (MalformedURLException e) {
+			e.printStackTrace();
+		} catch (NotBoundException e) {
+			LOG.warn("Could not find the remote event receiver at "
+					+ lookupName, e);
+			System.out.println(e.getMessage());
+			remoteEventReceiver = new RemoteEventProxy(null, 0);
+		}
+	}
+
+	/**
+	 * inits the multicast unit
+	 */
+	private void initializeMultiCasting() {
+		try {
+			MulticastSocket s = new MulticastSocket(multicastPort);
+			s.joinGroup(multiCastGroup);
+			// send hello message
+			String IP = XuluConfig.getXuluConfig().getProperty(
+					"XuluServer.multicastgroup");
+			DatagramPacket answer = new DatagramPacket(helloFromServerMessage
+					.getBytes(), helloFromServerMessage.length(), InetAddress
+					.getByName(IP), multicastPort);
+			s.send(answer);
+			// start thread that waits on client messages
+			multicastThread = new ServerMulticastReceiver(s);
+			multicastThread.start();
+		} catch (IOException e) {
+			// TODO Auto-generated catch block
+			LOG.warn("Could not initalize multicasting! Reason was "
+					+ e.getMessage(), e);
+
+		}
+	}
+
+	/**
+	 * @return whether this server is available or in use by another client
+	 * @see appl.parallel.ComputingResource#isAvailable()
+	 */
+	public boolean isAvailable() throws RemoteException {
+		/**
+		 * determine the calling host. Internal Server requires special
+		 * handling: notice that this happens very often in this class, but can
+		 * not externalized due to the behavior of #getClientHost();
+		 */
+		String callingHost = "localhost";
+		try {
+			callingHost = isInternalServer ? "localhost" : getClientHost();
+		} catch (ServerNotActiveException e) {
+			e.printStackTrace();
+		}
+		/** ********************************************************************** */
+		if (callingHost.equals(connectedClient))
+			return true;
+
+		if (connectedClient == null)
+			return true;
+		return false;
+	}
+
+	/**
+	 * @return if a client is connected
+	 */
+	public boolean isClientConnected() {
+		return connected;
+
+	}
+
+	/**
+	 * Loads a {@link SPMDTask} from the specified URL and returns an array of
+	 * instances of this class. There are so many instances, as there are
+	 * available processors on this machine!. This class also makes sure that
+	 * this happens only one time per connection (else this would of course be a
+	 * performance killer in fine grained parallelization).
+	 *
+	 * @param location
+	 *            the URL of the rootDirectory/networkLocation
+	 * @param spmdTaskClassName
+	 *            the name of the SPMDTask for which the newest class should be
+	 *            found
+	 * @return the instance of the class or <code>null</code> if loading fails
+	 */
+	private SPMDTask[] loadSPMDTasksfromURL(String location,
+			String spmdTaskClassName) {
+
+		SPMDTask[] spmdClassInstances = (SPMDTask[]) spmdTaskInstances
+				.get(spmdTaskClassName);
+
+		// if already loaded for this connection simply return the instances
+		if (spmdClassInstances != null)
+			return (SPMDTask[]) spmdClassInstances;
+		spmdClassInstances = new SPMDTask[toUseThreads];
+		Class spmdClass = null;
+		if (useCodeDownloading) {
+			try {
+				// lookup client and make sure that the newest class of the task
+				// is instantiated. Will avoid loading older cached or local
+				// filesystem version
+				URL[] locations = { new URL("http://" + location + "/") };
+				PreferredClassLoader classLoader = new PreferredClassLoader(
+						locations, Thread.currentThread()
+								.getContextClassLoader(), null, false);
+				LOG.debug("Try to load " + spmdTaskClassName + " from "
+						+ location);
+				spmdClass = classLoader.loadClass(spmdTaskClassName);
+			} catch (Exception e) {
+				LOG.error("Could not load class for " + spmdTaskClassName
+						+ " from " + location, e);
+				e.printStackTrace();
+			}
+		}
+		// if retrieval failed for some reason or code downloading disabled
+		// then use the local class
+		try {
+			if (spmdClass == null) {
+				spmdClass = Class.forName(spmdTaskClassName);
+			}
+
+			// instantiate the classes
+			for (int i = 0; i < spmdClassInstances.length; i++) {
+				Object task = spmdClass.newInstance();
+				if (!(task instanceof SPMDTask)) {
+					LOG.fatal(spmdTaskClassName
+							+ " was not an instance of SPMDTask!");
+					throw new UnsupportedOperationException(spmdTaskClassName
+							+ " was not an instance of SPMDTask!");
+				}
+				spmdClassInstances[i] = (SPMDTask) task;
+			}
+
+			spmdTaskInstances.put(spmdTaskClassName, spmdClassInstances);
+			return spmdClassInstances;
+
+		} catch (ClassNotFoundException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		} catch (InstantiationException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		} catch (IllegalAccessException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		throw new UnsupportedOperationException("Loading of class "
+				+ spmdTaskClassName
+				+ " failed on serverside! Execution canceled");
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.server.XuluServer#ping(java.lang.Object[])
+	 */
+	public Object ping(Object... o) throws RemoteException {
+		System.out.println("received ping");
+		return o;
+	}
+
+	/**
+	 * deletes all client-specific data data, so that a newly connected client
+	 * can use a clean system
+	 */
+	private void reset() {
+		if (dataManager != null)
+			dataManager.stop();
+		dataManager = null;
+		connectedClient = null;
+		spmdTaskInstances.clear();
+	}
+
+	/**
+	 * runs the benchmark defined in XuluServer.benchmarkclass
+	 */
+	private void runBenchmark() {
+		// see if the benchmark should be run
+
+		boolean runbench = XuluConfig.getXuluConfig().getBooleanProperty(
+				"XuluServer.runbench");
+		if (runbench) {
+			String classname = XuluConfig.getXuluConfig().getProperty(
+					"XuluServer.benchmarkclass");
+			if (classname != null) {
+				try {
+					// getBenchmarkClass
+					Benchmark bench = (Benchmark) Class.forName(classname)
+							.newInstance();
+					machineRating = bench.bench();
+					System.out
+							.println("Successfully run benchmark. Machine Rating is "
+									+ machineRating);
+				} catch (Exception e) {
+					System.err
+							.println("Could not load Benchmarkclass "
+									+ classname
+									+ ". Setting rating to 0 (which means average).  Reason was: "
+									+ e.getMessage());
+					machineRating = 0;
+				}
+			} else
+				System.out.println("Benchmark disabled");
+		}
+	}
+
+	/**
+	 * Every time {@link #runSPMDModelTask(String, int, Object[])} is called the
+	 * newest class is loaded from the client. For performance reasons this will
+	 * happen only one time per connection.
+	 *
+	 * @see appl.parallel.server.SPMDResource#runSPMDModelTask(String, int,
+	 *      Object[])
+	 */
+	@SuppressWarnings("unchecked")
+	public Object[] runSPMDModelTask(String spmdTaskName, int referenceID,
+			Object... parameters) throws RemoteException {
+		/**
+		 * determine the calling host. Internal Server requires special
+		 * handling: notice that this happens very often in this class, but can
+		 * not externalized due to the behavior of #getClientHost();
+		 */
+		String callingHost = "localhost";
+		try {
+			callingHost = isInternalServer ? "localhost" : getClientHost();
+		} catch (ServerNotActiveException e) {
+			e.printStackTrace();
+		}
+		/** ********************************************************************** */
+		Thread.currentThread().setPriority(taskPriority);
+		String clientIP = "<unknown Client>";
+		long time = System.nanoTime();
+
+		clientIP = callingHost;
+		if (!clientIP.equals(connectedClient)) {
+			LOG.warn(clientIP
+					+ " has tried to run a Task, but was not connected. "
+					+ "This server is in use by " + connectedClient);
+			throw new RemoteException(
+					"Run of SPMDTask failed! This server is in use by "
+							+ connectedClient);
+		}
+		if (LOG.isDebugEnabled())
+			LOG.debug("received task from " + clientIP
+					+ ". Starting evaluation now...");
+		// if no datamanager is found: exit
+		if (dataManager == null)
+			throw new UnsupportedOperationException(
+					"No DataManager found. Create one first using 'createDataManager' on this Server");
+
+		// lookup newest version of the class from the server at the url
+		// (or from local disk if remote class loading is disabled)
+		SPMDTask[] tasks = loadSPMDTasksfromURL(clientIP, spmdTaskName);
+
+		// The number of threads allowed for execution can be different
+		// from the number of user assigned threads
+		// because tasks may not support multithreadeding
+		int allowedThreads = 1;
+		if (tasks[0].supportsMultiThreading())
+			allowedThreads = toUseThreads;
+
+		Object results[] = new Object[allowedThreads];
+
+		// the following loop is only executed the first time a task is used!
+		if (!tasks[0].isInitialized()) {
+			if (LOG.isInfoEnabled())
+				LOG.info("Trying to use " + allowedThreads
+						+ " threads for execution of "
+						+ tasks[0].getClass().getName());
+			// calculate splitting for multiple threads:
+			int splitMapPos = dataManager.getInfo(referenceID).getSplitMapPos();
+			SplitMap splitMap = dataManager.getInfo(referenceID).getSplitMap();
+			SplitMap1DVertical map1DVertical = new SplitMap1DVertical(splitMap
+					.getPartitionCalculationBounds(splitMapPos).width, splitMap
+					.getPartitionCalculationBounds(splitMapPos).height, 0,
+					allowedThreads, NeighborhoodBoxingMode.outBoxing);
+
+			// create controllers and init the tasks
+			for (int i = 0; i < allowedThreads; i++) {
+				AdvancedSPMDServerController serverController = new AdvancedSPMDServerController(
+						dataManager, referenceID);
+				// set first thread as master thread
+				serverController.setMasterThread(i == 0);
+				// now assign the calculation area. Because we have assumed that
+				// the (Thread)-calculation
+				// area begins at (0,0) we must move it relative to the real
+				// local calculation area
+				Rectangle calculationBounds = map1DVertical
+						.getPartitionCalculationBounds(i);
+				int absolutX = (int) (serverController.getLocalCalcMinX() + calculationBounds
+						.getMinX());
+				int absolutY = (int) (serverController.getLocalCalcMinY() + calculationBounds
+						.getMinY());
+				calculationBounds.setLocation(absolutX, absolutY);
+				serverController.setLocalCalculationBounds(calculationBounds);
+				tasks[i].setSPMDServerController(serverController);
+				tasks[i].initialize();
+			}
+		}
+		if (allowedThreads == 1) // only for saving resources: no new thread
+		{ // if only one thread is used
+			Object executionResult = tasks[0].run(parameters);
+			results = new Object[] { executionResult };
+		} else {
+			// for more than 1 processor execute the multiple tasks in separate
+			// threads
+			for (int i = 0; i < allowedThreads; i++) {
+				resultCalls[i] = executor.submit(new SimpleCallThread(tasks[i],
+						parameters));
+			}
+			// wait for the Threads to finish
+			for (int i = 0; i < allowedThreads; i++) {
+				try {
+					results[i] = resultCalls[i].get();
+				} catch (InterruptedException e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				} catch (ExecutionException e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				}
+			}
+		}
+		// generate a event for the execution
+		if (remoteEventReceiver.isTimeMonitoringEnabled())
+			remoteEventReceiver.fireRemoteEvent(new TimeEvent((System
+					.nanoTime() - time), serverName, "DataServer",
+					CommType.REMOTE_EXECUTION));
+		return results;
+	}
+
+	/**
+	 * This method frees all resources.<br>
+	 * Notice that this method is not remotely accessible!
+	 */
+	public void stopServer() {
+		unbind();
+		if (dataManager != null)
+			dataManager.stop();
+		dataManager = null;
+		if (multicastThread != null)
+			multicastThread.stopThread();
+	}
+}

Added: trunk/src/appl/parallel/server/XuluServerProperties.java
===================================================================
--- trunk/src/appl/parallel/server/XuluServerProperties.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/server/XuluServerProperties.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,57 @@
+package appl.parallel.server;
+
+import java.io.Serializable;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryPoolMXBean;
+import java.lang.management.MemoryUsage;
+import java.lang.management.ThreadMXBean;
+import java.util.List;
+import java.util.Timer;
+
+import org.apache.log4j.lf5.util.Resource;
+
+import appl.parallel.ComputingResourceProperties;
+import appl.parallel.SimpleResourceProperties;
+
+/**
+ * Constructs information out of a XuluServer Object. Unfortunately there is no way
+ * to measure CPU load (for this you would need to have access to the OS core). This could
+ * be done with the use of the JNI, but that is low level programming and would be OS
+ * dependent.
+ *  
+ * Must be invoked on server side (which should be clear, anyway!).<br>
+ * 
+ * Sets the following properties:
+ * <br><br>
+ * Name <br>
+ * isAvailable<br>
+ * Uptime<br><br>
+ * 
+ * and of course the Properties the superclass sets<br>
+ * @author Dominik Appl
+ */
+public class XuluServerProperties extends SimpleResourceProperties implements
+		Serializable {
+
+	public XuluServerProperties(XuluServer server, String name) {
+		super();
+		if (name != null)
+			properties.setProperty("Name", name);
+		properties.setProperty("isAvailable", (!(server.isClientConnected()))
+				+ "");
+
+		//format uptime
+		int uptimeInSeconds = server.getUptime() / 1000;
+		int hours, minutes, seconds;
+		hours = uptimeInSeconds / 3600;
+		uptimeInSeconds = uptimeInSeconds - (hours * 3600);
+		minutes = uptimeInSeconds / 60;
+		uptimeInSeconds = uptimeInSeconds - (minutes * 60);
+		seconds = uptimeInSeconds;
+		String formatedTime = hours + "h " + minutes + "m " + seconds + "s";
+		properties.setProperty("Uptime", formatedTime);
+		properties.setProperty("Rating", server.getRating() + "");
+		properties.setProperty("Port", server.getRegistryPort() + "");
+	}
+
+}
\ No newline at end of file

Added: trunk/src/appl/parallel/server/package.html
===================================================================
--- trunk/src/appl/parallel/server/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/server/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,6 @@
+<html>
+<body>
+	Contains server related classes required for parallelization. Especially it contains the
+	XuluServer itself. 
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/parallel/services/DiscoveryService.java
===================================================================
--- trunk/src/appl/parallel/services/DiscoveryService.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/services/DiscoveryService.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,20 @@
+package appl.parallel.services;
+
+import java.util.Vector;
+
+import appl.parallel.ComputingResource;
+import appl.parallel.ComputingResourceContainer;
+
+/**
+ * A discovery service locates {@link ComputingResource ComputingRessouces} in a
+ * network.
+ * 
+ * @author Dominik Appl
+ */
+public interface DiscoveryService extends Service {
+
+	/**
+	 * @return the discovered resources
+	 */
+	Vector<ComputingResourceContainer> getResources();
+}

Added: trunk/src/appl/parallel/services/GlobalDiscoveryService.java
===================================================================
--- trunk/src/appl/parallel/services/GlobalDiscoveryService.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/services/GlobalDiscoveryService.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,146 @@
+package appl.parallel.services;
+
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import appl.ext.XuluConfig;
+import appl.parallel.ComputingResource;
+import appl.parallel.ComputingResourceContainer;
+
+/**
+ * This class is responsible for discovering Resources. For this it first starts
+ * all known {@link DiscoveryService DiscoveryServices} and queries them for
+ * known {@link ComputingResource Computing Resources}. <br>
+ * <br>
+ * This class starts all {@link DiscoveryService}s registered with the following
+ * property in the {@link XuluConfig}: <br>
+ * <br>
+ * DiscoveryServices.activeServices<br>
+ * <br>
+ * Register {@link DiscoveryService DiscoveryServices} with their fully
+ * qualified java name because
+ * {@link java.lang.Class#forName(String)  Class.forName} will be called on that
+ * String.
+ * 
+ * @author Dominik Appl
+ */
+public class GlobalDiscoveryService implements Service {
+
+	private final Logger LOG = LogManager.getLogger(this.getClass().getName());
+
+	private static GlobalDiscoveryService instance;
+
+	Vector<DiscoveryService> services = new Vector<DiscoveryService>();
+
+	private boolean isRunning;
+
+	/**
+	 * @return all active {@link ComputingResource RemoteResources} in a
+	 *          container class with meta in the a ComputingResourceContainer
+	 *          Object. They are queried from all known Discovery Services. Do
+	 *          not query more than necessary!
+	 */
+	public Vector<ComputingResourceContainer> getRemoteResources() {
+		Vector<ComputingResourceContainer> discResources = new Vector<ComputingResourceContainer>();
+		// query all services for RemoteResources
+		for (DiscoveryService disc : services) {
+			Vector<ComputingResourceContainer> newResources = disc
+					.getResources();
+			// do not add double entrys
+			for (ComputingResourceContainer container : newResources) {
+				if (!(checkAlreadyInside(container, discResources)))
+					discResources.add(container);
+			}
+		}
+		return discResources;
+	}
+
+	/**
+	 * checks if the a remoteResource of a given container is in a Vector of
+	 * RemoteResourceContainers
+	 *
+	 * @param container
+	 * @return
+	 */
+	private boolean checkAlreadyInside(ComputingResourceContainer container,
+			Vector<ComputingResourceContainer> containers) {
+		for (ComputingResourceContainer originalcontainer : containers) {
+			if (originalcontainer.getResource().equals(container.getResource()))
+				return true;
+		}
+		return false;
+	}
+
+	/**
+	 * Looks up all services from the config file, loads them and also starts
+	 * them.
+	 */
+	public GlobalDiscoveryService() {
+		String[] classnames = XuluConfig.getXuluConfig().getMultiProperty(
+				"DiscoveryServices.activeServices");
+		for (String classname : classnames) {
+			Class serviceclass;
+			try {
+				serviceclass = Class.forName(classname);
+				DiscoveryService service = (DiscoveryService) serviceclass
+						.newInstance();
+				services.add(service);
+				service.startService();
+
+			} catch (ClassNotFoundException e) {
+				LOG.error("Class was not found for string" + classname);
+				LOG.error(e.getMessage());
+			} catch (InstantiationException e) {
+				LOG.error("Could not load class " + classname);
+				LOG.error(e.getMessage());
+			} catch (IllegalAccessException e) {
+				LOG.error("Could not load class " + classname);
+				LOG.error(e.getMessage());
+			}
+		}
+		// allow some time for the services to discover Resources
+		try {
+			Thread.currentThread().sleep(200);
+		} catch (InterruptedException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+	}
+
+	
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.services.Service#isRunning()
+	 */
+	public boolean isRunning() {
+		return isRunning;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.services.Service#startService()
+	 */
+	public void startService() {
+		isRunning = true;
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.services.Service#stopService()
+	 */
+	public void stopService() {
+		for (DiscoveryService s : services) {
+			s.stopService();
+		}
+		isRunning = false;
+
+	}
+
+}

Added: trunk/src/appl/parallel/services/HostnameDiscoveryService.java
===================================================================
--- trunk/src/appl/parallel/services/HostnameDiscoveryService.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/services/HostnameDiscoveryService.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,254 @@
+package appl.parallel.services;
+
+import java.net.MalformedURLException;
+import java.rmi.ConnectException;
+import java.rmi.Naming;
+import java.rmi.NotBoundException;
+import java.rmi.RemoteException;
+import java.rmi.UnknownHostException;
+import java.util.Iterator;
+import java.util.Vector;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import appl.ext.XuluConfig;
+import appl.parallel.ComputingResource;
+import appl.parallel.ComputingResourceContainer;
+import appl.parallel.starter.Starter;
+import appl.parallel.starter.client.StarterContainer;
+import appl.parallel.starter.server.XuluServerStarter;
+import appl.parallel.test.PingTestObject;
+
+/**
+ * Very simple Discovery Service that simply looks up hosts from Property <br>
+ * <br>
+ * <code>DiscoveryServices.hostname.hosts</code> <br>
+ * <br>
+ * of the {@link XuluConfig} <br>
+ * <br>
+ * Refreshes the hostlist on every {@link #getResources()}, if <br>
+ * <br>
+ * <code> DiscoveryServices.hostname.refresh</code> <br>
+ * <br>
+ * is set to 1, it gets the ips from Property <br>
+ * <br>
+ * DiscoveryService.hostname.hosts <br>
+ * <br>
+ * in {@link XuluConfig}
+ *
+ * @author Dominik Appl
+ */
+public class HostnameDiscoveryService implements DiscoveryService {
+	private final Logger LOG = LogManager.getLogger(this.getClass().getName());
+
+	Vector<ComputingResource> res = new Vector<ComputingResource>();
+
+	ExecutorService executor = Executors.newCachedThreadPool();
+
+	private String[] lookupStrings;
+
+	private int timeout;
+
+	private boolean firstRefresh = true;
+
+	/** @return true
+	 * @see appl.parallel.services.Service#isRunning()
+	 */
+	public boolean isRunning() {
+		return true;
+	}
+
+	/**
+	 * @see appl.parallel.services.Service#startService()
+	 */
+	public void startService() {
+		executor = Executors.newCachedThreadPool();
+	}
+
+	/**
+	 * stops the service
+	 */
+	public void stopService() {
+		executor.shutdownNow();
+	}
+
+	/**
+	 * tries to (re-)discover every resource in Property <code>HostnameDiscoveryService.hosts</code>
+	 * of {@link XuluConfig}. After the time in ms specified in DiscoveryServices.timeout
+	 *
+	 */
+	@SuppressWarnings("unchecked")
+	public synchronized void refresh() {
+		//get timeout
+		initVariables();
+		res.addAll(getResourcesForLookupStrings());
+	}
+
+	private void initVariables() {
+		timeout = XuluConfig.getXuluConfig().getIntProperty(
+				"DiscoveryServices.timeout");
+		if (timeout == 0) {
+			LOG
+					.warn("DiscoveryServices.timeout was not set or was 0! Setting connect timeout to 500...");
+			timeout = 500;
+		}
+		//get IPs
+		res.clear();
+		String[] ips = XuluConfig.getXuluConfig().getMultiProperty(
+				"DiscoveryServices.hostname.hosts");
+		if (ips.length == 0 || (ips.length == 1 && ips[0].equals(""))) {
+			LOG.warn("No Resources found in DiscoveryServices.hostname.hosts");
+			ips = new String[0];
+		}
+		//generate lookupStrings:
+		lookupStrings = ips;
+	}
+
+	/** gets resources, but pings them first to see if they are alive. Not
+	 * 	reachable resouces are removed.
+	 *
+	 * @see appl.parallel.services.DiscoveryService#getResources()
+	 */
+	public Vector<ComputingResourceContainer> getResources() {
+		if (firstRefresh
+				|| XuluConfig.getXuluConfig().getBooleanProperty(
+						"DiscoveryServices.hostname.refresh") == true)
+			refresh();
+		firstRefresh = false;
+		return appl.parallel.util.Helper.getResourceContainersForVector(res);
+	}
+
+	/**
+	 * @return starterContainers for {@link XuluServerStarter}s
+	 */
+	public Vector<StarterContainer> getStarterContainers() {
+		initVariables();
+		String[] lookupNames = new String[lookupStrings.length];
+		for (int i = 0; i < lookupStrings.length; i++)
+			lookupNames[i] = "rmi://" + lookupStrings[i] + "/XuluServerStarter";
+
+		Vector<Starter> discoveredStarters = new Vector<Starter>();
+		Vector<StarterContainer> containers = new Vector<StarterContainer>();
+		// make a new Thread for each resouce
+		Future[] futures = new Future[lookupStrings.length];
+		for (int i = 0; i < lookupStrings.length; i++) {
+			futures[i] = executor.submit(new LookupCallable(lookupNames[i]));
+		}
+
+		// the time at which the result must be there:
+		long timeoutTime = System.currentTimeMillis() + timeout;
+		for (int i = 0; i < futures.length; i++) {
+			// servers previous in iterations may have caused a delay
+			// so the remaining time is calculated
+			long remainingTime = Math.max(10, timeoutTime
+					- System.currentTimeMillis());
+
+			try {
+				Starter starter = (Starter) futures[i].get(remainingTime,
+						TimeUnit.MILLISECONDS);
+				if (starter != null) {
+					discoveredStarters.add(starter);
+					containers.add(new StarterContainer(starter,
+							lookupStrings[i]));
+					LOG.debug("Discovered Starter: " + lookupNames[i]);
+				}
+			} catch (InterruptedException e) {
+				LOG.error(e);
+				e.printStackTrace();
+			} catch (ExecutionException e) {
+				LOG.error("Error while connecting to " + lookupNames[i]
+						+ " (Connect exception)");
+			} catch (TimeoutException e) {
+				LOG.warn("Could not find Starter " + lookupNames[i]
+						+ ". Timed out after " + timeout + "ms");
+				futures[i].cancel(true);
+			}
+		}
+		return containers;
+	}
+
+	private Vector<ComputingResource> getResourcesForLookupStrings() {
+		initVariables();
+		String[] lookupNames = new String[lookupStrings.length];
+		for (int i = 0; i < lookupStrings.length; i++)
+			lookupNames[i] = "rmi://" + lookupStrings[i] + "/XuluServer";
+
+		Vector<ComputingResource> discoveredResources = new Vector<ComputingResource>(
+				lookupNames.length);
+		// make a new Thread for each resource
+		Future[] futures = new Future[lookupNames.length];
+		for (int i = 0; i < lookupNames.length; i++) {
+			futures[i] = executor.submit(new LookupCallable(lookupNames[i]));
+		}
+
+		// the time at which the result must be there:
+		long timeoutTime = System.currentTimeMillis() + timeout;
+		for (int i = 0; i < futures.length; i++) {
+			// servers previous in iterations may have caused a delay
+			// so the remaining time is calculated
+			long remainingTime = Math.max(0, timeoutTime
+					- System.currentTimeMillis());
+
+			try {
+				ComputingResource server = (ComputingResource) futures[i].get(
+						remainingTime, TimeUnit.MILLISECONDS);
+				discoveredResources.add(server);
+				LOG.debug("Discovered resource: " + lookupNames[i]);
+			} catch (InterruptedException e) {
+				LOG.error(e);
+				e.printStackTrace();
+			} catch (ExecutionException e) {
+				LOG.error("Error while connecting to " + lookupNames[i], e);
+			} catch (TimeoutException e) {
+				LOG.warn("Could not add server " + lookupNames[i]
+						+ ". Timed out after " + timeout + "ms");
+				futures[i].cancel(true);
+			}
+		}
+		return discoveredResources;
+	}
+
+	/**
+	 * This class is used for lookup of remote resources. It handles all errors
+	 * and submits them to the LOG
+	 *
+	 * @author Dominik Appl
+	 */
+	private class LookupCallable implements Callable {
+
+		private final String lookupString;
+
+		private ComputingResource server = null;
+
+		public LookupCallable(String lookupString) {
+			this.lookupString = lookupString;
+
+		}
+
+		/* (non-Javadoc)
+		 * @see java.util.concurrent.Callable#call()
+		 */
+		public Object call() throws Exception {
+			try {
+				return Naming.lookup(lookupString);
+			} catch (UnknownHostException e) {
+				LOG.warn("(Unknown Host) Could not find host " + lookupString);
+			} catch (java.rmi.NotBoundException e) {
+				LOG.warn("(Not Bound) Could not find host " + lookupString);
+			} catch (java.rmi.ConnectException e) {
+				LOG.warn("(No Connection) Could not connect to host "
+						+ lookupString);
+			}
+			return null;
+		}
+	}
+
+}

Added: trunk/src/appl/parallel/services/MulticastDiscoveryService.java
===================================================================
--- trunk/src/appl/parallel/services/MulticastDiscoveryService.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/services/MulticastDiscoveryService.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,439 @@
+package appl.parallel.services;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.InetAddress;
+import java.net.MulticastSocket;
+import java.net.UnknownHostException;
+import java.rmi.Naming;
+import java.rmi.RemoteException;
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.apache.log4j.BasicConfigurator;
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import appl.ext.XuluConfig;
+import appl.parallel.ComputingResource;
+import appl.parallel.ComputingResourceContainer;
+import appl.parallel.server.XuluServer;
+import appl.parallel.test.PingTestObject;
+import appl.parallel.util.Helper;
+
+/**
+ * Responsible for discovery of RemoteResources on the network, especially but
+ * not only {@link XuluServer XuluServers}. It listens for the following
+ * messages: <br>
+ * <br>
+ * "Hello Xulu from XuluServer" - sent by RemoteResources like
+ * {@link XuluServer} when starting <br>
+ * "Goodbye Xulu" - sent by RemoteResources like {@link XuluServer} when
+ * stopping <br>
+ * <br>
+ * and sends: <br>
+ * "Hello Servers" - when started If multicasting does not work try to disable
+ * your firewall or better configure it to allow multicast packages. Notice
+ * also, that multicasting may not work in virtual machines like MS Virtual PC
+ * 2004. <Warning><b>THIS CLASS IS STILL FOR DEMONSTRATION ONLY</b></Warning>
+ * 
+ * @author Dominik Appl
+ * @see XuluServer
+ */
+public class MulticastDiscoveryService implements DiscoveryService {
+
+	// the data to send
+	final String sendHello = "Hello Servers";
+
+	// data to receive
+	final String helloFromXuluServers = "Hello Xulu from XuluServer";
+
+	final String recGoodBye = "Goodbye Xulu";
+
+	// the Thread which waits on Server hello/goodbyes
+	volatile ReceiveThread receiveThread;
+
+	// volatile RenewalThread renewalThread;
+
+	// the thread that checks if servers are alive
+	// volatile CheckThread checkThread;
+
+	// the data is read from XuluConfig
+	InetAddress group;
+
+	int port;
+
+	int lease;
+
+	MulticastSocket socket;
+
+	boolean isRunning = false;
+
+	private final Logger LOG = LogManager.getLogger(this.getClass().getName());
+
+	/**
+	 * Constructs a new service reading port and lease time from
+	 * {@link appl.ext.XuluConfig}
+	 */
+	public MulticastDiscoveryService() {
+		XuluConfig config = XuluConfig.getXuluConfig();
+		port = Integer.valueOf(config
+				.getProperty("DiscoveryServices.multicast.port"));
+		// lease = Integer.valueOf(config
+		// .getProperty("MulticastDiscoveryService.lease"));
+		try {
+			group = InetAddress.getByName(config
+					.getProperty("DiscoveryServices.multicast.group"));
+		} catch (UnknownHostException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * Constructs a new service
+	 * 
+	 * @param port
+	 *            port where the multicasting happens
+	 * @param lease
+	 *            timeintervall (in ms) after whi
+	 */
+	public MulticastDiscoveryService(int port, int lease) {
+		this();
+		this.port = port;
+		this.lease = lease;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.services.Service#startService()
+	 */
+	public void startService() {
+		try {
+			LOG.info("Discoveryservice started");
+			// All Servers must listen on the port specified, in order fo
+			// the socket to receive
+			if (socket == null)
+				socket = new MulticastSocket(port);
+			// open a multicast group and join it
+
+			socket.joinGroup(group);
+
+			socket.setSoTimeout(5000);
+
+			// create and send Hello world
+			DatagramPacket datagram = new DatagramPacket(sendHello.getBytes(),
+					sendHello.length(), group, port);
+			System.out.println(group);
+			LOG.info("Send hello to all listening servers with broadcast IP "
+					+ group);
+
+			socket.send(datagram);
+
+			if (receiveThread == null) {
+				receiveThread = new ReceiveThread(socket, helloFromXuluServers,
+						recGoodBye);
+			}
+			if (!(receiveThread.isAlive()))
+				receiveThread.start();
+
+		} catch (UnknownHostException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.services.DiscoveryService#getResources()
+	 */
+	public Vector<ComputingResourceContainer> getResources() {
+		return receiveThread.getResources();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.services.Service#stopService()
+	 */
+	public void stopService() {
+		receiveThread.stopThread();
+		// renewalThread.stopThread();
+		try {
+			Thread.currentThread().sleep(100);
+		} catch (InterruptedException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		socket.close();
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.services.Service#isRunning()
+	 */
+	public boolean isRunning() {
+		return isRunning;
+	}
+
+	/** waits for incoming calls */
+
+	class ReceiveThread extends Thread {
+
+		// Resources discovered so far
+		Vector<ComputingResource> discoveredResources;
+
+		private volatile Thread receiveThread;
+
+		boolean exit = false;
+
+		MulticastSocket socket;
+
+		private final String recHello2;
+
+		private final String recGoodBye2;
+
+		private boolean discoveryInProgress = false;
+
+		/**
+		 * @returns a Vector of discovered Ressources before return, all values
+		 *          are pinged and only returned if alive
+		 */
+		public Vector<ComputingResourceContainer> getResources() {
+			return Helper.getResourceContainersForVector(discoveredResources);
+		}
+
+		/**
+		 * @param socket2
+		 *            Socket which is used for listening
+		 * @param helloFromXuluServers
+		 *            String that equals the hello message of the server
+		 * @param recGoodBye
+		 *            String that equals the Goordbye message of the server
+		 */
+		public ReceiveThread(MulticastSocket socket, String recHello,
+				String recGoodBye) {
+			recHello2 = recHello;
+			recGoodBye2 = recGoodBye;
+			this.socket = socket;
+			discoveredResources = new Vector<ComputingResource>();
+		}
+
+		/**
+		 * Safe method to stop the Thread. Use this method instead of
+		 * {@link Thread}
+		 */
+		public void stopThread() {
+			if (receiveThread != null) {
+				exit = true;
+				// the only way to stop the Thread is to send a package so that
+				// the receive operation no longer blocks
+				DatagramPacket datagram = new DatagramPacket(
+						"Stopping receive Thread".getBytes(),
+						"Stopping receive Thread".length(), group, port);
+				try {
+					socket.send(datagram);
+					// wait on stop
+					Thread.currentThread().sleep(100);
+				} catch (IOException e) {
+					e.printStackTrace();
+				} catch (InterruptedException e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				} finally {
+					exit = false;
+				}
+				exit = false;
+
+			}
+
+		}
+
+		public void run() {
+			receiveThread = Thread.currentThread();
+			while (!exit) {
+				try {
+					// receive buffer
+
+					byte[] buffer = new byte[256];
+					DatagramPacket datagram = new DatagramPacket(buffer,
+							buffer.length);
+					socket.receive(datagram);
+					// get the message in the right
+					byte[] result = new byte[datagram.getLength()];
+					System.arraycopy(datagram.getData(), 0, result, 0, datagram
+							.getLength());
+					// check if message is from XuluServer
+					if (new String(result).equals(helloFromXuluServers)) {
+						LOG.debug("received hello from server "
+								+ datagram.getAddress());
+
+						String newname = "rmi:/" + datagram.getAddress()
+								+ "/XuluServer";
+
+						ComputingResource server = (ComputingResource) Naming
+								.lookup(newname);
+						addRessource(server, datagram.getAddress().toString());
+
+					} else if (LOG.isDebugEnabled())
+						LOG.debug("received message |" + new String(result)
+								+ "| from " + datagram.getAddress());
+
+				} catch (java.net.SocketTimeoutException e) {
+					// catch timeout exception
+				}
+
+				catch (IOException e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				} catch (Exception e) {
+					if (!(e instanceof InterruptedException))
+						e.printStackTrace();
+				}
+			}
+			System.out.println("exit Thread " + this.toString());
+		}
+
+		/**
+		 * adds ressource to vector but first looks if its not already added
+		 * 
+		 * @param server
+		 */
+		private void addRessource(ComputingResource server, String IP) {
+			// check for double entries
+			for (ComputingResource s : discoveredResources) {
+				if (s.equals(server)) {
+					LOG.debug("Not adding " + server.toString()
+							+ " to discovered Ressources again!");
+					return;
+				}
+			}
+			LOG.info("Adding Xulu Server: " + IP + "to discovered Ressources");
+			// try {
+			// Thread.currentThread().sleep(2000);
+			// } catch (InterruptedException e) {
+			// // TODO Auto-generated catch block
+			// e.printStackTrace();
+			// }
+			discoveredResources.add(server);
+		}
+
+		/**
+		 * Gets the {@link Resource
+		 */
+		public void pingResources() {
+			PingTestObject po = new PingTestObject(32);
+			// cannot make a for each loop because of
+			// java.util.ConcurrentModificationException
+			int i = discoveredResources.size() - 1;
+			while (i >= 0) {
+				boolean error = true;
+				ComputingResource r = discoveredResources.get(i);
+				if (!(r == null)) {
+
+					try {
+						r.ping();
+						error = false;
+						LOG.debug("Ping to " + r + " was successfull!");
+					} catch (Exception e) {
+						e.printStackTrace();
+					}
+					// if not successfull remove object
+					if (error) {
+						LOG.debug("Ping to " + r
+								+ " was NOT successfull! Removing ressource");
+
+						discoveredResources.remove(r);
+					}
+				}
+				i--;
+			}
+		}
+
+	}
+
+	/**
+	 * simple Thread that caused rediscovery of Ressources at a given time
+	 * intervall **
+	 */
+
+	class RenewalThread extends Thread {
+
+		private volatile Thread thisThread;
+
+		boolean exit = false;
+
+		private final long timeintervall;
+
+		private volatile ReceiveThread discoveryToRenew;
+
+		/**
+		 * invokes rediscovery on the given thread at the given time intervall
+		 */
+		public RenewalThread(ReceiveThread discoveryToRenew, long timeintervall) {
+			this.discoveryToRenew = discoveryToRenew;
+			this.timeintervall = timeintervall;
+
+		}
+
+		/**
+		 * Safe method to stop this Thread. Use this method instead of
+		 * {@link Thread}
+		 */
+		public void stopThread() {
+			if (thisThread != null)
+				exit = true;
+		}
+
+		public void run() {
+			thisThread = Thread.currentThread();
+			while (!exit) {
+				discoveryToRenew.pingResources();
+				try {
+					Thread.currentThread().sleep(timeintervall);
+				} catch (InterruptedException e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				}
+			}
+			System.out.println("exit renewal Thread");
+		}
+
+	}
+
+	/**
+	 * just for testing..edit as you like
+	 */
+	public static void main(String[] args) {
+		BasicConfigurator.configure();
+		MulticastDiscoveryService bro = new MulticastDiscoveryService();
+		bro.startService();
+		try {
+			Thread.currentThread().sleep(5000);
+		} catch (InterruptedException e) {
+			e.printStackTrace();
+		}
+		// bro.stopService();
+		while (true)
+			try {
+				Vector<ComputingResourceContainer> v = bro.getResources();
+				for (ComputingResourceContainer container : v) {
+					System.out.print("Active Object: ");
+					System.out.println(container.getInformation().getProperty(
+							"name")
+							+ " with IP "
+							+ container.getInformation().getProperty("IP"));
+				}
+				Thread.currentThread().sleep(5000);
+			} catch (InterruptedException e) {
+
+			}
+	}
+
+}

Added: trunk/src/appl/parallel/services/RemoteEventProxy.java
===================================================================
--- trunk/src/appl/parallel/services/RemoteEventProxy.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/services/RemoteEventProxy.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,190 @@
+package appl.parallel.services;
+
+import java.rmi.RemoteException;
+import java.util.Vector;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import appl.parallel.event.CommEventSink;
+import appl.parallel.event.RemoteEvent;
+import appl.parallel.event.RemoteEventSink;
+import appl.parallel.event.TimeEvent;
+import appl.parallel.event.TransferEvent;
+
+/**
+ * Delays events and fires them after the delay all <b>at once</b> in one
+ * object (this will save communication time)
+ * 
+ * @author Dominik Appl
+ */
+public class RemoteEventProxy implements CommEventSink, Service {
+
+	/**
+	 * This Thread submits the events after the delay
+	 * 
+	 * @author Dominik Appl
+	 */
+	private class SubmitThread extends Thread {
+
+		private boolean exit = false;
+
+		private final ConcurrentLinkedQueue<RemoteEvent> queue2;
+
+		private final CommEventSink sink;
+
+		private final long delay;
+
+		SubmitThread(ConcurrentLinkedQueue<RemoteEvent> queue,
+				CommEventSink sink, long delay) {
+			queue2 = queue;
+			this.sink = sink;
+			this.delay = Math.max(100, delay);
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see java.lang.Thread#run()
+		 */
+		public void run() {
+			while (!exit) {
+				try {
+					this.sleep(delay);
+				} catch (InterruptedException e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				}
+				// add all new events to a vector submit them at once
+				Vector<RemoteEvent> events = new Vector<RemoteEvent>();
+				while (queue.peek() != null)
+					events.add(queue.poll());
+				try {
+					if (events.size() > 0)
+						sink.fireRemoteEvents((RemoteEvent[]) events
+								.toArray(new RemoteEvent[events.size()]));
+				} catch (RemoteException e) {
+					// TODO Auto-generated catch block
+					LOG.warn("Could not transmit events." + e.getMessage(), e);
+					events.clear();
+				}
+			}
+		}
+
+		public void startThread() {
+			exit = false;
+			this.start();
+		}
+
+		public void stopThread() {
+			exit = true;
+		}
+	}
+
+	private final Logger LOG = LogManager.getLogger(this.getClass().getName());
+
+	private boolean timeMonitoring = false;
+
+	private boolean transferMonitoring = false;
+
+	private boolean isRunning;
+
+	SubmitThread submitThread;
+
+	ConcurrentLinkedQueue<RemoteEvent> queue;
+
+	private final CommEventSink eventSink;
+
+	private final long delay;
+
+	/**
+	 * Creates a new proxy
+	 * 
+	 * @param targetSink
+	 *            the sink where the events should be submitted to
+	 * @param delay
+	 *            the delay (in milliseconds)
+	 */
+	public RemoteEventProxy(CommEventSink targetSink, long delay) {
+		this.eventSink = targetSink;
+		this.delay = delay;
+		queue = new ConcurrentLinkedQueue<RemoteEvent>();
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.event.RemoteEventSink#fireRemoteEvent(appl.parallel.event.RemoteEvent)
+	 */
+	public void fireRemoteEvent(RemoteEvent e) throws RemoteException {
+		queue.add(e);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.event.RemoteEventSink#fireRemoteEvents(appl.parallel.event.RemoteEvent[])
+	 */
+	public void fireRemoteEvents(RemoteEvent[] e) throws RemoteException {
+		for (RemoteEvent event : e) {
+			fireRemoteEvent(event);
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.services.Service#isRunning()
+	 */
+	public boolean isRunning() {
+		return isRunning;
+	}
+
+	/**
+	 * @return true if the service is running and time monitoring is enabled
+	 */
+	public boolean isTimeMonitoringEnabled() throws RemoteException {
+		return timeMonitoring;
+	}
+
+	/**
+	 * @return true if the service is running and tansfer monitoring is enabled
+	 */
+	public boolean isTransferMonitoringEnabled() throws RemoteException {
+		return transferMonitoring;
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.services.Service#startService()
+	 */
+	public void startService() {
+		isRunning = true;
+		if (submitThread != null)
+			submitThread.stopThread();
+		submitThread = new SubmitThread(queue, eventSink, delay);
+		submitThread.startThread();
+		try {
+			this.timeMonitoring = eventSink.isTimeMonitoringEnabled();
+			this.transferMonitoring = eventSink.isTransferMonitoringEnabled();
+		} catch (RemoteException e) {
+			LOG.error("Could not connect to CommEventSink!!!");
+		}
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.services.Service#stopService()
+	 */
+	public void stopService() {
+		isRunning = false;
+		if (submitThread != null)
+			submitThread.stopThread();
+	}
+}

Added: trunk/src/appl/parallel/services/Service.java
===================================================================
--- trunk/src/appl/parallel/services/Service.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/services/Service.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,24 @@
+package appl.parallel.services;
+
+/**
+ * Superclass of all Services.
+ * 
+ * @author Dominik Appl
+ */
+public interface Service {
+
+	/**
+	 * Starts the service
+	 */
+	public void startService();
+
+	/**
+	 * Stops the service
+	 */
+	public void stopService();
+
+	/**
+	 * @return true, if the service is running
+	 */
+	public boolean isRunning();
+}

Added: trunk/src/appl/parallel/services/package.html
===================================================================
--- trunk/src/appl/parallel/services/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/services/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,6 @@
+<html>
+<body>
+	Contains some service classes used with the parallelization. The discovery classes are used
+	to find servers in a network. 
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/parallel/spmd/AbstractSPMDTask.java
===================================================================
--- trunk/src/appl/parallel/spmd/AbstractSPMDTask.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/AbstractSPMDTask.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,117 @@
+package appl.parallel.spmd;
+
+import java.awt.Rectangle;
+
+import schmitzm.data.WritableGrid;
+
+/**
+ * This class may be used as the superclass to all {@link SPMDTask SPMDTasks}
+ * which should be executed on servers using the SPMD-paradigm. Subclasses
+ * should override the {@link #init()} and the {@link #run(Object...)} method,
+ * but never the {@link #initialize()} method. <br>
+ * <br>
+ * The Task provides access to the {@link SPMDClientInterface} and the
+ * {@link AdvancedSPMDClientInterface}. <br>
+ * <br>
+ * Notice that the {@link #init()} method is called exactly one time before
+ * execution for every instance (in multithreading there are multiple parallel
+ * instances of the same task, running on different parts of the resource).
+ * 
+ * @author Dominik Appl
+ */
+public abstract class AbstractSPMDTask implements SPMDTask {
+
+	protected transient AdvancedSPMDServerInterface serverController;
+
+	private boolean initalized = false;
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.spmd.SPMDTask#incomingUpdate(schmitzm.data.WritableGrid,
+	 *      java.awt.Rectangle)
+	 */
+	public void incomingUpdate(WritableGrid outgoingGrid, Rectangle location) {
+		// TODO Auto-generated method stub
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.spmd.SPMDTask#outgoingUpdate(schmitzm.data.WritableGrid,
+	 *      java.awt.Rectangle)
+	 */
+	public void outgoingUpdate(WritableGrid incomingGrid, Rectangle location) {
+		// TODO Auto-generated method stub
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.spmd.SPMDTask#run()
+	 */
+	public abstract Object run(Object... parameters);
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.spmd.SPMDTask#getSPMDServerController()
+	 */
+	public SPMDServerInterface getSPMDServerController() {
+		return serverController;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.spmd.SPMDTask#getAdvancedSPMDServerController()
+	 */
+	public AdvancedSPMDServerInterface getAdvancedSPMDServerController() {
+		return serverController;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.spmd.SPMDTask#setSPMDServerController(appl.parallel.spmd.SPMDServerController)
+	 */
+	public void setSPMDServerController(AdvancedSPMDServerInterface controller) {
+		this.serverController = controller;
+	}
+
+	/**
+	 * Use this method to implement if you want t
+	 */
+	public abstract void init();
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.spmd.SPMDTask#initialize()
+	 */
+	public final void initialize() {
+		init();
+		initalized = true;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.spmd.SPMDTask#isInitialized()
+	 */
+	public boolean isInitialized() {
+		return initalized;
+	}
+
+	/**
+	 * returns false. Override this method to enable multithreading
+	 * 
+	 * @see appl.parallel.spmd.SPMDTask#supportsMultiThreading()
+	 */
+	public boolean supportsMultiThreading() {
+		return false;
+	}
+
+}

Added: trunk/src/appl/parallel/spmd/AdvancedSPMDClientController.java
===================================================================
--- trunk/src/appl/parallel/spmd/AdvancedSPMDClientController.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/AdvancedSPMDClientController.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,185 @@
+package appl.parallel.spmd;
+
+import java.io.PrintStream;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import appl.parallel.ComputingResourceContainer;
+import appl.parallel.client.ClientDataServer;
+import appl.parallel.event.CommEventSink;
+import appl.parallel.thread.OneMethodThread;
+
+/**
+ * Performance optimizations on client side can be made with this class. Allows
+ * heavy multithreading.<br>
+ * <br>
+ * Merging can be done in a separate thread (parallel to further computation)<br>
+ * 
+ * @see SPMDClientController for details on the usage of a client controller
+ * 
+ * @author Dominik Appl
+ */
+public class AdvancedSPMDClientController extends SPMDClientController
+		implements AdvancedSPMDClientInterface {
+
+	private final Logger LOG = LogManager.getLogger(this.getClass().getName());
+
+	// used for synchronization
+	private static final Object syncOperationMontitor = new Object();
+
+	/**
+	 * For each {@link SyncPoint} a vector of threads associated with the point
+	 * is created
+	 */
+	HashMap<SyncPoint, Vector<OneMethodThread>> vectorMap = new HashMap<SyncPoint, Vector<OneMethodThread>>();
+
+	/**
+	 * Empty thread which is used as indicator for a already synchronized sync
+	 * point
+	 */
+	private static final Vector<OneMethodThread> alreadySynchronized = new Vector<OneMethodThread>(
+			1);
+
+	/**
+	 * same parameters as superclass
+	 * 
+	 * @see SPMDClientController#SPMDClientController(Vector, double[],
+	 *      ClientDataServer, CommEventSink)
+	 */
+	public AdvancedSPMDClientController(
+			Vector<ComputingResourceContainer> computingResources,
+			double[] weights, ClientDataServer spmdClient,
+			CommEventSink eventProxy) {
+		super(computingResources, weights, spmdClient, eventProxy);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.spmd.AdvancedSPMDClientInterface#mergePartition(java.lang.Object,
+	 *      appl.parallel.spmd.SyncPoint)
+	 */
+	public void mergePartition(final Object partition, SyncPoint s,
+			final PrintStream stream, final String message) {
+		checkSplittable(partition);
+		// create a new thread
+		OneMethodThread newThread = new OneMethodThread("mergeThread"
+				+ s.getId(), s.getPriority()) {
+			@Override
+			public void run() {
+				mergePartition(partition);
+				if (stream != null) {
+					stream.println(message);
+				}
+			}
+		};
+		mapThreadToSyncPoint(newThread, s);
+		newThread.start();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.spmd.AdvancedSPMDClientInterface#mergePartition(java.lang.Object,
+	 *      appl.parallel.spmd.SyncPoint)
+	 */
+	public synchronized void mergePartition(Object partition, SyncPoint s) {
+		mergePartition(partition, s, null, null);
+	}
+
+	/**
+	 * Puts a Thread/Syncpoint pair into the Hashmap/Vector structure
+	 */
+	private void mapThreadToSyncPoint(OneMethodThread thread, SyncPoint s) {
+		// access to the syncpoints must be synchronized when working with
+		// multithreading
+		synchronized (syncOperationMontitor) {
+			Vector<OneMethodThread> threads = vectorMap.get(s);
+			// if this is the first thread for the syncPoint: create a new
+			// Vector
+			if (threads == null) {
+				threads = new Vector<OneMethodThread>(5);
+				vectorMap.put(s, threads);
+			}
+			threads.add(thread);
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.spmd.AdvancedSPMDClientInterface#mergeMultiData(appl.parallel.spmd.MultiDataObject,
+	 *      int, appl.parallel.spmd.SyncPoint, java.io.PrintStream,
+	 *      java.lang.String)
+	 */
+	public synchronized void mergeMultiData(MultiDataObject multidata, int idx,
+			SyncPoint s, PrintStream stream, String message) {
+		// create a new thread
+		OneMethodThread newThread = new OneMethodThread("mergeThread-"
+				+ s.getId(), s.getPriority(), multidata, idx, stream, message) {
+			@Override
+			public void run() {
+				mergeMultiData((MultiDataObject) getParameter(0),
+						(Integer) getParameter(1));
+				if (getParameter(2) != null) {
+					PrintStream stream = (PrintStream) getParameter(2);
+					stream.println(getParameter(3));
+				}
+			}
+		};
+		mapThreadToSyncPoint(newThread, s);
+		newThread.start();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.spmd.AdvancedSPMDClientInterface#mergeMultiData(appl.parallel.spmd.MultiDataObject,
+	 *      int, appl.parallel.spmd.SyncPoint)
+	 */
+	public void mergeMultiData(MultiDataObject multidata, int idx, SyncPoint s) {
+		mergeMultiData(multidata, idx, s, null, null);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.spmd.AdvancedSPMDClientInterface#synchronizeToSyncPoint(appl.parallel.spmd.SyncPoint)
+	 */
+	public void synchronizeToSyncPoint(SyncPoint s) {
+		// access to the syncpoints must be synchronized when working with
+		// multithreading
+		synchronized (syncOperationMontitor) {
+			// join all threads associated with the given syncPoint
+			Vector<OneMethodThread> threads = vectorMap.get(s);
+			// Multithreading: check if another thread has already synchronized
+			// to
+			// the given point
+			if (threads == alreadySynchronized) {
+				if (LOG.isDebugEnabled())
+					LOG.debug("SyncPoint " + s.getId()
+							+ " was already synchronized");
+				return;
+			}
+			// if no thread was found: Some error occured.
+			if (threads == null) {
+				UnsupportedOperationException e = new UnsupportedOperationException(
+						"The Thread with the SyncPoint '" + s.getId()
+								+ "' does not exist. Synchronisation failed!!");
+				LOG.error("The Thread with the SyncPoint '" + s.getId()
+						+ "' was not found. Synchronisation failed!!", e);
+				throw e;
+			}
+			for (Iterator iter = threads.iterator(); iter.hasNext();) {
+				OneMethodThread thread = (OneMethodThread) iter.next();
+				thread.join();
+			}
+			// indicate as synchronized
+			vectorMap.put(s, alreadySynchronized);
+		}
+	}
+}

Added: trunk/src/appl/parallel/spmd/AdvancedSPMDClientInterface.java
===================================================================
--- trunk/src/appl/parallel/spmd/AdvancedSPMDClientInterface.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/AdvancedSPMDClientInterface.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,96 @@
+package appl.parallel.spmd;
+
+import java.io.PrintStream;
+
+import appl.parallel.server.PartitionDataManager;
+import appl.parallel.spmd.split.DataPartition;
+
+/**
+ * This class extends the {@link SPMDClientInterface} with additional features for performance tuning. You can merge
+ * partitions in background (so that the not very cpu-intensive communication can
+ * happen during extensive calculations). <br>
+ * 
+ * @author Dominik Appl
+ */
+public interface AdvancedSPMDClientInterface extends SPMDClientInterface {
+
+	/**
+	 * Merges like {@link SPMDClientController#mergePartition(int)}, but in a
+	 * separate thread, so that communication does not block computation. See
+	 * also {@link SyncPoint synchronization points}
+	 * 
+	 * @param partition
+	 *            the partition to be merged (must be splittable)
+	 * @param s
+	 *            a syncpoint
+	 */
+	public void mergePartition(Object partition, SyncPoint s);
+
+	/**
+	 * Merges like
+	 * {@link SPMDClientController#mergeMultiData(MultiDataObject, int)}. But
+	 * allows also {@link SyncPoint synchronization points}
+	 * 
+	 * @param multidata
+	 *            the multidataobject
+	 * @param idx
+	 *            the partition of the {@link MultiDataObject} to be merged
+	 * @param s
+	 *            a {@link SyncPoint}
+	 */
+	public void mergeMultiData(MultiDataObject multidata, int idx, SyncPoint s);
+
+	/**
+	 * Same functionality as {@link #mergePartition(Object, SyncPoint)}, gives
+	 * a message to the given {@link PrintStream}
+	 * 
+	 * @param partition
+	 *            the partition to merge
+	 * @param s
+	 *            a {@link SyncPoint}
+	 * @param stream
+	 *            the message is given out to this stream (or null for no
+	 *            message)
+	 * @param message
+	 *            the message to be displayed when finished (or null for no
+	 *            message)
+	 * @see #mergeMultiData(MultiDataObject, int, SyncPoint)
+	 */
+	public void mergePartition(Object partition, SyncPoint s,
+			PrintStream stream, String message);
+
+	/**
+	 * Merges like
+	 * {@link SPMDClientController#mergeMultiData(MultiDataObject, int)}. But
+	 * allows also {@link SyncPoint synchronization points}. At the end of the
+	 * merge a message is given to the provided {@link PrintStream}.
+	 * 
+	 * @param multidata
+	 *            the multidataobject
+	 * @param idx
+	 *            the partition of the {@link MultiDataObject} to be merged
+	 * @param s
+	 *            a {@link SyncPoint}
+	 * @param stream
+	 *            the message is given out to this stream (or null for no
+	 *            message)
+	 * @param message
+	 *            the message to be diplayed when finished (or null for no
+	 *            message)
+	 */
+	public void mergeMultiData(MultiDataObject multidata, int idx, SyncPoint s,
+			PrintStream stream, String message);
+
+	/**
+	 * Waits until the Thread with the specified SyncPoint finishes. After that
+	 * the Thread is removed. A second thread which synchronizes to the same
+	 * Point will directly continue.
+	 * 
+	 * @param s
+	 *            the {@link SyncPoint}
+	 * @throws UnsupportedOperationException
+	 *             if the SyncPoint does not exist and has never existed
+	 */
+	public void synchronizeToSyncPoint(SyncPoint s);
+
+}
\ No newline at end of file

Added: trunk/src/appl/parallel/spmd/AdvancedSPMDServerController.java
===================================================================
--- trunk/src/appl/parallel/spmd/AdvancedSPMDServerController.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/AdvancedSPMDServerController.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,223 @@
+package appl.parallel.spmd;
+
+import java.io.PrintStream;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import appl.parallel.ComputingResourceContainer;
+import appl.parallel.client.DataServer;
+import appl.parallel.client.ClientDataServer;
+import appl.parallel.event.CommEventSink;
+import appl.parallel.server.PartitionDataManager;
+import appl.parallel.spmd.split.DataPartition;
+import appl.parallel.thread.OneMethodThread;
+
+/**
+ * Performance optimizations can be made with this class. Allows heavy
+ * multithreading. Because multiple threads may use this class concurrently
+ * nearly all additional methods of this class are internally synchronized using a static variable.
+ * Also allows preloading of partitions using {@link SyncPoint}s.
+ * 
+ * @author Dominik Appl
+ */
+public class AdvancedSPMDServerController extends SPMDServerController
+		implements AdvancedSPMDServerInterface {
+
+	private final Logger LOG = LogManager.getLogger(this.getClass().getName());
+
+	private static final HashMap<String, String> partitionPreloadStatus = 
+		                                                    new HashMap<String, String>();
+
+	// private static final HashMap<Integer,String> multiPartitionPreloadStatus
+	// = new HashMap<Integer, String>();
+	/**
+	 * For each {@link SyncPoint} a vector of threads associated with the id of
+	 * a SyncPoint is created. The {@link HashMap} is static so all possible threads use
+	 * the same map. Access to this map must be synchronized
+	 */
+	private static final HashMap<Integer, Vector<OneMethodThread>> vectors =
+		                                              new HashMap<Integer, Vector<OneMethodThread>>();
+
+	private boolean isMaster = true;
+
+	/**
+	 * same parameters as superclass
+	 * 
+	 * @see SPMDServerController#SPMDServerController(PartitionDataManager, int)
+	 */
+	public AdvancedSPMDServerController(PartitionDataManager dataManager,
+			int referenceResouceID) {
+		super(dataManager, referenceResouceID);
+		// TODO Auto-generated constructor stub
+	}
+
+	/**
+	 * The partition is loaded in a separate thread into the local
+	 * {@link PartitionDataManager}<br>
+	 * You must specify the partition name and a {@link SyncPoint}.<br>
+	 * You can specify a priority for the thread in the {@link SyncPoint}.
+	 * <br>
+	 * <br>
+	 * <b>Preloading will only be done one time independent of the number of 
+	 * parallel threads calling this method. (synchronized)<br>
+	 * </b>
+	 * 
+	 * @param partition
+	 *            the name of the partition for identification
+	 * @param s
+	 *            the associated {@link SyncPoint}
+	 * @see SPMDServerController#getPartition(String)
+	 * @see #isMasterThread()
+	 */
+	public void preloadPartition(String partition, SyncPoint s) {
+		// create a new thread only if some other thread has not already
+		// triggered the preloading
+		synchronized (vectors) {
+			if (partitionPreloadStatus.get(partition) == null) {
+				partitionPreloadStatus.put(partition, "inProgress");
+				OneMethodThread newThread = new OneMethodThread(
+						"getPartitionThread " + s.getId(), s.getPriority(),
+						partition) {
+					@Override
+					public void run() {
+						// retrieving the partition will as a sideeffect trigger
+						// loading the
+						// partition into the PartitionDataManager
+						getPartition((String) getParameter(0));
+					}
+				};
+				mapThreadToSyncPoint(newThread, s);
+				newThread.start();
+			}
+		}
+	}
+
+	/**
+	 * The partition is loaded in a separate thread into the local
+	 * {@link PartitionDataManager} You must specify the partition name and a
+	 * {@link SyncPoint}. You can specify a priority for the thread in the
+	 * {@link SyncPoint} <br>
+	 * <b>Preloading will only be done one time independent of the number of 
+	 * parallel threads calling this method. (synchronized)<br>
+	 * </b>
+	 * 
+	 * @param multiPartition
+	 *            the name of the partition for identification
+	 * @param idx
+	 *            the index of the partition in the multidata object
+	 * @param s
+	 *            the associated {@link SyncPoint}
+	 * @see appl.parallel.spmd.AdvancedSPMDClientInterface#mergePartition(java.lang.Object,
+	 *      appl.parallel.spmd.SyncPoint)
+	 * @see SPMDServerController#getPartition(String)
+	 */
+	public void preloadMultiPartition(String multiPartition, int idx,
+			SyncPoint s) {
+		synchronized (vectors) {
+			// create a new thread only if some other thread has not already
+			// triggered the preloading
+			if (partitionPreloadStatus.get(multiPartition
+					+ MultiDataInfo.MULTISPLITCONSTANT + idx) == null) {
+				partitionPreloadStatus.put(multiPartition
+						+ MultiDataInfo.MULTISPLITCONSTANT + idx, "inProgress");
+
+				OneMethodThread newThread = new OneMethodThread(
+						"Preload thread - getMultiPartition SID:" + s.getId(),
+						s.getPriority(), multiPartition, idx) {
+					@Override
+					public void run() {
+						// retrieving the partition will also trigger loading
+						// the
+						// partition into the PartitionDataManager
+						getMultiPartition((String) getParameter(0),
+								(Integer) getParameter(1));
+					}
+				};
+				mapThreadToSyncPoint(newThread, s);
+				newThread.start();
+			}
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.spmd.AdvancedSPMDServerInterface#synchronizeToSyncPoint(appl.parallel.spmd.SyncPoint)
+	 */
+	public void synchronizeToSyncPoint(SyncPoint s) {
+		// join all threads associated with the given syncPoint
+		synchronized (vectors) {
+			Vector<OneMethodThread> threads = vectors.get(s.getId());
+			if (threads == null) {
+				UnsupportedOperationException e = new UnsupportedOperationException(
+						"The Thread with the SyncPoint '"
+								+ s.getId()
+								+ "' was not found or was earlier synchronized. Synchronisation failed!!");
+				LOG.error("The Thread with the SyncPoint '" + s.getId()
+						+ "' was not found. Synchronisation failed!!", e);
+				throw e;
+			}
+			for (Iterator iter = threads.iterator(); iter.hasNext();) {
+				OneMethodThread thread = (OneMethodThread) iter.next();
+				thread.join();
+
+			}
+		}
+	}
+
+	/**
+	 * You should call this method from time to time to clear all syncpoints and
+	 * the associated threads out of the memory
+	 */
+	public void clearSyncData() {
+		synchronized (vectors) {
+			vectors.clear();
+			partitionPreloadStatus.clear();
+		}
+	}
+
+	/**
+	 * Puts a thread/Syncpoint pair into the Hashmap/Vector structure
+	 */
+	private static void mapThreadToSyncPoint(OneMethodThread thread, SyncPoint s) {
+		Vector<OneMethodThread> threads = vectors.get(s.getId());
+		// if this is the first thread for the syncPoint: create a new
+		// Vector
+		if (threads == null) {
+			threads = new Vector<OneMethodThread>(5);
+			vectors.put(s.getId(), threads);
+		}
+		threads.add(thread);
+
+	}
+
+	/**
+	 * If there are multiple processors on the machine and the current task
+	 * {@link SPMDTask#supportsMultiThreading() supports multithreading} there
+	 * are several threads created. Each thread uses a different
+	 * {@link #getLocalBounds(DataPartition) calculation area}. Now there might
+	 * be parts of the task code were multithreading is undesired, e.g. when
+	 * operations affect the whole partition. In this case you should use this
+	 * method to guarantee that only one thread has access to a code block.
+	 * 
+	 * @return whether this thread is the "master" thread, which means whether
+	 *         this thread refers to the first task created.
+	 */
+	public boolean isMasterThread() {
+		return isMaster;
+
+	}
+
+	/**
+	 * @param isMaster
+	 *            true, if this should be the master thread
+	 * @see #isMasterThread()
+	 */
+	public void setMasterThread(boolean isMaster) {
+		this.isMaster = isMaster;
+	}
+}

Added: trunk/src/appl/parallel/spmd/AdvancedSPMDServerInterface.java
===================================================================
--- trunk/src/appl/parallel/spmd/AdvancedSPMDServerInterface.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/AdvancedSPMDServerInterface.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,81 @@
+package appl.parallel.spmd;
+
+import java.util.Iterator;
+import java.util.Vector;
+
+import appl.parallel.server.PartitionDataManager;
+import appl.parallel.spmd.split.DataPartition;
+import appl.parallel.thread.OneMethodThread;
+
+/**
+ * Performance optimizations can be made with this type of controller. It allows heavy
+ * multithreading. Also allows preloading of partitions using SyncPoints.
+ * 
+ * @author Dominik Appl
+ */
+public interface AdvancedSPMDServerInterface extends SPMDServerInterface {
+	/**
+	 * The partition is loaded in a separate thread into the local {@link PartitionDataManager}
+	 * You must specify the partitionname and a {@link SyncPoint}.
+	 * You can specifiy a priority for the thread in the {@link SyncPoint}
+	 * 
+	 * @param partition the name of the partition for identification
+	 * @param s the associated {@link SyncPoint}
+	 * 
+	 * @see appl.parallel.spmd.AdvancedSPMDClientInterface#mergePartition(java.lang.Object, appl.parallel.spmd.SyncPoint)
+	 * @see SPMDServerController#getPartition(String)
+	 * 
+	 */
+	public void preloadPartition(String partition, SyncPoint s);
+	
+	/**
+	 * The partition is loaded in a separate thread into the local {@link PartitionDataManager}
+	 * You must specify the partitionname and a {@link SyncPoint}.
+	 * You can specifiy a priority for the thread in the {@link SyncPoint}
+	 * 
+	 * @param partition the name of the partition for identification
+	 * @param idx the index of the partition in the multidata object
+	 * @param s the associated {@link SyncPoint}
+	 * 
+	 * @see appl.parallel.spmd.AdvancedSPMDClientInterface#mergePartition(java.lang.Object, appl.parallel.spmd.SyncPoint)
+	 * @see SPMDServerController#getPartition(String)
+	 * 
+	 */
+	public void preloadMultiPartition(String partition, int idx, SyncPoint s);
+	
+	
+	/**
+	 * Waits until the Thread with the specified SyncPoint finishes. After that
+	 * the Thread is removed. A second call will cause a exeception.
+	 * 
+	 * @param s
+	 *            the {@link SyncPoint}
+	 * @throws UnsupportedOperationException
+	 *             if a thread with the specified SyncPoint was not found or was
+	 *             already synchronized!
+	 */
+	public void synchronizeToSyncPoint(SyncPoint s); 
+	
+	/**
+	 * If there are multiple processors on the machine and the current task
+	 * supports
+	 * {@link SPMDTask#supportsMultiThreading() supports multithreading} there
+	 * are several threads created. Each thread uses a different
+	 * {@link SPMDServerInterface#getLocalCalculationBounds(DataPartition) calculation area}. Now there might
+	 * be parts of the taskcode were multithreading is undesired, e.g. when
+	 * operations affect the whole partition. In this case you should use this
+	 * method to guarantee that only one thread has access to a code block.
+	 *  
+	 * @return whether this thread is the "master" thread, which means whether this thread
+	 * 			refers to the first task created.
+	 */
+	public boolean isMasterThread();
+	
+	/**
+	 * You should call this method from time to time to clear all syncpoints and the associated
+	 * threads out of the memory
+	 */
+	public void clearSyncData();
+	
+	
+}

Added: trunk/src/appl/parallel/spmd/MultiDataInfo.java
===================================================================
--- trunk/src/appl/parallel/spmd/MultiDataInfo.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/MultiDataInfo.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,108 @@
+package appl.parallel.spmd;
+
+import java.io.Serializable;
+import java.rmi.RemoteException;
+import java.util.Vector;
+
+import appl.parallel.server.PartitionDataServer;
+import appl.parallel.server.PartitionDataManager;
+
+/**
+ * Instances of this class encapsulate information about multiple objects
+ * of the same type, e.g. lists of grids. In contrast to the MultiDataObject there
+ * are no objects stored, but only the IDs of the objects. That simplifies the
+ * the synchronization of multidata information over a network.
+ *
+
+ *
+ * @author Dominik Appl
+ */
+public class MultiDataInfo implements Serializable {
+	Vector<Integer> ids = new Vector<Integer>();
+
+	String name;
+
+	/**
+	 * This constant is used as a divider for adding multiple data associated with the same
+	 * name.
+	 * The dividing should be as follows: name + MULTISPLITCONSTANT + index
+	 */
+	public static final String MULTISPLITCONSTANT = ";)|(;";
+
+	public MultiDataInfo(int[] ids,  String name){
+		this.name = name;
+		for (int i : ids) {
+			this.ids.add(i);
+		}
+	}
+
+	/**
+	 * Adds a new Element with the specified id.
+	 * @param id The ID of the new element.
+	 * @return the name of the new Element
+	 *
+	 */
+	public String addElement(int id){
+		ids.add(id);
+		return getNameWithIdx(getCount()-1, name);
+	}
+
+
+	public int getMultiID(int idx){
+		return ids.get(idx);
+	}
+
+	/**
+	 * Generates a identification String based only on the given name and the given idx.
+	 * It can be used for identification of the same data over multiple resources
+	 *
+	 * @param idx the index of the element in the multidata
+	 * @param name the name of the element
+	 * @return the identification string
+	 *
+	 * @see #getIndexFromNameWithIdx(String)
+	 *
+	 */
+	public static String getNameWithIdx(int idx, String name){
+		return  name + MULTISPLITCONSTANT + idx;
+	}
+
+
+	/**
+	 * Extracts the the the index out of a identification
+	 * @param identificationName the identification
+	 * @return the index
+	 *
+	 * @see #getNameWithIdx(int, String)
+	 */
+	public static int getIndexFromNameWithIdx(String identificationName){
+		String index = identificationName.split(MULTISPLITCONSTANT)[1];
+		int i = Integer.valueOf(index);
+		System.out.println("MulitDataInfo: Returning " + i);
+		return i;
+	}
+
+	/**
+	 * Generates a new id for a given index, based on the id of the first element
+	 * in the multidata.
+	 * @param idx the index for which a new id should be generated
+	 * @return the new id
+	 */
+	public int getNewIDForIndex(int idx){
+		return getMultiID(0) * (-1) - idx;
+	}
+
+	/**
+	 * @return the number of elements currently in the multi-info
+	 */
+	public int getCount(){
+		return ids.size();
+	}
+
+	/**
+	 * @return the name associated with this multi-id
+	 */
+	public String getName(){
+		return name;
+	}
+}

Added: trunk/src/appl/parallel/spmd/MultiDataObject.java
===================================================================
--- trunk/src/appl/parallel/spmd/MultiDataObject.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/MultiDataObject.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,195 @@
+package appl.parallel.spmd;
+
+import java.rmi.RemoteException;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import schmitzm.data.WritableGrid;
+
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+
+import appl.parallel.client.DataServer;
+import appl.parallel.server.PartitionDataServer;
+import appl.parallel.spmd.split.DataPartition;
+
+/**
+ * A multi data object stores multiple elements of the same type.
+ * While the related {@link MultiDataInfo} stores only Information about 
+ * multi-data and is used by Xulu / V for transfer of metadata, this class
+ * is a actual user object. The user can retrieve a multidata object e.g. via the
+ * {@link SPMDServerController} and work with it (e.g. add elements)
+ * 
+ * @see SPMDServerInterface#getMultiData(String)
+ * @see MultiDataInfo
+ * 
+ * @author Dominik Appl
+ **/
+
+public class MultiDataObject {
+
+	private final Logger LOG = LogManager.getLogger(this.getClass().getName());
+
+	private final MultiDataInfo multiDataInfo;
+
+	private final DataServer dataServer;
+
+	private MultiGrid managedGrid = null;
+
+	/**
+	 * Construct a new Multidata object
+	 * 
+	 * @param info a {@link MultiDataInfo} object with the identification of the objects
+	 * @param dataServer a dataServer which is responsible for the actual loading of the data
+	 */
+	public MultiDataObject(MultiDataInfo info, DataServer dataServer) {
+		this.multiDataInfo = info;
+		this.dataServer = dataServer;
+	}
+
+	/**
+	 * @param idx the position of the element
+	 * @return the element at the indicated position
+	 */
+	public Object getElement(int idx) {
+		try {
+			checkIndex(idx);
+			return dataServer.getData(multiDataInfo.getMultiID(idx));
+		} catch (RemoteException e) {
+			LOG.error("RemoteExeception while retrieving data with ID "
+					+ multiDataInfo.getMultiID(idx)
+					+ " from PartitionDataServer");
+		}
+		return null;
+	}
+
+	/**
+	 * checks whether the indicated index is valid
+	 * @throws ArrayIndexOutOfBoundsException if idx is below zero or higher than number of elements 
+	 */
+	private void checkIndex(int idx) {
+		if ((idx > multiDataInfo.getCount() - 1) || idx <0 )
+			throw new ArrayIndexOutOfBoundsException("The Element with index "
+					+ idx + " was requested, but the MultiDataObject has only "
+					+ multiDataInfo.getCount() + " elements.");
+
+	}
+
+	/**
+	 * @return the number of elements in the multidataobject
+	 */
+	public int getCount() {
+		return multiDataInfo.getCount();
+	}
+
+	/**
+	 * Adds an element to MultiDataObjects. Method should be thread safe.
+	 * 
+	 * @return the index of the new element
+	 */
+	public synchronized int addElement() {
+		//the new ID of the MultiDataObject is generated by making
+		//the first id negative and than subtracting the index from 
+		//the ID
+		int idx = multiDataInfo.getCount() - 1;
+		try {
+			if (idx == -1)
+				throw new UnsupportedOperationException(
+						"The MultiDataInfo must have at least one element!");
+			//simply get the first element and create a empty one.
+			int firstElementID = multiDataInfo.getMultiID(0);
+			DataPartition firstElement = dataServer.getData(firstElementID);
+			//generate a new id by making the first ID negative and subtracting the index value
+			int newID = multiDataInfo.getNewIDForIndex(idx + 1);
+			//there is a rare chance of colliding with existing ids:
+			while (dataServer.getData(newID) != null) {
+				newID--;
+			}
+			//create new element 
+			DataPartition newElement = firstElement.getEmpty(newID);
+			multiDataInfo.addElement(newID);
+			//add the element to the dataServer and to the managed MultiGrid (if any)
+			dataServer.addData(newElement);
+			if (managedGrid != null)
+				managedGrid.addGrid((WritableGrid) newElement);
+			return idx + 1;
+		} catch (RemoteException e) {
+			LOG
+					.error("RemoteExeception while trying to add a new element with idx "
+							+ idx + " to MultiData");
+		}
+		return 0;
+	}
+
+	/**
+	 * Adds an element with the specified ID.
+	 * 
+	 * @param id the id of the element to add
+	 * @return the index of the new element or 0 if an error occurred
+	 */
+	public int addElement(int id) {
+		//actual maxIndex
+		int idx = multiDataInfo.getCount() - 1;
+		try {
+			if (idx == -1)
+				throw new UnsupportedOperationException(
+						"The MultiDataInfo must have at least one element!");
+			//simply get the first element and create a empty one.
+			int firstElementID = multiDataInfo.getMultiID(0);
+			DataPartition firstElement = dataServer.getData(firstElementID);
+
+			//create new element 
+			DataPartition newElement = firstElement.getEmpty(id);
+			multiDataInfo.addElement(id);
+			//add the element to the dataServer and to the managed MultiGrid (if any)
+			dataServer.addData(newElement);
+			if (managedGrid != null)
+				managedGrid.addGrid((WritableGrid) newElement);
+			return idx + 1;
+		} catch (RemoteException e) {
+			LOG
+					.error("RemoteExeception while trying to add a new element with idx "
+							+ idx + " to MultiData");
+		}
+		return 0;
+	}
+
+	/**
+	 * Manages a multigrid, which means that when a new element is added 
+	 * to the multiObject, then the same element is also added to 
+	 * the managed multiGrid.
+	 * 
+	 * @param toManageMultiGrid the grid to be managed. Only one grid will be 
+	 * managed at a time.
+	 *  
+	 */
+	public void setManagedGrid(MultiGrid toManageMultiGrid) {
+		this.managedGrid = toManageMultiGrid;
+	}
+
+	/**
+	 * @return the encapsulted {@link MultiDataInfo}
+	 */
+	public MultiDataInfo getMultiInfo() {
+		return this.multiDataInfo;
+	}
+
+	public String getName() {
+		return multiDataInfo.getName();
+	}
+
+	/**
+	 * removes the element with the specified index from the dataServer
+	 * 
+	 * @param idx the element
+	 */
+	public void deleteElement(int idx) {
+		checkIndex(idx);
+		try {
+			dataServer.removeData(multiDataInfo.getMultiID(idx));
+		} catch (RemoteException e) {
+			LOG.error("Could not reach DataServer" , e);
+			e.printStackTrace();
+		}	
+	}
+}

Added: trunk/src/appl/parallel/spmd/MultiDataPartitionObject.java
===================================================================
--- trunk/src/appl/parallel/spmd/MultiDataPartitionObject.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/MultiDataPartitionObject.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,58 @@
+package appl.parallel.spmd;
+
+import java.io.Serializable;
+import java.rmi.RemoteException;
+import java.util.Vector;
+
+import appl.parallel.client.DataServer;
+import appl.parallel.data.PartitionDataHandler;
+import appl.parallel.server.PartitionDataServer;
+import appl.parallel.server.PartitionDataManager;
+import appl.parallel.spmd.split.DataPartition;
+import appl.parallel.spmd.split.PartitionInfo;
+import appl.parallel.spmd.split.SinglePartitionInfo;
+
+/**
+ *  A extension of the {@link MultiDataObject} for storing {@link DataPartition DataPartitions}.
+ *    
+ * @author Dominik Appl
+ */
+public class MultiDataPartitionObject extends MultiDataObject {
+
+	private final PartitionDataServer partitionDataServer;
+	private final MultiDataInfo info;
+
+	public MultiDataPartitionObject(MultiDataInfo info, PartitionDataServer dataServer) {
+		super(info, dataServer);
+		this.info = info;
+		partitionDataServer = dataServer;
+	}
+
+	/**
+	 * Adds an element to the PartitionObject as {@link MultiDataObject} does. Also 
+	 * adds the needed {@link PartitionInfo} Object for the new Element
+	 * to the {@link PartitionDataServer}.
+	 * 
+	 * @return the index of the last element
+	 */
+	@Override
+	public int addElement() {
+		int lastIdx = super.addElement();
+		int newID = this.getMultiInfo().getMultiID(lastIdx);
+		//get PartitionInfo of the first grid and duplicate it
+		try {
+			SinglePartitionInfo partitionInfo = (SinglePartitionInfo) partitionDataServer.getPartitionInfo(info.getMultiID(0)).clone(newID);
+			//add the new PartitionInfo to the server
+			Vector<SinglePartitionInfo> partitionVector = new Vector<SinglePartitionInfo>();
+			partitionVector.add(partitionInfo);
+			partitionDataServer.addPartitionInfos(partitionVector);
+		} catch (RemoteException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		
+		return lastIdx;
+	}
+	
+
+}

Added: trunk/src/appl/parallel/spmd/SPMDClientController.java
===================================================================
--- trunk/src/appl/parallel/spmd/SPMDClientController.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/SPMDClientController.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,946 @@
+package appl.parallel.spmd;
+
+import java.net.InetAddress;
+import java.rmi.RemoteException;
+import java.util.HashMap;
+import java.util.Vector;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+import appl.data.DataLoader;
+import appl.ext.XuluConfig;
+import appl.parallel.ComputingResource;
+import appl.parallel.ComputingResourceContainer;
+import appl.parallel.ComputingResourceProperties;
+import appl.parallel.client.RemoteEventHandler;
+import appl.parallel.client.ClientDataServer;
+import appl.parallel.data.PartitionDataHandler;
+import appl.parallel.data.PartitionHandlerFactory;
+import appl.parallel.data.XuluClientLoader;
+import appl.parallel.event.CommEvent;
+import appl.parallel.event.CommEventSink;
+import appl.parallel.event.TimeEvent;
+import appl.parallel.event.TimeMonitor;
+import appl.parallel.event.TransferEvent;
+import appl.parallel.event.TransferMonitor;
+import appl.parallel.event.CommEvent.CommType;
+import appl.parallel.server.PartitionDataServer;
+import appl.parallel.server.SPMDResource;
+import appl.parallel.spmd.split.AbstractSplitMap;
+import appl.parallel.spmd.split.DataPartition;
+import appl.parallel.spmd.split.SinglePartitionInfo;
+import appl.parallel.spmd.split.SplitMap;
+import appl.parallel.spmd.split.SplittableResource;
+import appl.parallel.spmd.split.AbstractSplitMap.NeighborhoodBoxingMode;
+import appl.parallel.thread.ComputingResourceThread;
+import appl.parallel.thread.DataServerThread;
+import appl.parallel.model.AbstractParallelStepModel;
+
+/**
+ * This class controls all the parallelization action on the client side and is
+ * the counterpart to {@link SPMDServerController}. It is accessed by the model
+ * developer by retrieving the {@link SPMDClientInterface} from the
+ * {@link AbstractParallelStepModel}.
+ *
+ * @author Dominik Appl
+ */
+public class SPMDClientController implements SPMDClientInterface {
+
+	/**
+	 * There are two states: <br>
+	 * <br>
+	 * <b>STATE.INIT</b> is the initializing state. In this state it is
+	 * allowed:<br>
+	 * to add resources to split control<br>
+	 * change neighborhodRange/boxing modes/reference resource<br>
+	 * <br>
+	 * All other methods are disabled and will throw
+	 * {@link UnsupportedOperationException}<br>
+	 * <br>
+	 * <b>STATE.RUN</b> is the running stage. All methods of {@link STATE#INIT}
+	 * are disabled and will throw {@link UnsupportedOperationException}. This
+	 * mode is automatically set by the first call to
+	 * {@link SPMDClientController#runSPMDModelTask(SPMDTask, Object...)}
+	 */
+	public enum STATE {
+		INIT, RUN
+	}
+
+	private STATE state = STATE.INIT;
+
+	private final String splitMapClassPropertyName = "Parallel.splitmapforclass";
+
+	private final Logger LOG = LogManager.getLogger(this.getClass().getName());
+
+	/**
+	 * participating servers
+	 */
+	private final SPMDResource[] servers;
+
+	private final ComputingResourceProperties[] serverInfos;
+
+	/**
+	 * stores the {@link PartitionDataServer DataServers} of the resources. They
+	 * are retrieved, after all resources are submitted to split control.
+	 */
+	private final PartitionDataServer[] dataServers;;
+
+	/**
+	 * number of partitions (== no of participating resources)
+	 */
+	private final int noOfPartitions;
+
+	/**
+	 * contains the {@link SinglePartitionInfo} of the
+	 * {@link SplittableResource splitted resources} for each server
+	 */
+	private final Vector<SinglePartitionInfo>[] singlePartitionInfos;
+
+	private final Vector<SinglePartitionInfo>[] toTransferPartitionInfos;
+
+	private HashMap<String, Object> toTransferBaseParameters;
+
+	private final HashMap<String, MultiDataInfo> multiDataInfos = new HashMap<String, MultiDataInfo>(
+			10);
+
+	private final HashMap<String, MultiDataInfo> toTransferMultiDataObjects = new HashMap<String, MultiDataInfo>(
+			10);
+
+	/** The IP-Addresses of the resources */
+	private String[] IPs;
+
+	/***************************************************************************
+	 * This Vector contains all IDs of the resources, which are currently under
+	 * splitControl
+	 *
+	 * @see #addToSplitControl(SplittableResource, String)
+	 * @see #mergePartition(SplittableResource)
+	 **************************************************************************/
+	private Vector<Integer> listOfAllActivelyControlledData = new Vector<Integer>();
+
+	/**
+	 * @see AbstractSplitMap.NeighborhoodBoxingMode
+	 */
+	private NeighborhoodBoxingMode boxingMode = AbstractSplitMap.NeighborhoodBoxingMode.inBoxing;
+
+	/** current neighborhood range, default is 0 */
+	private int neighborhoodRange = 0;
+
+	private final ClientDataServer spmdClient;
+
+	/**
+	 * Local calculation bounds on server side are calculated using the
+	 * reference resource This is the ID of that resource
+	 */
+	protected int referenceResourceID = -1;
+
+	/** Thread execution pool */
+	private final ExecutorService executor;
+
+	/** true if there is data which has to be transfered to the servers */
+	private boolean dataToTransfer = false;
+
+	private SplitMap splitMap;
+
+	private final CommEventSink eventProxy;
+
+	private final double[] weights;
+
+	/**
+	 * Creates a new Client controller.
+	 *
+	 * @param computingResources
+	 *            the resources which are used by this controller
+	 * @param spmdClient
+	 *            the spmd client responsible for the data retrieval
+	 * @param weights
+	 *            the weights for the distribution over the computing resources
+	 *            (values with a sum of 1) or null (distribution will be
+	 *            average)
+	 * @param eventProxy
+	 *            a {@link RemoteEventHandler} for eventHandling
+	 */
+	@SuppressWarnings("unchecked")
+	public SPMDClientController(
+			Vector<ComputingResourceContainer> computingResources,
+			double[] weights, ClientDataServer spmdClient,
+			CommEventSink eventProxy) {
+		if (weights == null)
+			weights = averageWeights(computingResources.size());
+		this.weights = weights;
+
+		this.eventProxy = eventProxy;
+		this.noOfPartitions = computingResources.size();
+		if (noOfPartitions == 0)
+			throw new UnsupportedOperationException(
+					"No Computing Ressources found");
+
+		this.spmdClient = spmdClient;
+		dataServers = new PartitionDataServer[noOfPartitions];
+		serverInfos = new ComputingResourceProperties[noOfPartitions];
+		servers = new SPMDResource[noOfPartitions];
+		for (int i = 0; i < computingResources.size(); i++) {
+			serverInfos[i] = computingResources.get(i).getInformation();
+			servers[i] = (SPMDResource) computingResources.get(i).getResource();
+
+		}
+		// extract the IPs
+		IPs = new String[noOfPartitions];
+		for (int i = 0; i < IPs.length; i++) {
+			IPs[i] = serverInfos[i].getIP();
+			IPs[i] = serverInfos[i].getPort() == null ? IPs[i] : IPs[i] + ":"
+					+ serverInfos[i].getPort();
+
+			if (IPs[i] == null)
+				LOG
+						.fatal("The IP-Information of a computingRessource was NULL. "
+								+ "This will result in failure of the computation!");
+		}
+
+		// initialize the singlePartitionInfos and tasks. Notice that the array
+		// singlePartitionInfos is final.
+		// Each vector of infos is permanently associated with one server.
+		this.singlePartitionInfos = new Vector[noOfPartitions];
+		this.toTransferPartitionInfos = new Vector[noOfPartitions];
+		this.toTransferBaseParameters = new HashMap<String, Object>();
+		for (int i = 0; i < noOfPartitions; i++) {
+			singlePartitionInfos[i] = new Vector<SinglePartitionInfo>();
+			toTransferPartitionInfos[i] = new Vector<SinglePartitionInfo>();
+		}
+
+		// initialize executor
+		executor = Executors.newCachedThreadPool();
+
+		// connect to all participating servers
+		connectAll();
+		// initialize DataServers (must be after connect)
+		for (int i = 0; i < noOfPartitions; i++)
+			try {
+				dataServers[i] = servers[i].createDataServer(IPs);
+			} catch (RemoteException e) {
+				LOG.fatal(e);
+				e.printStackTrace();
+			}
+	}
+
+	private double[] averageWeights(int noResources) {
+		// create weighted rating with the same weight
+		double[] weights = new double[noResources];
+		for (int i = 0; i < weights.length; i++) {
+			weights[i] = 1 / noResources;
+		}
+		return weights;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.spmd.SPMDClientInterface#addBaseParameter(java.lang.Object,
+	 *      java.lang.String)
+	 */
+	public void addBaseParameter(Object parameter, String parameterName) {
+		toTransferBaseParameters.put(parameterName, parameter);
+		dataToTransfer = true;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.spmd.SPMDClientInterface#addBaseParameters(java.lang.Object[],
+	 *      java.lang.String[])
+	 */
+	public void addBaseParameters(Object[] parameters, String[] parameterNames) {
+		for (int i = 0; i < parameterNames.length; i++) {
+			addBaseParameter(parameters[i], parameterNames[i]);
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.spmd.SPMDClientInterface#addToMultiDataSplitControl(java.lang.Object[],
+	 *      java.lang.String)
+	 */
+	public MultiDataObject addToMultiDataSplitControl(
+			Object splittableResources[], String name) {
+		if (splittableResources.length == 0) {
+			throw new UnsupportedOperationException(
+					"There must be at least one resource to create a MultiData Element");
+		}
+		// Check if adding is allowed:
+		checkState(STATE.INIT);
+		SplittableResource[] resources = checkSplittableArray(splittableResources);
+
+		// add each element to splitcontrol. The constant gives each element a
+		// unique name and identifies it on the server side as belonging to a multisplit
+
+		MultiDataInfo multi = new MultiDataInfo(new int[0], name);
+		for (int i = 0; i < resources.length; i++) {
+			multi.addElement(resources[i].getRootID());
+			addToSplitControl(resources[i], MultiDataInfo.getNameWithIdx(i,
+					name));
+		}
+		toTransferMultiDataObjects.put(name, multi);
+		multiDataInfos.put(name, multi);
+		dataToTransfer = true;
+		return new MultiDataObject(multi, spmdClient);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.spmd.SPMDClientInterface#addToMultiDataSplitControl(edu.bonn.xulu.plugin.data.grid.MultiGrid,
+	 *      java.lang.String)
+	 */
+	public MultiDataObject addToMultiDataSplitControl(MultiGrid multiGrid,
+			String name) {
+		MultiDataObject dataObject = addToMultiDataSplitControl(multiGrid
+				.toArray(), name);
+		dataObject.setManagedGrid(multiGrid);
+		return dataObject;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.spmd.SPMDClientInterface#addToSplitControl(java.lang.Object,
+	 *      java.lang.String)
+	 */
+	public void addToSplitControl(Object splittableResource, String name) {
+
+		SplittableResource resource = checkSplittable(splittableResource);
+		// Check if adding is allowed:
+		checkState(STATE.INIT);
+		// if first call, than this is the reference for now - a map will be
+		// generated
+		if (referenceResourceID == -1)
+			setReferenceResource(resource);
+
+		// add the data to the SPMDClient for server retrieval
+		spmdClient.addData(resource);
+		// add the the resource to the controlled resources
+		listOfAllActivelyControlledData.add(resource.getRootID());
+		// make the singlePartitionInfos for each participating server and store
+		// the
+		// info for later use
+
+		SplitMap map = getSplitMap();
+		// create a partition info for each Server (only the
+		// splitMapPosition differs)
+		for (int i = 0; i < singlePartitionInfos.length; i++) {
+			PartitionDataHandler loader = PartitionHandlerFactory.newInstance(
+					resource.getRootID(), spmdClient,
+					map.getPartitionBounds(i), map
+							.getPartitionCalculationBounds(i));
+			SinglePartitionInfo info = new SinglePartitionInfo(resource
+					.getRootID(), name, loader, map, i);
+			singlePartitionInfos[i].add(info);
+			toTransferPartitionInfos[i].add(info);
+			dataToTransfer = true;
+		}
+	}
+
+	/**
+	 * Checks if the given object is an instance of {@link SplittableResource}
+	 * and gives it back as splittable.
+	 *
+	 * @param splittableResource
+	 * @throws UnsupportedOperationException
+	 *             if not instance of {@link SplittableResource}
+	 * @return the object as {@link SplittableResource}
+	 */
+	protected SplittableResource checkSplittable(Object splittableResource) {
+		if (!(splittableResource instanceof SplittableResource))
+			throw new UnsupportedOperationException(
+					"Operation failed: the argument for 'addToSplitControl' \n "
+							+ "must be an instance of SplittableResource! (like e.g. SplittableLLProxyGrid).\n "
+							+ "You can add non splittable Objects as Parameters of the SPMDTasks! For arrays"
+							+ "of SplittableResources use addToMultiSplitControl");
+		return (SplittableResource) splittableResource;
+	}
+
+	/**
+	 * checks if every object of the array is an instance of
+	 * {@link SplittableResource} and gives it back as splittable
+	 *
+	 * @param splittableResources
+	 *            an array of (hopefully)
+	 *            {@link SplittableResource SplittableResources}
+	 * @throws UnsupportedOperationException
+	 *             if not all elements are instances of
+	 *             {@link SplittableResource} or if the splitHeights or
+	 *             SplitWidths do not match
+	 * @return the object as {@link SplittableResource} array
+	 */
+	protected SplittableResource[] checkSplittableArray(
+			Object[] splittableResources) {
+		SplittableResource[] res = new SplittableResource[splittableResources.length];
+		for (int i = 0; i < splittableResources.length; i++) {
+			if (!(splittableResources[i] instanceof SplittableResource))
+				throw new UnsupportedOperationException(
+						"Operation failed: the argument must be an instance "
+								+ "of SplittableResource! (like e.g. SplittableLLProxyGrid).\n "
+								+ "You can add non splittable Objects as Parameters of the SPMDTasks!");
+			res[i] = (SplittableResource) splittableResources[i];
+		}
+		// check if the splitLengths match
+		if (res.length == 0)
+			return res;
+		int splitHeight = res[0].getSplitHeight();
+		int splitWidth = res[0].getSplitWidth();
+		for (SplittableResource resource : res) {
+			if (resource.getSplitHeight() != splitHeight
+					|| resource.getSplitWidth() != splitWidth)
+				throw new UnsupportedOperationException(
+						"Operation Failed: Splitvalues (height/width) of the array elements do not match!");
+		}
+		return res;
+	}
+
+	/**
+	 * Throws a {@link UnsupportedOperationException} if the state does not
+	 * match the required state
+	 *
+	 * @param requiredState
+	 *            the required state
+	 */
+	private void checkState(STATE requiredState) {
+		if (requiredState != state)
+			throw new UnsupportedOperationException(
+					"This Operation is not available: " + "You are in state"
+							+ state + " but you should be in state "
+							+ requiredState + ". See documentation of "
+							+ state.getClass().getName()
+							+ " for more information ");
+	}
+
+	/**
+	 * disconnects from all servers
+	 */
+	public void close() {
+		disconnectAll();
+	}
+
+	/**
+	 * connects to all servers
+	 */
+	@SuppressWarnings("unchecked")
+	private void connectAll() {
+		checkState(STATE.INIT);
+		long l = System.currentTimeMillis();
+		Future[] futureResults = new Future[servers.length];
+		for (int i = 0; i < servers.length; i++) {
+			futureResults[i] = executor.submit(new ComputingResourceThread(
+					servers[i], serverInfos[i], null, CommType.CONNECT,
+					eventProxy, true) {
+				public Object run() throws Exception {
+					getServer().connect();
+					return null;
+				}
+			});
+		}
+		try {
+			// wait for threads to finish
+			for (Future future : futureResults) {
+				future.get();
+			}
+		} catch (Exception e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		System.out.println("Connect time: " + (System.currentTimeMillis() - l)
+				+ " ms");
+	}
+
+	/**
+	 * disconnect from all servers
+	 */
+	private void disconnectAll() {
+		Future[] futureResults = new Future[servers.length];
+		for (int i = 0; i < servers.length; i++) {
+			futureResults[i] = executor.submit(new ComputingResourceThread(
+					servers[i], serverInfos[i], null, CommType.DISCONNECT,
+					eventProxy, true) {
+				public Object run() throws Exception {
+					getServer().disconnect();
+					return null;
+				}
+			});
+		}
+		try {
+			// wait threads to finish
+			for (Future future : futureResults) {
+				future.get();
+			}
+		} catch (Exception e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+
+	}
+
+	/**
+	 * @return the actual splitmap. The referenceResource must be set before
+	 *         call!
+	 */
+	private SplitMap getSplitMap() {
+		if (referenceResourceID == -1) {
+			LOG.error("NO MAP CREATED YET!");
+			return null;
+		} else
+			return splitMap;
+	}
+
+	/**
+	 * @return the current state
+	 */
+	public STATE getState() {
+		return state;
+	}
+
+	/**
+	 * Creates a {@link SplitMap} for the specified resource. Use
+	 * {@link #getSplitMap()} for retrieval.
+	 *
+	 * @param splittable
+	 *            the resource, for which the {@link SplitMap} is created
+	 */
+	private void makeSplitMap(SplittableResource splittable) {
+		SplitMap map = null;
+
+		// get splitMap implementation for this splittable from XuluConfig
+		String classname = XuluConfig.getXuluConfig().getProperty(
+				splitMapClassPropertyName + "."
+						+ splittable.getClass().getSimpleName());
+		// if no entry was found lookup default splitter
+		if (classname == null)
+			classname = XuluConfig.getXuluConfig().getProperty(
+					splitMapClassPropertyName + "." + "default");
+		try {
+			map = (SplitMap) Class.forName(classname).newInstance();
+			map.setParameters(splittable, neighborhoodRange, noOfPartitions,
+					boxingMode);
+			map.setWeights(weights);
+			map.makeMap();
+		} catch (Exception e) {
+			String error = "Could not create Splitmap from classname : '"
+					+ classname + "' out of property '"
+					+ splitMapClassPropertyName + "'. Nested errormessage is :"
+					+ e.getMessage();
+			LOG.fatal(error, e);
+			throw new UnsupportedOperationException(error);
+
+		}
+		this.splitMap = map;
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.spmd.SPMDClientInterface#mergeAllPartitions()
+	 */
+	@SuppressWarnings("unchecked")
+	public synchronized void mergeAllPartitions() {
+		// clone the list first, because mergePartition(int) removes elements
+		// from the list, which causes
+		// problems with the for-each loop
+		Vector<Integer> activeIDs = (Vector<Integer>) listOfAllActivelyControlledData
+				.clone();
+		// Vector<Future> futures = new Vector<Future>();
+		// for (Integer id : activeIDs) {
+		// futures.add(executor.submit(new DataServerThread(null, id) {
+		// public Object call() throws Exception {
+		// mergePartition(getIntArgument());
+		// return null;
+		// }
+		// }));
+		// }
+		// // wait on tasks to finish
+		// for (Future future : futures) {
+		// try {
+		// future.get();
+		// } catch (Exception e) {
+		// e.printStackTrace();
+		// }
+		//
+		// }
+		for (Integer id : activeIDs) {
+			mergePartition((int) id);
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.spmd.SPMDClientInterface#mergeMultiData(appl.parallel.spmd.MultiDataObject)
+	 */
+	public synchronized void mergeMultiData(MultiDataObject multidata) {
+		// the problem is that perhaps on serverside grids were added, but not
+		// on client side. It is assumed that all servers have created the
+		// same number of grids with the same names (which is assured by
+		// multiDataInfo)
+
+		// first lookup the local multiData info and the info of any
+		// (here the first) dataserver multiInfo - as i said: all should be the
+		// same
+		MultiDataInfo localInfo = multidata.getMultiInfo();
+		String name = multidata.getName();
+		MultiDataInfo remoteInfo;
+		try {
+			// all remote infos should be the same, so it is enough to retrieve
+			// the first one
+			remoteInfo = dataServers[0].getMultiDataInfo(name);
+			if (localInfo == null || remoteInfo == null) {
+				LOG.error("Could not lookup MultidataInfo with name " + name
+						+ ". localInfo was " + localInfo + " remote info was "
+						+ remoteInfo);
+				return;
+			}
+			// merge the ids which are there on both sides:
+			int i = 0;
+			for (; i < localInfo.getCount(); i++)
+				mergePartition(localInfo.getMultiID(i));
+			// merge the new partitions
+			for (; i < remoteInfo.getCount(); i++) {
+				// get the new ID (the same as on server side)
+				int newID = remoteInfo.getMultiID(i);
+				// first create the new data element out of the first element in
+				// the list:
+				multidata.addElement(newID);
+				SplittableResource newResource = (SplittableResource) multidata
+						.getElement(multidata.getCount() - 1);
+				spmdClient.addData(newResource);
+				// now merge
+				mergePartition(newID);
+			}
+		} catch (RemoteException e) {
+			LOG.error("ERROR while trying to merge multi data: "
+					+ e.getMessage(), e);
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.spmd.SPMDClientInterface#mergeMultiData(appl.parallel.spmd.MultiDataObject,
+	 *      int)
+	 */
+	public void mergeMultiData(MultiDataObject multidata, int idx) {
+		// the problem is that perhaps on serverside grids were added, but not
+		// on client side. It is assumed that all servers have created the
+		// same number of grids with the same names (which is assured by
+		// multiDataInfo)
+
+		// first lookup the local multiData info and the info of any
+		// (here the first) dataserver multiInfo - as i said: all should be the
+		// same
+		MultiDataInfo localInfo = multidata.getMultiInfo();
+		String name = multidata.getName();
+		MultiDataInfo remoteInfo;
+		try {
+			// all remote infos should be the same, so it is enough to retrieve
+			// the first one
+			remoteInfo = dataServers[0].getMultiDataInfo(name);
+			if (localInfo == null || remoteInfo == null) {
+				LOG.error("Could not lookup MultidataInfo with name " + name
+						+ ". localInfo was " + localInfo + " remote info was "
+						+ remoteInfo);
+				return;
+			}
+			// merge the grid with the given index
+			// for a local idx:
+			if (idx < localInfo.getCount())
+				mergePartition(localInfo.getMultiID(idx));
+			// else create a new grid
+			else {
+				// get the new ID (the same as on server side)
+				int newID = remoteInfo.getMultiID(idx);
+				if (newID == 0)
+					throw new UnsupportedOperationException(
+							"For the requested index (" + idx
+									+ ") was no grid found on the servers");
+				// first create the new data element out of the first element in
+				// the list:
+				multidata.addElement(newID);
+				SplittableResource newResource = (SplittableResource) multidata
+						.getElement(multidata.getCount() - 1);
+				spmdClient.addData(newResource);
+				// now merge the serverdata into the new clientgrid
+				mergePartition(newID);
+			}
+		} catch (RemoteException e) {
+			LOG.error("ERROR while trying to merge multi data: "
+					+ e.getMessage(), e);
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.spmd.SPMDClientInterface#mergePartition(int)
+	 */
+	public synchronized void mergePartition(int rootID) {
+		checkState(STATE.RUN);
+		Future[] futures = new Future[noOfPartitions];
+		for (int i = 0; i < noOfPartitions; i++)
+			futures[i] = executor.submit(new DataServerThread(dataServers[i],
+					serverInfos[i], rootID, CommType.CLIENT_MERGE, eventProxy) {
+				public Object run() throws Exception {
+					getServer().unloadToSource(getIntArgument());
+					return null;
+				}
+			});
+		// wait on tasks to finish:
+		try {
+			// wait threads to finish
+			for (Future future : futures) {
+				future.get();
+			}
+		} catch (Exception e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		listOfAllActivelyControlledData.remove((Integer) rootID);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.spmd.SPMDClientInterface#mergePartition(java.lang.Object)
+	 */
+	public void mergePartition(Object splittableResource) {
+		checkSplittable(splittableResource);
+		checkState(STATE.RUN);
+		mergePartition(((SplittableResource) splittableResource).getRootID());
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.spmd.SPMDClientInterface#runSPMDModelTask(appl.parallel.spmd.SPMDTask,
+	 *      java.lang.Object[])
+	 */
+	@SuppressWarnings("unchecked")
+	public Object[] runSPMDModelTask(final SPMDTask task, Object... parameters)
+			throws Throwable {
+		state = STATE.RUN;
+		// transfer needed data
+		if (dataToTransfer) {
+			transferDataToServers();
+		}
+		// submit task and arguments to the resources
+		// each task is calculated in its own thread;
+		// create tasks
+		parameters = (parameters == null) ? new Object[0] : parameters;
+		try {
+			Future futureResults[] = new Future[servers.length];
+			for (int i = 0; i < servers.length; i++) {
+				futureResults[i] = executor.submit(new ComputingResourceThread(
+						servers[i], serverInfos[i], new Object[] { task,
+								referenceResourceID, parameters },
+						CommType.CLIENT_EXECUTION, eventProxy) {
+					public Object run() throws Exception {
+						SPMDResource server = (SPMDResource) getServer();
+						return server.runSPMDModelTask(task.getClass()
+								.getName(),
+								(Integer) getObjectArrayArgument()[1],
+								(Object[]) getObjectArrayArgument()[2]);
+					}
+				});
+			}
+
+			Vector<Object> results = new Vector<Object>(15);
+
+			// aim of the next loop is to get single Object-array containing all
+			// results!
+			// Notice that every server result is a result array.
+			// This is because serverexecution can happen in multiple threads
+			// (when multiple processors are available) each serverthread will
+			// produce its own result
+			for (int i = 0; i < noOfPartitions; i++) {
+				// wait for threads finished and collect results
+				Object[] result = (Object[]) futureResults[i].get();
+				for (int j = 0; j < result.length; j++)
+					results.add(result[j]);
+			}
+			return results.toArray();
+
+		} catch (ExecutionException e) {
+			LOG.fatal("Error while trying to execute task "
+					+ task.getClass().getName() + ": " + e.getMessage(), e);
+			throw e.getCause();
+		} catch (Exception e) {
+			LOG.error("Error while trying to execute task "
+					+ task.getClass().getName() + ": " + e.getMessage(), e);
+			e.printStackTrace();
+		}
+		return null;
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.spmd.SPMDClientInterface#setBoxingMode(appl.parallel.spmd.split.AbstractSplitMap.NeighborhoodBoxingMode)
+	 */
+	public void setBoxingMode(AbstractSplitMap.NeighborhoodBoxingMode boxingMode) {
+		checkState(STATE.INIT);
+		this.boxingMode = boxingMode;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.spmd.SPMDClientInterface#setNeighborhoodRange(int)
+	 */
+	public void setNeighborhoodRange(int neighborhoodRange) {
+		checkState(STATE.INIT);
+		this.neighborhoodRange = neighborhoodRange;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.spmd.SPMDClientInterface#setReferenceResource(java.lang.Object)
+	 */
+	public void setReferenceResource(Object splittableResource) {
+		checkSplittable(splittableResource);
+		SplittableResource res = (SplittableResource) splittableResource;
+		checkState(STATE.INIT);
+		if (res instanceof SplittableResource) {
+			referenceResourceID = res.getRootID();
+			makeSplitMap(res);
+		} else
+			LOG
+					.warn("Set reference failed: given resource was not an instance of SplittableResource!");
+
+	}
+
+	/**
+	 * transfers all collected data to the servers. (The data is collected to
+	 * save communication time)
+	 */
+	private void transferDataToServers() {
+		long time = System.currentTimeMillis();
+		Vector<Future> futures = new Vector<Future>();
+		if (toTransferPartitionInfos[0].size() > 0)
+			for (int i = 0; i < servers.length; i++) {
+				futures.add(executor.submit(new DataServerThread(
+						dataServers[i], serverInfos[i],
+						toTransferPartitionInfos[i],
+						CommType.TRANSFER_METADATA, eventProxy, true) {
+					public Object run() throws Exception {
+						getServer()
+								.addPartitionInfos(
+										(Vector<SinglePartitionInfo>) getObjectArgument());
+						return null;
+					}
+				}));
+			}
+		if (toTransferMultiDataObjects.size() > 0)
+			for (int i = 0; i < servers.length; i++) {
+				futures.add(executor.submit(new DataServerThread(
+						dataServers[i], serverInfos[i],
+						toTransferMultiDataObjects, CommType.TRANSFER_METADATA,
+						eventProxy, true) {
+					public Object run() throws Exception {
+						getServer()
+								.addMultiDataInfos(
+										(HashMap<String, MultiDataInfo>) getObjectArgument());
+						return null;
+					}
+				}));
+			}
+		if (toTransferBaseParameters.size() > 0)
+			for (int i = 0; i < servers.length; i++) {
+				futures.add(executor.submit(new DataServerThread(
+						dataServers[i], serverInfos[i],
+						toTransferBaseParameters, CommType.TRANSFER_PARAMETERS,
+						eventProxy) {
+					public Object run() throws Exception {
+						getServer().updateBaseParameter(
+								(HashMap) getObjectArgument());
+						return null;
+					}
+				}));
+			}
+		// wait on threads to finish
+		for (Future future : futures) {
+			try {
+				future.get();
+			} catch (InterruptedException e) {
+				LOG.error(e);
+				e.printStackTrace();
+			} catch (ExecutionException e) {
+				LOG.error(e);
+				e.printStackTrace();
+			}
+		}
+		dataToTransfer = false;
+		toTransferBaseParameters.clear();
+		toTransferBaseParameters.clear();
+		toTransferMultiDataObjects.clear();
+		if (LOG.isDebugEnabled())
+			LOG.debug("Transfered Data to clients in "
+					+ (System.currentTimeMillis() - time) / 1000000 + " ms");
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.spmd.SPMDClientInterface#updateNeighborhood(java.lang.Object)
+	 */
+	public void updateNeighborhood(Object splittableResource) {
+		checkSplittable(splittableResource);
+		SplittableResource res = (SplittableResource) splittableResource;
+		updateNeighborhood(res.getRootID());
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see appl.parallel.spmd.SPMDClientInterface#updateNeighborhood(appl.parallel.spmd.MultiDataObject,
+	 *      int)
+	 */
+	public void updateNeighborhood(MultiDataObject multiDataObject, int index) {
+		this.updateNeighborhood(multiDataObject.getMultiInfo()
+				.getMultiID(index));
+	}
+
+	/**
+	 * updates the neighborhood of the splittable with the given id on the
+	 * servers
+	 */
+	private void updateNeighborhood(int rootID) {
+		checkState(STATE.RUN);
+		Future[] futureResults = new Future[servers.length];
+		for (int i = 0; i < servers.length; i++) {
+			futureResults[i] = executor.submit(new DataServerThread(
+					dataServers[i], serverInfos[i], rootID,
+					CommType.CLIENT_UPDATE, eventProxy) {
+				public Object run() throws Exception {
+					getServer().updateFromNeighbors(getIntArgument());
+					return null;
+				}
+			});
+		}
+		try {
+			// wait threads to finish
+			for (Future future : futureResults) {
+				future.get();
+			}
+		} catch (Exception e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+	}
+}

Added: trunk/src/appl/parallel/spmd/SPMDClientInterface.java
===================================================================
--- trunk/src/appl/parallel/spmd/SPMDClientInterface.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/SPMDClientInterface.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,245 @@
+package appl.parallel.spmd;
+
+import appl.parallel.ComputingResource;
+import appl.parallel.spmd.split.AbstractSplitMap;
+import appl.parallel.spmd.split.SplitMap;
+import appl.parallel.spmd.split.SplittableResource;
+import appl.parallel.spmd.split.AbstractSplitMap.NeighborhoodBoxingMode;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+
+/**
+ * Using this interface the programmer can access the parallel functionality.
+ *
+ * @author Dominik Appl
+ */
+public interface SPMDClientInterface {
+
+	/**
+	 * <code>Base Parameters</code> are Objects which are used during the
+	 * execution of multiple {@link SPMDTask SPMD-Tasks}. They are transfered
+	 * to each of the participating
+	 * {@link ComputingResource computing resources} but are not synchronized
+	 * with the client and of course in no way splitted. <br>
+	 * <br>
+	 * <b>Notice:</b> For efficient transport it is recommended that multiple
+	 * parameters are transfered at once. To do this use the
+	 * {@link #addBaseParameters(Object[], String[])} method.
+	 *
+	 * @param parameter
+	 * @param parameterName
+	 * @see SPMDServerController
+	 */
+	public void addBaseParameter(Object parameter, String parameterName);
+
+	/**
+	 * Adds multiple Base-parameters at once. Notice that this is only for
+	 * convenience and has no performance advantages over
+	 * {@link #addBaseParameter(Object, String)}.
+	 *
+	 * @param parameters
+	 *            an array of parameters
+	 * @param parameterNames
+	 *            an array of names. The indexes of parameters and parameter
+	 *            names must of course match
+	 */
+	public void addBaseParameters(Object[] parameters, String[] parameterNames);
+
+	/**
+	 * All resources of the array are submitted to split-control. This means
+	 * they are (virtually) split and send (virtually) to the participating
+	 * computing units. The partitions can be requested on server side using the
+	 * {@link SPMDServerController#getMultiData(String)} method. It is assumed,
+	 * that all resources have the same Dimension. The same {@link SplitMap} and
+	 * splitmap Position is used for all elements. used for every element.
+	 *
+	 * @param splittableResources
+	 *            the resource to be splitted
+	 * @param name
+	 *            the name of the resource
+	 * @return the multi-data object can be used for adding elements to the
+	 *         multi data
+	 * @see SPMDServerController
+	 * @throws UnsupportedOperationException
+	 *             if splitHeight and splitWidth of the resouces does not match
+	 */
+	public MultiDataObject addToMultiDataSplitControl(
+			Object splittableResources[], String name);
+
+	/**
+	 * This method is specialized on handling MultiGrids. In principle the
+	 * {@link #addToMultiDataSplitControl(Object[], String)} could be used, but
+	 * using this method won't handle updates to the MultiGrid required for
+	 * correct display in the XuluModellingPlatform. <p/>
+	 * The elements of the Multigrid are split and send to the participating
+	 * computing units. The partitions can be requested on server side using the
+	 * {@link SPMDServerController#getMultiData(String)} method. It is assumed,
+	 * that all resources have the same Dimension. The same {@link SplitMap} and
+	 * splitmap position is used for all elements.
+	 * 
+	 * @param name
+	 *            the name of the resource
+	 * @return the multi-data object can be used for adding elements to the
+	 *         multi data
+	 * @see SPMDServerController
+	 * @throws UnsupportedOperationException
+	 *             if splitHeight and splitWidth of the resources does not match
+	 */
+	public MultiDataObject addToMultiDataSplitControl(MultiGrid multiGrid,
+			String name);
+
+	/**
+	 * The resource is submitted to splitControl. This means it is virtually
+	 * split and send virtually to the participating computing units. The
+	 * partitions can be requested on server side using the
+	 * {@link SPMDServerController#getPartition(String)} method. <br>
+	 * <br>
+	 * <i>What does "virtually" mean? </i>Well what really happens is that the
+	 * metadata is stored. When
+	 * {@link #runSPMDModelTask(SPMDTask, Object[]) runSPMDModelTask} is run
+	 * next time, the <b>metadata</b> (and all
+	 * {@link #addBaseParameter(Object, String)  base Parameters} btw.) are
+	 * Transfered to the servers. <br>
+	 * The "real" splitting will happen implicit, i.e. the participating servers
+	 * will request the correct partition.
+	 *
+	 * @param splittableResource
+	 *            the resource to be splitted
+	 * @param name
+	 *            a name for the resource (you will be able to request the
+	 *            resource on server side using this name)
+	 * @see SPMDServerController
+	 */
+	public void addToSplitControl(Object splittableResource, String name);
+
+	/**
+	 * Merges all the partitions from the server into the sources, from which
+	 * the objects were loaded (which may be the Xulu-Client, but may also be a
+	 * database or an other location if this feature is implemented).
+	 *
+	 * @see #mergeAllPartitions()
+	 * @see #addToSplitControl(Object, String)
+	 */
+	public void mergeAllPartitions();
+
+	/**
+	 * Merges all elements of the specified multidata object
+	 *
+	 * @param multidata
+	 *            the multidata to merge
+	 */
+	public void mergeMultiData(MultiDataObject multidata);
+
+	/**
+	 * Merges the element at the specified index
+	 *
+	 * @param multidata
+	 *            the multidata object containing the element to merge
+	 * @param idx
+	 *            the position of the element to merge
+	 */
+	public void mergeMultiData(MultiDataObject multidata, int idx);
+
+	/**
+	 * The counterpart of {@link #addToSplitControl(Object, String)}.
+	 * Merges the partitions from the server into the sources, from which the
+	 * objects were loaded (which will be the Xulu-Client in most cases, but may
+	 * also be a database at an other location if this feature is implemented).
+	 * Uses multithreading.
+	 *
+	 * @param rootID
+	 *            the ID of the source to be merged.
+	 * @see #mergeAllPartitions()
+	 * @see #addToSplitControl(Object, String)
+	 */
+	public void mergePartition(int rootID);
+
+	/**
+	 * The counterpart of {@link #addToSplitControl(Object, String)}.
+	 * Merges the partitions from the server into the sources, from which the
+	 * objects were loaded (which will be the Xulu-Client in most cases, but may
+	 * also be a database at an other location if this feature is implemented).
+	 * Use {@link #mergeAllPartitions()} to merge all partitions at once.
+	 *
+	 * @param splittableResource
+	 *            the resource to be merged. (must be an instance of
+	 *            {@link SplittableResource}
+	 * @see #mergeAllPartitions()
+	 * @see #addToSplitControl(Object, String)
+	 */
+	public void mergePartition(Object splittableResource);
+
+	/**
+	 * Run the given task on with the given parameters. The result is a Object
+	 * array with results from all participating servers. The number of elements
+	 * can therefore vary in different executions (using different numbers of
+	 * servers)
+	 *
+	 * @param task
+	 *            the task to be submitted. There may be certain restrictions of
+	 *            the task to be submitted.
+	 * @param parameters
+	 * @return All results are combined in one array. Should a server not return
+	 *         a result, the parallel programmer is responsible for handling
+	 *         <code>null</code> values inside the array.
+	 * @throws Throwable
+	 *             the Exceptions thrown on serverside!
+	 */
+	public Object[] runSPMDModelTask(SPMDTask task, Object... parameters)
+			throws Throwable;
+
+	/**
+	 * Here you can set the boxing mode. See {@link NeighborhoodBoxingMode}
+	 *
+	 * @param boxingMode
+	 *            the boxing mode
+	 */
+	public void setBoxingMode(AbstractSplitMap.NeighborhoodBoxingMode boxingMode);
+
+	/**
+	 * Sets the neighborhood range. From now on every splitting is done with the
+	 * given range. In most cases it should be called before any resources are
+	 * add to split control.
+	 *
+	 * @param neighborhoodRange
+	 *            the width of the neighborhood range (in cells)
+	 */
+	public void setNeighborhoodRange(int neighborhoodRange);
+
+	/**
+	 * All local bounds are calculated on server side using the reference
+	 * resource. If {@link SplittableResource splittable resources} of different
+	 * sizes or with different {@link SplitMap SplitMaps} are used, it is
+	 * possible to get the local bounds of an special resource using the
+	 * {@link SPMDServerController#getLocalCalculationBounds(appl.parallel.spmd.split.DataPartition)}
+	 * method of the SPMDServerController. <br>
+	 * <br>
+	 * If no reference resource is set, than the first call to
+	 * {@link #addToSplitControl(Object, String)} will set the reference.
+	 *
+	 * @param splittableResource
+	 *            the new reference resource (must be an instance of
+	 *            {@link SplittableResource})
+	 */
+	public void setReferenceResource(Object splittableResource);
+
+	/**
+	 * Signals to all participating servers to update the neighborhood and waits
+	 * until the update is finished.
+	 *
+	 * @param splittableResource
+	 *            (must be an instance of {@link SplittableResource}
+	 */
+	public void updateNeighborhood(Object splittableResource);
+
+	/**
+	 * Signals to all participating servers to update the neighborhood and waits
+	 * until the update is finished.
+	 *
+	 * @param multiDataObject
+	 *            the {@link MultiDataObject} to be updated
+	 * @param index
+	 *            the index of the partition to be updated
+	 */
+	public void updateNeighborhood(MultiDataObject multiDataObject, int index);
+
+}

Added: trunk/src/appl/parallel/spmd/SPMDServerController.java
===================================================================
--- trunk/src/appl/parallel/spmd/SPMDServerController.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/SPMDServerController.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,225 @@
+package appl.parallel.spmd;
+
+import java.awt.Rectangle;
+import java.rmi.RemoteException;
+import java.util.HashMap;
+import java.util.Vector;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import appl.parallel.ComputingResource;
+import appl.parallel.client.DataServer;
+import appl.parallel.data.WritableGridArrayPartition;
+import appl.parallel.model.AbstractParallelStepModel;
+import appl.parallel.server.PartitionDataManager;
+import appl.parallel.spmd.split.DataPartition;
+import appl.parallel.spmd.split.PartitionInfo;
+import appl.parallel.spmd.split.SplitMap;
+import appl.parallel.spmd.split.SplittableResource;
+
+/**
+ * This class controls all the parallelization action on the server side and is
+ * the counterpart to {@link SPMDClientController}. It is accessed by the model
+ * developer by retrieving the {@link SPMDServerInterface} from a
+ * {@link SPMDTask}.
+ * 
+ * @author Dominik Appl
+ */
+public class SPMDServerController implements SPMDServerInterface {
+
+	private Logger LOG = LogManager.getLogger(this.getClass().getName());
+
+	PartitionDataManager dataManager;
+	
+	private Rectangle localCalculationBounds;
+
+	private final SplitMap referenceSplitMap;
+
+	/**
+	 * the partition position (used for splitmaps)
+	 */
+	protected final int mapPosition;
+	
+	/**
+	 * Creates a new instance 
+	 * @param dataManager the partition data server responsible for managing the data on the server
+	 * @param referenceResouceID the id of the reference resource
+	 */
+	public SPMDServerController(PartitionDataManager dataManager,
+			int referenceResouceID) {
+		this.dataManager = dataManager;
+		// if there are any partitions the referenceID should be != -1
+		if (referenceResouceID != -1) {
+			referenceSplitMap = dataManager.getInfo(referenceResouceID)
+					.getSplitMap();
+			mapPosition = dataManager.getInfo(referenceResouceID)
+					.getSplitMapPos();
+		} else {
+			referenceSplitMap = null;
+			mapPosition = 0;
+		}
+		//setting the calculation bounds to the default area
+		localCalculationBounds=referenceSplitMap.getLocalCalculationBounds(mapPosition);
+	}
+	
+	/**
+	 * This method sets new calculation bounds. This is used to divide the rasters for 
+	 * parallel computation on one machine (using multiple cpu's or cpu cores)
+	 * 
+	 * @param newBounds the new calculation bounds
+	 */
+	public void setLocalCalculationBounds(Rectangle newBounds){
+		localCalculationBounds = newBounds;
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.SPMDServerInterface#getBaseParameter(java.lang.String)
+	 */
+	public Object getBaseParameter(String parameterName) {
+		Object returnValue =  dataManager.getBaseParameter(parameterName);
+		 if(returnValue==null)
+			 LOG.warn("No value for parameter '" + parameterName + "' found or value was null" );
+		 return returnValue;
+	}
+
+		
+
+	
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.SPMDServerInterface#getLocalCalculationBounds(appl.parallel.spmd.split.DataPartition)
+	 */
+	public Rectangle getLocalCalculationBounds(DataPartition partition) {
+		return dataManager.getInfo(partition.getRootID()).getSplitMap()
+				.getLocalCalculationBounds(mapPosition);
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.SPMDServerInterface#getLocalBounds(appl.parallel.spmd.split.DataPartition)
+	 */
+	public Rectangle getLocalBounds(DataPartition partition) {
+		PartitionInfo info = dataManager.getInfo(partition.getRootID());
+		return info.getSplitMap().getLocalBounds(mapPosition);
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.SPMDServerInterface#getGlobalBounds(appl.parallel.spmd.split.DataPartition)
+	 */
+	public Rectangle getGlobalBounds(DataPartition partition) {
+		PartitionInfo info = dataManager.getInfo(partition.getRootID());
+		return info.getSplitMap().getGlobalBounds();
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.SPMDServerInterface#getLocalCalculationBounds()
+	 */
+	public Rectangle getLocalCalculationBounds() {
+		return localCalculationBounds;
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.SPMDServerInterface#getLocalBounds()
+	 */
+	public Rectangle getLocalBounds() {
+		return referenceSplitMap.getLocalBounds(mapPosition);
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.SPMDServerInterface#getPartition(java.lang.String)
+	 */
+	public DataPartition getPartition(String name) {
+		DataPartition partition = dataManager.getData(name);
+		if (partition == null)
+			LOG.error("ERROR: The Partition with the name '" + name
+							+ "' was not found or was null");
+		return partition;
+	}
+	
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.SPMDServerInterface#getMultiPartition(java.lang.String)
+	 */
+	public DataPartition[] getMultiPartition(String name) {
+		DataPartition[] partitions = dataManager.getMultiData(name);
+		if (partitions == null)
+			LOG.error("ERROR: The Partition with the name '" + name
+							+ "' was not found or was null");
+//		if(partitions.length>0)
+//		  if(partitions[0] instanceof WritableGridArrayPartition.Float){
+//			WritableGridArrayPartition[] wgPartitions = new WritableGridArrayPartition[partitions.length];
+//			System.arraycopy(partitions, 0, wgPartitions, 0, partitions.length);
+//			return (DataPartition[]) wgPartitions;
+//		  }
+		return partitions;
+	}
+	
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.SPMDServerInterface#getMultiData(java.lang.String)
+	 */
+	public MultiDataObject getMultiData(String name){
+		MultiDataObject multiDataObject=null;
+		try {
+			multiDataObject = dataManager.getMultiDataObject(name);
+			if(multiDataObject==null)
+				LOG.warn("No Multidataobject with name '"  + name + "' found. Returning null!");
+		} catch (RemoteException e) {
+			// Should never be be called (local call)
+			e.printStackTrace();
+		}
+		return multiDataObject;
+	}
+	
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.SPMDServerInterface#getMultiPartition(java.lang.String, int)
+	 */
+	public DataPartition getMultiPartition(String name, int idx) {
+		DataPartition partition = dataManager.getMultiData(name,idx);
+		if (partition == null)
+			LOG.error("ERROR: The Partition with the name '" + name
+							+ "' was not found or was null");
+		return partition;
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.SPMDServerInterface#getLocalCalcMinX()
+	 */
+	public int getLocalCalcMinX() {
+		return (int) getLocalCalculationBounds().getX();
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.SPMDServerInterface#getLocalCalcMinY()
+	 */
+	public int getLocalCalcMinY() {
+		return (int) getLocalCalculationBounds().getY();
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.SPMDServerInterface#getLocalCalcMaxX()
+	 */
+	public int getLocalCalcMaxX() {
+		return (int) (getLocalCalculationBounds().getX()
+				+ getLocalCalculationBounds().getWidth() - 1);
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.SPMDServerInterface#getLocalCalcMaxY()
+	 */
+	public int getLocalCalcMaxY() {
+		return (int) (getLocalCalculationBounds().getY()
+				+ getLocalCalculationBounds().getHeight() - 1);
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.SPMDServerInterface#destroyData(java.lang.Object)
+	 */
+	public void destroyPartition(String name) {
+		dataManager.removeData(name);
+	}
+	
+	public void destroyMultiPartition(String name,int idx)
+	{
+		MultiDataObject multiData = this.getMultiData(name);
+		multiData.deleteElement(idx);
+	}
+
+}

Added: trunk/src/appl/parallel/spmd/SPMDServerInterface.java
===================================================================
--- trunk/src/appl/parallel/spmd/SPMDServerInterface.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/SPMDServerInterface.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,207 @@
+package appl.parallel.spmd;
+
+import java.awt.Rectangle;
+import java.util.HashMap;
+
+import edu.bonn.xulu.plugin.data.grid.GridList;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+
+import appl.parallel.ComputingResource;
+import appl.parallel.spmd.split.DataPartition;
+import appl.parallel.spmd.split.SplittableResource;
+
+/**
+ * Using this interface the programmer can access the parallel functionality on server side.
+ * The programmer should subclass {@link AbstractSPMDTask} and use its method {@link AbstractSPMDTask#getSPMDServerController()} to
+ * access the parallel control.
+ * @author Dominik Appl
+ */
+public interface SPMDServerInterface {
+
+	/**
+	 * Returns the base parameter with the specified id.
+	 *
+	 * @param parameterName the name of the parameter specified on client side
+	 * @return the base parameter
+	 *
+	 * @see SPMDClientInterface#addBaseParameter(Object, String)
+	 */
+	public Object getBaseParameter(String parameterName);
+
+	/**
+	 * Gives back the area which is actively used for read/write (in contrast
+	 * to neighborhood area, which is often accessed will be accessed read only).
+	 *
+	 * @param partition
+	 *            a partition for which the the bounds are requested
+	 * @return the calculation bounds in local coordinates (local means relative
+	 *         to the upper left corner of all available data)
+	 */
+	public Rectangle getLocalCalculationBounds(DataPartition partition);
+
+	/**
+	 * Gives back the area which is available for local access (including
+	 * Neighborhood)
+	 *
+	 * @param partition
+	 *            a partition for which the the bounds are requested
+	 * @return the calculation bounds in local coordinates - the upper left
+	 *         corner of the {@link Rectangle} will be (0,0)
+	 */
+	public Rectangle getLocalBounds(DataPartition partition);
+
+	/**
+	 * Gives back the global bounds, which are the bounds of all partitions over all servers.
+	 * To be clear: This are the bounds of the unsplitted data!
+	 * @param partition partition for which the bounds are queried
+	 * @return the global bounds
+	 */
+	public Rectangle getGlobalBounds(DataPartition partition);
+
+	/**
+	 * Gives back the area which is actively used for read/write (in contrast
+	 * to neighborhood area, which is often accessed will be accessed read only).
+	 *
+	 * @return the calculation bounds in local coordinates (local means relative
+	 *         to the upper left corner of all available data) of the reference
+	 *         resource (which is the first resource added to split-control on
+	 *         client side)
+	 *
+	 * @see SPMDClientController#addToSplitControl(Object, String)
+	 * @see SPMDClientController#setReferenceResource(Object)
+	 */
+	public Rectangle getLocalCalculationBounds();
+
+	/**
+	 * Gives back the area which is available for local access (including
+	 * Neighborhood)
+	 *
+	 * @return the calculation bounds in local coordinates of the reference
+	 *         resource (which is the first resource added to split-control on
+	 *         client side) - the upper left corner of the {@link Rectangle}
+	 *         will be (0,0)
+	 * @see SPMDClientController#addToSplitControl(Object, String)
+	 * @see SPMDClientController#setReferenceResource(Object)
+	 */
+	public Rectangle getLocalBounds();
+
+	/**
+	 * The whole {@link DataPartition} available for this task. In contrast to
+	 * {@link #getLocalCalculationBounds()} the neighborhood is included!
+	 *
+	 * @param name
+	 *            the name of the splittable
+	 * @return the partition of the resource which is available for local
+	 *         calculation
+	 * @see SPMDClientController#addToSplitControl(Object, String)
+	 */
+	public DataPartition getPartition(String name);
+
+	/**
+	 * Gets the array of {@link DataPartition DataPartitions} which were
+	 * submitted on client side via
+	 * {@link SPMDClientController#addToMultiDataSplitControl(Object[], String)}
+	 * All resources are retrieved from the data source and given back. If you
+	 * only need a specific resource you can use
+	 * {@link #getMultiPartition(String, int)} to avoid loading all data.
+	 *
+	 * @param name
+	 *            the name of the splittable
+	 * @return the partition of the resource which is available for local
+	 *         calculation
+	 * @see SPMDClientController#addToMultiDataSplitControl(Object[], String)
+	 * @see #getMultiPartition(String, int)
+	 */
+	public DataPartition[] getMultiPartition(String name);
+
+	/**
+	 * Gives back a MultiDataObject. A MultiDataObject can encapsulate multiple
+	 * objects and is especially intended for use with {@link GridList} and
+	 * {@link MultiGrid} types. See {@link MultiDataObject} for more details.
+	 *
+	 * @param name the name associated with the object on client side
+	 * @return the MDO
+	 */
+	public MultiDataObject getMultiData(String name);
+
+	/**
+	 * Gets a {@link DataPartition} which was submitted on client side via
+	 * {@link SPMDClientController#addToMultiDataSplitControl(Object[], String)}.
+	 * Only the grid with the index is returned. All other partitions are NOT
+	 * retrieved.
+	 *
+	 * @param name
+	 *            the name of the splittable
+	 * @param idx
+	 * @return the partition of the resource which is available for local
+	 *         calculation
+	 * @see SPMDClientController#addToMultiDataSplitControl(Object[], String)
+	 * @see #getMultiPartition(String)
+	 */
+	public DataPartition getMultiPartition(String name, int idx);
+
+	/**
+	 * Convenience method. Gets the coordinate out from the Rectangle which the
+	 * {@link #getLocalCalculationBounds()} returns
+	 *
+	 * @return the x-coordinate upperleft corner of the calcarea
+	 * @see SPMDServerController#getLocalCalculationBounds()
+	 * @see SPMDServerController#getLocalCalcMinX()
+	 * @see SPMDServerController#getLocalCalcMaxX()
+	 * @see SPMDServerController#getLocalCalcMinY()
+	 * @see SPMDServerController#getLocalCalcMaxY()
+	 */
+	public int getLocalCalcMinX();
+
+	/**
+	 * Convenience method. Gets the coordinate out from the Rectangle which the
+	 * {@link #getLocalCalculationBounds()} returns
+	 *
+	 * @return the y-coordinate upper left corner of the calculation area
+	 * @see SPMDServerController#getLocalCalculationBounds()
+	 * @see SPMDServerController#getLocalCalcMinX()
+	 * @see SPMDServerController#getLocalCalcMaxX()
+	 * @see SPMDServerController#getLocalCalcMinY()
+	 * @see SPMDServerController#getLocalCalcMaxY()
+	 */
+	public int getLocalCalcMinY();
+
+	/**
+	 * Convenience method. Gets the coordinate out from the Rectangle which the
+	 * {@link #getLocalCalculationBounds()} returns
+	 *
+	 * @return the x-coordinate lower right corner of the calculation area
+	 * @see SPMDServerController#getLocalCalculationBounds()
+	 * @see SPMDServerController#getLocalCalcMinX()
+	 * @see SPMDServerController#getLocalCalcMaxX()
+	 * @see SPMDServerController#getLocalCalcMinY()
+	 * @see SPMDServerController#getLocalCalcMaxY()
+	 */
+	public int getLocalCalcMaxX();
+
+	/**
+	 * Convenience method. Gets the coordinate out from the Rectangle which the
+	 * {@link #getLocalCalculationBounds()} returns
+	 *
+	 * @return the y-coordinate lower right corner of the calculation area
+	 * @see SPMDServerController#getLocalCalculationBounds()
+	 * @see SPMDServerController#getLocalCalcMinX()
+	 * @see SPMDServerController#getLocalCalcMaxX()
+	 * @see SPMDServerController#getLocalCalcMinY()
+	 * @see SPMDServerController#getLocalCalcMaxY()
+	 */
+	public int getLocalCalcMaxY();
+
+	/**
+	 * Removes the partition from memory. You may want to call {@link System#gc()} afterwards
+	 * @param name the name of the partition to remove
+	 */
+	public void destroyPartition(String name);
+
+	/**
+	 * Removes the partition from memory. You may want to call {@link System#gc()} afterwards
+	 * @param name the name of the multidata
+	 * @param idx the index of the partition to remove
+	 */
+	public void destroyMultiPartition(String name,int idx);
+}

Added: trunk/src/appl/parallel/spmd/SPMDTask.java
===================================================================
--- trunk/src/appl/parallel/spmd/SPMDTask.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/SPMDTask.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,89 @@
+package appl.parallel.spmd;
+
+import java.awt.Rectangle;
+import java.io.Serializable;
+
+import appl.parallel.server.XuluServer;
+
+import schmitzm.data.WritableGrid;
+
+/**
+ * A SPMDTask should be executed on servers using the SPMD-paradigm. 
+ * <br>
+ * The Task provides access to the {@link SPMDClientInterface} and the
+ * {@link AdvancedSPMDClientInterface}. <br>
+ * <br>
+ * @see AbstractSPMDTask for more details
+ * 
+ * @author Dominik Appl
+ */
+public interface SPMDTask extends Serializable {
+
+	/**
+	 * Gives access the {@link AdvancedSPMDServerInterface} for advanced parallel
+	 * programming, including performance optimizations like preloading.
+	 * @return the interface
+	 */
+	public AdvancedSPMDServerInterface getAdvancedSPMDServerController();
+
+	/**
+	 * Gives access the {@link SPMDServerInterface} for parallel programming.
+	 * 
+	 * @return the interface
+	 */
+	public SPMDServerInterface getSPMDServerController();
+
+	/**
+	 * Associates the given SPMDController with the task. Will be called e.g. by
+	 * the {@link XuluServer}.
+	 * 
+	 * @param controller
+	 */
+	public void setSPMDServerController(AdvancedSPMDServerInterface controller);
+
+	/**
+	 * Currently not used. May be used later when introducing write access on
+	 * neighborhood regions.
+	 * 
+	 * @param incomingGrid
+	 * @param location
+	 */
+	public void outgoingUpdate(WritableGrid incomingGrid, Rectangle location);
+
+	/**
+	 * Currently not used. May be used later when introducing write access on
+	 * neighborhood regions.
+	 * 
+	 * @param outgoingGrid
+	 * @param location
+	 */
+	public void incomingUpdate(WritableGrid outgoingGrid, Rectangle location);
+
+	/**
+	 * Starts the task with the given parameters. Overwrite this method to
+	 * implement the task.
+	 * 
+	 * @param parameters
+	 * @return the result of the task computation (if any)
+	 */
+	public Object run(Object... parameters);
+
+	/**
+	 * Initializes the task. Initializing is only done once!
+	 */
+	public void initialize();
+
+	/**
+	 * @return whether the task is initialized or {@link #initialize()} must be
+	 *         called
+	 */
+	public boolean isInitialized();
+
+	/**
+	 * If you want to support multiple processors, this method must return true.
+	 * 
+	 * @return whether multithreading can be used by this task
+	 */
+	public boolean supportsMultiThreading();
+
+}

Added: trunk/src/appl/parallel/spmd/SyncPoint.java
===================================================================
--- trunk/src/appl/parallel/spmd/SyncPoint.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/SyncPoint.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,91 @@
+package appl.parallel.spmd;
+
+/**
+ * Specifies details about a synchronization point. These points are used in
+ * the {@link AdvancedSPMDClientController} or {@link AdvancedSPMDServerController}
+ * as preloading-Points or multithread-barriers. They are associated with a priority. 
+ * 
+ * @author Dominik Appl
+ */
+public class SyncPoint {
+	
+	/**
+	 * A high priority means a high priority on operating system level. It should
+	 * be used by implementations of {@link AdvancedSPMDClientController} and {@link AdvancedSPMDServerController}
+	 * 
+	 * @author Dominik Appl
+	 */
+	public enum Priority
+	{
+		LOW(Thread.MIN_PRIORITY),
+		BELOW_NORMAL(Thread.NORM_PRIORITY-1),
+		NORMAL(Thread.NORM_PRIORITY),
+		ABOVE_NORMAL(Thread.NORM_PRIORITY+1),
+		HIGH(Thread.MAX_PRIORITY);
+		
+		private final int realPriorityNo;
+		
+		Priority(int realPriorityNo)
+		{
+		   this.realPriorityNo=realPriorityNo;
+		}
+		
+		/**
+		 * @return the priority
+		 */
+		public int getPriority(){
+			return realPriorityNo;
+		}
+		
+	}
+	private final int id;
+	private final Priority priority;
+
+	/**
+	 * Creates a new Sync-Point with normal priority
+	 * 
+	 * @param pointID a id for this syncPoint
+	 */
+	public SyncPoint(int pointID) {
+		this(pointID,Priority.NORMAL);
+	}
+	
+	/**
+	 * Creates a new Sync-Point with normal {@link Priority} (and with hashcode as id)
+	 */
+	public SyncPoint() {
+		this.id = this.hashCode();
+		this.priority = Priority.NORMAL;
+	}
+	
+	/**
+	 * @param id a id for the 
+	 * @param priority 
+	 */
+	public SyncPoint(int id, Priority priority ) {
+		this.id = id;
+		this.priority = priority;
+	}
+
+	/**
+	 * Creates a new Sync-Point with the given {@link Priority}
+	 */
+	public SyncPoint(Priority priority) {
+		id = this.hashCode();
+		this.priority = priority;
+	}
+
+	/**
+	 * @return the id
+	 */
+	public int getId() {
+		return id;
+	}
+
+	/**
+	 * @return the priority of the Thread (as system dependent for direct use in {@link Thread Threads})
+	 */
+	public int getPriority() {
+		return priority.getPriority();
+	}
+}

Added: trunk/src/appl/parallel/spmd/package.html
===================================================================
--- trunk/src/appl/parallel/spmd/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,5 @@
+<html>
+<body>
+	Contains classes related the the SPMD execution. 
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/parallel/spmd/split/AbstractSplitMap.java
===================================================================
--- trunk/src/appl/parallel/spmd/split/AbstractSplitMap.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/split/AbstractSplitMap.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,232 @@
+package appl.parallel.spmd.split;
+
+import java.awt.Rectangle;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * This class can be used for the implementation of {@link SplitMap}s. It already
+ * provides most of the functions. Normally subclasses only have to implement the methods
+ * {@link SplitMap#makeMap()} and {@link SplitMap#getNeighborsForPosition(int)}.
+ *
+ * @see SplitMap
+ *
+ * @author Dominik Appl
+ */
+public abstract class AbstractSplitMap implements SplitMap {
+
+	public enum NeighborhoodBoxingMode {
+		inBoxing, outBoxing
+	}
+
+	protected NeighborhoodBoxingMode boxingMode;
+	protected int noOfPartitions;
+	protected int globalHeight;
+	protected int globalWidth;
+
+	/**
+	 * a value of weights determines how big the share of the
+	 * partition with this position is. The sum of all values
+	 * should be 1 or near to 1.
+	 */
+	protected double[] weights;
+	protected int neighborhoodRange;
+
+	/** the Rectangle of the whole Grid **/
+	protected Rectangle globalBounds;
+	/** the calculation area of each partition */
+	protected Rectangle[] partitionCalculationBounds;
+	/** the bounds of the neighborhood data of the partition */
+	protected Rectangle[] partitionNeighborhoodBounds;
+    protected String[] IPs;
+
+	public AbstractSplitMap(SplittableResource splittable, int neighborhoodRange,
+			int noOfPartitions,
+			NeighborhoodBoxingMode boxingMode) {
+		this(splittable.getSplitWidth(),splittable.getSplitHeight(),neighborhoodRange, noOfPartitions, boxingMode);
+
+	}
+
+	public AbstractSplitMap() {
+		this.globalWidth = 1;
+		this.globalHeight = 1;
+		this.neighborhoodRange = 0;
+		this.noOfPartitions = 1;
+		this.boxingMode = NeighborhoodBoxingMode.inBoxing;
+		init();
+		makeMap();
+	}
+
+	 /**
+	 * @param width
+	 * @param height
+	 * @param neighborhoodRange
+	 * @param noOfPartitions
+	 * @param boxingMode
+	 */
+	public AbstractSplitMap(int width, int height, int neighborhoodRange, int noOfPartitions, NeighborhoodBoxingMode boxingMode) {
+		this.globalWidth = width;
+		this.globalHeight = height;
+		this.neighborhoodRange = neighborhoodRange;
+		this.noOfPartitions = noOfPartitions;
+		this.boxingMode = boxingMode;
+		init();
+		makeMap();
+	}
+
+	/* non java-doc
+	 * @see appl.parallel.spmd.split.SplitMap#setParameters(SplittableResource, int, int, appl.parallel.spmd.split.AbstractSplitMap.NeighborhoodBoxingMode)
+	 */
+	public void setParameters(SplittableResource splittable, int neighborhoodRange, int noOfPartitions, NeighborhoodBoxingMode boxingMode) {
+		this.globalWidth = splittable.getSplitWidth();
+		this.globalHeight = splittable.getSplitHeight();
+		this.neighborhoodRange = neighborhoodRange;
+		this.noOfPartitions = noOfPartitions;
+		this.boxingMode = boxingMode;
+		init();
+	}
+
+	/**
+	 * Initializes the bounds of the partitions
+	 */
+	protected void init() {
+		if (noOfPartitions < 1)
+			throw new UnsupportedOperationException(
+					"Number of Partions must be > 0");
+
+		//Initialize the weight for equal split (should not matter if not excactly 100%)
+		weights = new double[noOfPartitions];
+		for (int i = 0; i < noOfPartitions; i++)
+			weights[i] = (1.0 / noOfPartitions);
+		globalBounds = new Rectangle(0, 0, globalWidth, globalHeight);
+		partitionCalculationBounds = new Rectangle[noOfPartitions];
+		partitionNeighborhoodBounds = new Rectangle[noOfPartitions];
+
+	}
+
+
+
+	public void setWeights(double... weights) {
+		if (weights.length != noOfPartitions)
+			throw new UnsupportedOperationException("The number of weights ("
+					+ weights.length
+					+ ") does not match the number of partitions ("
+					+ noOfPartitions + ")");
+		//check if the weights are valid
+		for (double weight : weights) {
+			if(weight <=0 || weight > 1)
+				throw new UnsupportedOperationException("A weight was '" + weight + "' but must be between 0 and 1");
+		}
+		this.weights = weights;
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.SplitMap#getDescription()
+	 */
+	public abstract String getDescription();
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.SplitMap#getNeighborsForPosition(int)
+	 */
+	public abstract int[] getNeighborsForPosition(int pos);
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.SplitMap#makeMap()
+	 */
+	public abstract void makeMap();
+
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.SplitMap#getGlobalCalculationBounds()
+	 */
+	public Rectangle getGlobalCalculationBounds() {
+		return globalBounds;
+	}
+
+
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.SplitMap#getLocalCalculationArea(int)
+	 */
+	public Rectangle getLocalCalculationBounds(int pos){
+		Rectangle localBounds = (Rectangle) partitionCalculationBounds[pos].clone();
+		//move relative to the partition bounds
+		double xdiff=partitionCalculationBounds[pos].getX()-partitionNeighborhoodBounds[pos].getX();
+		double ydiff=partitionCalculationBounds[pos].getY()-partitionNeighborhoodBounds[pos].getY();
+		//set to the local coordinates
+		localBounds.setLocation((int) xdiff, (int) ydiff);
+		return localBounds;
+	}
+
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.SplitMap#getLocalNeighborhoodArea(int)
+	 */
+	public Rectangle getLocalNeighborhoodBounds(int pos) {
+		Rectangle localBounds = (Rectangle) partitionNeighborhoodBounds[pos]
+				.clone();
+		//move to (0,0)
+		localBounds.setLocation(0, 0);
+		return localBounds;
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.SplitMap#getPartitionCalculationArea(int)
+	 */
+	public Rectangle getPartitionCalculationBounds(int pos) {
+		return partitionCalculationBounds[pos];
+	}
+
+	public Rectangle getPartitionNeighborhoodBounds(int pos) {
+		return partitionNeighborhoodBounds[pos];
+	}
+
+
+	 /* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.SplitMap#getGlobalBounds()
+	 */
+	public Rectangle getGlobalBounds() {
+		return globalBounds;
+	}
+
+    /* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.SplitMap#getPartitionBounds(int)
+	 */
+	public Rectangle getPartitionBounds(int pos) {
+		return partitionNeighborhoodBounds[pos];
+	}
+
+	public Rectangle getLocalBounds(int pos)
+	{
+		return getLocalNeighborhoodBounds(pos);
+	}
+
+
+    /* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.SplitMap#getIP(int)
+	 */
+	public String getIP(int pos) {
+	  if(IPs==null)
+		  return null;
+	  if(IPs.length!=noOfPartitions)
+		  return null;
+	  return IPs[pos];
+	}
+
+    /* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.SplitMap#setIPs(java.lang.String[])
+	 */
+	public void setIPs(String[] IPs) {
+       this.IPs = IPs;
+	}
+
+    /**
+	 * @return the neighborhoodRange
+	 */
+	public int getNeighborhoodRange() {
+		return neighborhoodRange;
+	}
+
+	public int getCount(){
+		return noOfPartitions;
+	}
+}

Added: trunk/src/appl/parallel/spmd/split/DataPartition.java
===================================================================
--- trunk/src/appl/parallel/spmd/split/DataPartition.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/split/DataPartition.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,52 @@
+package appl.parallel.spmd.split;
+
+import java.awt.Rectangle;
+
+/**
+ * Represents a data partition. It has an id which identifies the resource, which is the mother
+ * of the partition.
+ *
+ * @author Dominik Appl
+ */
+public interface DataPartition {
+
+	/**
+	 * Returns the id of the super data structure this partition is a part of.
+	 * @return the id of the super data structure this partition is a part of.
+	 */
+	public int getRootID();
+
+	 /**
+	  * Returns the bounds of the partition as a rectangle. The coordinates
+	  * of the rectangle are global (which means relative to the root structure).
+	  * @return the bounds of the partition as a rectangle. The coordinates
+	  * of the rectangle are global (which means relative to the root structure).
+	 */
+	 public Rectangle getPartitionBounds();
+	 /**
+     * Returns the partition specified by the given {@link Rectangle}. Note, that
+     * partitioning by a rectangle does not mean, that the underlying datastructure
+     * has to be 2D, but only that the splitting has to be at max. 2D.
+     * @param partitionBounds the bounds of the partition which are to be retrieved
+     * in global coordinates (the coordinates should be relative to the root-structure)
+     */
+    public DataPartition getPartition(Rectangle partitionBounds);
+
+    /**
+     * Overwrites the data at the location specified by the {@link Rectangle} with
+     * the given partition-data.
+     *
+     * @param partition the new data
+     * @param partitionBounds the target location of the data (in coordinates of the root structure)
+     */
+    public void setPartition(DataPartition partition, Rectangle partitionBounds);
+
+	/**
+	 * Creates an empty Object with the given id. (Used e.g. by Multi-Data-Objects)
+	 * @param newID the id of the new Object
+	 * @return an Empty element with the same dimension as this element.
+	 */
+	public DataPartition getEmpty(int newID);
+
+
+}

Added: trunk/src/appl/parallel/spmd/split/PartitionInfo.java
===================================================================
--- trunk/src/appl/parallel/spmd/split/PartitionInfo.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/split/PartitionInfo.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,42 @@
+package appl.parallel.spmd.split;
+
+/**
+ * A {@link PartitionInfo} object contains information about the partition, which is
+ * normally transfered a server. It contains a {@link SplitMap} for the
+ * partition, the position inside the {@link SplitMap}, the name of the base
+ * resource (the mother resource) and a method which supports cloning the
+ * information.
+ * 
+ * @see SinglePartitionInfo
+ * 
+ * @author Dominik Appl
+ */
+public interface PartitionInfo extends Cloneable {
+
+	/**
+	 * @return the splitMap for this partition
+	 */
+	public abstract SplitMap getSplitMap();
+
+	/**
+	 * @return the splitMapPos position inside the {@link SplitMap}
+	 */
+	public abstract int getSplitMapPos();
+
+	/**
+	 * @return the baseResourceName the name of the base resource (mother resource). The name
+	 * is string which is the user provides for identification an retrieval on server side. 
+	 */
+	public abstract String getBaseResourceName();
+
+	/**
+	 * This method can especially be used by multi data methods to create a new instance of this 
+	 * data type
+	 * 
+	 * @param rootID the id of the base resource for the NEW copy of the {@link PartitionInfo}
+	 * 
+	 * @return the new {@link PartitionInfo}
+	 */
+	public abstract PartitionInfo clone(int rootID);
+
+}
\ No newline at end of file

Added: trunk/src/appl/parallel/spmd/split/SinglePartitionInfo.java
===================================================================
--- trunk/src/appl/parallel/spmd/split/SinglePartitionInfo.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/split/SinglePartitionInfo.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,104 @@
+package appl.parallel.spmd.split;
+
+import java.io.Serializable;
+
+import appl.data.DataLoader;
+import appl.parallel.data.PartitionDataHandler;
+
+// fuer Doku
+import javax.activation.DataHandler;
+import appl.parallel.client.DataServer;
+import appl.parallel.data.XuluClientLoader;
+
+/**
+ * This class collects the metadata of a partitioning
+ * The following information is encapsulated in a SinglePartitionInfo Object:
+ * <ul>
+ * <li>
+ * The <b>ID</b>of the {@link SplittableResource SplittableResource}
+ * </li>
+ * <li>The <b>baseResourceName</b> of the resource (given by the parallel programmer)</li>
+ * <li>The <b>{@link DataHandler}</b>, which loads the data of the partition. This is a very important aspect.
+ * The handler defines how the data is actually loaded. It may for example be loaded
+ * from a {@link DataServer} using a {@link XuluClientLoader}, but it may also be used
+ * to load data from local disk, databases etc. without communication with the client.
+ * The {@link DataHandler} is also responsible for writing the the data back to the source
+ * </li>
+ * <li>
+ * The <b>{@link SplitMap}</b> which represents the current partitioning.
+ * </li>
+ * <li>
+ * A <b>splitmap position</b>, which identifies the partition number in the split.
+ * </li>
+ *
+ * @author Dominik Appl
+ *
+ *
+ */
+public class SinglePartitionInfo implements Serializable, PartitionInfo{
+
+	private final int baseResourceID;
+    private final PartitionDataHandler handler;
+    private final SplitMap splitMap;
+    private final int splitMapPos;
+    private final String baseResourceName;
+
+    /**
+     * The constructor.
+     *
+     * @param baseResourceID the root id (see {@link DataPartition#getRootID()})
+     * @param baseResourceName the name of the resource (given by parallel programmer)
+     * @param handler {@link PartitionDataHandler}
+     * 			which is responsible for loading and unloading
+     * @param splitMap splitmap describing the partitioning
+     * @param splitMapPos the position inside the splitmap
+     */
+    public SinglePartitionInfo(int baseResourceID, String baseResourceName, PartitionDataHandler handler, SplitMap splitMap, int splitMapPos){
+        this.baseResourceID = baseResourceID;
+        this.baseResourceName = baseResourceName;
+        this.handler = handler;
+        this.splitMap = splitMap;
+        this.splitMapPos = splitMapPos;
+    }
+
+    /**
+	 * @return the baseResourceID
+	 */
+	public int getBaseResourceID() {
+		return baseResourceID;
+	}
+    /**
+	 * @return the handler
+	 */
+	public PartitionDataHandler getPartitionDataHandler() {
+		return handler;
+	}
+    /* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.PartitionInfo#getSplitMap()
+	 */
+	public SplitMap getSplitMap() {
+		return splitMap;
+	}
+    /* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.PartitionInfo#getSplitMapPos()
+	 */
+	public int getSplitMapPos() {
+		return splitMapPos;
+	}
+
+    /* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.PartitionInfo#getBaseResourceName()
+	 */
+	public String getBaseResourceName() {
+		return baseResourceName;
+	}
+
+	public PartitionInfo clone(int newRootID){
+		PartitionDataHandler clonedHandler = handler.clone();
+		clonedHandler.setRootID(newRootID);
+		return new SinglePartitionInfo(newRootID,
+				this.baseResourceName,clonedHandler,this.splitMap,
+				this.splitMapPos);
+	}
+
+}

Added: trunk/src/appl/parallel/spmd/split/SplitMap.java
===================================================================
--- trunk/src/appl/parallel/spmd/split/SplitMap.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/split/SplitMap.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,147 @@
+package appl.parallel.spmd.split;
+
+import java.awt.Rectangle;
+import java.io.Serializable;
+import java.net.InetAddress;
+
+import appl.parallel.spmd.split.SplittableResource;
+import appl.parallel.spmd.split.AbstractSplitMap.NeighborhoodBoxingMode;
+
+/**
+ * Defines a split map over a {@link SplittableResource}. A split map is a
+ * layout of an actual partitioning. Each partition is associated with a number,
+ * ranging from 0 to noOfPartitions-1.
+ * <br>
+ * The partitions are layouted as rectangles, where each rectangle represents a partition
+ * or a neighborhood around a partition. Every partition or neighborhood can be queried.
+ * IP-Addresses can be associated with partitions to identify the server on which a partition is located.
+ * <br>
+ * The interface is largely implementation independent. Multiple implementations exist.
+ *
+ * You can query the SplitMap for neighbors of a partition.
+ *
+ * @see SplitMap1DHorizontal
+ * @see SplitMap1DVertical
+ * @see SplitMap2D
+ * @see AbstractSplitMap
+ *
+ * @author Dominik Appl
+ */
+public interface SplitMap extends Serializable{
+
+	/**
+	 * returns an Array of neighbors for that position in the splitmap.
+	 *
+	 * @param pos position in splitmap
+	 * @return the array
+	 *
+	 */
+	int[] getNeighborsForPosition(int pos);
+
+
+	/**
+	 * With this setter, you can assign each partition a weight, so that
+	 * the data you split is not splitted equally, but arcording to
+	 * these values. A value of weights specifies how big the share of the
+	 * partition with this position is. The sum of all values
+	 * should be 1 or near to 1.
+	 *
+	 * @param weights
+	 * @throws UnsupportedOperationException if the number of weights does
+	 * not match the number of partitions
+	 */
+	public void setWeights(double... weights);
+
+	/**
+	 * @return a short description of the type of the Splitting
+	 */
+	public String getDescription();
+
+	/**
+	 * @param pos the partition number
+	 * @return the bounds of the partiton calculation area in global coordinates
+	 */
+	public Rectangle getPartitionCalculationBounds(int pos);
+
+	/**
+	 * @param pos the partition number
+	 * @return the bounds of the partiton neighborhood area in global coordinates
+	 */
+	public Rectangle getPartitionNeighborhoodBounds(int pos);
+
+	/**
+	 * @param pos the partition number
+	 * @return  the bounds of the partiton in global coordinates,
+	 * 			which should be the same as {@link #getPartitionNeighborhoodBounds(int)}
+	 *
+	 */
+	public Rectangle getPartitionBounds(int pos);
+
+
+	/**
+	 * @return {@link #getGlobalBounds()}
+	 */
+	public Rectangle getGlobalCalculationBounds();
+
+	/**
+	 * @return the bounds of the whole area starting with 0,0 in the topleft corner
+	 */
+	public Rectangle getGlobalBounds();
+
+	/**
+	 * Gets the whole partition bounds (including available neighborhood)
+	 * @param pos the partition number
+	 * @return the bounds of the partition using local coordinates. (0,0) is the topleft corner.
+	 */
+	public Rectangle getLocalBounds(int pos);
+	/**
+	 * @param pos the partition number
+	 * @return the calculation bounds of the partition using local coordinates.
+	 */
+	public Rectangle getLocalCalculationBounds(int pos);
+	/**
+	 * @param pos the partition number
+	 * @return the bounds of the partition using local coordinates. (0,0) is the topleft corner.
+	 */
+	public Rectangle getLocalNeighborhoodBounds(int pos);
+
+
+	/**
+	 * Sets the given values. Call makeMap() for this changes to take effekt.
+	 *
+	 * @param splittable the resource on which the splitmap is calculated
+	 * @param neighborhoodRange the neighborhoodrange
+	 * @param noOfPartitions the number of partitions to be generated
+	 * @param boxingMode the boxing mode
+	 *
+	 */
+	public void setParameters(SplittableResource splittable, int neighborhoodRange,
+			int noOfPartitions,
+			NeighborhoodBoxingMode boxingMode);
+
+	/**
+	 * @param IPs a String Array of IPs which are mapped to the partition in the given order.
+	 *
+	 */
+	public void setIPs(String IPs[]);
+	/**
+	 * @param pos position for this splitmap
+	 * @return the IP associated with this position
+	 */
+	public String getIP(int pos);
+
+	 /**
+	 * @return the neighborhoodRange
+	 */
+	public int getNeighborhoodRange();
+
+	/**
+	 * Creates the map
+	 */
+	public void makeMap();
+
+	/**
+	 * @return the number of partitions
+	 */
+	public int getCount();
+}

Added: trunk/src/appl/parallel/spmd/split/SplitMap1DHorizontal.java
===================================================================
--- trunk/src/appl/parallel/spmd/split/SplitMap1DHorizontal.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/split/SplitMap1DHorizontal.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,132 @@
+package appl.parallel.spmd.split;
+
+import java.awt.Rectangle;
+import java.awt.geom.Rectangle2D;
+
+import appl.parallel.spmd.split.AbstractSplitMap.NeighborhoodBoxingMode;
+import appl.util.RasterMetaData;
+import schmitzm.data.WritableGrid;
+
+/**
+ * Responsible for splitting a 2D Area (e.g a {@link WritableGrid}) in a 
+ * 1D fashion, which means in this case horizontal (by rows). This is only a
+ * a virtual split (a map of a split). 
+ * 
+ * A neighborhood range can be specified to create partitions that
+ * overlap each other. This overlapping can be done in two different
+ * ways: <br><br>
+ * 
+ * <b>Inboxing</b>(default):<br><br>
+ * Inboxing means, that the neighborhood area is not part of the calculation
+ * area. 
+ * <br> <br>
+ * <b>Outboxing:</b><br>
+ * Outboxing means that the neighborhood area is part of the calculation area.
+ *  <br> <br>
+ * 
+ *
+ * Note that this class is flexible. It may also be applied 
+ * to one dimensional data structures like for example arrays. 
+ * If u want to do this, simply choose one of the dimensions as 1. <br>
+ * 
+ * @author Dominik Appl
+ */
+
+public class SplitMap1DHorizontal extends AbstractSplitMap implements SplitMap {
+
+
+
+	public SplitMap1DHorizontal(int width, int height, int neighborhoodRange, int noOfPartitions,
+			NeighborhoodBoxingMode boxingMode) {
+		
+		super(width,height,neighborhoodRange, noOfPartitions, boxingMode);
+	}
+	
+
+	/**
+	 * needed for serialization
+	 */
+	public SplitMap1DHorizontal(){
+		
+	}
+	
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.DataSplitter#getDescription()
+	 */
+	public String getDescription() {
+		return "1D-GridSplitter";
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.DataSplitter#split(appl.parallel.spmd.split.SplittableRessource)
+	 */
+	public void makeMap() {
+			//the local calculation area is partitioned
+			int nextUpperLeftCorner = (int) globalBounds.getY(); //next y-value (will be 0)
+			for (int i = 0; i < noOfPartitions; i++) {
+				
+				//calculate length based on weights
+				int pHeight = (int) (globalBounds.getHeight() * weights[i]);
+				
+				//for the last position make sure, that ALL data is used 
+				//and no line is lost due to rounding errors in weight calculation
+				if(i==noOfPartitions-1)
+					pHeight = (int) globalBounds.getHeight() - nextUpperLeftCorner;
+				
+				//create inboxing(!) partition 
+				partitionCalculationBounds[i] = new Rectangle(
+						(int) globalBounds.getX(), nextUpperLeftCorner, (int)globalBounds.getWidth(),
+						pHeight);
+				
+				//if there is only one partition there are no explicit neighborhood bounds
+				if(noOfPartitions==1)
+					partitionNeighborhoodBounds[i]=partitionCalculationBounds[i];
+				//else simply calculate the neighborhood bounds out of the previosly 
+				//created calculation Area (@see AbstractSplitMap)
+				else 
+					partitionNeighborhoodBounds[i] = new Rectangle(
+							(int) globalBounds.getX(),
+							(int) partitionCalculationBounds[i].getY() - neighborhoodRange,
+							(int)(partitionCalculationBounds[i].getWidth()),
+						    (int)(partitionCalculationBounds[i].getHeight()+ 2 * neighborhoodRange));
+				
+			    //the first and the last partition have a neighborhood area only on one side of 
+			    //the calculation area:
+			    partitionNeighborhoodBounds[i] = partitionNeighborhoodBounds[i].intersection(globalBounds);
+				nextUpperLeftCorner += pHeight; //+1 not required - the partitions will not overlap
+				
+				//the partitionCalculation bounds were created for inboxing:
+				if(boxingMode==NeighborhoodBoxingMode.outBoxing)
+					partitionCalculationBounds[i]=partitionNeighborhoodBounds[i];			
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.SplitMap#getNeighborsForPosition(int)
+	 */
+	public int[] getNeighborsForPosition(int pos) {
+		int[] oneReturn = new int[1];
+		int[] twoReturns = new int[2];
+
+		//this is very simple in one 1D case, of course:
+		//if only one Partition return null
+		if (noOfPartitions == 1)
+			return new int[0];
+		
+		//for first partition
+		if ((pos == 0)) {
+			oneReturn[0] = 1;
+			return oneReturn;
+		}
+		//for last partition
+		if (pos == noOfPartitions - 1) {
+			oneReturn[0] = noOfPartitions - 2;
+			return oneReturn;
+		}
+		//for every other partition
+		twoReturns[0] = pos - 1;
+		twoReturns[1] = pos + 1;
+		return twoReturns;
+	}
+
+}

Added: trunk/src/appl/parallel/spmd/split/SplitMap1DVertical.java
===================================================================
--- trunk/src/appl/parallel/spmd/split/SplitMap1DVertical.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/split/SplitMap1DVertical.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,139 @@
+package appl.parallel.spmd.split;
+
+import java.awt.Rectangle;
+import java.awt.geom.Rectangle2D;
+
+import appl.parallel.spmd.split.AbstractSplitMap.NeighborhoodBoxingMode;
+import appl.util.RasterMetaData;
+import schmitzm.data.WritableGrid;
+
+/**
+ * Responsible for splitting a 2D Area (e.g a {@link WritableGrid}) in a 
+ * 1D fashion, which means in this case vertical (by cols). This is only a
+ * a virtual split (a map of a split). 
+ * 
+ * A neighborhood range can be specified to create partitions that
+ * overlap each other. This overlapping can be done in two different
+ * ways: <br><br>
+ * 
+ * <b>Inboxing</b>(default):<br><br>
+ * Inboxing means, that the neighborhood area is not part of the calculation
+ * area. 
+ * <br> <br>
+ * <b>Outboxing:</b><br>
+ * Outboxing means that the neighborhood area is part of the calculation area.
+ *  <br> <br>
+ * 
+ *
+ * Note that this class is flexible. It may also be applied 
+ * to one dimensional data structures like for example arrays. 
+ * If u want to do this, simply choose one of the dimensions as 1. <br>
+ * 
+ * @author Dominik Appl
+ */
+
+public class SplitMap1DVertical extends AbstractSplitMap implements SplitMap {
+
+	
+//	public SplitMap1DVertical(SplittableResource splittable, int neighborhoodRange, int noOfPartitions,
+//			NeighborhoodBoxingMode boxingMode) {
+//		
+//		super(splittable,neighborhoodRange, noOfPartitions, boxingMode);
+//	}
+	
+
+	public SplitMap1DVertical(int width, int height, int neighborhoodRange, int noOfPartitions,
+			NeighborhoodBoxingMode boxingMode) {
+		
+		super(width,height,neighborhoodRange, noOfPartitions, boxingMode);
+	}
+	
+
+	/**
+	 * needed for serialization
+	 */
+	public SplitMap1DVertical(){
+		
+	}
+	
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.DataSplitter#getDescription()
+	 */
+	public String getDescription() {
+		return "1D-GridSplitter";
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.DataSplitter#split(appl.parallel.spmd.split.SplittableRessource)
+	 */
+	public void makeMap() {
+			//the local calculation area is partitioned
+			int nextUpperLeftCorner = (int) globalBounds.getX(); //next x-value (will be 0)
+			for (int i = 0; i < noOfPartitions; i++) {
+				
+				//calculate length based on weights
+				int pWidth = (int) (globalBounds.getWidth() * weights[i]);
+				
+				//for the last position make sure, that ALL data is used 
+				//and no line is lost due to rounding errors in weight calculation
+				if(i==noOfPartitions-1)
+					pWidth = (int) globalBounds.getWidth() - nextUpperLeftCorner;
+				
+				//create inboxing(!) partition 
+				partitionCalculationBounds[i] = new Rectangle(
+						nextUpperLeftCorner, (int) globalBounds.getY(), pWidth,
+						(int) globalBounds.getHeight());
+				
+				//if there is only one partition there are no explicit neighborhood bounds
+				if(noOfPartitions==1)
+					partitionNeighborhoodBounds[i]=partitionCalculationBounds[i];
+				//else simply calculate the neighborhood bounds out of the previosly 
+				//created calculation Area
+				else 
+					partitionNeighborhoodBounds[i] = new Rectangle(
+						(int)partitionCalculationBounds[i].getX() - neighborhoodRange,
+						(int) globalBounds.getY(),
+						(int)(partitionCalculationBounds[i].getWidth() + 2 * neighborhoodRange),
+						(int)(partitionCalculationBounds[i].getHeight()));
+				
+			    //the first and the last partition have a neighborhood area only on one side of 
+			    //the calculation area:
+			    partitionNeighborhoodBounds[i] = partitionNeighborhoodBounds[i].intersection(globalBounds);
+				nextUpperLeftCorner += pWidth; //+1 not required - the partitions will not overlap
+				
+				//the partitionCalculation bounds were created for inboxing:
+				if(boxingMode==NeighborhoodBoxingMode.outBoxing)
+					partitionCalculationBounds[i]=partitionNeighborhoodBounds[i];
+				
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.split.SplitMap#getNeighborsForPosition(int)
+	 */
+	public int[] getNeighborsForPosition(int pos) {
+		int[] oneReturn = new int[1];
+		int[] twoReturns = new int[2];
+
+		//this is very simple in one 1D case, of course:
+		//if only one Partition return null
+		if (noOfPartitions == 1)
+			return new int[0];
+		
+		//for first partition
+		if ((pos == 0)) {
+			oneReturn[0] = 1;
+			return oneReturn;
+		}
+		//for last partition
+		if (pos == noOfPartitions - 1) {
+			oneReturn[0] = noOfPartitions - 2;
+			return oneReturn;
+		}
+		//for every other partition
+		twoReturns[0] = pos - 1;
+		twoReturns[1] = pos + 1;
+		return twoReturns;
+	}
+
+}

Added: trunk/src/appl/parallel/spmd/split/SplitMap2D.java
===================================================================
--- trunk/src/appl/parallel/spmd/split/SplitMap2D.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/split/SplitMap2D.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,210 @@
+package appl.parallel.spmd.split;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.geom.Rectangle2D;
+import java.util.Vector;
+
+import appl.parallel.client.RemoteExecutionController;
+import appl.parallel.spmd.split.AbstractSplitMap.NeighborhoodBoxingMode;
+import appl.parallel.util.Helper;
+import appl.util.RasterMetaData;
+import schmitzm.data.WritableGrid;
+
+/**
+ * Responsible for splitting a 2D Area (e.g a {@link WritableGrid}) in a 2D
+ * fashion. The splitting is irregular, meaning that the rectangles are not
+ * equally sized, but partitioned according to the given weights. 
+ * Splitting is as follows: <br><br>
+ * 1 to 4 Partitions: 1 row <br>
+ * 4 to 8 Partitions: 2 rows <br>
+ * 9 to 15 Partitions: 3 rows <br>
+ * and so on (depending on the square root of the partititons)<br>
+ * <br>
+ * For partitioning the this class strongly depends on {@link SplitMap1DHorizontal}
+ * and {@link SplitMap1DVertical}. First the squareroot of the number of
+ * participating resources is taken to determine how many rows should be
+ * created. After this the height of the rows is weighted by adding the weight
+ * of the resources in that horizontal partition. The Grid is then splitted
+ * horizontal. Finally the horizontal partitions are splitted vertical according
+ * to the relative weight to each other. This is only a a virtual split (a map
+ * of a split). <br>
+ * A neighborhood range can be specified to create partitions that overlap each
+ * other. This overlapping can be done in two different ways: <br>
+ * <br>
+ * <b>Inboxing</b>(default):<br>
+ * <br>
+ * Inboxing means, that the neighborhood area is not part of the calculation
+ * area. <br>
+ * <br>
+ * <b>Outboxing:</b><br>
+ * Outboxing means that the neighborhood area is part of the calculation area.
+ * <br>
+ * <br>
+ * Note that this may also be applied to three dimensional data structures (a 2D
+ * splitting of a 3D datatype).
+ * 
+ * @author Dominik Appl
+ */
+
+public class SplitMap2D extends AbstractSplitMap implements SplitMap {
+
+	private SplitMap1DHorizontal horizontalMap;
+
+	private SplitMap1DVertical[] verticalMaps;
+
+	public SplitMap2D(int width, int height, int neighborhoodRange,
+			int noOfPartitions, NeighborhoodBoxingMode boxingMode) {
+		super(width, height, neighborhoodRange, noOfPartitions, boxingMode);
+	}
+
+	/**
+	 * needed for serialization
+	 */
+	public SplitMap2D() {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.spmd.split.AbstractSplitMap#makeMap()
+	 */
+	public void makeMap() {
+		// take the squareroot of the number of participating resources to
+		// determine the number of rows:
+		int noOfRows = (int) Math.sqrt(noOfPartitions);
+		// calculate weights for the rows (sum of the weights of the partitions
+		// inside that row)
+		double rowWeights[] = new double[noOfRows];
+		int noOfCols[] = new int[noOfRows]; // noOfCols per row
+		for (int row = 0; row < noOfRows; row++) {
+			// calculate no. of cols in the row:
+			noOfCols[row] = (noOfPartitions / noOfRows);
+			// the last row may contain a greater number of cols
+			if (row == noOfRows - 1)
+				noOfCols[row] = noOfPartitions
+						- ((noOfRows - 1) * noOfCols[row]);
+			for (int col = 0; col < noOfCols[row]; col++)
+				rowWeights[row] += weights[row * col + col];
+		}
+
+		// create the horizontal Splitmap
+		horizontalMap = new SplitMap1DHorizontal(globalWidth, globalHeight,
+				neighborhoodRange, noOfRows, boxingMode);
+		horizontalMap.setWeights(rowWeights);
+		horizontalMap.makeMap();
+
+		// for each horizontal partition create a vertical split
+		verticalMaps = new SplitMap1DVertical[noOfRows];
+		for (int row = 0; row < noOfRows; row++) {
+			//notice: all splitmaps start at (0,0), later a conversion must be made
+			verticalMaps[row] = new SplitMap1DVertical((int) horizontalMap
+					.getGlobalBounds().getWidth(), (int) horizontalMap
+					.getPartitionCalculationBounds(row).getHeight(), neighborhoodRange,
+					noOfCols[row], boxingMode);
+			int ratings[] = new int[noOfCols[row]];
+			for (int col = 0; col < noOfCols[row]; col++) {
+				{
+					// the rating of the col is the weight of the col * 100000
+					// (ratings must be positive integers)
+					ratings[col] = (int) (weights[row * col + col] * 1000000);
+
+				}
+
+				verticalMaps[row].setWeights(Helper.calculateWeights(ratings));
+				verticalMaps[row].makeMap();
+			}
+		}
+		// now we have partitioned the grid. Lets assign the calculation and
+		// neighborhoodareas:
+		for (int i = 0; i < noOfPartitions; i++) {
+			int row = getRowForIdx(i);
+			int col = getColForIdx(i);
+			partitionCalculationBounds[i] = verticalMaps[row]
+					.getPartitionCalculationBounds(col);
+			//because all splitmaps start with (0,0) we must move 
+			//the rectangles to the right position
+			int x = (int) partitionCalculationBounds[i].getX(); //the x value remains unchanged
+			partitionCalculationBounds[i].setLocation(
+					new Point(x,(int) horizontalMap.getPartitionCalculationBounds(row).getY()));
+			// if there is only one partition there are no explicit neighborhood
+			// bounds
+			if (noOfPartitions == 1)
+				partitionNeighborhoodBounds[i] = partitionCalculationBounds[i];
+			// else simply extend the Rectangle with the Neighborhoodbounds
+			// created calculation Area (@see AbstractSplitMap)
+			else
+				partitionNeighborhoodBounds[i] = new Rectangle(
+						(int) partitionCalculationBounds[i].getX()
+								- neighborhoodRange,
+						(int) partitionCalculationBounds[i].getY()
+								- neighborhoodRange,
+						(int) (partitionCalculationBounds[i].getWidth() + 2 * neighborhoodRange),
+						(int) (partitionCalculationBounds[i].getHeight() + 2 * neighborhoodRange));
+
+			// cut of the obverlapping sections which are out of the grid:
+			partitionNeighborhoodBounds[i] = partitionNeighborhoodBounds[i]
+					.intersection(globalBounds);
+
+			// the partitionCalculation bounds were created for inboxing:
+			if (boxingMode == NeighborhoodBoxingMode.outBoxing)
+				partitionCalculationBounds[i] = partitionNeighborhoodBounds[i];
+		}
+	}
+
+	/**
+	 * @param i
+	 * @return
+	 */
+	private int getColForIdx(int index) {
+		int noOfRows = (int) Math.sqrt(noOfPartitions);
+		int avgNoOfCols = noOfPartitions / noOfRows;
+		int currentRow = getRowForIdx(index);
+		int returnValue = (index - currentRow*avgNoOfCols);
+		return returnValue;
+	}
+
+	private int getRowForIdx(int index) {
+		int noOfRows = (int) Math.sqrt(noOfPartitions);
+		int avgNoOfCols = noOfPartitions / noOfRows;
+		int returnValue = index / avgNoOfCols;
+		//special handling for the last row (contains more partitions)
+		if(noOfRows==returnValue)
+			return noOfRows-1;
+		else return returnValue;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.spmd.split.SplitMap#getNeighborsForPosition(int)
+	 */
+	public int[] getNeighborsForPosition(int pos) {
+		Vector neighbors = new Vector();
+		// simply intersect with all partitions to find the neighbors:
+		for (int i = 0; i < noOfPartitions; i++) {
+			if (i == pos)
+				continue;
+			if (partitionNeighborhoodBounds[i]
+					.intersects(partitionNeighborhoodBounds[pos]))
+				neighbors.add(pos);
+		}
+		int results[] = new int[neighbors.size()];
+		// copy into array
+		for (int i = 0; i < results.length; i++) {
+			results[i] = (Integer) neighbors.get(i);
+		}
+		return results;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.spmd.split.AbstractSplitMap#getDescription()
+	 */
+	@Override
+	public String getDescription() {
+		return "2D-irregular Splitmap";
+	}
+
+}

Added: trunk/src/appl/parallel/spmd/split/SplittableGrid.java
===================================================================
--- trunk/src/appl/parallel/spmd/split/SplittableGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/split/SplittableGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,14 @@
+package appl.parallel.spmd.split;
+
+import java.awt.Rectangle;
+
+import schmitzm.data.WritableGrid;
+
+/**
+ * A grid that is {@link SplittableResource splittable}
+ * 
+ * @author Dominik Appl
+ */
+public interface SplittableGrid extends SplittableResource, WritableGrid{
+	
+}

Added: trunk/src/appl/parallel/spmd/split/SplittableResource.java
===================================================================
--- trunk/src/appl/parallel/spmd/split/SplittableResource.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/split/SplittableResource.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,47 @@
+package appl.parallel.spmd.split;
+
+import java.awt.Rectangle;
+
+import org.w3c.dom.css.Rect;
+
+import appl.data.DataLoader;
+
+/**
+ * A resource that is splittable must provide some information to work with {@link SplitMap}s.
+ * Important is the with and the height of the resource to be splitted.
+ *
+ *
+ * @author Dominik Appl
+ */
+public interface SplittableResource extends DataPartition {
+	/**
+	 * Should return a unique ID for this resource. Standard implementation
+	 * would be returning the {@link Object#hashCode() hashcode} of the object.
+	 *
+	 * @return a ID which is unique for this client
+	 *
+	 */
+	public int getRootID();
+
+	/**
+	 * Returns the loader which is responible for loading the data. This loader should be
+	 * independet from the current system. This means that, e.g. for a loader which
+	 * loads a grid from filesystem, that all paths should be relative (and not
+	 * absolute), so that a possibly remote resource can load the data from its local
+	 * filesystem, if the data is stored in the same position relative to the home
+	 * directory.
+	 *
+	 * @return a loader for this resource.
+	 */
+	public DataLoader getLocalLoader();
+
+	/**
+	 * @return the splittable is splitted according to its splitHeight (example: the height of a raster)
+	 * */
+	public int getSplitHeight();
+
+	/**
+	 * @return the splittable is splitted according to its splitWidth  (example: the width of a raster or the length of an array)
+	 * */
+	public int getSplitWidth();
+}

Added: trunk/src/appl/parallel/spmd/split/WritableGridPartition.java
===================================================================
--- trunk/src/appl/parallel/spmd/split/WritableGridPartition.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/split/WritableGridPartition.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,12 @@
+package appl.parallel.spmd.split;
+
+import schmitzm.data.WritableGrid;
+
+/**
+ * A {@link DataPartition} that is splittable itself.
+ * 
+ * @author Dominik Appl
+ */
+public interface WritableGridPartition extends DataPartition, WritableGrid {
+
+}

Added: trunk/src/appl/parallel/spmd/split/package.html
===================================================================
--- trunk/src/appl/parallel/spmd/split/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/spmd/split/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,5 @@
+<html>
+<body>
+	Contains classes related to the data splitting during spmd-execution.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/parallel/starter/Starter.java
===================================================================
--- trunk/src/appl/parallel/starter/Starter.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/starter/Starter.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,40 @@
+package appl.parallel.starter;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+/**
+ * An interface for programs which start themself other programs as separate
+ * processes. It is possible to start/stop and restart the encapsulated process.
+ * 
+ * @author Dominik Appl
+ */
+
+public interface Starter extends Remote {
+	/**
+	 * Starts the process
+	 * 
+	 * @throws RemoteException
+	 */
+	public void start() throws RemoteException;
+
+	/**
+	 * stops the process
+	 * 
+	 * @throws RemoteException
+	 */
+	public void stop() throws RemoteException;
+
+	/**
+	 * restarts the process
+	 * 
+	 * @throws RemoteException
+	 */
+	public void restart() throws RemoteException;
+
+	/**
+	 * @return true, if the process is running
+	 * @throws RemoteException
+	 */
+	public boolean isRunning() throws RemoteException;
+}

Added: trunk/src/appl/parallel/starter/client/StarterClientGUI.java
===================================================================
--- trunk/src/appl/parallel/starter/client/StarterClientGUI.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/starter/client/StarterClientGUI.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,48 @@
+package appl.parallel.starter.client;
+
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import javax.swing.JFrame;
+
+import org.apache.log4j.BasicConfigurator;
+
+import appl.parallel.starter.Starter;
+
+/**
+ * This is a GUI for controlling the {@link Starter Starters} in the network.
+ * It has options to start/stop and restart selected servers.
+ * @author Dominik Appl
+ *
+ */
+public class StarterClientGUI extends JFrame {
+	/**
+	 * Creates a new GUI
+	 */
+	public StarterClientGUI() {
+		super("Server starter");
+		this.getContentPane().add(new XuluStarterController().getPanel());
+		this.setSize(300, 400);
+		this.addWindowListener(new ExitListener());
+	}
+
+	/**
+	 * @param args no arguments interpreted
+	 */
+	public static void main(String[] args) {
+		BasicConfigurator.configure();
+		StarterClientGUI clientGUI = new StarterClientGUI();
+		clientGUI.setVisible(true);
+	}
+
+	/**
+	 * Shuts down the application on exit
+	 * 
+	 * @author Dominik Appl
+	 */
+	public class ExitListener extends WindowAdapter {
+		public void windowClosing(WindowEvent event) {
+			System.exit(0);
+		}
+	}
+}

Added: trunk/src/appl/parallel/starter/client/StarterContainer.java
===================================================================
--- trunk/src/appl/parallel/starter/client/StarterContainer.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/starter/client/StarterContainer.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,49 @@
+package appl.parallel.starter.client;
+
+import java.rmi.RemoteException;
+
+import appl.parallel.starter.Starter;
+
+/**
+ * Just a small container class used e.g. in the
+ * {@link XuluStarterControllerFrame} for display
+ * 
+ * @author Dominik Appl
+ */
+public class StarterContainer {
+	private final Starter starter;
+
+	private boolean isRunning;
+
+	private final String hostInfo;
+
+	/**
+	 * A Container for use in SwingComponents. The status ({@link #isServerRunning()}
+	 * is only the status at the creation of the object!
+	 * 
+	 * @param starter
+	 *            The encapsulated Starter
+	 * @param hostInfo
+	 */
+	public StarterContainer(Starter starter, String hostInfo) {
+		this.starter = starter;
+		this.hostInfo = hostInfo;
+		try {
+			isRunning = starter.isRunning();
+		} catch (RemoteException e) {
+			isRunning = false;
+		}
+	}
+
+	public boolean isServerRunning() {
+		return isRunning;
+	}
+
+	public Starter getStarter() {
+		return starter;
+	}
+
+	public String toString() {
+		return hostInfo;
+	}
+}

Added: trunk/src/appl/parallel/starter/client/XuluStarterClientPanel.java
===================================================================
--- trunk/src/appl/parallel/starter/client/XuluStarterClientPanel.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/starter/client/XuluStarterClientPanel.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,224 @@
+package appl.parallel.starter.client;
+
+import javax.swing.JPanel;
+import java.awt.GridBagLayout;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.BoxLayout;
+import javax.swing.ListSelectionModel;
+import java.awt.Insets;
+import javax.swing.border.SoftBevelBorder;
+import javax.swing.table.DefaultTableModel;
+import edu.bonn.xulu.XuluModellingPlatform;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+
+import appl.parallel.gui.ParallelControlPanelEngine;
+
+import java.awt.Rectangle;
+import javax.swing.JList;
+import java.awt.CardLayout;
+import java.awt.GridLayout;
+
+/**
+ * The GUI for the XuluStarterController . The events are controlled by the
+ * {@link XuluStarterController}. This GUI was created with the Visual Editor
+ * plugin for eclipse and should be edited using this VE.
+ * 
+ * @author Dominik Appl
+ */
+public class XuluStarterClientPanel extends JPanel {
+
+	static final long serialVersionUID = 1L;
+
+	JPanel executionPanel = null;
+
+	JLabel Steps = null;
+
+	JScrollPane jScrollPane1 = null;
+
+	JPanel buttonPanel = null;
+
+	JList serverList = null;
+
+	JButton refreshButton = null;
+
+	JButton startButton = null;
+
+	JButton stopButton = null;
+
+	JButton restartButton = null;
+
+	/**
+	 * This is the default constructor. It should be only used be the eclipse VE
+	 */
+	public XuluStarterClientPanel() {
+		super();
+		initialize();
+	}
+
+	/**
+	 * This method initializes this
+	 * 
+	 * @return void
+	 */
+	private void initialize() {
+		this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
+		this.setSize(248, 292);
+		this.add(getExecutionPanel(), null);
+	}
+
+	/**
+	 * This method initializes executionPanel
+	 * 
+	 * @return javax.swing.JPanel
+	 */
+	private JPanel getExecutionPanel() {
+		if (executionPanel == null) {
+			GridBagConstraints gridBagConstraints1 = new GridBagConstraints();
+			gridBagConstraints1.gridx = 1;
+			gridBagConstraints1.fill = GridBagConstraints.HORIZONTAL;
+			gridBagConstraints1.insets = new Insets(0, 5, 5, 5);
+			gridBagConstraints1.gridy = 4;
+			GridBagConstraints gridBagConstraints12 = new GridBagConstraints();
+			gridBagConstraints12.gridx = 1;
+			gridBagConstraints12.fill = GridBagConstraints.HORIZONTAL;
+			gridBagConstraints12.insets = new Insets(0, 5, 5, 5);
+			gridBagConstraints12.gridy = 3;
+			GridBagConstraints gridBagConstraints11 = new GridBagConstraints();
+			gridBagConstraints11.fill = GridBagConstraints.BOTH;
+			gridBagConstraints11.weighty = 1.0;
+			gridBagConstraints11.gridx = 0;
+			gridBagConstraints11.gridy = 1;
+			gridBagConstraints11.ipadx = 0;
+			gridBagConstraints11.insets = new Insets(5, 5, 5, 5);
+			gridBagConstraints11.gridwidth = 2;
+			gridBagConstraints11.weightx = 1.0;
+			GridBagConstraints gridBagConstraints = new GridBagConstraints();
+			gridBagConstraints.insets = new Insets(0, 0, 0, 0);
+			gridBagConstraints.gridy = 0;
+			gridBagConstraints.anchor = GridBagConstraints.NORTH;
+			gridBagConstraints.gridheight = 1;
+			gridBagConstraints.gridwidth = 2;
+			gridBagConstraints.gridx = 0;
+			Steps = new JLabel();
+			Steps.setText("Potential Servers");
+			Steps.setName("Steps");
+			executionPanel = new JPanel();
+			executionPanel.setLayout(new GridBagLayout());
+			executionPanel.setBorder(new SoftBevelBorder(
+					SoftBevelBorder.LOWERED));
+			executionPanel.setVisible(true);
+			executionPanel.add(Steps, gridBagConstraints);
+			executionPanel.add(getJScrollPane1(), gridBagConstraints11);
+			executionPanel.add(getButtonPanel(), gridBagConstraints12);
+			executionPanel.add(getRefreshButton(), gridBagConstraints1);
+		}
+		return executionPanel;
+	}
+
+	/**
+	 * This method initializes jScrollPane1
+	 * 
+	 * @return javax.swing.JScrollPane
+	 */
+	private JScrollPane getJScrollPane1() {
+		if (jScrollPane1 == null) {
+			jScrollPane1 = new JScrollPane();
+			jScrollPane1.setName("jScrollPane1");
+			jScrollPane1.setViewportView(getServerList());
+			jScrollPane1.setPreferredSize(new Dimension(200, 250));
+		}
+		return jScrollPane1;
+	}
+
+	/**
+	 * This method initializes buttonPanel
+	 * 
+	 * @return javax.swing.JPanel
+	 */
+	protected JPanel getButtonPanel() {
+		if (buttonPanel == null) {
+			GridLayout gridLayout = new GridLayout();
+			gridLayout.setRows(1);
+			buttonPanel = new JPanel();
+			buttonPanel.setLayout(gridLayout);
+			buttonPanel.add(getStartButton(), null);
+			buttonPanel.add(getStopButton(), null);
+			buttonPanel.add(getRestartButton(), null);
+		}
+		return buttonPanel;
+	}
+
+	/**
+	 * This method initializes serverList
+	 * 
+	 * @return javax.swing.JList
+	 */
+	private JList getServerList() {
+		if (serverList == null) {
+			serverList = new JList();
+			serverList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+		}
+		return serverList;
+	}
+
+	/**
+	 * This method initializes refreshButton
+	 * 
+	 * @return javax.swing.JButton
+	 */
+	private JButton getRefreshButton() {
+		if (refreshButton == null) {
+			refreshButton = new JButton();
+			refreshButton.setText("Refresh");
+		}
+		return refreshButton;
+	}
+
+	/**
+	 * This method initializes startButton
+	 * 
+	 * @return javax.swing.JButton
+	 */
+	private JButton getStartButton() {
+		if (startButton == null) {
+			startButton = new JButton();
+			startButton.setText("Start");
+			startButton.setName("startButton");
+		}
+		return startButton;
+	}
+
+	/**
+	 * This method initializes stopButton
+	 * 
+	 * @return javax.swing.JButton
+	 */
+	private JButton getStopButton() {
+		if (stopButton == null) {
+			stopButton = new JButton();
+			stopButton.setText("Stop");
+			stopButton.setName("stopButton");
+		}
+		return stopButton;
+	}
+
+	/**
+	 * This method initializes restartButton
+	 * 
+	 * @return javax.swing.JButton
+	 */
+	private JButton getRestartButton() {
+		if (restartButton == null) {
+			restartButton = new JButton();
+			restartButton.setText("Restart");
+			restartButton.setName("restartButton");
+		}
+		return restartButton;
+	}
+
+} // @jve:decl-index=0:visual-constraint="10,10"

Added: trunk/src/appl/parallel/starter/client/XuluStarterController.java
===================================================================
--- trunk/src/appl/parallel/starter/client/XuluStarterController.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/starter/client/XuluStarterController.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,140 @@
+package appl.parallel.starter.client;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.rmi.RemoteException;
+import java.util.Vector;
+
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.DefaultListModel;
+import javax.swing.JList;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import appl.parallel.client.RemoteExecutionController;
+import appl.parallel.services.HostnameDiscoveryService;
+import appl.parallel.starter.Starter;
+import appl.parallel.starter.server.XuluServerStarter;
+
+/**
+ * This is the Controller for the {@link XuluStarterControllerFrame}, which is
+ * the user interface for the {@link XuluServerStarter}. All events are handled
+ * here. <br>
+ * 
+ * The controller updates a list of {@link Starter}s it finds in the network.
+ * At the moment is uses the {@link HostnameDiscoveryService} to discover
+ * starters.
+ * 
+ * @see HostnameDiscoveryService#getStarterContainers()
+ * @author Dominik Appl
+ */
+public class XuluStarterController implements ActionListener {
+
+	Logger LOG = LogManager.getLogger(this.getClass().getName());
+
+	private XuluStarterClientPanel GUI;
+
+	private HostnameDiscoveryService discovery;
+
+	private Vector<StarterContainer> currentData;
+
+	/**
+	 * 
+	 */
+	public XuluStarterController() {
+		GUI = new XuluStarterClientPanel();
+		// start simpleDiscovery service
+		discovery = new HostnameDiscoveryService();
+		discovery.startService();
+		updateList();
+		initGUI();
+	}
+
+	private void initGUI() {
+		GUI.startButton.addActionListener(this);
+		GUI.stopButton.addActionListener(this);
+		GUI.refreshButton.addActionListener(this);
+		GUI.restartButton.addActionListener(this);
+	}
+
+	public XuluStarterClientPanel getPanel() {
+		return GUI;
+	}
+
+	/**
+	 * 
+	 */
+	private void updateList() {
+		currentData = discovery.getStarterContainers();
+		GUI.serverList.setCellRenderer(new MyCellRenderer(currentData));
+		// DefaultListModel serverListModel = new DefaultListModel();
+		// GUI.serverList.setModel(serverListModel);
+		GUI.serverList.setListData(currentData);
+	}
+
+	private Starter getSelectedStarter() {
+		Object value = GUI.serverList.getSelectedValue();
+		if (value != null) {
+			return ((StarterContainer) value).getStarter();
+		}
+		return null;
+	}
+
+	public void actionPerformed(ActionEvent e) {
+		if (e.getSource() == GUI.refreshButton) {
+			updateList();
+		}
+		Starter selectedStarter = getSelectedStarter();
+		// if nothing selected: return
+		if (selectedStarter == null)
+			return;
+		try {
+			if (e.getSource() == GUI.startButton) {
+				selectedStarter.start();
+				updateList();
+			}
+			if (e.getSource() == GUI.stopButton) {
+				selectedStarter.stop();
+				updateList();
+			}
+			if (e.getSource() == GUI.restartButton) {
+				selectedStarter.restart();
+				updateList();
+			}
+		} catch (RemoteException e1) {
+			LOG
+					.error(
+							"Could not access selected Starter. Remote Exeception occured.",
+							e1);
+		}
+	}
+
+	class MyCellRenderer extends DefaultListCellRenderer {
+		private final Vector<StarterContainer> containers;
+
+		public MyCellRenderer(Vector<StarterContainer> containers) {
+			this.containers = containers;
+			// TODO Auto-generated constructor stub
+		}
+
+		@Override
+		public Component getListCellRendererComponent(JList list, Object value,
+				int index, boolean isSelected, boolean cellHasFocus) {
+			// TODO Auto-generated method stub
+			Component listCellRendererComponent = super
+					.getListCellRendererComponent(list, value, index,
+							isSelected, cellHasFocus);
+			if (!isSelected) {
+				if (containers.get(index).isServerRunning())
+					listCellRendererComponent.setBackground(Color.green);
+				else
+					listCellRendererComponent.setBackground(Color.red);
+			}
+			return listCellRendererComponent;
+		}
+
+	}
+}

Added: trunk/src/appl/parallel/starter/client/XuluStarterControllerFrame.java
===================================================================
--- trunk/src/appl/parallel/starter/client/XuluStarterControllerFrame.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/starter/client/XuluStarterControllerFrame.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,37 @@
+package appl.parallel.starter.client;
+
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import javax.swing.JFrame;
+
+import org.apache.log4j.BasicConfigurator;
+
+import appl.parallel.starter.Starter;
+
+/**
+ * This is a GUI for controlling the {@link Starter Starters} in the network
+ * independent of Xulu.
+ * @author appl
+ *
+ */
+public class XuluStarterControllerFrame extends JFrame {
+	public XuluStarterControllerFrame() {
+		super("Server starter");
+		this.getContentPane().add(new XuluStarterController().getPanel());
+		this.setSize(300, 400);
+		this.addWindowListener(new ExitListener());
+	}
+
+	public static void main(String[] args) {
+		BasicConfigurator.configure();
+		XuluStarterControllerFrame clientGUI = new XuluStarterControllerFrame();
+		clientGUI.setVisible(true);
+	}
+
+	public class ExitListener extends WindowAdapter {
+		public void windowClosing(WindowEvent event) {
+			System.exit(0);
+		}
+	}
+}

Added: trunk/src/appl/parallel/starter/client/XuluStarterControllerPlugin.java
===================================================================
--- trunk/src/appl/parallel/starter/client/XuluStarterControllerPlugin.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/starter/client/XuluStarterControllerPlugin.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,38 @@
+package appl.parallel.starter.client;
+
+import appl.util.XuluFrameAdapter;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.XuluPlugin;
+import edu.bonn.xulu.gui.XuluInternalFrame;
+import edu.bonn.xulu.plugin.appl.AbstractMenuPlugin;
+
+/**
+ * The starter-controller {@link XuluPlugin}.
+ * 
+ * @see XuluStarterController
+ * 
+ * @author Dominik Appl
+ */
+public class XuluStarterControllerPlugin extends AbstractMenuPlugin {
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see edu.bonn.xulu.plugin.appl.AbstractMenuPlugin#createPluginApplication()
+	 */
+	@Override
+	protected XuluInternalFrame createPluginApplication() throws Exception {
+		XuluStarterController controller = new XuluStarterController();
+
+		return new XuluFrameAdapter("Xulu/V - Starter control", controller
+				.getPanel());
+	}
+
+	/**
+	 * 
+	 */
+	public XuluStarterControllerPlugin() {
+		super(4, "Xulu/V - Starter control");
+	}
+
+}

Added: trunk/src/appl/parallel/starter/client/package.html
===================================================================
--- trunk/src/appl/parallel/starter/client/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/starter/client/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,6 @@
+<html>
+<body>
+	Contains classes related the client side of the starter functionality. If a programm is executed by a Starter, the
+	execution can be controlled remotely (start/stop/restart the process).
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/parallel/starter/package.html
===================================================================
--- trunk/src/appl/parallel/starter/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/starter/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,6 @@
+<html>
+<body>
+	Contains classes related the starter functionality. If a programm is executed by a Starter, the
+	execution can be controlled remotely (start/stop/restart the process).
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/parallel/starter/server/XuluServerStarter.java
===================================================================
--- trunk/src/appl/parallel/starter/server/XuluServerStarter.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/starter/server/XuluServerStarter.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,647 @@
+package appl.parallel.starter.server;
+
+import java.awt.AWTException;
+import java.awt.Image;
+import java.awt.MenuItem;
+import java.awt.PopupMenu;
+import java.awt.SystemTray;
+import java.awt.Toolkit;
+import java.awt.TrayIcon;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.SequenceInputStream;
+import java.rmi.AccessException;
+import java.rmi.Naming;
+import java.rmi.NotBoundException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.UnicastRemoteObject;
+
+import javax.swing.JOptionPane;
+import javax.swing.JTextArea;
+
+import schmitzm.swing.TextAreaPrintStream;
+import schmitzm.swing.event.PopupMenuListener;
+
+import appl.ext.XuluConfig;
+import appl.parallel.ComputingResource;
+import appl.parallel.server.XuluServer;
+import appl.parallel.starter.Starter;
+import appl.parallel.util.Helper;
+import appl.util.GeneralUtil;
+
+/**
+ * A running instance of the XuluServerStarter waits for a signal to start a
+ * {@link XuluServer}. When {@link #start()} is called the Server is started.
+ * All output from the new Serverprocess are forwarded to the actual screen (if
+ * any). The Server can also be {@link #restart() restarted} or
+ * {@link #stop() stopped}. <br>
+ * <br>
+ * For configuration of the XuluServer the {@link XuluConfig} is used. The
+ * following configuration entries are supported <TABLE border="1"
+ * <tr>
+ * <th>Entry</th>
+ * <th>Default</th>
+ * <th>Description</th>
+ * </tr>
+ * <tr>
+ * <td>XuluServerStarter.port</td>
+ * <td>1099</td>
+ * <td> The port which is used for the registry creation (if none is running)</td>
+ * </tr>
+ * <tr>
+ * <td>XuluServerStarter.javaprogram</td>
+ * <td>java</td>
+ * <td> The path to the java program</td>
+ * </tr>
+ * <tr>
+ * <td>XuluServerStarter.codebasedir</td>
+ * <td></td>
+ * <td> The absolute path to the codebase directory (should be the path to the
+ * binaries)</td>
+ * </tr>
+ * <tr>
+ * <td>XuluServerStarter.securitypolicy</td>
+ * <td></td>
+ * <td> The path to the security policy</td>
+ * </tr>
+ * <tr>
+ * <td>XuluServerStarter.furtherjavaarguments</td>
+ * <td></td>
+ * <td> further JVM arguments</td>
+ * </tr>
+ * <tr>
+ * <td>XuluServerStarter.classpath</td>
+ * <td></td>
+ * <td> The libaries needed</td>
+ * </tr>
+ * <tr>
+ * <td>XuluServerStarter.memorymax</td>
+ * <td>64</td>
+ * <td> The maximum memory the XuluSever attempts to use (-xmx)</td>
+ * </tr>
+ * <tr>
+ * <td>XuluServerStarter.memorymin</td>
+ * <td>4</td>
+ * <td> The inital memory the XuluServer uses (-xms)</td>
+ * </tr>
+ * </TABLE>
+ * 
+ * @author Dominik Appl
+ */
+public class XuluServerStarter extends UnicastRemoteObject implements Starter,
+		ActionListener {
+
+	private enum Status {
+		/** server is not started */
+		serverOff,
+		/** * Server is started */
+		serverStarted,
+		/** A client is connected */
+		serverActive
+	}
+
+	private String bindingName = "XuluServerStarter";
+
+	private int port = 1099;
+
+	private String javaprogram = "java";
+
+	private String codebase = "";
+
+	private String securitypolicy = "";
+
+	private String furtherjavaarguments = "";
+
+	private String xuluserverarguments = "";
+
+	private String classpath = "";
+
+	private String XuluServerString = "appl.parallel.server.XuluServer";
+
+	private Process p;
+
+	// private BufferedReader input;
+
+	private SimpleConsoleOutputThread thread;
+
+	private int xms = 64;
+
+	private int xmx = 128;
+
+	private SequenceInputStream twoStreams;
+
+	private XuluStarterServerGUI starterServerGUI;
+
+	private TextAreaPrintStream textAreaOutput;
+
+	private MenuItem menu_exit;
+
+	private MenuItem menu_start;
+
+	private MenuItem menu_stop;
+
+	private MenuItem menu_showConsole;
+
+	private TrayIcon trayIcon;
+
+	private ComputingResource xuluServer;
+
+	private Image redIcon;
+
+	private Image greenIcon;
+
+	private Image yellowIcon;
+
+	private String cmd;
+
+	/**
+	 * @param cmd
+	 *            the command to be executed by the starter. If null, the
+	 *            XuluConfig is used to create the commandline
+	 * @param showGUI
+	 *            if false, no GUI/Tray is shown
+	 * @throws RemoteException
+	 */
+	private XuluServerStarter(String cmd, boolean showGUI)
+			throws RemoteException {
+		super();
+		this.cmd = cmd;
+		this.bind(bindingName, this, port);
+		if (showGUI) {
+			redIcon = Toolkit.getDefaultToolkit().getImage(
+					"resource/xulu_icon_red.gif");
+			greenIcon = Toolkit.getDefaultToolkit().getImage(
+					"resource/xulu_icon_green.gif");
+			yellowIcon = Toolkit.getDefaultToolkit().getImage(
+					"resource/xulu_icon_yellow.gif");
+			createGUI();
+			createTray();
+			setStatus(Status.serverOff);
+		}
+	}
+
+	/**
+	 * Should be called if the status has changed (changes tray icon)
+	 * 
+	 * @param newStatus
+	 *            the new status
+	 */
+	private void setStatus(Status newStatus) {
+		// if tray disabled: return
+		if (trayIcon == null)
+			return;
+		switch (newStatus) {
+		case serverOff:
+			trayIcon.setImage(redIcon);
+			trayIcon.setToolTip("XuluServer is disabled");
+			break;
+		case serverStarted:
+			trayIcon.setImage(greenIcon);
+			trayIcon.setToolTip("Xulu Server is ready and waiting for tasks");
+			break;
+		case serverActive:
+			trayIcon.setImage(yellowIcon);
+			trayIcon.setToolTip("A client is connected to the XuluServer");
+			break;
+		}
+	}
+
+	/**
+	 * creates and inits the tray icon.
+	 */
+	private void createTray() {
+
+		if (SystemTray.isSupported()) {
+
+			SystemTray tray = SystemTray.getSystemTray();
+			Image image = Toolkit.getDefaultToolkit().getImage(
+					"temp/xulu_icon.gif");
+
+			// create menu entries
+			PopupMenu popup = new PopupMenu();
+			menu_exit = new MenuItem("Exit");
+			menu_start = new MenuItem("Start Server");
+			menu_stop = new MenuItem("Stop Server");
+			menu_showConsole = new MenuItem("Show contol window");
+			menu_exit.addActionListener(this);
+			menu_start.addActionListener(this);
+			menu_stop.addActionListener(this);
+			menu_showConsole.addActionListener(this);
+
+			popup.add(menu_start);
+			popup.add(menu_stop);
+			popup.add(menu_showConsole);
+			popup.add(menu_exit);
+			trayIcon = new TrayIcon(image, "Xulu Server", popup);
+			trayIcon.setImageAutoSize(true);
+			trayIcon.addMouseListener(new MouseAdapter() {
+				// on doubleclick popup the control-window
+				public void mouseClicked(MouseEvent e) {
+					if (e.getClickCount() > 1) {
+						starterServerGUI.setVisible(!starterServerGUI
+								.isVisible());
+					}
+				}
+			});
+
+			try {
+				tray.add(trayIcon);
+			} catch (AWTException e) {
+				System.err.println("TrayIcon could not be added.");
+				tray = null;
+			}
+
+		} else {
+			// System Tray is not supported
+			System.out.println("System Tray not supported"); 
+			trayIcon = null;
+		}
+
+	}
+
+	/**
+	 * creates the GUI for the Starter
+	 */
+	private void createGUI() {
+		// create new GUI
+		starterServerGUI = new XuluStarterServerGUI();
+		// register this instance as button listener
+		starterServerGUI.button_exit.addActionListener(this);
+		starterServerGUI.button_start.addActionListener(this);
+		starterServerGUI.button_stop.addActionListener(this);
+
+		// register TextArea as OutputStream
+		textAreaOutput = new TextAreaPrintStream(starterServerGUI.consoleArea);
+		System.setErr(textAreaOutput);
+		System.setOut(textAreaOutput);
+
+	}
+
+	/**
+	 * reads the configuration out of the {@link XuluConfig}
+	 */
+	private void loadConfig() {
+		XuluConfig config = XuluConfig.getXuluConfig();
+		if (config.getIntProperty("XuluServerStarter.port") != 0)
+			port = config.getIntProperty("XuluServerStarter.port");
+		if (config.getProperty("XuluServerStarter.javaprogram") != null)
+			javaprogram = config.getProperty("XuluServerStarter.javaprogram");
+		if (config.getProperty("XuluServerStarter.codebasedir") != null)
+			codebase = config.getProperty("XuluServerStarter.codebasedir");
+		if (config.getProperty("XuluServerStarter.securitypolicy") != null)
+			securitypolicy = config
+					.getProperty("XuluServerStarter.securitypolicy");
+		if (config.getProperty("XuluServerStarter.furtherjavaarguments") != null)
+			furtherjavaarguments = config
+					.getProperty("XuluServerStarter.furtherjavaarguments");
+		if (config.getProperty("XuluServerStarter.classpath") != null)
+			classpath = config.getProperty("XuluServerStarter.classpath");
+		if (config.getProperty("XuluServerStarter.memorymax") != null)
+			xmx = config.getIntProperty("XuluServerStarter.memorymax");
+		if (config.getProperty("XuluServerStarter.memorymin") != null)
+			xms = config.getIntProperty("XuluServerStarter.memorymin");
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.starter.Starter#restart()
+	 */
+	public void restart() throws RemoteException {
+		this.stop();
+		this.start();
+	}
+
+	/**
+	 * Creates the Java commandline and starts the {@link XuluServer}
+	 * 
+	 * @see appl.parallel.starter.Starter#start()
+	 */
+	public void start() throws RemoteException {
+		loadConfig();
+		try {
+			if (p != null) {
+				System.out
+						.println("Process is already running. Stop process first");
+				return;
+			}
+			String commandline = "\"" + javaprogram + "\"" + " -cp \""
+					+ codebase;
+			if (!(classpath.equals("")))
+				commandline += (";" + classpath);
+			commandline += "\" ";
+			if (xms != 0)
+				commandline += (" -Xms" + xms + "M ");
+			if (xmx != 0)
+				commandline += (" -Xmx" + xmx + "M ");
+
+			commandline += (" -Djava.rmi.server.codebase=file:///" + codebase
+					+ " -Djava.security.policy=" + securitypolicy + " "
+					+ furtherjavaarguments + " " + XuluServerString + " " + xuluserverarguments);
+			// if there is a user commandline, use this instead
+			if (cmd != null)
+				commandline = cmd;
+			System.out.println("Executing commandline: " + commandline);
+			p = Runtime.getRuntime().exec(commandline);
+			xuluServer = null;
+			// forward the inputstream of the new process to the
+			// console/textarea
+			InputStream standardInput = p.getInputStream();
+			InputStream errorInput = p.getErrorStream();
+			thread = new SimpleConsoleOutputThread(standardInput, errorInput);
+			thread.startThread();
+			// wait until the server is bound to the registry
+			Thread.sleep(5000);
+			// lookup the new Server
+			xuluServer = (ComputingResource) Naming
+					.lookup("rmi://localhost/XuluServer");
+			setStatus(Status.serverStarted);
+			System.out
+					.println("The Starter has successfully discovered the XuluServer instance");
+
+		} catch (IOException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		} catch (NotBoundException e) {
+			System.out
+					.println("Could not find the Xulu server instance(NotBoundException).\n Creation of the XuluServer failed..please correct the commandline...");
+
+		} catch (InterruptedException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.starter.Starter#stop()
+	 */
+	public void stop() throws RemoteException {
+		try {
+			if (twoStreams != null)
+				twoStreams.close();
+			if (thread != null)
+				thread.stopThread();
+			// if (input != null)
+			// input.close();
+			if (p != null)
+				p.destroy();
+			p = null;
+			System.out.println("Process stopped");
+			this.setStatus(Status.serverOff);
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * Starts the XuluServerStarter <br/> The parameter -start can be used to
+	 * start the Server at launch of the Starter. <br>
+	 * The parameter -cmd <command> will use the given command to try to start
+	 * the server. Else the XuluConfig will be used. <br>
+	 * The parameter -noGUI forces the starter to not use any GUI functionality.
+	 */
+	public static void main(String[] args) {
+		try {
+			System.out
+					.println("Use the parameter -help to see all available commandline options");
+			String cmd = null;
+			boolean noGUI = false;
+			boolean start = false;
+			// search for command parameter
+			for (int i = 0; i < args.length; i++) {
+				if (args[i].toLowerCase().equals("-cmd") && i < args.length)
+					cmd = args[i + 1];
+				if (args[i].toLowerCase().equals("-nogui") && i < args.length)
+					noGUI = true;
+				if (args[i].toLowerCase().equals("-start"))
+					start = true;
+				if (args[i].toLowerCase().equals("-help"))
+					printHelp();
+			}
+			XuluServerStarter starter = new XuluServerStarter(cmd, !noGUI);
+			System.out.println("XuluServerStarter initialized .... ");
+			if (start) {
+				starter.start();
+			}
+			if (!starter.isRunning()) {
+				System.out
+						.println("Hint: use parameter '-start' to start the server directly");
+			}
+		} catch (RemoteException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * 
+	 */
+	private static void printHelp() {
+		System.out
+				.println("The following commands can be used: \n\n"
+						+ "-start can be used to start the Server at launch of the Starter.\n"
+						+ "-cmd <command> will use the given command to try to start the server."
+						+ " Else the XuluConfig will be used.\n"
+						+ "-noGUI doesn't use any GUI functionality.\n"
+						+ "-help displays this help");
+
+	}
+
+	public boolean isRunning() throws RemoteException {
+		return (p != null);
+
+	}
+
+	/**
+	 * Copied from {@link Helper} and modified so that it does not depend on
+	 * log4j. Binds the remote object's stub in the registry. Creates a registry
+	 * if no running registry is found.
+	 * 
+	 * @param bindingName
+	 *            the name to be used for binding
+	 * @param bindingInstance
+	 *            an instance of the type to bind to the registry
+	 * @param defaultPort
+	 *            the default registry port
+	 * @throws RemoteException
+	 *             if something goes wrong
+	 */
+	public void bind(String bindingName, Remote bindingInstance, int defaultPort)
+			throws RemoteException {
+		boolean failed = true;
+		Registry registry;
+		try {
+			registry = LocateRegistry.getRegistry();
+			registry.rebind(bindingName, bindingInstance);
+			failed = false;
+		} catch (AccessException e) {
+			System.err.println("Not enough permissions to bind" + bindingName
+					+ "to the registry! Adjust your security permission file!");
+			e.printStackTrace();
+		} catch (RemoteException e) {
+			if (e instanceof java.rmi.ConnectException) {
+				System.out
+						.println("Could not connect to registry! Trying to create new one...");
+				try {
+					registry = LocateRegistry.createRegistry(defaultPort);
+					registry.rebind(bindingName, bindingInstance);
+					System.out.println("Registry successfully created at port "
+							+ defaultPort);
+					failed = false;
+				} catch (RemoteException e1) {
+					// TODO Auto-generated catch block
+					e1.printStackTrace();
+				}
+			} else
+				e.printStackTrace();
+		}
+		if (failed)
+			throw new RemoteException("Could not find or create registry!");
+	}
+
+	/**
+	 * The Thread is used to direct the output of the process to System.out.
+	 * Notice that this stream may be redirected to a
+	 * {@link TextAreaPrintStream} or any other printstream using
+	 * {@link System#setOut(java.io.PrintStream)}
+	 * 
+	 * @author appl
+	 */
+	class SimpleConsoleOutputThread implements Runnable {
+		private volatile Thread outputThread;
+
+		private boolean exit;
+
+		private final InputStream standardInput;
+
+		private final InputStream errorInput;
+
+		private final BufferedReader input;
+
+		private final SequenceInputStream twoStreams;
+
+		private boolean availableLastTime = false;
+
+		/**
+		 * Creates a new thread. The parmeters are the inputstreams which should
+		 * be forwarded to System.out
+		 * 
+		 * @param standardInput
+		 * @param errorInput
+		 */
+		public SimpleConsoleOutputThread(InputStream standardInput,
+				InputStream errorInput) {
+			this.standardInput = standardInput;
+			this.errorInput = errorInput;
+			// combine the streams
+			twoStreams = new SequenceInputStream(standardInput, errorInput);
+			input = new BufferedReader(new InputStreamReader(twoStreams));
+		}
+
+		public void startThread() {
+			exit = false;
+			if (outputThread == null)
+				outputThread = new Thread(this);
+			outputThread.start();
+		}
+
+		public void stopThread() {
+			exit = true;
+			outputThread.interrupt();
+			try {
+				input.close();
+			} catch (IOException e) {
+				System.out.println("Input closed");
+				e.printStackTrace();
+			}
+		}
+
+		public void run() {
+			String line;
+			while (exit == false) {
+				try {
+					while (input.ready()) {
+						line = input.readLine();
+						System.out.println(line);
+					}
+					Thread.sleep(1000);
+					// check if server is active for tray icon change
+					if (xuluServer != null)
+						if (availableLastTime != xuluServer.isAvailable()) {
+							if (availableLastTime)
+								setStatus(Status.serverActive);
+							else
+								setStatus(Status.serverStarted);
+							availableLastTime = (!availableLastTime);
+						}
+
+				} catch (IOException e) {
+					System.out
+							.println("Connection to server failed. Input closed");
+					e.printStackTrace();
+					exit = true;
+				} catch (InterruptedException e) {
+					if (exit == true)
+						System.out.println("Stopped output thread...");
+				}
+			}
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
+	 */
+	public void actionPerformed(ActionEvent e) {
+		if (e.getSource() == starterServerGUI.button_stop
+				|| e.getSource() == menu_stop) {
+			try {
+				this.stop();
+			} catch (Exception e1) {
+				System.out
+						.println("Could not stop the Server. Reason follows: ");
+				e1.printStackTrace();
+			}
+		} else if (e.getSource() == starterServerGUI.button_exit
+				|| e.getSource() == menu_exit) {
+			// if user does not confirm: return.
+			if (JOptionPane
+					.showConfirmDialog(
+							starterServerGUI,
+							"Are you sure that you want to exit the Starter-Application?",
+							"Confirm exit", JOptionPane.OK_CANCEL_OPTION) != JOptionPane.OK_OPTION)
+				return;
+			try {
+				this.stop();
+			} catch (RemoteException e1) {
+			}
+			System.exit(1);
+
+		} else if (e.getSource() == starterServerGUI.button_start
+				|| e.getSource() == menu_start) {
+			try {
+				this.start();
+			} catch (Exception e1) {
+				System.out
+						.println("Could not start the Server. Reason follows: ");
+				e1.printStackTrace();
+			}
+		} else if (e.getSource() == menu_showConsole) {
+			starterServerGUI.setVisible(true);
+		}
+
+	}
+}

Added: trunk/src/appl/parallel/starter/server/XuluStarterServerGUI.java
===================================================================
--- trunk/src/appl/parallel/starter/server/XuluStarterServerGUI.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/starter/server/XuluStarterServerGUI.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,294 @@
+package appl.parallel.starter.server;
+
+import java.awt.BorderLayout;
+import javax.swing.JPanel;
+import javax.swing.JFrame;
+import java.awt.GridBagLayout;
+import javax.swing.JTextArea;
+import javax.swing.JLabel;
+import javax.swing.JButton;
+import java.awt.GridBagConstraints;
+import java.awt.Dimension;
+import javax.swing.JScrollPane;
+import javax.swing.BoxLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JPopupMenu;
+import javax.swing.JMenuItem;
+
+import schmitzm.swing.event.PopupMenuListener;
+import java.awt.FlowLayout;
+import java.awt.GridLayout;
+import java.awt.CardLayout;
+
+/**
+ * This is the GUI for the {@link XuluServerStarter}
+ * 
+ * @author Dominik Appl
+ */
+public class XuluStarterServerGUI extends JFrame {
+
+	private static final long serialVersionUID = 1L;
+
+	private JPanel jContentPane = null;
+
+	private JPanel controlPanel = null;
+
+	 JTextArea consoleArea = null;
+
+	JButton button_start = null;
+
+	 JButton button_stop = null;
+
+	 JButton button_exit = null;
+
+	private JScrollPane jScrollPane = null;
+
+	private JPopupMenu jPopupMenu = null;  //  @jve:decl-index=0:visual-constraint="615,231"
+
+	private JMenuItem clearText = null;
+
+	private JPanel jPanel = null;
+
+	private JButton button_clear = null;
+
+	/**
+	 * This is the default constructor
+	 */
+	public XuluStarterServerGUI() {
+		super();
+		initialize();
+	}
+
+	/**
+	 * This method initializes this
+	 * 
+	 * @return void
+	 */
+	private void initialize() {
+		this.setSize(450, 316);
+		this.setContentPane(getJContentPane());
+		this.setTitle("Xulu Server Starter");
+	}
+
+	/**
+	 * This method initializes jContentPane
+	 * 
+	 * @return javax.swing.JPanel
+	 */
+	private JPanel getJContentPane() {
+		if (jContentPane == null) {
+			GridBagConstraints gridBagConstraints8 = new GridBagConstraints();
+			gridBagConstraints8.fill = GridBagConstraints.HORIZONTAL;
+			GridBagConstraints gridBagConstraints6 = new GridBagConstraints();
+			gridBagConstraints6.gridx = 0;
+			gridBagConstraints6.ipadx = 140;
+			gridBagConstraints6.gridy = 2;
+			GridBagConstraints gridBagConstraints5 = new GridBagConstraints();
+			gridBagConstraints5.fill = GridBagConstraints.BOTH;
+			gridBagConstraints5.gridy = 1;
+			gridBagConstraints5.ipadx = 0;
+			gridBagConstraints5.ipady = 0;
+			gridBagConstraints5.weightx = 1.0;
+			gridBagConstraints5.weighty = 1.0;
+			gridBagConstraints5.insets = new Insets(0, 5, 0, 5);
+			gridBagConstraints5.gridx = 0;
+			GridBagConstraints gridBagConstraints3 = new GridBagConstraints();
+			gridBagConstraints3.gridx = 0;
+			gridBagConstraints3.ipadx = 0;
+			gridBagConstraints3.ipady = 0;
+			gridBagConstraints3.fill = GridBagConstraints.HORIZONTAL;
+			gridBagConstraints3.gridy = 5;
+			jContentPane = new JPanel();
+			jContentPane.setLayout(new GridBagLayout());
+			jContentPane.add(getJScrollPane(), gridBagConstraints5);
+			jContentPane.add(getControlPanel(), gridBagConstraints6);
+			jContentPane.add(getJPanel(), gridBagConstraints8);
+		}
+		return jContentPane;
+	}
+
+	/**
+	 * This method initializes controlPanel	
+	 * 	
+	 * @return javax.swing.JPanel	
+	 */
+	private JPanel getControlPanel() {
+		if (controlPanel == null) {
+			GridBagConstraints gridBagConstraints11 = new GridBagConstraints();
+			gridBagConstraints11.fill = GridBagConstraints.BOTH;
+			gridBagConstraints11.gridy = 3;
+			gridBagConstraints11.weightx = 1.0;
+			gridBagConstraints11.weighty = 1.0;
+			gridBagConstraints11.gridx = 0;
+			GridBagConstraints gridBagConstraints2 = new GridBagConstraints();
+			gridBagConstraints2.gridx = 3;
+			gridBagConstraints2.anchor = GridBagConstraints.EAST;
+			gridBagConstraints2.gridy = 1;
+			GridBagConstraints gridBagConstraints1 = new GridBagConstraints();
+			gridBagConstraints1.gridx = 2;
+			gridBagConstraints1.anchor = GridBagConstraints.WEST;
+			gridBagConstraints1.gridy = 1;
+			GridBagConstraints gridBagConstraints = new GridBagConstraints();
+			gridBagConstraints.gridx = 0;
+			gridBagConstraints.anchor = GridBagConstraints.WEST;
+			gridBagConstraints.gridy = 1;
+			controlPanel = new JPanel();
+			controlPanel.setLayout(new GridBagLayout());
+			controlPanel.add(getButton_start(), gridBagConstraints);
+			controlPanel.add(getButton_stop(), gridBagConstraints1);
+			controlPanel.add(getButton_exit(), gridBagConstraints2);
+		}
+		return controlPanel;
+	}
+
+	/**
+	 * This method initializes consoleArea	
+	 * 	
+	 * @return javax.swing.JTextArea	
+	 */
+	private JTextArea getConsoleArea() {
+		if (consoleArea == null) {
+			consoleArea = new JTextArea();
+			consoleArea.setToolTipText("");
+			consoleArea.setWrapStyleWord(false);
+			consoleArea.setLineWrap(true);
+			consoleArea.addMouseListener(new PopupMenuListener(this.getJPopupMenu()));
+		}
+		return consoleArea;
+	}
+
+	/**
+	 * This method initializes button_start	
+	 * 	
+	 * @return javax.swing.JButton	
+	 */
+	private JButton getButton_start() {
+		if (button_start == null) {
+			button_start = new JButton();
+			button_start.setText("Start Server");
+		}
+		return button_start;
+	}
+
+	/**
+	 * This method initializes button_stop	
+	 * 	
+	 * @return javax.swing.JButton	
+	 */
+	private JButton getButton_stop() {
+		if (button_stop == null) {
+			button_stop = new JButton();
+			button_stop.setText("Stop Server");
+		}
+		return button_stop;
+	}
+
+	/**
+	 * This method initializes button_exit	
+	 * 	
+	 * @return javax.swing.JButton	
+	 */
+	private JButton getButton_exit() {
+		if (button_exit == null) {
+			button_exit = new JButton();
+			button_exit.setText("Exit Starter");
+		}
+		return button_exit;
+	}
+
+	/**
+	 * This method initializes jScrollPane	
+	 * 	
+	 * @return javax.swing.JScrollPane	
+	 */
+	private JScrollPane getJScrollPane() {
+		if (jScrollPane == null) {
+			jScrollPane = new JScrollPane();
+			jScrollPane.setDoubleBuffered(false);
+			jScrollPane.setViewportView(getConsoleArea());
+		}
+		return jScrollPane;
+	}
+
+	/**
+	 * This method initializes jPopupMenu	
+	 * 	
+	 * @return javax.swing.JPopupMenu	
+	 */
+	private JPopupMenu getJPopupMenu() {
+		if (jPopupMenu == null) {
+			jPopupMenu = new JPopupMenu();
+			jPopupMenu.add(getClearText());
+
+			
+		}
+		return jPopupMenu;
+	}
+
+	/**
+	 * This method initializes clearText	
+	 * 	
+	 * @return javax.swing.JMenuItem	
+	 */
+	private JMenuItem getClearText() {
+		if (clearText == null) {
+			clearText = new JMenuItem();
+			clearText.setText("clear");
+			clearText.addActionListener(new java.awt.event.ActionListener() {
+				public void actionPerformed(java.awt.event.ActionEvent e) {
+					getConsoleArea().setText("");
+				}
+			});
+		}
+		return clearText;
+	}
+
+	/**
+	 * This method initializes jPanel	
+	 * 	
+	 * @return javax.swing.JPanel	
+	 */
+	private JPanel getJPanel() {
+		if (jPanel == null) {
+			FlowLayout flowLayout = new FlowLayout();
+			flowLayout.setHgap(0);
+			flowLayout.setVgap(0);
+			GridBagConstraints gridBagConstraints9 = new GridBagConstraints();
+			gridBagConstraints9.gridx = 0;
+			gridBagConstraints9.anchor = GridBagConstraints.EAST;
+			gridBagConstraints9.gridy = 0;
+			GridBagConstraints gridBagConstraints4 = new GridBagConstraints();
+			gridBagConstraints4.gridy = -1;
+			gridBagConstraints4.anchor = GridBagConstraints.WEST;
+			gridBagConstraints4.gridx = -1;
+			jPanel = new JPanel();
+			jPanel.setLayout(flowLayout);
+			jPanel.add(getButton_clear(), null);
+		}
+		return jPanel;
+	}
+
+	/**
+	 * This method initializes button_clear	
+	 * 	
+	 * @return javax.swing.JButton	
+	 */
+	private JButton getButton_clear() {
+		if (button_clear == null) {
+			button_clear = new JButton();
+			button_clear.setText("Clear Console");
+			button_clear.setPreferredSize(new Dimension(130, 15));
+			button_clear.setName("jButton");
+			button_clear.addActionListener(new java.awt.event.ActionListener() {
+				public void actionPerformed(java.awt.event.ActionEvent e) {
+					getConsoleArea().setText("");
+				}
+			});
+		}
+		return button_clear;
+	}
+
+}  //  @jve:decl-index=0:visual-constraint="10,10"

Added: trunk/src/appl/parallel/starter/server/package.html
===================================================================
--- trunk/src/appl/parallel/starter/server/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/starter/server/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,6 @@
+<html>
+<body>
+	Contains classes related the server side of the starter functionality. If a programm is executed by a Starter, the
+	execution can be controlled remotely (start/stop/restart the process).
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/parallel/test/AverageNeighborhoodTestTask.java
===================================================================
--- trunk/src/appl/parallel/test/AverageNeighborhoodTestTask.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/test/AverageNeighborhoodTestTask.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,80 @@
+package appl.parallel.test;
+
+import java.awt.Rectangle;
+
+import schmitzm.data.WritableGrid;
+import appl.parallel.spmd.AbstractSPMDTask;
+import appl.parallel.spmd.SPMDServerInterface;
+import appl.util.RasterUtil;
+
+/**
+ * @author Dominik Appl
+ */
+public class AverageNeighborhoodTestTask extends AbstractSPMDTask {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 13L;
+
+    /* (non-Javadoc)
+	 * @see appl.parallel.spmd.SPMDTask#run()
+	 */
+	public Object run(Object...parameters) {
+		
+		SPMDServerInterface controller = getSPMDServerController();
+		WritableGrid gridInput = (WritableGrid) controller
+				.getPartition("inputGrid");
+		WritableGrid gridOutput = (WritableGrid) controller
+				.getPartition("outputGrid");
+		int neighborhoodRange = (Integer) parameters[0];
+		/********************** START REMOTE ALGORITHM *********************
+		 * start the calculation (notice that only the outer loop variables have changed)
+		 * *****************************************************************/
+		float overallSum = 0;
+		Rectangle partition = controller.getLocalBounds();
+		//System.out.println("290,64: " + gridInput.getRasterSampleAsFloat(controller.getLocalCalcMinX()+289,64));
+		for (int y = controller.getLocalCalcMinY(); y < controller
+				.getLocalCalcMaxY() + 1; y++)
+			for (int x = controller.getLocalCalcMinX(); x < controller
+					.getLocalCalcMaxX() + 1; x++) {
+				float tmp = gridInput.getRasterSampleAsFloat(x,y);
+				if(!Float.isNaN(tmp))
+					overallSum += tmp;
+				//the local sum is simply the sum over all elements in the neighborhood
+				float localSum = 0;
+				//number of cells over which the sum is calculated
+				int noOfCells = 0;
+				//for each cell: calculate the sum of all neighbors
+				for (int y2 = y - neighborhoodRange; y2 <= y
+						+ neighborhoodRange; y2++)
+					for (int x2 = x - neighborhoodRange; x2 <= x
+							+ neighborhoodRange; x2++)
+						//check if the coordinates are valid (inside the grid and not NaN)
+						if (partition.contains(x2, y2))
+							if (!Float.isNaN(gridInput
+									.getRasterSampleAsFloat(x2, y2))) {
+								localSum += gridInput.getRasterSampleAsFloat(
+										x2, y2);
+								noOfCells++;
+							}
+				gridOutput.setRasterSample(localSum / (float) (noOfCells), x,y);
+
+			}
+	//copy values into results from output to input (for next step)
+	RasterUtil.copyInto(gridOutput, gridInput);
+	return overallSum;
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.AbstractSPMDTask#init()
+	 */
+	@Override
+	public void init() {
+		// TODO Auto-generated method stub
+		
+	}
+
+	
+	
+}
\ No newline at end of file

Added: trunk/src/appl/parallel/test/AverageNeighborhoodTestTask_MultiGrid.java
===================================================================
--- trunk/src/appl/parallel/test/AverageNeighborhoodTestTask_MultiGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/test/AverageNeighborhoodTestTask_MultiGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,89 @@
+package appl.parallel.test;
+
+import java.awt.Rectangle;
+
+import schmitzm.data.WritableGrid;
+import appl.parallel.spmd.AbstractSPMDTask;
+import appl.parallel.spmd.SPMDServerInterface;
+import appl.parallel.spmd.split.DataPartition;
+import appl.util.RasterUtil;
+
+/**
+ * @author Dominik Appl
+ */
+public class AverageNeighborhoodTestTask_MultiGrid extends AbstractSPMDTask {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 13L;
+
+    /* (non-Javadoc)
+	 * @see appl.parallel.spmd.SPMDTask#run()
+	 */
+	public Object run(Object...parameters) {
+		SPMDServerInterface controller = getSPMDServerController();
+//		WritableGrid gridInput = (WritableGrid) controller
+//				.getPartition("inputGrid");
+//		WritableGrid gridOutput = (WritableGrid) controller
+//				.getPartition("outputGrid");
+		
+		
+//		WritableGrid gridInput = (WritableGrid) controller
+//		.getMultiPartition("gridData",0);
+//		WritableGrid gridOutput = (WritableGrid) controller
+//		.getMultiPartition("gridData",1);
+//		
+		DataPartition[] gridData = (DataPartition[]) controller.getMultiPartition("gridData");
+		WritableGrid gridInput = (WritableGrid) gridData[0]; 
+		WritableGrid gridOutput = (WritableGrid) gridData[1];
+		
+		int neighborhoodRange = (Integer) parameters[0];
+		/********************** START REMOTE ALGORITHM *********************
+		 * start the calculation (notice that only the outer loop variables have changed)
+		 * *****************************************************************/
+		float overallSum = 0;
+		Rectangle partition = controller.getLocalBounds();
+		//System.out.println("290,64: " + gridInput.getRasterSampleAsFloat(controller.getLocalCalcMinX()+289,64));
+		for (int y = controller.getLocalCalcMinY(); y < controller
+				.getLocalCalcMaxY() + 1; y++)
+			for (int x = controller.getLocalCalcMinX(); x < controller
+					.getLocalCalcMaxX() + 1; x++) {
+				float tmp = gridInput.getRasterSampleAsFloat(x,y);
+				if(!Float.isNaN(tmp))
+					overallSum += tmp;
+				//the local sum is simply the sum over all elements in the neighborhood
+				float localSum = 0;
+				//number of cells over which the sum is calculated
+				int noOfCells = 0;
+				//for each cell: calculate the sum of all neighbors
+				for (int y2 = y - neighborhoodRange; y2 <= y
+						+ neighborhoodRange; y2++)
+					for (int x2 = x - neighborhoodRange; x2 <= x
+							+ neighborhoodRange; x2++)
+						//check if the coordinates are valid (inside the grid and not NaN)
+						if (partition.contains(x2, y2))
+							if (!Float.isNaN(gridInput
+									.getRasterSampleAsFloat(x2, y2))) {
+								localSum += gridInput.getRasterSampleAsFloat(
+										x2, y2);
+								noOfCells++;
+							}
+				gridOutput.setRasterSample(localSum / (float) (noOfCells), x,y);
+
+			}
+	//copy values into results from output to input (for next step)
+	RasterUtil.copyInto(gridOutput, gridInput);
+	return overallSum;
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.AbstractSPMDTask#init()
+	 */
+	@Override
+	public void init() {
+		// TODO Auto-generated method stub
+		
+	}
+	
+}
\ No newline at end of file

Added: trunk/src/appl/parallel/test/MulticastSocketTest.java
===================================================================
--- trunk/src/appl/parallel/test/MulticastSocketTest.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/test/MulticastSocketTest.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,35 @@
+package appl.parallel.test;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.MulticastSocket;
+import java.net.UnknownHostException;
+
+public class MulticastSocketTest {
+	public static void main( String[] args ) throws IOException
+	  {
+	
+		 String msg = "Hello";
+		 InetAddress group = InetAddress.getByName("224.0.0.1");
+		 MulticastSocket s = new MulticastSocket(50000);
+		 s.joinGroup(group);
+		 DatagramPacket hi = new DatagramPacket(msg.getBytes(), msg.length(),
+		                             group, 6789);
+		 System.out.println("sending");
+		 s.send(hi);
+		 // get their responses!
+		 System.out.println("waiting");
+		 byte[] buf = new byte[1000];
+		 
+		 DatagramPacket recv = new DatagramPacket(buf, buf.length);
+		 s.receive(recv);
+		 System.out.println("finished");
+		 // OK, I'm done talking - leave the group...
+		 s.leaveGroup(group);
+		 
+	  	}
+
+}
+

Added: trunk/src/appl/parallel/test/PartitialGridTest.java
===================================================================
--- trunk/src/appl/parallel/test/PartitialGridTest.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/test/PartitialGridTest.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,66 @@
+package appl.parallel.test;
+
+
+import java.awt.Rectangle;
+import java.io.File;
+import java.io.FileNotFoundException;
+import appl.parallel.spmd.split.WritableGridPartition;
+import appl.parallel.util.PartitionUtil;
+import appl.util.RasterUtil;
+import schmitzm.data.WritableGridRaster;
+import schmitzm.geotools.io.GeoExportUtil;
+import schmitzm.geotools.io.GeoImportUtil;
+
+/**
+ * Simple JUnit Test
+ * @author Dominik Appl
+ */
+public class PartitialGridTest {
+
+	/**
+	 * @throws java.lang.Exception
+	 */
+	public void setUp() throws Exception {
+	}
+
+	/**
+	 * @throws java.lang.Exception
+	 */
+	public void tearDown() throws Exception {
+	}
+
+	/**
+	 * Test method for {@link appl.parallel.util.PartitionUtil#getPartitialGrid2D(schmitzm.data.WritableGrid, Rectangle, int)}.
+	 */
+	public void testGetPartitialGrid2D() {
+		WritableGridRaster baseGrid;
+		try {
+			baseGrid = GeoImportUtil
+					.readGridRasterFromArcInfoASCII(new File(
+							"../Xulu-Data/minigrid.arc"));
+			GeoExportUtil.writeGridRasterToArcInfoASCII(baseGrid, new File(
+					"TEST_getpartitialgrid2d_o1"));
+			RasterUtil.printGrid(baseGrid, 4, 0, "base partition");
+			//make five partitions: four quarters and one inner partition
+					RasterUtil.printGrid(PartitionUtil.getPartitialGrid2D(baseGrid, new Rectangle(0, 0, 5, 5),0),4,0, "upperleft partition");
+					RasterUtil.printGrid(PartitionUtil.getPartitialGrid2D(baseGrid,new Rectangle( 5, 0, 5, 5),0),4,0, "upperright partition");
+					RasterUtil.printGrid(PartitionUtil.getPartitialGrid2D(baseGrid, new Rectangle(0, 5, 5, 5),0),4,0, "lowerleft partition");
+					RasterUtil.printGrid(PartitionUtil.getPartitialGrid2D(baseGrid, new Rectangle(5, 5, 5, 5),0),4,0, "lowerright partition");
+					WritableGridPartition baseGrid2 = PartitionUtil.getPartitialGrid2D(baseGrid,new Rectangle( 0, 0, 10, 10),0);
+					System.out.println("********************* Starting test 2 *********************");
+					RasterUtil.printGrid(baseGrid2,5,0, "baseGrid2");
+					WritableGridPartition baseGrid2partition = PartitionUtil.getPartitialGrid2D(baseGrid, new Rectangle(0, 0, 5, 5),0);
+					RasterUtil.printGrid(baseGrid2partition,5,0, "baseGrid2 partition");
+					baseGrid2.setPartition(baseGrid2partition, new Rectangle(1,1,5,5));
+					RasterUtil.printGrid(baseGrid2,5,0, "baseGrid2 (after setting baseGrid2-partition to (1,1)");
+
+		} catch (FileNotFoundException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		} catch (Exception e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+
+	}
+}

Added: trunk/src/appl/parallel/test/PingTestObject.java
===================================================================
--- trunk/src/appl/parallel/test/PingTestObject.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/test/PingTestObject.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,23 @@
+package appl.parallel.test;
+
+import java.io.Serializable;
+
+/**
+ * Simply constructs a object with a given size which can be used for pinging.
+ * @author Dominik Appl
+ */
+public class PingTestObject implements Serializable {
+	byte[] data = null;
+	
+	
+	/**
+	 * @param bytes pingobject size in bytes
+	 */
+	public PingTestObject(int bytes)
+{
+		data = new byte[bytes];
+		for (int i = 0; i < data.length; i++) {
+			data[i]=(byte) i;
+		}}
+
+}

Added: trunk/src/appl/parallel/test/SPMDTest.java
===================================================================
--- trunk/src/appl/parallel/test/SPMDTest.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/test/SPMDTest.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,250 @@
+package appl.parallel.test;
+
+import java.awt.Rectangle;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.Serializable;
+import java.util.Random;
+import java.util.Vector;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.apache.log4j.BasicConfigurator;
+import org.apache.log4j.ConsoleAppender;
+import org.apache.log4j.Layout;
+import org.apache.log4j.Level;
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+import org.apache.log4j.PropertyConfigurator;
+
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.plugin.io.grid.array.WritableGridArrayFactory;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.WritableGridArray;
+import schmitzm.data.WritableGridRaster;
+import schmitzm.geotools.io.GeoImportUtil;
+
+import appl.parallel.ComputingResourceContainer;
+import appl.parallel.client.RemoteEventHandler;
+import appl.parallel.client.ClientDataServer;
+import appl.parallel.data.splittable.SplittableLLProxyGrid;
+import appl.parallel.services.GlobalDiscoveryService;
+import appl.parallel.spmd.AbstractSPMDTask;
+import appl.parallel.spmd.SPMDClientController;
+import appl.parallel.spmd.SPMDTask;
+import appl.parallel.spmd.SPMDServerController;
+import appl.parallel.spmd.split.SplittableGrid;
+import appl.util.RasterMetaData;
+import appl.util.RasterUtil;
+
+/**
+ * Generated code for the test suite <b>SPMDTest</b> located at
+ * <i>/XuluSVN/javasrc/appl/parallel/test/SPMDTest.testsuite</i>. This class
+ * tests all the SPMD functionality, using only XULU/V and nearly nothing of
+ * XULU
+ */
+public class SPMDTest extends TestCase implements Serializable {
+
+	transient private final Logger LOG = LogManager.getLogger(this.getClass()
+			.getName());
+
+	transient private ClientDataServer client;
+	transient private Vector<ComputingResourceContainer> computingResources;
+	transient private SPMDClientController clientController;
+
+	transient SplittableGrid gridInput;
+	transient SplittableGrid remoteInput;
+	transient SplittableGrid localOutput;
+	transient SplittableGrid remoteOutput;
+
+	/**
+	 * Constructor for SPMDTest.
+	 * 
+	 * @param name
+	 */
+	public SPMDTest(String name) {
+		super(name);
+	}
+
+	/**
+	 * Returns the JUnit test suite that implements the <b>SPMDTest</b>
+	 * definition.
+	 */
+	public static Test suite() {
+		TestSuite sPMDTest = new TestSuite("SPMDTest");
+//		sPMDTest.setArbiter(DefaultTestArbiter.INSTANCE).setId(
+//				"E873D66A70977ED2A98AAC10B54511DB");
+//
+//		sPMDTest.addTest(new SPMDTest("testSPMD").setId(
+//				"E873D66A70977ED2E5E8ED20B54511DB").setTestInvocationId(
+//				"E873D66A70977ED2EF7E3C00B54511DB"));
+		return sPMDTest;
+	}
+
+	/**
+	 * @see junit.framework.TestCase#setUp()
+	 */
+	protected void setUp() throws Exception {
+		PropertyConfigurator.configure("xululog4j.cfg");
+		computingResources = new GlobalDiscoveryService()
+				.getRemoteResources();
+
+		for (ComputingResourceContainer computingRes : computingResources) {
+			System.out.println("DiscoveredRessource " + computingRes);
+		}
+		LOG.info("Discovery finished...");
+		RemoteEventHandler handler = new RemoteEventHandler();
+		client = new ClientDataServer(handler);
+		clientController = new SPMDClientController(computingResources,null, client,handler);
+		// ////////// Initialise data \\\\\\\\\\\\\
+		WritableGridRaster baseGrid = GeoImportUtil
+				.readGridRasterFromArcInfoASCII(new File(
+						"../Xulu-Data/minigrid2.arc")); // small data
+//		 "../Xulu-Data/large_clue_data/sc1gr0.0")); //large data
+		gridInput = new SplittableLLProxyGrid(new WritableGridArrayFactory(),
+				new RasterMetaData(baseGrid));
+		localOutput = new SplittableLLProxyGrid(new WritableGridArrayFactory(),
+				new RasterMetaData(baseGrid));
+		remoteInput = new SplittableLLProxyGrid(new WritableGridArrayFactory(),
+				new RasterMetaData(baseGrid));
+		remoteOutput = new SplittableLLProxyGrid(
+				new WritableGridArrayFactory(), new RasterMetaData(baseGrid));
+		RasterUtil.copyInto(baseGrid, gridInput);
+		RasterUtil.copyInto(baseGrid, remoteInput);
+		//RasterUtil.copyInto(baseGrid, localOutput);
+		//RasterUtil.copyInto(baseGrid, remoteOutput);
+	}
+
+	/**
+	 * @see junit.framework.TestCase#tearDown()
+	 */
+	protected void tearDown() throws Exception {
+		client.close();
+		clientController.close();
+		// GlobalDiscoveryService.getInstance().stopServices();
+	}
+
+	/**
+	 * TestSPMD
+	 * 
+	 * @throws Exception
+	 */
+	public void testSPMD() throws Exception {
+		int steps = 3;
+		int neighborhoodRange = 6;
+		System.out.println("Starting step 1: ");
+				
+		/***********************************************************************
+		 * START LOCAL ALGORITHM ******************** The simple Algorithm will
+		 * calculate the average of the neighborhood und write the output to the
+		 * coresponing cell in the output cell
+		 **********************************************************************/
+
+		Rectangle partition = new Rectangle(0, 0, gridInput.getWidth(),
+				gridInput.getHeight());
+		if (gridInput.getWidth() < 20)
+			RasterUtil.printGrid(gridInput, 5, 1, "Input");
+		
+		for (int step = 0; step < steps; step++) {
+//			 the overallsum is simply the sum over all elements
+			float overallSum = 0f;
+			long localStartTime = System.currentTimeMillis();
+			for (int y = 0; y < gridInput.getHeight(); y++)
+				for (int x = 0; x < gridInput.getWidth(); x++) {
+					float tmp = gridInput.getRasterSampleAsFloat(x, y);
+					if (!Float.isNaN(tmp))
+						overallSum += tmp;
+					// the local sum is simply the sum over all elements in the
+					// neighborhood
+					float localSum = 0;
+					// number of cells over which the sum is calculated
+					int noOfCells = 0;
+					// for each cell: calculate the sum of all neighbors
+					for (int y2 = y - neighborhoodRange; y2 <= y
+							+ neighborhoodRange; y2++)
+						for (int x2 = x - neighborhoodRange; x2 <= x
+								+ neighborhoodRange; x2++)
+							// check if the coordinates are valid (inside the
+							// grid and not NaN)
+							if (partition.contains(x2, y2))
+								if (!Float.isNaN(gridInput
+										.getRasterSampleAsFloat(x2, y2))) {
+									localSum += gridInput
+											.getRasterSampleAsFloat(x2, y2);
+									noOfCells++;
+								}
+
+					localOutput.setRasterSample(localSum / (float) (noOfCells),
+							x, y);
+
+				}
+
+			System.out.print("Finished step " + (step+1) + " in "
+					+ ((System.currentTimeMillis() - localStartTime)) + " ms");
+			localStartTime = System.currentTimeMillis();
+			System.out.println(" with sum (local calculated): " + overallSum);
+			//copy values into results from output to input (for next step)
+			RasterUtil.copyInto(localOutput, gridInput);
+		 }
+		 if(gridInput.getWidth()<20)
+		 RasterUtil.printGrid(localOutput, 5, 1, "Local Output");
+
+		/***********************************************************************
+		 * START REMOTE ALGORITHM
+		 *  ******************** All the same..now remotely********************/
+		 //set back the grid to the original input
+		 
+		 System.out
+				.println("******************* starting remote execution *****************");
+		long remoteStartTime = System.currentTimeMillis();
+		clientController.setNeighborhoodRange(neighborhoodRange);
+		clientController.addToSplitControl(remoteInput, "inputGrid");
+		clientController.addToSplitControl(remoteOutput, "outputGrid");
+		System.out.println("After "
+				+ ((System.currentTimeMillis() - remoteStartTime))
+				+ "ms: finished with adding to splitcontroll");
+		
+		//********************** START STEP CONTROL *********************
+		for (int step = 0; step < steps; step++) {
+			if(step > 0){
+				long updateStartTime = System.currentTimeMillis();
+				clientController.updateNeighborhood(remoteInput);
+				System.out.println("Update took:" + (System.currentTimeMillis()-updateStartTime));
+			}
+			try {
+				Object[] sum =clientController.runSPMDModelTask(
+						new AverageNeighborhoodTestTask(), neighborhoodRange);
+//				add results
+				float overallSum = 0;
+				for (int i = 0; i < sum.length; i++)
+					overallSum += (Float) sum[i];
+				System.out.println("finished step "
+						+ (step+1) + " in "
+						+ ((System.currentTimeMillis() - remoteStartTime))
+						+ "ms " + " with sum "+
+						+ overallSum);
+				remoteStartTime = System.currentTimeMillis();
+			} catch (Throwable e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+		}
+		//***************** END STEP CONTROL *****************************
+		
+		//After execution:
+		// merge partitions and check if the local and remotely calculated
+		// versions are equal
+		remoteStartTime = System.currentTimeMillis();
+		clientController.mergePartition(remoteOutput);
+		System.out.println("Merging took another "
+				+ ((System.currentTimeMillis() - remoteStartTime))
+				+ "ms");
+		// Thread.currentThread().sleep(10000);
+		 if(remoteInput.getWidth()<20)
+			 RasterUtil.printGrid(remoteOutput, 5, 1, "Remote Output");
+		assertTrue(RasterUtil.checkEqual(remoteOutput, localOutput, true));
+	}
+}

Added: trunk/src/appl/parallel/test/SPMDTest.testsuite
===================================================================
(Binary files differ)


Property changes on: trunk/src/appl/parallel/test/SPMDTest.testsuite
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/appl/parallel/test/SPMDTest_MultiGrid.java
===================================================================
--- trunk/src/appl/parallel/test/SPMDTest_MultiGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/test/SPMDTest_MultiGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,259 @@
+package appl.parallel.test;
+
+import java.awt.Rectangle;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.Serializable;
+import java.util.Random;
+import java.util.Vector;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.apache.log4j.BasicConfigurator;
+import org.apache.log4j.ConsoleAppender;
+import org.apache.log4j.Layout;
+import org.apache.log4j.Level;
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+import org.apache.log4j.PropertyConfigurator;
+
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.plugin.io.grid.array.WritableGridArrayFactory;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.WritableGridArray;
+import schmitzm.data.WritableGridRaster;
+import schmitzm.geotools.io.GeoImportUtil;
+
+import appl.parallel.ComputingResourceContainer;
+import appl.parallel.client.RemoteEventHandler;
+import appl.parallel.client.ClientDataServer;
+import appl.parallel.data.splittable.SplittableLLProxyGrid;
+import appl.parallel.services.GlobalDiscoveryService;
+import appl.parallel.spmd.AbstractSPMDTask;
+import appl.parallel.spmd.SPMDClientController;
+import appl.parallel.spmd.SPMDTask;
+import appl.parallel.spmd.SPMDServerController;
+import appl.parallel.spmd.split.SplittableGrid;
+import appl.util.RasterMetaData;
+import appl.util.RasterUtil;
+
+/**
+ * This is a minor modification of {@link SPMDTest}. It is only used to test the
+ * Multi-Splittable functionality of the parallelization. For the test of all
+ * other features and more detailed information see {@link SPMDTest}.
+ * 
+ * @author Dominik Appl
+ */
+public class SPMDTest_MultiGrid extends TestCase implements Serializable {
+
+	transient private final Logger LOG = LogManager.getLogger(this.getClass()
+			.getName());
+
+	transient private ClientDataServer client;
+	transient private Vector<ComputingResourceContainer> computingResources;
+	transient private SPMDClientController clientController;
+
+	transient SplittableGrid gridInput;
+	transient SplittableGrid remoteInput;
+	transient SplittableGrid localOutput;
+	transient SplittableGrid remoteOutput;
+
+	/**
+	 * Constructor for SPMDTest.
+	 * 
+	 * @param name
+	 */
+	public SPMDTest_MultiGrid(String name) {
+		super(name);
+	}
+
+	/**
+	 * Returns the JUnit test suite that implements the <b>SPMDTest</b>
+	 * definition.
+	 */
+	public static Test suite() {
+		TestSuite sPMDTest = new TestSuite("SPMDTest");
+//		sPMDTest.setArbiter(DefaultTestArbiter.INSTANCE).setId(
+//				"E873D66A70977ED2A98AAC10B54511DB");
+//
+//		sPMDTest.addTest(new SPMDTest("testSPMD").setId(
+//				"E873D66A70977ED2E5E8ED20B54511DB").setTestInvocationId(
+//				"E873D66A70977ED2EF7E3C00B54511DB"));
+		return sPMDTest;
+	}
+
+	/**
+	 * @see junit.framework.TestCase#setUp()
+	 */
+	protected void setUp() throws Exception {
+		PropertyConfigurator.configure("xululog4j.cfg");
+		computingResources = new GlobalDiscoveryService()
+				.getRemoteResources();
+
+		for (ComputingResourceContainer computingRes : computingResources) {
+			System.out.println("DiscoveredRessource " + computingRes);
+		}
+		LOG.info("Discovery finished...");
+		RemoteEventHandler handler = new RemoteEventHandler();
+		client = new ClientDataServer(handler);
+		clientController = new SPMDClientController(computingResources,null, client,handler);
+		// ////////// Initialise data \\\\\\\\\\\\\
+		WritableGridRaster baseGrid = GeoImportUtil
+				.readGridRasterFromArcInfoASCII(new File(
+						"../Xulu-Data/minigrid2.arc")); // small data
+//		 "../Xulu-Data/large_clue_data/sc1gr0.0")); //large data
+		gridInput = new SplittableLLProxyGrid(new WritableGridArrayFactory(),
+				new RasterMetaData(baseGrid));
+		localOutput = new SplittableLLProxyGrid(new WritableGridArrayFactory(),
+				new RasterMetaData(baseGrid));
+		remoteInput = new SplittableLLProxyGrid(new WritableGridArrayFactory(),
+				new RasterMetaData(baseGrid));
+		remoteOutput = new SplittableLLProxyGrid(
+				new WritableGridArrayFactory(), new RasterMetaData(baseGrid));
+		RasterUtil.copyInto(baseGrid, gridInput);
+		RasterUtil.copyInto(baseGrid, remoteInput);
+		//RasterUtil.copyInto(baseGrid, localOutput);
+		//RasterUtil.copyInto(baseGrid, remoteOutput);
+	}
+
+	/**
+	 * @see junit.framework.TestCase#tearDown()
+	 */
+	protected void tearDown() throws Exception {
+		client.close();
+		clientController.close();
+		// GlobalDiscoveryService.getInstance().stopServices();
+	}
+
+	/**
+	 * TestSPMD
+	 * 
+	 * @throws Exception
+	 */
+	public void testSPMD() throws Exception {
+		int steps = 4;
+		int neighborhoodRange = 3;
+		System.out.println("Starting step 1: ");
+				
+		/***********************************************************************
+		 * START LOCAL ALGORITHM ******************** The simple Algorithm will
+		 * calculate the average of the neighborhood und write the output to the
+		 * coresponing cell in the output cell
+		 **********************************************************************/
+
+		Rectangle partition = new Rectangle(0, 0, gridInput.getWidth(),
+				gridInput.getHeight());
+		if (gridInput.getWidth() < 20)
+			RasterUtil.printGrid(gridInput, 5, 1, "Input");
+		
+		for (int step = 0; step < steps; step++) {
+//			 the overallsum is simply the sum over all elements
+			float overallSum = 0f;
+			long localStartTime = System.currentTimeMillis();
+			for (int y = 0; y < gridInput.getHeight(); y++)
+				for (int x = 0; x < gridInput.getWidth(); x++) {
+					float tmp = gridInput.getRasterSampleAsFloat(x, y);
+					if (!Float.isNaN(tmp))
+						overallSum += tmp;
+					// the local sum is simply the sum over all elements in the
+					// neighborhood
+					float localSum = 0;
+					// number of cells over which the sum is calculated
+					int noOfCells = 0;
+					// for each cell: calculate the sum of all neighbors
+					for (int y2 = y - neighborhoodRange; y2 <= y
+							+ neighborhoodRange; y2++)
+						for (int x2 = x - neighborhoodRange; x2 <= x
+								+ neighborhoodRange; x2++)
+							// check if the coordinates are valid (inside the
+							// grid and not NaN)
+							if (partition.contains(x2, y2))
+								if (!Float.isNaN(gridInput
+										.getRasterSampleAsFloat(x2, y2))) {
+									localSum += gridInput
+											.getRasterSampleAsFloat(x2, y2);
+									noOfCells++;
+								}
+
+					localOutput.setRasterSample(localSum / (float) (noOfCells),
+							x, y);
+
+				}
+
+			System.out.print("Finished step " + (step+1) + " in "
+					+ ((System.currentTimeMillis() - localStartTime)) + " ms");
+			localStartTime = System.currentTimeMillis();
+			System.out.println(" with sum (local calculated): " + overallSum);
+			//copy values into results from output to input (for next step)
+			RasterUtil.copyInto(localOutput, gridInput);
+		 }
+		 if(gridInput.getWidth()<20)
+		 RasterUtil.printGrid(localOutput, 5, 1, "Local Output");
+
+		
+		 
+		 
+		 /***********************************************************************
+		 * 							START REMOTE ALGORITHM
+		 *  ******************** All the same..now remotely********************/
+		 
+		 System.out
+				.println("******************* starting remote execution *****************");
+		long remoteStartTime = System.currentTimeMillis();
+		clientController.setNeighborhoodRange(neighborhoodRange);
+//		initialize as MulitSplittable
+		WritableGrid[] testSplittable = {remoteInput,remoteOutput};
+		clientController.addToMultiDataSplitControl(testSplittable, "gridData");
+		
+//		clientController.addToSplitControl(remoteInput, "inputGrid");
+//		clientController.addToSplitControl(remoteOutput, "outputGrid");
+		System.out.println("After "
+				+ ((System.currentTimeMillis() - remoteStartTime))
+				+ "ms: finished with adding to splitcontroll");
+		
+		//********************** START STEP CONTROL *********************
+		for (int step = 0; step < steps; step++) {
+			if(step > 0){
+				long updateStartTime = System.currentTimeMillis();
+				clientController.updateNeighborhood(remoteInput);
+				System.out.println("Update took:" + (System.currentTimeMillis()-updateStartTime));
+			}
+			Object[] sum;
+			try {
+				sum = clientController.runSPMDModelTask(
+						new AverageNeighborhoodTestTask_MultiGrid(), neighborhoodRange);
+				//add results
+				float overallSum = 0;
+				for (int i = 0; i < sum.length; i++)
+					overallSum += (Float) sum[i];
+				System.out.println("finished step "
+						+ (step+1) + " in "
+						+ ((System.currentTimeMillis() - remoteStartTime))
+						+ "ms " + " with sum "+
+						+ overallSum);
+				remoteStartTime = System.currentTimeMillis();
+				
+			} catch (Throwable e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+		}
+		//***************** END STEP CONTROL *****************************
+		
+		//After execution:
+		// merge partitions and check if the local and remotely calculated
+		// versions are equal
+		remoteStartTime = System.currentTimeMillis();
+		clientController.mergePartition(remoteOutput);
+		System.out.println("Merging took another "
+				+ ((System.currentTimeMillis() - remoteStartTime))
+				+ "ms");
+		// Thread.currentThread().sleep(10000);
+		 if(remoteInput.getWidth()<20)
+			 RasterUtil.printGrid(remoteOutput, 5, 1, "Remote Output");
+		assertTrue(RasterUtil.checkEqual(remoteOutput, localOutput, true));
+	}
+}

Added: trunk/src/appl/parallel/test/SplitMapTest.java
===================================================================
--- trunk/src/appl/parallel/test/SplitMapTest.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/test/SplitMapTest.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,184 @@
+package appl.parallel.test;
+
+import java.awt.Rectangle;
+import java.io.File;
+import java.io.FileInputStream;
+
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import appl.parallel.data.splittable.SplittableGridLLFactory;
+import appl.parallel.data.splittable.SplittableLLProxyGrid;
+import appl.parallel.spmd.split.AbstractSplitMap;
+import appl.parallel.spmd.split.SplitMap;
+import appl.parallel.spmd.split.SplitMap1DHorizontal;
+import appl.parallel.spmd.split.SplitMap1DVertical;
+import appl.parallel.spmd.split.SplitMap2D;
+import appl.parallel.util.Helper;
+import appl.util.GeneralUtil;
+import appl.util.RasterMetaData;
+import appl.util.RasterUtil;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.WritableGridRaster;
+import schmitzm.geotools.io.GeoImportUtil;
+
+/**
+ * Generated code for the test suite <b>SplitMapTest</b> located at
+ * <i>/XuluSVN/javasrc/appl/parallel/test/SplitMapTest.testsuite</i>.
+ *
+ * Tests different splitmaps
+ */
+public class SplitMapTest extends TestCase {
+
+	Rectangle globalCalcBounds;
+
+	Rectangle partitionCalcBounds;
+
+	Rectangle partitionNeighborhoodBounds;
+
+	Rectangle globalNeighborhoodBounds;
+
+	Rectangle localCalcBounds;
+
+	Rectangle localNeighborhoodBounds;
+
+	private SplittableLLProxyGrid baseGrid;
+
+	private SplitMap map;
+
+	/**
+	 * Constructor for SplitMapTest.
+	 * @param name
+	 */
+	public SplitMapTest(String name) {
+		super(name);
+	}
+
+	/**
+	 * Returns the JUnit test suite that implements the <b>SplitMapTest</b>
+	 * definition.
+	 */
+	public static Test suite() {
+		TestSuite splitMapTest = new TestSuite("SplitMapTest");
+		//		splitMapTest.setArbiter(DefaultTestArbiter.INSTANCE).setId(
+		//				"D35DB07792EF13413F23D9D0B19111DB");
+		//	
+		//		splitMapTest.addTest(new SplitMapTest("test1DSplitMap").setId(
+		//				"D35DB07792EF134149AEAC40B19111DB").setTestInvocationId(
+		//				"D35DB07792EF134168064FE0B19111DB"));
+		return splitMapTest;
+	}
+
+	/**
+	 * @see junit.framework.TestCase#setUp()
+	 */
+	protected void setUp() throws Exception {
+		//		load a very simple 10x10 Grid 
+		WritableGrid loadGrid = GeoImportUtil
+				.readGridRasterFromArcInfoASCII(new File(
+						"../Xulu-Data/regularGrid.arc"));
+		baseGrid = new SplittableLLProxyGrid(new RasterMetaData(loadGrid),2);
+		RasterUtil.copyInto(loadGrid, baseGrid);
+		//RasterUtil.printGrid(baseGrid, "Base grid");
+	}
+
+	/**
+	 * @see junit.framework.TestCase#tearDown()
+	 */
+	protected void tearDown() throws Exception {
+	}
+
+	public void basicTest() {
+		//make simply 2 Partitions without neighborhood
+		map.makeMap();
+		//check first partition
+		initVariables(map, 0);
+		assertEquals(new Rectangle(0, 0, 10, 10), globalCalcBounds);
+		assertEquals(new Rectangle(0, 0, 10, 10), globalNeighborhoodBounds);
+		assertEquals(new Rectangle(0, 0, 5, 10), partitionCalcBounds);
+		assertEquals(new Rectangle(0, 0, 5, 10), partitionNeighborhoodBounds);
+		assertEquals(new Rectangle(0, 0, 5, 10), localCalcBounds);
+		assertEquals(new Rectangle(0, 0, 5, 10), localNeighborhoodBounds);
+		//check second partition
+		initVariables(map, 1);
+		assertEquals(globalCalcBounds, new Rectangle(0, 0, 10, 10));
+		assertEquals(globalNeighborhoodBounds, new Rectangle(0, 0, 10, 10));
+		assertEquals(partitionCalcBounds, new Rectangle(5, 0, 5, 10));
+		assertEquals(partitionNeighborhoodBounds, new Rectangle(5, 0, 5, 10));
+		assertEquals(localCalcBounds, new Rectangle(0, 0, 5, 10));
+		assertEquals(localNeighborhoodBounds, new Rectangle(0, 0, 5, 10));
+	}
+
+	public void test1DHorizontal() {
+        //2 Partitions
+		map = new SplitMap1DHorizontal(baseGrid.getWidth(), baseGrid.getHeight(),
+				1, 2, AbstractSplitMap.NeighborhoodBoxingMode.inBoxing);
+		
+		
+	    
+	    map = new SplitMap1DHorizontal(baseGrid.getWidth(), baseGrid.getHeight(),
+				1, 3, AbstractSplitMap.NeighborhoodBoxingMode.inBoxing);
+	   
+	    
+	}
+	
+	public void print(){
+		for(int i=0; i < map.getCount(); i++){
+			RasterUtil.printGrid(baseGrid.getPartition(map.getPartitionCalculationBounds(i)),3,0,"Calculation Partition " + (i+1) + "/" + map.getCount());
+		}
+		for(int i=0; i < map.getCount(); i++){
+			RasterUtil.printGrid(baseGrid.getPartition(map.getPartitionNeighborhoodBounds(i)),3,0,"Neighborhood Partition " + (i+1) + "/" + map.getCount());
+		}
+	}
+	
+	public void test2DIrregular(){
+//		map = new SplitMap2D(10, 10,
+//				1, 3, AbstractSplitMap.NeighborhoodBoxingMode.inBoxing);
+		
+	    map = new SplitMap2D(baseGrid.getWidth(), baseGrid.getHeight(),
+				1, 9, AbstractSplitMap.NeighborhoodBoxingMode.inBoxing);
+	    print();
+	}
+
+	/**
+	 * 1DSplitMap
+	 * @throws Exception
+	 */
+	public void test1DVertical() throws Exception {
+		//2 Partitions
+		map = new SplitMap1DVertical(baseGrid.getWidth(), baseGrid.getHeight(),
+				0, 2, AbstractSplitMap.NeighborhoodBoxingMode.inBoxing);
+		basicTest();
+		//make 3 Partitions
+		map = new SplitMap1DVertical(baseGrid.getWidth(), baseGrid.getHeight(),
+				0, 3, AbstractSplitMap.NeighborhoodBoxingMode.inBoxing);
+		
+		//make 2 Partitions with neighborhoodrange 2
+		map = new SplitMap1DVertical(baseGrid.getWidth(), baseGrid.getHeight(),
+				2, 2, AbstractSplitMap.NeighborhoodBoxingMode.inBoxing);
+		//intersect the partitions and see if you have the right rect
+
+		Rectangle r = map.getPartitionNeighborhoodBounds(0).intersection(
+				map.getPartitionNeighborhoodBounds(1));
+		assertEquals(new Rectangle(3, 0, 4, 10), r);
+
+		initVariables(map, 1);
+	}
+
+	/**
+	 * @param map
+	 */
+	private void initVariables(SplitMap map, int pos) {
+		globalCalcBounds = map.getGlobalCalculationBounds();
+		partitionCalcBounds = map.getPartitionCalculationBounds(pos);
+		partitionNeighborhoodBounds = map.getPartitionNeighborhoodBounds(pos);
+		globalNeighborhoodBounds = map.getGlobalBounds();
+		localCalcBounds = map.getLocalCalculationBounds(pos);
+		localNeighborhoodBounds = map.getLocalNeighborhoodBounds(pos);
+
+	}
+
+}

Added: trunk/src/appl/parallel/test/SplitMaps.testsuite
===================================================================
(Binary files differ)


Property changes on: trunk/src/appl/parallel/test/SplitMaps.testsuite
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/appl/parallel/test/XuluGridTestCase.java
===================================================================
--- trunk/src/appl/parallel/test/XuluGridTestCase.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/test/XuluGridTestCase.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,159 @@
+package appl.parallel.test;
+
+import java.awt.Rectangle;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import edu.bonn.xulu.plugin.io.grid.array.WritableGridArrayFactory_ArcInfoAsciiGrid;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.WritableGridArray;
+import schmitzm.data.WritableGridRaster;
+import schmitzm.geotools.io.GeoExportUtil;
+import schmitzm.geotools.io.GeoImportUtil;
+import appl.parallel.data.xulugridfile.XuluGridFile;
+import appl.parallel.spmd.split.WritableGridPartition;
+import appl.util.RasterMetaData;
+import appl.util.RasterUtil;
+
+/**
+ * Generated code for the test suite <b>XuluGridTestCase</b> located at
+ * <i>/Xulu-latest/javasrc/appl/test/XuluGridTestCase.testsuite</i>.
+ *
+ * Extensivly tests the XuluGridFile for errors
+ */
+public class XuluGridTestCase extends TestCase {
+	 XuluGridFile gridFile;
+	
+	/**
+	 * Constructor for XuluGridTestCase.
+	 * @param name
+	 */
+	public XuluGridTestCase(String name) {
+		super(name);
+	}
+
+	/**
+	 * Returns the JUnit test suite that implements the <b>XuluGridTestCase</b>
+	 * definition.
+	 */
+	public static Test suite() {
+		TestSuite xuluGridTestCase = new TestSuite("XuluGridTestCase");
+//		xuluGridTestCase.setArbiter(DefaultTestArbiter.INSTANCE).setId(
+//				"D14CC6AE1994BD92F864B0C0A54011DB");
+//	
+//		xuluGridTestCase.addTest(new XuluGridTestCase("testReadingPartitialGrid")
+//				.setId("D14CC6AE1994BD92132B3E60A54111DB").setTestInvocationId(
+//						"D14CC6AE1994BD9269E4C820A54111DB"));
+//	
+//		xuluGridTestCase.addTest(new XuluGridTestCase("testMartin").setId(
+//				"D14CC6AE1994BD92FC1EA54AA62111DB").setTestInvocationId(
+//				"D14CC6AE1994BD9262B92000A62211DB"));
+		return xuluGridTestCase;
+	}
+
+	/**
+	 * @see junit.framework.TestCase#setUp()
+	 */
+	protected void setUp() throws Exception {
+	}
+
+	/**
+	 * @see junit.framework.TestCase#tearDown()
+	 */
+	protected void tearDown() throws Exception {
+		if (gridFile!=null) 
+			gridFile.close();	
+	}
+
+    /**
+	* testReadingPartitial Grid
+	* @throws Exception
+	*/
+	public void testReadingPartitialGrid()
+	throws Exception
+	{
+		
+		//base file: all assertions are checked against this grid
+		WritableGridRaster baseGrid = GeoImportUtil.readGridRasterFromArcInfoASCII(new File("../Xulu-Data/minigrid.arc"));
+		printSmall(baseGrid);
+		GeoExportUtil.writeGridRasterToArcInfoASCII(baseGrid, new File("BaseGridExport_miniGrid_export1"));
+        
+		// write a XuluGridFile / check it against baseGrid 
+        File file = new File("XuluGridFile_miniGrid.xgrid");
+        XuluGridFile.writeToXuluGridFile(baseGrid,file);
+        // fill the grid2 with any Data
+        WritableGrid grid2 = GeoImportUtil.readGridRasterFromArcInfoASCII(new File("../Xulu-Data/SimpleGrid.arc"));
+        assertFalse(RasterUtil.checkEqual(baseGrid,grid2,true));
+        XuluGridFile.readIntoGridFromXuluGridFile(grid2, file);
+        assertTrue(RasterUtil.checkEqual(baseGrid,grid2,true));
+        
+        //export und reimport an check it again (this caused some hard to trace errors in the past, even if it should not.)
+        GeoExportUtil.writeGridRasterToArcInfoASCII((WritableGridRaster)grid2, new File("BaseGridExport_miniGrid_export2"));
+        grid2 = GeoImportUtil.readGridRasterFromArcInfoASCII(new File("BaseGridExport_miniGrid_export2"));
+        assertTrue(RasterUtil.checkEqual(baseGrid,grid2,true));
+        
+        //initialize a new XuluGrid 
+        gridFile = new XuluGridFile(new File("XuluGridFile_miniGrid.xgrid"),"r");
+        RasterMetaData meta = gridFile.getMetaData();
+        //get the whole gridFile using the partition method and check it
+        WritableGrid wholeGrid = gridFile.getPartitialGrid2D(new Rectangle(0, 0, meta.getWidth(), meta.getHeight()));
+        assertTrue(RasterUtil.checkEqual(baseGrid,wholeGrid,true));
+        assertTrue(RasterUtil.checkEqual(grid2,wholeGrid,true));
+        //write all data from wholeGrid into grid2, then export grid2
+        for (int y = meta.getMinY(); y < meta.getHeight()- meta.getMinY(); y++)
+        		for (int x = meta.getMinX(); x < meta.getWidth() - meta.getMinY(); x++)
+        			grid2.setRasterSample(wholeGrid.getRasterSample(x,y),x,y);
+        GeoExportUtil.writeGridRasterToArcInfoASCII(baseGrid, new File("XuluGrid2FromWholeGrid_test"));
+        	        
+        
+        //new WritableGridArrayFactory_ArcInfoAsciiGrid().exportObject(wholeGrid, new BufferedOutputStream(new FileOutputStream("XuluGridTest_ARCINFO2")));
+        
+//        for (y = 1; y < metadata.getheight(); y++)
+//            for (x = 1; x < metadata.getwidth(); x++) {
+        //get left half of the gridFile
+        WritableGrid leftHalf = gridFile.getPartitialGrid2D(new Rectangle(0, 0, (meta.getWidth()/2), meta.getHeight()));
+        new WritableGridArrayFactory_ArcInfoAsciiGrid().exportObject(leftHalf, new BufferedOutputStream(new FileOutputStream("LeftHalf_XULUGRID")));
+        
+        //########################### no gridfile test ###############################
+        XuluGridFile gridfile = new XuluGridFile(new File("XuluGridFile_miniGrid.xgrid"),"rw");
+        WritableGridPartition partition = gridfile.getPartitialGrid2D(new Rectangle(0,0,5,5));
+        printSmall(partition);
+         partition = gridfile.getPartitialGrid2D(new Rectangle(0,0,4,4));
+        printSmall(partition);
+         partition = gridfile.getPartitialGrid2D(new Rectangle(1,1,8,8));
+        printSmall(partition);
+         partition = gridfile.getPartitialGrid2D(new Rectangle(5,5,5,5));
+        printSmall(partition);
+         partition = gridfile.getPartitialGrid2D(new Rectangle(1,1,2,2));
+        printSmall(partition);
+        
+}
+	/**
+	 * prints only small grids
+	 * 
+	 * @param grid
+	 */
+	public void printSmall(WritableGrid grid){
+		if(grid.getWidth()<20 && grid.getHeight()<20)
+			RasterUtil.printGrid(grid,5,1,"output");
+	}
+
+public void testMartin()
+	throws Exception
+	{
+		WritableGridRaster baseGrid = GeoImportUtil.readGridRasterFromArcInfoASCII(new File("../Xulu-Data/standard_clue_data/CLUE-Datensatz1/sc1gr0.23"));
+		WritableGridArray testGrid = new WritableGridArray.Float(baseGrid.getMinX(),baseGrid.getMinY(),baseGrid.getWidth(),baseGrid.getHeight(),baseGrid.getX(),baseGrid.getY(),baseGrid.getRealWidth(),baseGrid.getRealHeight(),null,null);
+		for (int y = baseGrid.getMinY(); y < baseGrid.getHeight()- baseGrid.getMinY(); y++)
+    		for (int x = baseGrid.getMinX(); x < baseGrid.getWidth() - baseGrid.getMinY(); x++)
+    			testGrid.setRasterSample(baseGrid.getRasterSample(x,y),x,y);
+       GeoExportUtil.writeGridRasterToArcInfoASCII(baseGrid, new File("Test_baseGrid"));
+       new WritableGridArrayFactory_ArcInfoAsciiGrid().exportObject(testGrid,new FileOutputStream("Test_testGrid2"));
+	}
+}

Added: trunk/src/appl/parallel/test/XuluGridTestCase.testsuite
===================================================================
(Binary files differ)


Property changes on: trunk/src/appl/parallel/test/XuluGridTestCase.testsuite
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/appl/parallel/test/XuluServerTest.java
===================================================================
--- trunk/src/appl/parallel/test/XuluServerTest.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/test/XuluServerTest.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,113 @@
+package appl.parallel.test;
+
+import java.io.Serializable;
+import java.net.MalformedURLException;
+import java.rmi.Naming;
+import java.rmi.NotBoundException;
+import java.rmi.RemoteException;
+
+import appl.parallel.server.XuluServer;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Generated code for the test suite <b>XuluServerTest</b> located at
+ * <i>/XuluSVN/javasrc/appl/parallel/test/XuluServerTest.testsuite</i>.
+ *
+ * Tests the Server functionality
+ */
+public class XuluServerTest extends TestCase {
+	public final String IP = "192.168.18.238";
+	XuluServer server;
+
+	/**
+	 * @see junit.framework.TestCase#setUp()
+	 */
+	protected void setUp() throws Exception {
+		String name = "rmi://" + IP + "/XuluServer";
+
+		server = (XuluServer) Naming.lookup(name);
+
+
+	}
+
+	/**
+	 * Constructor for XuluServerTest.
+	 * @param whatsthis
+	 */
+	public XuluServerTest(String whatsthis) {
+		super(whatsthis);
+	}
+
+	/**
+	 * Returns the JUnit test suite that implements the <b>XuluServerTest</b>
+	 * definition.
+	 */
+	public static Test suite() {
+		TestSuite xuluServerTest = new TestSuite("XuluServerTest");
+//		xuluServerTest.setArbiter(DefaultTestArbiter.INSTANCE).setId(
+//				"F534D0796F99AD6BA80D9B00A9AA11DB");
+
+		return xuluServerTest;
+	}
+
+
+	/**
+	 * @see junit.framework.TestCase#tearDown()
+	 */
+	protected void tearDown() throws Exception {
+	}
+
+    /**
+		* testServer
+		* @throws Exception
+		*/
+		public void testPingServer()
+		throws Exception
+		{
+			  try{
+			    	Object data;
+			    	PingTestObject pingObj = new PingTestObject(32);
+	    			// do 10 pings
+					long sum1 = 0;
+					for (int i = 0; i < 10; i++) {
+						long mstime = System.currentTimeMillis();
+			            data = server.ping(pingObj);
+				        long mstimediff = System.currentTimeMillis() - mstime;
+				        sum1 += mstimediff;
+				       // Thread.sleep(100);
+					}
+					long sum2 = 0;
+					for (int i = 0; i < 10; i++) {
+						long nanotime = System.nanoTime();
+			            data = server.ping(pingObj);
+				        long nanolatency = System.nanoTime() - nanotime;
+				        double timediff = (double)nanolatency / 1000000.0;
+				        sum2+= nanolatency;
+				        //Thread.sleep(100);
+					}
+					System.out.println("Average MS: " + sum1/10 + " Average nano: " + (double)sum2 / 10000000.0  );
+
+
+				} catch (RemoteException e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				}
+
+
+		}
+
+    /**
+	* sendModel
+	* @throws Exception
+	*/
+	public void testSendModel()
+	throws Exception
+	{
+		System.out.println("fu");
+	// Enter your code here
+	}
+
+}

Added: trunk/src/appl/parallel/test/XuluServerTest.testsuite
===================================================================
(Binary files differ)


Property changes on: trunk/src/appl/parallel/test/XuluServerTest.testsuite
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/appl/parallel/test/generalTestClass.java
===================================================================
--- trunk/src/appl/parallel/test/generalTestClass.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/test/generalTestClass.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,20 @@
+package appl.parallel.test;
+
+
+import java.awt.Rectangle;
+
+
+import schmitzm.data.WritableGrid;
+
+/**
+ * @author Dominik Appl
+ */
+public class generalTestClass {
+
+	public static void main(String[] args) {
+		String testString = "Blueberry";
+		System.out.println(testString.getClass().getCanonicalName());
+	}
+
+
+}

Added: trunk/src/appl/parallel/test/package.html
===================================================================
--- trunk/src/appl/parallel/test/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/test/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,5 @@
+<html>
+<body>
+	Contains some thread related classes.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/parallel/thread/ComputingResourceThread.java
===================================================================
--- trunk/src/appl/parallel/thread/ComputingResourceThread.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/thread/ComputingResourceThread.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,25 @@
+package appl.parallel.thread;
+
+import appl.parallel.ComputingResource;
+import appl.parallel.ComputingResourceProperties;
+import appl.parallel.event.CommEventSink;
+import appl.parallel.event.CommEvent.CommType;
+
+/**
+ * @author Dominik Appl
+ */
+public abstract class ComputingResourceThread extends ExecutionThread{
+
+	
+	 public ComputingResourceThread(ComputingResource resource, ComputingResourceProperties resourceInfos, Object argument,  CommType type, CommEventSink sink){
+			super(resource, resourceInfos, argument,type,sink,false);
+		}
+	 
+	 public ComputingResourceThread(ComputingResource resource, ComputingResourceProperties resourceInfos, Object argument,  CommType type, CommEventSink sink, boolean disableTransferEvents){
+			super(resource, resourceInfos, argument,type,sink,disableTransferEvents);
+		}
+		
+		protected ComputingResource getServer(){
+			return (ComputingResource) server;
+		}
+}

Added: trunk/src/appl/parallel/thread/DataServerThread.java
===================================================================
--- trunk/src/appl/parallel/thread/DataServerThread.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/thread/DataServerThread.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,25 @@
+package appl.parallel.thread;
+
+import appl.parallel.ComputingResourceProperties;
+import appl.parallel.event.CommEventSink;
+import appl.parallel.event.CommEvent.CommType;
+import appl.parallel.server.PartitionDataServer;
+
+/**
+ * @author Dominik Appl
+ */
+public abstract class DataServerThread extends ExecutionThread {
+	
+	public DataServerThread(PartitionDataServer dataServer,ComputingResourceProperties resourceInfos, Object argument,CommType type, CommEventSink sink){
+		super(dataServer,resourceInfos,argument,type,sink,false);
+	}
+	
+	public DataServerThread(PartitionDataServer dataServer,ComputingResourceProperties resourceInfos, Object argument,CommType type, CommEventSink sink, boolean disableTransferEvents){
+		super(dataServer,resourceInfos,argument,type,sink,disableTransferEvents);
+	}
+	
+	protected PartitionDataServer getServer(){
+		return (PartitionDataServer) server;
+	}
+	
+}
\ No newline at end of file

Added: trunk/src/appl/parallel/thread/ExecutionThread.java
===================================================================
--- trunk/src/appl/parallel/thread/ExecutionThread.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/thread/ExecutionThread.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,158 @@
+package appl.parallel.thread;
+
+import java.nio.channels.Pipe.SinkChannel;
+import java.rmi.RemoteException;
+import java.util.concurrent.Callable;
+
+import appl.parallel.ComputingResourceProperties;
+import appl.parallel.client.RemoteEventHandler;
+import appl.parallel.event.CommEvent;
+import appl.parallel.event.CommEventSink;
+import appl.parallel.event.TimeEvent;
+import appl.parallel.event.TransferEvent;
+import appl.parallel.event.CommEvent.CommType;
+
+/**
+ * A simple helper class for more easy Thread handling with anonymous classes.
+ *
+ * @see DataServerThread
+ * @see ComputingResourceThread
+ *
+ * @author Dominik Appl
+ */
+public abstract class ExecutionThread implements Callable {
+
+	protected final Object server;
+
+	protected final Object argument;
+
+	protected final CommType commType;
+
+	protected final ComputingResourceProperties serverInfos;
+
+	protected final CommEventSink eventSink;
+
+	protected boolean disableTransferEvents=false;
+
+	/**
+	 * creates a new thread
+	 *
+	 * @param server
+	 *            the server which is accessed with this thread
+	 * @param serverInfos the serverinfos (used for event info)
+	 * @param argument
+	 *            an argument which can be used inside the anonymous class
+	 * @param type the type of the communication
+	 * @param sink events are submitted to this sink
+	 * @param disableTransferEvents says whether to ignore transfer events (if the transfer volume is to low to be counted))
+	 */
+	public ExecutionThread(Object server,
+			ComputingResourceProperties serverInfos, Object argument,
+			CommType type, CommEventSink sink, boolean disableTransferEvents) {
+		this.server = server;
+		this.serverInfos = serverInfos;
+		this.argument = argument;
+		this.commType = type;
+		this.eventSink = sink;
+		this.disableTransferEvents = disableTransferEvents;
+	}
+
+	/**
+	 * @return the server given the constructor (should be overwrited by a
+	 *         subclass)
+	 */
+	protected Object getServer() {
+		return server;
+	}
+
+	/**
+	 * @return the argument given in the constructor as int value
+	 */
+	protected int getIntArgument() {
+		return (Integer) argument;
+	}
+
+	/**
+	 * @return the argument given in the constructor as object value
+	 */
+	protected Object getObjectArgument() {
+		return argument;
+	}
+
+	/**
+	 * @return the argument given in the constructor as array value
+	 */
+	protected Object[] getObjectArrayArgument() {
+		return (Object[]) argument;
+	}
+
+	/**
+	 * Sends standard {@link CommEvent CommEvents} to the {@link CommEventSink} given with the
+	 * constructor. Executes the {@link #run()} method and returns its result.
+	 *
+	 * @return the result of {@link #run()}.
+	 *
+	 * @see java.util.concurrent.Callable#call()
+	 */
+	public Object call() throws Exception {
+		long l = System.nanoTime();
+		Object result = run();
+		if (eventSink.isTimeMonitoringEnabled())
+			fireTimeEvents((System.nanoTime() - l), result);
+		if (eventSink.isTransferMonitoringEnabled())
+			fireTransferEvent(result);
+		return result;
+
+	}
+
+	/**
+	 * Sends the time events for this execution. Method generates only the event of
+	 * this execution. If you want more events (e.g. details from a remote
+	 * execution) you can overwrite this method. This method is only called if time
+	 * monitoring is enabled
+	 *
+	 * @param execTime
+	 *            the time of THIS execution
+	 * @param result the result of the computation (may be of use when overwriting)
+	 */
+	protected void fireTimeEvents(long execTime, Object result) {
+		// localhost as String for performance reasons
+		try {
+			eventSink.fireRemoteEvent(new TimeEvent(execTime, "localhost",
+					serverInfos.getName(), commType));
+		} catch (RemoteException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * The TransferEvents for this execution. Method generates only the event
+	 * out of the size of {@link #getObjectArgument()}.If you want more events
+	 * (e.g. details from a remote execution) you can overwrite this method.
+	 * This method is only called if time monitoring is enabled.
+	 *  Notice that this will be very slow for large Data!!
+	 *
+	 * @param result
+	 *            the result of the execution (per default not needed)
+	 */
+	protected void fireTransferEvent(Object result) {
+		if(!disableTransferEvents)
+		// client as String for performance reasons
+		try {
+			eventSink.fireRemoteEvent(new TransferEvent("Xulu/V-Client",
+					serverInfos.getName(), commType, argument));
+		} catch (RemoteException e) {
+			e.printStackTrace();
+		}
+
+	}
+
+	/**
+	 * This method should implement the real running code.
+	 * @return the result you want to retrieve later
+	 * @throws Exception the exceptions thrown by your code
+	 */
+	protected abstract Object run() throws Exception;
+
+}

Added: trunk/src/appl/parallel/thread/OneMethodThread.java
===================================================================
--- trunk/src/appl/parallel/thread/OneMethodThread.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/thread/OneMethodThread.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,74 @@
+package appl.parallel.thread;
+/**
+ * Executes a method call in a single Thread
+ *
+ * @author Dominik Appl
+ */
+public abstract class OneMethodThread implements Runnable {
+	private volatile Thread thisThread;
+
+	private final String threadName;
+
+	private final int priority;
+
+	private final Object[] parameters;
+
+	protected Object executionResult;
+
+	/**
+	 * Creates a new Thread. Do not forget to {@link #start()} it.
+	 * @param threadName a name for the thread (usefull while debugging)
+	 * @param priority a priority for the Thread
+	 * @param parameters the parameters may be used later in the run method by calling the {@link #getParameter(int)} method
+	 *
+	 */
+	public OneMethodThread(String threadName, int priority, Object... parameters) {
+		this.threadName = threadName;
+		this.priority = priority;
+		// TODO Auto-generated constructor stub
+		this.parameters = parameters;
+	}
+
+	public abstract void run();
+
+	/**
+	 * Starts the thread
+	 */
+	public void start() {
+		thisThread = new Thread(this);
+		thisThread.setName(threadName);
+		thisThread.setPriority(priority);
+		thisThread.start();
+	}
+
+	/**
+	 * @param paraNo the position in the given parameter array
+	 * @return the parameter given in the constructor
+	 */
+	public Object getParameter(int paraNo) {
+		return parameters[paraNo];
+	}
+
+	/**
+	 * waits until the encapulated Thread has finished
+	 *
+	 */
+	public void join(){
+		try {
+			thisThread.join();
+		} catch (InterruptedException e) {
+			e.printStackTrace();
+		}
+	}
+
+
+	/**
+	 * the execution result must be explicitly set in the {@link #run()} method.
+	 *
+	 * @return the result
+	 */
+	public Object getExecutionResult(){
+		return executionResult;
+	}
+
+}

Added: trunk/src/appl/parallel/thread/package.html
===================================================================
--- trunk/src/appl/parallel/thread/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/thread/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,6 @@
+<html>
+<body>
+	Contains classes related the client side of the starter functionality. If a programm is executed by a Starter, the
+	execution can be controlled remotely (start/stop/restart the process).
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/parallel/util/Helper.java
===================================================================
--- trunk/src/appl/parallel/util/Helper.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/util/Helper.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,233 @@
+package appl.parallel.util;
+
+import java.rmi.AccessException;
+import java.rmi.NotBoundException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.util.Vector;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+
+import appl.parallel.ComputingResource;
+import appl.parallel.ComputingResourceContainer;
+import appl.parallel.ComputingResourceProperties;
+import appl.parallel.test.PingTestObject;
+
+/**
+ * See method description for details.
+ *
+ * @author Dominik Appl
+ */
+public class Helper {
+	private static final Logger LOG = LogManager.getLogger("appl.parallel.util.Helper");
+
+	/**
+	 * 	Bind the remote object's stub in the registry. Creates a registry if no running registry
+	 * is found.
+	 *
+	 * @param bindingName the name to be used for binding (with port specified, if necessary)
+	 * @param bindingInstance an instance of the type to bind to the registry
+	 * @param registryPort the default registry port
+	 * @throws RemoteException if something goes wrong
+	 */
+	public static void bind(String bindingName, Remote bindingInstance, int registryPort) throws RemoteException{
+		boolean failed=true;
+		Registry registry;
+		try {
+			 registry = LocateRegistry.getRegistry(registryPort);
+			 registry.rebind(bindingName, bindingInstance);
+			 failed = false;
+		} catch (AccessException e) {
+			System.err.println("Not enough permissions to bind" + bindingName +
+					"to the registry! Adjust your security permission file!");
+			LOG.error("Not enough permissions to bind" + bindingName +
+					"to the registry! Adjust your security permission file!",e);
+			e.printStackTrace();
+		} catch (RemoteException e) {
+			if(e instanceof java.rmi.ConnectException){
+				System.out.println("Could not connect to registry! Trying to create new one...");
+				try {
+					registry = LocateRegistry.createRegistry(registryPort);
+					registry.rebind(bindingName, bindingInstance);
+					System.out.println("Registry successfully created at port " + registryPort);
+					failed = false;
+				} catch (RemoteException e1) {
+					// TODO Auto-generated catch block
+					e1.printStackTrace();
+				}
+			}
+			else
+			  e.printStackTrace();
+		}
+		if(failed)
+			throw new RemoteException("Could not find or create registry!");
+	}
+
+	/**
+	 * Unbinds a a stub from the registry!
+	 * @param bindingName
+	 */
+	public static void unbind(String bindingName){
+	Registry registry;
+	try {
+		registry = LocateRegistry.getRegistry();
+		registry.unbind(bindingName);
+		LOG.debug("Sucessfully removed " + bindingName + " from reggie");
+	} catch (RemoteException e) {
+		LOG.debug("tried to unbind " + bindingName
+				+ " from reggie, but an exception occured: "
+				+ e.getMessage());
+	} catch (NotBoundException e) {
+		LOG.debug("tried to unbind " + bindingName
+				+ " from reggie, but the name was not bound "
+				+ e.getMessage());
+	}
+	}
+
+	/**
+	 * Gets the remote resources from all given {@link ComputingResource} objects.
+	 * For this all resources are queried. If a ressouce does not respond the
+	 * Resource is removed form the Vector(!!!!!) and a warning is given to the
+	 * logger.
+	 *
+	 * @param res
+	 */
+	public static Vector<ComputingResourceContainer> getResourceContainersForVector(
+			Vector<ComputingResource> res) {
+
+	final Vector<ComputingResourceContainer> containers = new Vector<ComputingResourceContainer>();
+    ExecutorService executor = Executors.newCachedThreadPool();
+
+	//this is not a for each loop to avoid ConcurrentModificationException form threads
+
+	Future[] results = new Future[res.size()];
+	int i = res.size() - 1;
+	while (i >= 0) {
+			results[i] = executor.submit(new Helper().new SimpleConnectionThread(res,i));
+		i--;
+	}
+	//wait for the threads to finish  /
+	//add the responding containers to a new Vector and return it
+	for (int j = 0; j < results.length; j++) {
+		Object result;
+		try {
+			result = results[j].get();
+			if(result!=null)
+				containers.add((ComputingResourceContainer) result);
+		} catch (InterruptedException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		} catch (ExecutionException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+
+	}
+	return containers;
+}
+
+	/**
+	 * if a connection to the given resource is possible the ResourceProperties of this object
+	 * are returned. Else NULL is returned.
+	 *
+	 * @author Dominik Appl
+	 */
+	public class SimpleConnectionThread implements Callable {
+
+		private final Vector<ComputingResource> containers;
+
+		private final int position;
+
+		public SimpleConnectionThread(
+				Vector<ComputingResource> containers, int position) {
+			this.containers = containers;
+			this.position = position;
+		}
+
+		/*
+		 * (non-Javadoc)
+		 *
+		 * @see java.util.concurrent.Callable#call()
+		 */
+		public Object call() throws Exception {
+//			will remain true, if there is a connection error
+			boolean error = true;
+			ComputingResource r = (ComputingResource) containers.get(position);
+			try {
+				// throw a exeception in case of a connection error:
+				ComputingResourceProperties rp = r.getResourceInformation();
+				error = false;
+				if (LOG.isDebugEnabled())
+					LOG.debug("Getting of resInfo of <"
+							+ rp.getProperty("Name") + "> was successfull!");
+				return new ComputingResourceContainer(r, rp);
+			} catch (Exception e) {
+				LOG.warn("A server was not responding .. removing ressouce!");
+				if (LOG.isDebugEnabled())
+					LOG.debug("Reason was: " + e.getMessage());
+			}
+			return null;
+		}
+	}
+
+
+	/**
+	 * Calculates weights out of ratings. A rating is a value >=1. If the rating
+	 * is 0 an average rating is assumed. This method weights the ratings
+	 * relative to each other so that a weight is a double value between 0 and
+	 * 1 and the sum of all calculated weights is 1.
+	 *
+	 * @param ratings
+	 */
+	public static double[] calculateWeights(int ratings[]){
+		// values with 0 are weightes average. Add all values and count the
+		// values ==0
+		double sum = 0;
+		double nulls = 0;
+		for (int i : ratings) {
+			sum += i;
+			if (i == 0)
+				nulls++;
+		}
+		// for each null add the average
+		double average = (sum / (ratings.length - nulls));
+		// if there are ONLY nulls define the average seperately
+		if (nulls == ratings.length)
+			average = 1000.0 / ratings.length;
+		sum += average * nulls;
+
+		// calculate weights
+		double[] weights = new double[ratings.length];
+		for (int i = 0; i < weights.length; i++) {
+			if (ratings[i] == 0)
+				ratings[i] = (int) average;
+			weights[i] = ratings[i] / sum;
+		}
+
+		if (true == true) {
+			String weightString = "Calculated weights: ";
+			for (double d : weights) {
+				weightString += (d + " ");
+			}
+			LOG.debug("Calculated weights: + " + weightString);
+			System.out.println(weightString);
+		}
+		return weights;
+
+
+
+	}
+
+}
+
+

Added: trunk/src/appl/parallel/util/PartitionUtil.java
===================================================================
--- trunk/src/appl/parallel/util/PartitionUtil.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/util/PartitionUtil.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,157 @@
+package appl.parallel.util;
+
+import java.awt.Rectangle;
+import java.awt.image.DataBuffer;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.WritableGridArray;
+import appl.parallel.data.WritableGridArrayPartition;
+import appl.parallel.data.WritableGridArrayPartition.Double;
+import appl.parallel.data.WritableGridArrayPartition.Float;
+import appl.parallel.data.WritableGridArrayPartition.Integer;
+import appl.parallel.spmd.split.SplittableResource;
+import appl.parallel.spmd.split.WritableGridPartition;
+import appl.util.RasterMetaData;
+
+/**
+ * See method description for details.
+ * 
+ * @author Dominik Appl
+ */
+public class PartitionUtil {
+
+	/**
+		 * Returns partition of a {@link WritableGrid} as a {@link WritableGridArray}.
+		 * Notice, that the minX and minY values are ignored and will be set to 0
+		 * (see {@link WritableGrid} for more information about minX and minY). If
+		 * the given {@link WritableGrid} is not an instance of
+		 * {@link WritableGridPartition} it is assumed that the topLeft corner of
+		 * the source grid is (0,0) (like in standard image processing).<br>
+		 * If the partition is a {@link WritableGridPartition} it is assumed that
+		 * the the bounds of the two Partition refer to the same coordinate system.
+		 * Real coordinates are supposed to reference the South(!)-West Corner.
+		 * 
+		 * @param sourceGrid
+		 *            the grid to be partitioned
+		 * @param partitionBounds
+		 *            the rectangle describing the partition
+		 * @param rootID
+		 *            the id to identify the root partition
+		 * @return the new partition including the given corners
+		 * @see SplittableResource#getRootID()
+		 */
+		public static WritableGridPartition getPartitialGrid2D(WritableGrid sourceGrid,
+				Rectangle partitionBounds, int rootID) {
+			
+	//				(int) partitionBounds.getX(),
+	//				(int) partitionBounds.getY(),
+	//				(int) (partitionBounds.getX() + partitionBounds.getWidth() - 1),
+	//				(int) (partitionBounds.getY() + partitionBounds.getHeight() - 1));
+			
+	//		get Metadata of the big Grid
+			RasterMetaData bigMeta = new RasterMetaData(sourceGrid);
+	
+			//create MetaData for the new partitial Grid
+			//Height an width of the partitial Grid
+			int pHeight = (int) partitionBounds.getHeight();
+			int pWidth = (int)partitionBounds.getWidth();
+	
+			//real coordinates of the partitial Grid (which are referenced by the SW Corner)
+			double pX = partitionBounds.getX() * bigMeta.getCellWidth() + bigMeta.getX();
+			double pY = (partitionBounds.getY() + partitionBounds.getHeight() - 1) * bigMeta.getCellHeight() + bigMeta.getY();
+			double pRealWidth = pWidth * bigMeta.getCellWidth();
+			double pRealHeight = pHeight * bigMeta.getCellHeight();
+	
+			//the MetaData of the new Grid
+			RasterMetaData pMetaData = new RasterMetaData(bigMeta.getDataType(),
+					pWidth, pHeight, 0, 0, pX, pY, pRealWidth, pRealHeight, bigMeta.getCoordinateReferenceSystem());
+	
+			//create empty return Grid
+			WritableGridPartition pGrid;
+			switch(bigMeta.getDataType()){
+			case DataBuffer.TYPE_INT:
+				pGrid = new WritableGridArrayPartition.Integer(pMetaData,rootID,partitionBounds);	
+				break;
+			case DataBuffer.TYPE_DOUBLE:
+				pGrid = new WritableGridArrayPartition.Double(pMetaData,rootID,partitionBounds);
+				break;
+			default:
+				pGrid = new WritableGridArrayPartition.Float(pMetaData,rootID,partitionBounds);	
+			}
+			
+			//if the sourceGrid is a partition itself then we do not want to to start reading from (0,0)
+			//but shifted relative to the global coordinate system. So we calculate now the start values:
+			
+			//for standard WritableGrids these are simply the bounds of the new partition...
+			int startX = (int) partitionBounds.getX();
+			int startY = (int) partitionBounds.getY();
+			
+			// ...but for partitions these values are shifted:
+			if(sourceGrid instanceof WritableGridPartition){
+				Rectangle srcBounds = ((WritableGridPartition) sourceGrid).getPartitionBounds();
+				startX -= srcBounds.getX();
+				startY -= srcBounds.getY();
+			}
+			//read the data into the raster from left to right and downwards
+			int x=0,y=0;
+			try{
+			for (y = 0; y < pHeight; y++)
+				for (x = 0; x < pWidth; x++)
+					pGrid.setRasterSample(
+							sourceGrid.getRasterSample(startX  + x, startY + y),
+							x, 
+							y);
+			}catch (Exception e) {
+				System.out.println("stop");
+			}
+			return pGrid;
+		}
+
+	/**
+	     * Overwrites the data at the location specified by the {@link Rectangle} with
+	     * the given partition-data. If the given baseGrid is NOT an instance
+		 * of {@link WritableGridPartition} it is assumed that its the topLeft corner (0,0). 
+		 * If it IS a {@link WritableGridPartition} it is assumed that the the
+		 * bounds of the two Partition refer to the same coordinate system and the partition
+		 * is inserted at the correct absolut position.
+	     * 
+		 * @param baseGrid the grid in which the data is inserted
+		 * @param gridPartition the grid to be inserted
+		 * @param partitionBounds the excact location in coordinates of the baseGrid
+		 */
+		public static void setPartition(WritableGrid baseGrid, WritableGrid gridPartition, Rectangle partitionBounds) {
+			//Check if partition and the rectangle fit
+			if((gridPartition.getWidth()!=partitionBounds.getWidth()) ||
+					(gridPartition.getHeight()!=partitionBounds.getHeight()))
+			  throw new UnsupportedOperationException("The partition width/height does not match the rectangle width/height");
+			
+			//if the baseeGrid is a partition itself then we do not want to to start writing from (0,0)
+			//but shifted relative to the global coordinate system. So we calculate now the start values:
+			
+			//for standard WritableGrids these are simply the bounds of the new partition...
+			int startX = (int) partitionBounds.getX();
+			int startY = (int) partitionBounds.getY();
+			
+			// ...but for partitions these values are shifted:
+			if(baseGrid instanceof WritableGridPartition){
+				Rectangle targetBounds = ((WritableGridPartition) baseGrid).getPartitionBounds();
+				startX -= targetBounds.getX();
+				startY -= targetBounds.getY();
+			}
+			//check if the partition fits in
+	//		if(((partitionBounds.getX()+partitionBounds.getWidth()-1)>baseGrid.getWidth()  ||
+	//				(partitionBounds.getY()+partitionBounds.getHeight()-1)>baseGrid.getHeight()))
+	//				System.out.println("X");
+				//throw new UnsupportedOperationException("The partition does not fit in the Grid!");
+			//write the partition into the Grid
+			
+			for(int y = 0; y < partitionBounds.getHeight();y++)
+				for(int x = 0; x < partitionBounds.getWidth(); x++)
+					baseGrid.setRasterSample(
+											gridPartition.getRasterSample(x,y),
+											x + startX, 
+											y + startY);
+			
+		}
+
+}

Added: trunk/src/appl/parallel/util/package.html
===================================================================
--- trunk/src/appl/parallel/util/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/parallel/util/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,5 @@
+<html>
+<body>
+	Contains some helper classes.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/plugin/multimodelcontrol/ModelListObject.java
===================================================================
--- trunk/src/appl/plugin/multimodelcontrol/ModelListObject.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/plugin/multimodelcontrol/ModelListObject.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,58 @@
+package appl.plugin.multimodelcontrol;
+
+import edu.bonn.xulu.gui.ModelControlFrame;
+import edu.bonn.xulu.model.XuluModel;
+
+/**
+ * Simple container class that encapulates the data stored a model list (GUI Component)
+ * 
+ * @author Dominik Appl
+ */
+public class ModelListObject {
+
+	private final ModelControlFrame frame;
+    private final XuluModel model;
+    private final String name;
+
+    /**
+     * 
+	 * @param frame modelcontrolframe responsible for the model
+	 * @param model the model
+	 * @param name name of the model
+	 */
+	public ModelListObject(ModelControlFrame frame, XuluModel model, String name) {
+        this.frame = frame;
+		// TODO Auto-generated constructor stub
+        this.model = model;
+        this.name = name;
+	}
+
+    /**
+	 * @return the frame
+	 */
+	public ModelControlFrame getFrame() {
+		return frame;
+	}
+
+    /**
+	 * @return the model
+	 */
+	public XuluModel getModel() {
+		return model;
+	}
+
+    /**
+	 * @return the name
+	 */
+	public String getName() {
+		return name;
+	}
+	
+	/* (non-Javadoc)
+	 * @see java.lang.Object#toString()
+	 */
+	public String toString(){
+        return name;}
+	
+	
+}

Added: trunk/src/appl/plugin/multimodelcontrol/MultiModelControlFrame.java
===================================================================
--- trunk/src/appl/plugin/multimodelcontrol/MultiModelControlFrame.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/plugin/multimodelcontrol/MultiModelControlFrame.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,489 @@
+package appl.plugin.multimodelcontrol;
+
+import java.awt.BorderLayout;
+import javax.swing.JPanel;
+import javax.swing.JFrame;
+import javax.swing.JSplitPane;
+import java.awt.GridBagLayout;
+import java.awt.Dimension;
+import javax.swing.JList;
+import java.awt.GridBagConstraints;
+
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JTextField;
+import javax.swing.JRadioButton;
+import javax.swing.BoxLayout;
+import java.awt.CardLayout;
+import javax.swing.DefaultListModel;
+import javax.swing.ListSelectionModel;
+import javax.swing.BorderFactory;
+import javax.swing.border.EtchedBorder;
+import java.awt.FlowLayout;
+import java.awt.Insets;
+import java.awt.GridLayout;
+import javax.swing.border.SoftBevelBorder;
+import java.awt.ComponentOrientation;
+import java.awt.Cursor;
+import javax.swing.plaf.multi.MultiPanelUI;
+import javax.swing.plaf.basic.BasicPanelUI;
+import javax.swing.JCheckBox;
+import javax.swing.SwingConstants;
+import javax.swing.JToggleButton;
+import java.awt.Font;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+
+import javax.swing.JTabbedPane;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.gui.XuluInternalFrame;
+import javax.swing.JScrollPane;
+import appl.parallel.gui.ParallelControlPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JMenuItem;
+import javax.swing.JTextPane;
+import javax.swing.JTextArea;
+import javax.swing.border.TitledBorder;
+import java.awt.Color;
+
+// fuer Doku
+import appl.parallel.gui.ParallelControlPanelEngine;
+
+/**
+ * The GUI for the ModelControlCenter (MCC). All the interesting stuff happens in the
+ * {@link ParallelControlPanelEngine}.
+ * This GUI was created with the Visual Editor plugin for eclipse.
+ *
+ * @author Dominik Appl
+ */
+public class MultiModelControlFrame extends XuluInternalFrame {
+
+	 static final long serialVersionUID = 1L;
+	 JPanel jContentPane = null;
+     JPanel modelPanel = null;
+     JPanel synchronisationPanel = null;
+     JList modelList = null;
+     JLabel loadedModels = null;
+     JList syncCommandList = null;
+     JLabel syncPanelName = null;
+     JButton addStepCommand = null;
+     JButton newOverAllStep = null;
+     JButton clearModelSteps = null;
+     JPanel syncButtonsPanel = null;
+     JScrollPane jScrollPane = null;
+	 private JPanel jPanel = null;
+	private JPanel controlPanel = null;
+	 JButton startButton = null;
+	 JButton stepButton = null;
+	 JButton stopButton = null;
+	private JPanel jPanel3 = null;
+	private JScrollPane jScrollPane1 = null;
+	private JPanel jPanel5 = null;
+	private JScrollPane jScrollPane2 = null;
+	private JLabel jLabel3 = null;
+	JTextArea console = null;
+
+
+	public MultiModelControlFrame() {
+		super("Multi Model ControlFrame");
+		initialize();
+	}
+
+	/**
+	 * This method initializes this
+	 *
+	 * @return void
+	 */
+	private void initialize() {
+		this.setSize(486, 395);
+		this.setContentPane(getJContentPane());
+		this.setTitle("Multi Model Control");
+		this.setClosable(true);
+		this.setDefaultCloseOperation(HIDE_ON_CLOSE);
+	}
+	/**
+	 * This method initializes jContentPane
+	 *
+	 * @return javax.swing.JPanel
+	 */
+	private JPanel getJContentPane() {
+		if (jContentPane == null) {
+			jContentPane = new JPanel();
+			jContentPane.setLayout(new BoxLayout(getJContentPane(), BoxLayout.Y_AXIS));
+			jContentPane.add(getControlPanel(), null);
+			jContentPane.add(getJPanel(), null);
+			jContentPane.add(getJPanel5(), null);
+		}
+		return jContentPane;
+	}
+    /**
+	 * This method initializes modelPanel
+	 *
+	 * @return javax.swing.JPanel
+	 */
+	private JPanel getModelPanel() {
+		if (modelPanel == null) {
+			GridBagConstraints gridBagConstraints3 = new GridBagConstraints();
+			gridBagConstraints3.insets = new Insets(0, 0, 2, 0);
+			gridBagConstraints3.gridy = 2;
+			gridBagConstraints3.ipadx = 0;
+			gridBagConstraints3.ipady = 0;
+			gridBagConstraints3.gridx = 0;
+			GridBagConstraints gridBagConstraints2 = new GridBagConstraints();
+			gridBagConstraints2.fill = GridBagConstraints.BOTH;
+			gridBagConstraints2.gridy = 1;
+			gridBagConstraints2.ipadx = 0;
+			gridBagConstraints2.ipady = 0;
+			gridBagConstraints2.weightx = 1.0;
+			gridBagConstraints2.weighty = 1.0;
+			gridBagConstraints2.insets = new Insets(5, 5, 5, 5);
+			gridBagConstraints2.gridx = 0;
+			GridBagConstraints gridBagConstraints = new GridBagConstraints();
+			gridBagConstraints.insets = new Insets(3, 3, 3, 3);
+			gridBagConstraints.gridy = 0;
+			gridBagConstraints.ipadx = 0;
+			gridBagConstraints.gridx = 0;
+			loadedModels = new JLabel();
+			loadedModels.setText("Models");
+			loadedModels.setMinimumSize(new Dimension(86, 10));
+			GridBagConstraints gridBagConstraints1 = new GridBagConstraints();
+			gridBagConstraints1.fill = GridBagConstraints.BOTH;
+			gridBagConstraints1.weighty = 1.0;
+			gridBagConstraints1.weightx = 1.0;
+			modelPanel = new JPanel();
+			modelPanel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
+			modelPanel.setName("modelPanel");
+			modelPanel.setLayout(new GridBagLayout());
+			modelPanel.add(loadedModels, gridBagConstraints);
+			modelPanel.add(getJScrollPane(), gridBagConstraints2);
+			modelPanel.add(getAddStepCommand(), gridBagConstraints3);
+		}
+		return modelPanel;
+	}
+
+    /**
+	 * This method initializes synchronisationPanel
+	 *
+	 * @return javax.swing.JPanel
+	 */
+	private JPanel getSynchronisationPanel() {
+		if (synchronisationPanel == null) {
+			GridBagConstraints gridBagConstraints11 = new GridBagConstraints();
+			gridBagConstraints11.fill = GridBagConstraints.BOTH;
+			gridBagConstraints11.weighty = 1.0;
+			gridBagConstraints11.gridy = 1;
+			gridBagConstraints11.insets = new Insets(0, 5, 2, 5);
+			gridBagConstraints11.weightx = 1.0;
+			GridBagConstraints gridBagConstraints5 = new GridBagConstraints();
+			gridBagConstraints5.gridx = 0;
+			gridBagConstraints5.insets = new Insets(0, 0, 2, 0);
+			gridBagConstraints5.gridy = 11;
+			GridBagConstraints gridBagConstraints7 = new GridBagConstraints();
+			gridBagConstraints7.gridx = 0;
+			gridBagConstraints7.ipady = 0;
+			gridBagConstraints7.insets = new Insets(3, 0, 3, 0);
+			gridBagConstraints7.gridy = 0;
+			syncPanelName = new JLabel();
+			syncPanelName.setText("Commands");
+			synchronisationPanel = new JPanel();
+			synchronisationPanel.setToolTipText("Here you can synchronize the steps of multiple models");
+			synchronisationPanel.setLayout(new GridBagLayout());
+			synchronisationPanel.add(syncPanelName, gridBagConstraints7);
+			synchronisationPanel.add(getJScrollPane1(), gridBagConstraints11);
+			synchronisationPanel.add(getSyncButtonsPanel(), gridBagConstraints5);
+		}
+		return synchronisationPanel;
+	}
+    /**
+	 * This method initializes jList
+	 *
+	 * @return javax.swing.JList
+	 */
+	private JList getModelList() {
+		if (modelList == null) {
+			modelList = new JList();
+			modelList.setName("modelList");
+			modelList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+			modelList.setToolTipText("All models, which are currently loaded. Doubleclick on a model to set propertys");
+		}
+		return modelList;
+	}
+    /**
+	 * This method initializes jList
+	 *
+	 * @return javax.swing.JList
+	 */
+	private JList getSyncCommandList() {
+		if (syncCommandList == null) {
+			syncCommandList = new JList();
+			syncCommandList.setToolTipText("The list of commands to be executed");
+
+		}
+		return syncCommandList;
+	}
+
+    /**
+	 * This method initializes addStepCommand
+	 *
+	 * @return javax.swing.JButton
+	 */
+	private JButton getAddStepCommand() {
+		if (addStepCommand == null) {
+			addStepCommand = new JButton();
+			addStepCommand.setText("Add ====> ");
+			addStepCommand.setPreferredSize(new Dimension(100, 20));
+		}
+		return addStepCommand;
+	}
+    /**
+	 * This method initializes newOverAllStep
+	 *
+	 * @return javax.swing.JButton
+	 */
+	private JButton getNewOverAllStep() {
+		if (newOverAllStep == null) {
+			newOverAllStep = new JButton();
+			newOverAllStep.setText("Add Repeat");
+			newOverAllStep.setPreferredSize(new Dimension(119, 20));
+		}
+		return newOverAllStep;
+	}
+    /**
+	 * This method initializes clearModelSteps
+	 *
+	 * @return javax.swing.JButton
+	 */
+	private JButton getClearModelSteps() {
+		if (clearModelSteps == null) {
+			clearModelSteps = new JButton();
+			clearModelSteps.setText("Delete entry");
+			clearModelSteps.setPreferredSize(new Dimension(64, 20));
+		}
+		return clearModelSteps;
+	}
+    /**
+	 * This method initializes syncButtonsPanel
+	 *
+	 * @return javax.swing.JPanel
+	 */
+	private JPanel getSyncButtonsPanel() {
+		if (syncButtonsPanel == null) {
+			GridLayout gridLayout1 = new GridLayout();
+			gridLayout1.setRows(1);
+			gridLayout1.setColumns(2);
+			GridBagConstraints gridBagConstraints9 = new GridBagConstraints();
+			gridBagConstraints9.anchor = GridBagConstraints.WEST;
+			gridBagConstraints9.gridx = -1;
+			gridBagConstraints9.gridy = -1;
+			gridBagConstraints9.fill = GridBagConstraints.HORIZONTAL;
+			GridBagConstraints gridBagConstraints8 = new GridBagConstraints();
+			gridBagConstraints8.fill = GridBagConstraints.HORIZONTAL;
+			gridBagConstraints8.gridy = -1;
+			gridBagConstraints8.gridx = -1;
+			syncButtonsPanel = new JPanel();
+			syncButtonsPanel.setLayout(gridLayout1);
+			syncButtonsPanel.add(getNewOverAllStep(), null);
+			syncButtonsPanel.add(getClearModelSteps(), null);
+		}
+		return syncButtonsPanel;
+	}
+    /* (non-Javadoc)
+	 * @see edu.bonn.xulu.gui.XuluInternalFrame#refresh()
+	 */
+	@Override
+	public void refresh() {
+		// TODO Auto-generated method stub
+
+	}
+
+    /**
+	 * This method initializes jScrollPane
+	 *
+	 * @return javax.swing.JScrollPane
+	 */
+	private JScrollPane getJScrollPane() {
+		if (jScrollPane == null) {
+			jScrollPane = new JScrollPane();
+			jScrollPane.setViewportView(getModelList());
+		}
+		return jScrollPane;
+	}
+
+	/**
+	 * This method initializes jPanel
+	 *
+	 * @return javax.swing.JPanel
+	 */
+	private JPanel getJPanel() {
+		if (jPanel == null) {
+			GridLayout gridLayout = new GridLayout();
+			gridLayout.setRows(1);
+			gridLayout.setVgap(0);
+			gridLayout.setColumns(4);
+			gridLayout.setHgap(0);
+			jPanel = new JPanel();
+			jPanel.setLayout(gridLayout);
+			jPanel.add(getModelPanel(), null);
+			jPanel.add(getSynchronisationPanel(), null);
+		}
+		return jPanel;
+	}
+
+	/**
+	 * This method initializes controlPanel
+	 *
+	 * @return javax.swing.JPanel
+	 */
+	private JPanel getControlPanel() {
+		if (controlPanel == null) {
+			GridLayout gridLayout3 = new GridLayout();
+			gridLayout3.setRows(1);
+			gridLayout3.setHgap(5);
+			gridLayout3.setColumns(2);
+			gridLayout3.setVgap(5);
+			controlPanel = new JPanel();
+			controlPanel.setMaximumSize(new Dimension(1000, 20));
+			controlPanel.setLayout(gridLayout3);
+			controlPanel.add(getJPanel3(), null);
+		}
+		return controlPanel;
+	}
+
+	/**
+	 * This method initializes startButton
+	 *
+	 * @return javax.swing.JButton
+	 */
+	private JButton getStartButton() {
+		if (startButton == null) {
+			startButton = new JButton();
+			startButton.setText("Start");
+		}
+		return startButton;
+	}
+
+	/**
+	 * This method initializes stepButton
+	 *
+	 * @return javax.swing.JButton
+	 */
+	private JButton getStepButton() {
+		if (stepButton == null) {
+			stepButton = new JButton();
+			stepButton.setText("Step");
+		}
+		return stepButton;
+	}
+
+	/**
+	 * This method initializes stopButton
+	 *
+	 * @return javax.swing.JButton
+	 */
+	private JButton getStopButton() {
+		if (stopButton == null) {
+			stopButton = new JButton();
+			stopButton.setText("Stop");
+		}
+		return stopButton;
+	}
+
+
+
+	/**
+	 * This method initializes jPanel3
+	 *
+	 * @return javax.swing.JPanel
+	 */
+	private JPanel getJPanel3() {
+		if (jPanel3 == null) {
+			GridBagConstraints gridBagConstraints14 = new GridBagConstraints();
+			gridBagConstraints14.gridx = -1;
+			gridBagConstraints14.gridy = -1;
+			GridBagConstraints gridBagConstraints13 = new GridBagConstraints();
+			gridBagConstraints13.gridx = -1;
+			gridBagConstraints13.gridy = -1;
+			GridBagConstraints gridBagConstraints12 = new GridBagConstraints();
+			gridBagConstraints12.anchor = GridBagConstraints.WEST;
+			gridBagConstraints12.gridy = -1;
+			gridBagConstraints12.gridx = -1;
+			jPanel3 = new JPanel();
+			jPanel3.setLayout(new GridBagLayout());
+			jPanel3.add(getStartButton(), gridBagConstraints12);
+			jPanel3.add(getStepButton(), gridBagConstraints13);
+			jPanel3.add(getStopButton(), gridBagConstraints14);
+		}
+		return jPanel3;
+	}
+
+	/**
+	 * This method initializes jScrollPane1
+	 *
+	 * @return javax.swing.JScrollPane
+	 */
+	private JScrollPane getJScrollPane1() {
+		if (jScrollPane1 == null) {
+			jScrollPane1 = new JScrollPane();
+			jScrollPane1.setViewportView(getSyncCommandList());
+		}
+		return jScrollPane1;
+	}
+
+	/**
+	 * This method initializes jPanel5
+	 *
+	 * @return javax.swing.JPanel
+	 */
+	private JPanel getJPanel5() {
+		if (jPanel5 == null) {
+			GridBagConstraints gridBagConstraints4 = new GridBagConstraints();
+			gridBagConstraints4.anchor = GridBagConstraints.NORTH;
+			gridBagConstraints4.insets = new Insets(3, 0, 0, 0);
+			gridBagConstraints4.gridy = 3;
+			jLabel3 = new JLabel();
+			jLabel3.setText("Console");
+			GridBagConstraints gridBagConstraints15 = new GridBagConstraints();
+			gridBagConstraints15.fill = GridBagConstraints.BOTH;
+			gridBagConstraints15.weighty = 1.0;
+			gridBagConstraints15.gridy = 4;
+			gridBagConstraints15.gridx = 0;
+			gridBagConstraints15.anchor = GridBagConstraints.SOUTH;
+			gridBagConstraints15.insets = new Insets(5, 5, 5, 5);
+			gridBagConstraints15.weightx = 1.0;
+			jPanel5 = new JPanel();
+			jPanel5.setLayout(new GridBagLayout());
+			jPanel5.add(jLabel3, gridBagConstraints4);
+			jPanel5.add(getJScrollPane2(), gridBagConstraints15);
+		}
+		return jPanel5;
+	}
+
+	/**
+	 * This method initializes jScrollPane2
+	 *
+	 * @return javax.swing.JScrollPane
+	 */
+	private JScrollPane getJScrollPane2() {
+		if (jScrollPane2 == null) {
+			jScrollPane2 = new JScrollPane();
+			jScrollPane2.setViewportView(getConsole());
+		}
+		return jScrollPane2;
+	}
+
+	/**
+	 * This method initializes console
+	 *
+	 * @return javax.swing.JTextArea
+	 */
+	private JTextArea getConsole() {
+		if (console == null) {
+			console = new JTextArea();
+		}
+		return console;
+	}
+
+}  //  @jve:decl-index=0:visual-constraint="10,10"

Added: trunk/src/appl/plugin/multimodelcontrol/MultiModelControlHandler.java
===================================================================
--- trunk/src/appl/plugin/multimodelcontrol/MultiModelControlHandler.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/plugin/multimodelcontrol/MultiModelControlHandler.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,773 @@
+package appl.plugin.multimodelcontrol;
+
+import java.awt.Color;
+import java.awt.PopupMenu;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Vector;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import javax.swing.DefaultListModel;
+import javax.swing.JList;
+import javax.swing.JOptionPane;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+import appl.parallel.gui.ParallelControlPanelEngine;
+
+import schmitzm.data.event.ObjectEvent;
+import schmitzm.data.event.ObjectListener;
+import schmitzm.lang.WorkingThread;
+import schmitzm.lang.WorkingThreadAdapter;
+import schmitzm.lang.WorkingThreadListener;
+import schmitzm.swing.TextAreaPrintStream;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.ModelControlManager;
+import edu.bonn.xulu.gui.ModelControlFrame;
+import edu.bonn.xulu.model.StepModel;
+import edu.bonn.xulu.model.XuluModel;
+import edu.bonn.xulu.model.event.ModelEvent;
+import edu.bonn.xulu.model.event.ModelListener;
+import edu.bonn.xulu.plugin.gui.ModelControlFrame_Basic;
+
+/**
+ * The class allows to control several models at once. At the moment it provides
+ * a batch like execution functionality. It is still under development but
+ * should basically work. It was developed in very short time and is therefore
+ * not as well commented, as other classes.
+ * 
+ * @author Dominik Appl
+ */
+public class MultiModelControlHandler implements ListSelectionListener,
+		ObjectListener, ActionListener {
+
+	private MultiModelControlFrame frame;
+
+	private final XuluModellingPlatform xulu;
+
+	private DefaultListModel modelListModel;
+
+	private ParallelControlPanelEngine parallelControlPanelEngine;
+
+	private DefaultListModel commandListModel;
+
+	private InterpretingThread interpretingThread;
+
+	private TextAreaPrintStream consoleStream;
+
+	private String string;
+
+	public MultiModelControlHandler(XuluModellingPlatform xulu) {
+		this.xulu = xulu;
+		frame = new MultiModelControlFrame();
+		initGUI();
+		consoleStream = new TextAreaPrintStream(frame.console);
+	}
+
+	/**
+	 * 
+	 */
+	private void initGUI() {
+		// register as listener for changes in the ModelControlManager
+		xulu.getModelControlManager().addObjectListener(this);
+		// init model list
+		initModelList();
+		initCommandList();
+		registerListeners();
+	}
+
+	/**
+	 * 
+	 */
+	private void registerListeners() {
+		frame.addStepCommand.addActionListener(this);
+		frame.newOverAllStep.addActionListener(this);
+		frame.clearModelSteps.addActionListener(this);
+		frame.startButton.addActionListener(this);
+		frame.stopButton.addActionListener(this);
+		frame.stepButton.addActionListener(this);
+		frame.modelList.addMouseListener(new java.awt.event.MouseAdapter() {
+			public void mouseClicked(java.awt.event.MouseEvent e) {
+				if (e.getClickCount() == 2) {
+					handleModelListDoubleClick();
+				}
+			}
+		});
+	}
+
+	/**
+	 * 
+	 */
+	private void initCommandList() {
+		commandListModel = new DefaultListModel();
+		frame.syncCommandList.setModel(commandListModel);
+		commandListModel.addElement(new StartCommand());
+		commandListModel.addElement(new StopCommand());
+		frame.syncCommandList
+				.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+		frame.syncCommandList.setSelectedIndex(0);
+	}
+
+	/**
+	 * inits the modelList
+	 */
+	private void initModelList() {
+		modelListModel = new DefaultListModel();
+		frame.modelList.setModel(modelListModel);
+		frame.modelList.addListSelectionListener(this);
+		int modelCount = xulu.getModelControlManager().getCount();
+		for (int i = 0; i < modelCount; i++) {
+			ModelControlFrame frame = xulu.getModelControlManager().getAll()[i];
+			this.addModelControlFrame(frame);
+		}
+		// frame.modelList.add(frame.modelPopupMenu);
+	}
+
+	public MultiModelControlFrame getFrame() {
+		return frame;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see schmitzm.data.event.ObjectListener#performObjectEvent(schmitzm.data.event.ObjectEvent)
+	 */
+	public void performObjectEvent(ObjectEvent e) {
+		// only listen for ChangeEvents
+		if (!(e instanceof ModelControlManager.ChangeEvent))
+			return;
+		ModelControlManager.ChangeEvent event = (ModelControlManager.ChangeEvent) e;
+		// if model was added:
+		if (event.getOldValue() == null && event.getNewValue() != null
+				&& event.getNewValue() instanceof ModelControlFrame)
+			addModelControlFrame((ModelControlFrame) event.getNewValue());
+		// if model was removed
+		if (event.getOldValue() != null && event.getNewValue() == null
+				&& event.getOldValue() instanceof ModelControlFrame)
+			removeModelControlFrame((ModelControlFrame) event.getOldValue());
+	}
+
+	/**
+	 * @param model
+	 */
+	private void addModelControlFrame(ModelControlFrame frame2) {
+		modelListModel.addElement(new ModelListObject(frame2,
+				frame2.getModel(), frame2.getModel().getName()));
+
+	}
+
+	/**
+	 * Removes the model, which belongs to the specified ModelControlFrame from
+	 * the list in the MCC
+	 * 
+	 * @param frame2
+	 *            the ModelControlFrame from the removed model
+	 */
+	private void removeModelControlFrame(ModelControlFrame frame2) {
+		// find the index of the model in the vector
+		for (int i = 0; i < modelListModel.size(); i++) {
+			ModelListObject m = (ModelListObject) modelListModel.get(i);
+			if (frame2.equals(m.getFrame()))
+				modelListModel.remove(i);
+		}
+	}
+
+	/**
+	 * @returns the actually selected ModelListObject from the model list
+	 */
+	private ModelListObject getSelectedModelListObject() {
+		return (ModelListObject) frame.modelList.getSelectedValue();
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see javax.swing.event.ListSelectionListener#valueChanged(javax.swing.event.ListSelectionEvent)
+	 */
+	public void valueChanged(ListSelectionEvent e) {
+		// TODO Auto-generated method stub
+	}
+
+	abstract class ModelCommand {
+		protected boolean finished = false;
+
+		public abstract String toString();
+
+		public void execute() {
+			finished = true;
+		}
+
+		public void reset() {
+			finished = false;
+		}
+
+		// /**
+		// * executed after all commands are executed
+		// */
+		// public void dispose()
+		// {
+		//			
+		// }
+
+		/**
+		 * @return true, if the execution is finished and no further execution
+		 *         is required
+		 */
+		public boolean hasFinished() {
+			return finished;
+		}
+
+		/**
+		 * tries to stop the execution of the command
+		 */
+		public void stop() {
+		};
+
+		/**
+		 * @return Message to be displayed in the console
+		 */
+		public String startMessage() {
+			return null;
+		}
+
+		/**
+		 * @return Message to be displayed
+		 */
+		public String finshedMessage() {
+			return null;
+		}
+	}
+
+	class RepeatStartCommand extends ModelCommand {
+		private final int execTimes;
+
+		private int alreadyExec;
+
+		/**
+		 * @param execTimes
+		 */
+		public RepeatStartCommand(int execTimes) {
+			this.execTimes = execTimes;
+			alreadyExec = 0;
+			// TODO Auto-generated constructor stub
+		}
+
+		public String toString() {
+			return "Start Repeat (" + execTimes + " exec)";
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.plugin.multimodelcontrol.MultiModelControlHandler.ModelCommand#finshedMessage()
+		 */
+		@Override
+		public String finshedMessage() {
+			return "Starting Repeat (" + (alreadyExec) + "/" + execTimes + ")";
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.plugin.multimodelcontrol.MultiModelControlHandler.ModelCommand#startMessage()
+		 */
+		@Override
+		public String startMessage() {
+			return null;
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.plugin.multimodelcontrol.MultiModelControlHandler.ModelCommand#execute()
+		 */
+		@Override
+		public void execute() {
+			alreadyExec++;
+			finished = true;
+		}
+
+		public void reset() {
+			finished = false;
+			alreadyExec = 0;
+		}
+	}
+
+	/**
+	 * The commands between start and stop are repeated
+	 * 
+	 * @author Dominik Appl
+	 */
+	class RepeatStopCommand extends ModelCommand {
+		private final int execTimes;
+
+		private int alreadyExec;
+
+		/**
+		 * @param execTimes
+		 */
+		public RepeatStopCommand(int execTimes) {
+			this.execTimes = execTimes;
+			alreadyExec = 0;
+		}
+
+		public String toString() {
+			return "End Repeat (" + execTimes + " exec)";
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.plugin.multimodelcontrol.MultiModelControlHandler.ModelCommand#finshedMessage()
+		 */
+		@Override
+		public String finshedMessage() {
+			return "Loop iteration finished.(" + alreadyExec + "/" + execTimes
+					+ ")";
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.plugin.multimodelcontrol.MultiModelControlHandler.ModelCommand#startMessage()
+		 */
+		@Override
+		public String startMessage() {
+			return null;
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.plugin.multimodelcontrol.MultiModelControlHandler.ModelCommand#execute()
+		 */
+		@Override
+		public void execute() {
+			alreadyExec++;
+			if (alreadyExec == execTimes)
+				finished = true;
+		}
+
+		public void reset() {
+			finished = false;
+			alreadyExec = 0;
+		}
+	}
+
+	class StartCommand extends ModelCommand {
+		public String toString() {
+			return "------- START MODELLING -------";
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.plugin.multimodelcontrol.MultiModelControlHandler.ModelCommand#finshedMessage()
+		 */
+		@Override
+		public String finshedMessage() {
+			return "Starting execution...";
+		}
+
+	}
+
+	class StopCommand extends ModelCommand {
+		public String toString() {
+			return "------- MODELLING FINISHED -------";
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.plugin.multimodelcontrol.MultiModelControlHandler.ModelCommand#finshedMessage()
+		 */
+		@Override
+		public String finshedMessage() {
+			return "Finished execution";
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.plugin.multimodelcontrol.MultiModelControlHandler.ModelCommand#startMessage()
+		 */
+		@Override
+		public String startMessage() {
+			return null;
+		}
+	}
+
+	class ModelStepCommand extends ModelCommand {
+		private ModelControlFrame_Basic controlFrame;
+
+		private final Lock lock = new ReentrantLock();
+
+		private final Condition threadStillRunning = lock.newCondition();
+
+		private String name;
+
+		private XuluModel model;
+
+		private final int execTimes;
+
+		private int finishedExecutions = 0;
+
+		public void reset() {
+			finishedExecutions = 0;
+		}
+
+		/**
+		 * 
+		 */
+		public ModelStepCommand(ModelListObject mlo, int execTimes) {
+			this.execTimes = execTimes;
+			if (!(mlo.getFrame() instanceof ModelControlFrame_Basic))
+				throw new UnsupportedOperationException(
+						"The modelframe must be an instance of ModelControlFrame_Basic");
+			controlFrame = (ModelControlFrame_Basic) mlo.getFrame();
+			name = mlo.getName();
+			model = mlo.getModel();
+		}
+
+		public void execute() {
+			// check first if the model must be initialised
+			if (!model.isInitialised() && !model.isRunning()) {
+				controlFrame.setModelResources();
+				controlFrame.getControlContainer().init();
+			}
+			lock.lock();
+			try {
+				WorkingThreadAdapter adapter = new WorkingThreadAdapter() {
+					/*
+					 * (non-Javadoc)
+					 * 
+					 * @see schmitzm.lang.WorkingThreadAdapter#threadPaused(schmitzm.lang.WorkingThread)
+					 */
+					@Override
+					public void threadPaused(WorkingThread thread) {
+						try {
+							lock.lock();
+							// signal finished if the step is finished
+							threadStillRunning.signal();
+						} finally {
+							lock.unlock();
+						}
+					}
+
+					/*
+					 * (non-Javadoc)
+					 * 
+					 * @see schmitzm.lang.WorkingThreadAdapter#threadStopped(schmitzm.lang.WorkingThread)
+					 */
+					@Override
+					public void threadStopped(WorkingThread thread) {
+						try {
+							lock.lock();
+							// signal finished if the step is finished
+							threadStillRunning.signal();
+						} finally {
+							lock.unlock();
+						}
+					}
+				};
+				controlFrame.getControlContainer().getModelThread()
+						.addThreadListener(adapter);
+				controlFrame.getControlContainer().step();
+				// wait for the model step to finish
+				threadStillRunning.await();
+				controlFrame.getControlContainer().getModelThread()
+						.removeThreadListener(adapter);
+				finishedExecutions++;
+			} catch (InterruptedException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			} finally {
+				lock.unlock();
+			}
+		}
+
+		public void stop() {
+			if (!model.isStopped())
+				controlFrame.getControlContainer().stop();
+			// try {
+			// controlFrame.getControlContainer().getModelThread().join();
+			// } catch (InterruptedException e) {
+			// // TODO Auto-generated catch block
+			// e.printStackTrace();
+			// }
+		}
+
+		@Override
+		public boolean hasFinished() {
+			return finishedExecutions >= execTimes;
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.plugin.multimodelcontrol.MultiModelControlHandler.ModelCommand#toString()
+		 */
+		@Override
+		public String toString() {
+			return name + " (" + execTimes + " exec)";
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.plugin.multimodelcontrol.MultiModelControlHandler.ModelCommand#finshedMessage()
+		 */
+		@Override
+		public String finshedMessage() {
+			return "...finished";
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see appl.plugin.multimodelcontrol.MultiModelControlHandler.ModelCommand#startMessage()
+		 */
+		@Override
+		public String startMessage() {
+			return "Executing step of " + name;
+		}
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
+	 */
+	public void actionPerformed(ActionEvent e) {
+		if (e.getSource() == frame.addStepCommand) {
+			handleAddNewStep();
+		}
+		if (e.getSource() == frame.newOverAllStep) {
+			handleRepeatStep();
+		}
+		if (e.getSource() == frame.startButton) {
+			startInterpreting();
+		}
+		if (e.getSource() == frame.stopButton) {
+			if (interpretingThread != null) {
+				interpretingThread.stopThread();
+			}
+			// ToDO: dispose all models
+
+		}
+		if (e.getSource() == frame.clearModelSteps) {
+			int delIdx = frame.syncCommandList.getSelectedIndex();
+			// do not delete first or last entry
+			if (delIdx > 0 && delIdx < commandListModel.getSize() - 1)
+				commandListModel.remove(delIdx);
+			frame.syncCommandList.setSelectedIndex(delIdx);
+
+		}
+	}
+
+	/**
+	 * 
+	 */
+	private void handleAddNewStep() {
+		if (checkInsertAllowed()) {
+			if (getSelectedModelListObject() == null) {
+				JOptionPane.showMessageDialog(null, "No model selected",
+						"No model selected", JOptionPane.ERROR_MESSAGE);
+				return;
+			}
+			int selIdx = frame.syncCommandList.getSelectedIndex();
+			int execTimes = 1;
+			// get execution times from user
+			try {
+				string = JOptionPane.showInputDialog(frame,
+						"How many steps do you want to execute for this enty?",
+						1);
+				execTimes = Integer.valueOf(string);
+				if (execTimes <= 0)
+					throw new UnsupportedOperationException(
+							"Only positive number allowed!");
+			} catch (Exception ex) {
+				JOptionPane.showMessageDialog(null,
+						"Only positive number allowed", "Error",
+						JOptionPane.ERROR_MESSAGE);
+				return;
+			}
+			commandListModel.add(selIdx + 1, new ModelStepCommand(
+					getSelectedModelListObject(), execTimes));
+			// select new entry
+			frame.syncCommandList.setSelectedIndex(selIdx + 1);
+		}
+	}
+
+	/**
+	 * 
+	 */
+	protected void handleModelListDoubleClick() {
+		ModelListObject selectedModelListObject = getSelectedModelListObject();
+		if (selectedModelListObject != null) {
+			selectedModelListObject.getFrame().setVisible(true);
+			selectedModelListObject.getFrame().toFront();
+		}
+
+	}
+
+	/**
+	 * 
+	 */
+	private void handleRepeatStep() {
+		if (checkInsertAllowed()) {
+			int selIdx = frame.syncCommandList.getSelectedIndex();
+			int execTimes = 1;
+			// get execution times from user
+			try {
+				string = JOptionPane.showInputDialog(frame,
+						"How many steps do you want to execute for this enty?",
+						1);
+				execTimes = Integer.valueOf(string);
+				if (execTimes <= 0)
+					throw new UnsupportedOperationException(
+							"Only positive numbers allowed!");
+			} catch (Exception ex) {
+				JOptionPane.showMessageDialog(null,
+						"Only positive numbers allowed", "Error",
+						JOptionPane.ERROR_MESSAGE);
+				return;
+			}
+			commandListModel.add(selIdx + 1, new RepeatStartCommand(execTimes));
+			commandListModel.add(selIdx + 2, new RepeatStopCommand(execTimes));
+
+			// select new entry
+			frame.syncCommandList.setSelectedIndex(selIdx + 1);
+		}
+	}
+
+	private void startInterpreting() {
+		// clear console and start Thread
+		frame.console.setText("");
+		interpretingThread = new InterpretingThread();
+		interpretingThread.start();
+
+	}
+
+	public void toggleGUI(boolean enabled) {
+		frame.modelList.setEnabled(enabled);
+		frame.addStepCommand.setEnabled(enabled);
+		frame.newOverAllStep.setEnabled(enabled);
+		frame.clearModelSteps.setEnabled(enabled);
+		if (enabled)
+			frame.syncCommandList.setSelectionBackground(Color.LIGHT_GRAY);
+		else
+			frame.syncCommandList.setSelectionBackground(Color.red);
+	}
+
+	/**
+	 * insert is allowed if its not the last position
+	 */
+	private boolean checkInsertAllowed() {
+		if (commandListModel.getSize() - 1 > frame.syncCommandList
+				.getSelectedIndex())
+			return true;
+		JOptionPane.showMessageDialog(null,
+				"You can add nothing after the end command!", "Error",
+				JOptionPane.ERROR_MESSAGE);
+		return false;
+	}
+
+	/**
+	 * Interprets the commandlist
+	 * 
+	 * @author Dominik Appl
+	 */
+	class InterpretingThread extends Thread {
+
+		private boolean exit;
+
+		private ModelCommand currentCommand;
+
+		/**
+		 * Creates a new Thread
+		 */
+		public InterpretingThread() {
+			exit = false;
+		}
+
+		/**
+		 * stops the Thread execution
+		 */
+		public void stopThread() {
+			exit = true;
+			if (currentCommand != null)
+				currentCommand.stop();
+		}
+
+		public void run() {
+			toggleGUI(false);
+			// reset all commands
+			for (int i = 0; i < frame.syncCommandList.getModel().getSize(); i++)
+				((ModelCommand) frame.syncCommandList.getModel()
+						.getElementAt(i)).reset();
+			// select first element
+			try {
+				frame.syncCommandList.setSelectedIndex(0);
+				int currentIdx = 0;
+				while (exit != true) {
+					currentCommand = (ModelCommand) commandListModel
+							.getElementAt(currentIdx);
+					// if the current command is an end of of a global loop
+					// than go back in the list until the start of the loop is
+					// found
+					if (currentCommand instanceof RepeatStopCommand) {
+						currentCommand.execute();
+						// if the all steps are done, just go on
+						if (currentCommand.hasFinished()) {
+							currentIdx++;
+							currentCommand = (ModelCommand) commandListModel
+									.getElementAt(currentIdx);
+						}
+						// else do the repetition by decreasing the index
+						// until the RepeatStartCommand is reached
+						else {
+							while (!(currentCommand instanceof RepeatStartCommand)) {
+								currentIdx--;
+								// if some structure error occured:
+								if (currentIdx <= 0) {
+									JOptionPane
+											.showMessageDialog(
+													frame,
+													"Something is wrong with the command structure. Do not use nested loops or other komplex structures!");
+									exit = true;
+									break;
+								}
+								currentCommand = (ModelCommand) commandListModel
+										.getElementAt(currentIdx);
+							}
+						}
+
+					}
+					if (currentCommand.startMessage() != null)
+						consoleStream.print(currentCommand.startMessage());
+					frame.syncCommandList.setSelectedIndex(currentIdx);
+					currentCommand.execute();
+					if (currentCommand.finshedMessage() != null)
+						consoleStream.println(currentCommand.finshedMessage());
+					// if the command has finished executing, get the next
+					// command
+					if (currentCommand.hasFinished())
+						currentIdx++;
+					if (currentIdx == commandListModel.getSize())
+						exit = true;
+				}
+			} catch (Exception e) {
+				e.printStackTrace();
+			} finally {
+				toggleGUI(true);
+			}
+		}
+	}
+
+}

Added: trunk/src/appl/plugin/multimodelcontrol/MultiModelControlPlugin.java
===================================================================
--- trunk/src/appl/plugin/multimodelcontrol/MultiModelControlPlugin.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/plugin/multimodelcontrol/MultiModelControlPlugin.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,29 @@
+package appl.plugin.multimodelcontrol;
+
+import javax.swing.JMenuItem;
+
+import edu.bonn.xulu.gui.XuluInternalFrame;
+import edu.bonn.xulu.plugin.appl.AbstractMenuPlugin;
+
+/**
+ * The Xulu plugin class. See {@link MultiModelControlHandler} for details.
+ *
+ * @author Dominik Appl
+ */
+public class MultiModelControlPlugin extends AbstractMenuPlugin{
+
+	/**
+	 */
+	public MultiModelControlPlugin() {
+		super(1,"Multi Model Control");
+	}
+
+	/* (non-Javadoc)
+	 * @see edu.bonn.xulu.plugin.appl.AbstractMenuPlugin#createPluginApplication()
+	 */
+	@Override
+	protected XuluInternalFrame createPluginApplication() throws Exception {
+		return new MultiModelControlHandler(this.appl).getFrame();
+	}
+
+}

Added: trunk/src/appl/plugin/multimodelcontrol/package.html
===================================================================
--- trunk/src/appl/plugin/multimodelcontrol/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/plugin/multimodelcontrol/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,5 @@
+<html>
+<body>
+	Contains a plugin which allows to control the execution of multiple models at once.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/util/GeneralUtil.java
===================================================================
--- trunk/src/appl/util/GeneralUtil.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/util/GeneralUtil.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,96 @@
+package appl.util;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.net.URL;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import net.jini.loader.pref.PreferredClassLoader;
+
+/**
+ * General utility class. See method description for details.
+ * 
+ * @author Dominik Appl
+ */
+public class GeneralUtil {
+
+	public static Logger LOG = LogManager.getLogger("appl.util.GeneralUtil");
+
+	/**
+	 * Loads a class from the specified URL and returns an instance of this class.
+	 * @param location the URL of the rootDirectory/networkLocation
+	 * @param classname the fully qualified name of the class (the class must have a 
+	 * 
+	 * @return the instance of the class or <code>null</code> if loading fails
+	 */
+	public static Object loadClassFromURL(URL location, String classname) {
+		try {
+			URL[] locations = { location };
+			PreferredClassLoader classLoader = new PreferredClassLoader(
+					locations, Thread.currentThread().getContextClassLoader(),
+					null, false);
+			LOG.debug("Try to load " + classname.getClass().getName()
+					+ " from " + location);
+			Class classObject = classLoader.loadClass(classname);
+			return classObject.newInstance();
+		} catch (Exception e) {
+			LOG.error("Could not load class for " + classname + " from "
+					+ location, e);
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	/**
+	 * Serializes the given object into the specified file. All exceptions are printed to console.
+	 * @param o the object
+	 * @param destFile the file to write to
+	 */
+	public static void SerializeToFile(Object o, File destFile) {
+		try {
+			destFile.createNewFile();
+			BufferedOutputStream fos = new BufferedOutputStream(
+					new FileOutputStream(destFile));
+			ObjectOutputStream oos = new ObjectOutputStream(fos);
+			oos.writeObject(o);
+			oos.close();
+			fos.close();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * Reads the first object out of the file
+	 * @param loadFile the file to read from
+	 * @return the object
+	 */
+	public static Object readSerializedFrom(File loadFile) {
+		Object loadedObject = null;
+		try {
+			BufferedInputStream fis = new BufferedInputStream(
+					new FileInputStream(loadFile));
+			ObjectInputStream ois = new ObjectInputStream(fis);
+			loadedObject = ois.readObject();
+			ois.close();
+			fis.close();
+			// remove File from Filesystem
+		} catch (FileNotFoundException e) {
+			LOG.error(e);
+			e.printStackTrace();
+
+		} catch (Exception e) {
+			LOG.error(e);
+			e.printStackTrace();
+		}
+		return loadedObject;
+	}
+}

Added: trunk/src/appl/util/NonEditableTableModel.java
===================================================================
--- trunk/src/appl/util/NonEditableTableModel.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/util/NonEditableTableModel.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,35 @@
+package appl.util;
+
+import javax.swing.table.DefaultTableModel;
+import javax.swing.table.TableModel;
+
+/**
+ * Simple {@link TableModel} that allows to specify columns which are not editable
+ * 
+ * @author Dominik Appl
+ */
+public class NonEditableTableModel extends DefaultTableModel {
+	private final boolean[] isEditable;
+
+	/**
+	 * @param columnNames
+	 *            <code>array</code> containing the names of the new columns;
+	 *            if this is <code>null</code> then the model has no columns
+	 * 
+	 * @param isEditable Specifies for each column if editable or not
+	 * 
+	 * @param rowCount
+	 *            the number of rows the table holds
+	 */
+	public NonEditableTableModel(Object[] columnNames, boolean[] isEditable,
+			int rowCount) {
+		super(columnNames, rowCount);
+		this.isEditable = isEditable;
+	}
+
+	@Override
+	public boolean isCellEditable(int row, int column) {
+		return isEditable[column];
+	}
+
+}

Added: trunk/src/appl/util/RasterUtil.java
===================================================================
--- trunk/src/appl/util/RasterUtil.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/util/RasterUtil.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,219 @@
+package appl.util;
+
+import java.awt.image.DataBuffer;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.geotools.io.GeoImportUtil;
+
+import org.geotools.gce.arcgrid.ArcGridRaster;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+/** 
+ * This Class provides some simple mostly independent functions 
+ * related to Geo-Rasters and {@link WritableGrid WritableGrids}.
+ * 
+ * @author Dominik Appl
+ *
+ */
+
+public class RasterUtil {
+
+		/**
+		 * Extracts metadata out of a ArcGridASCII File without reading the
+		 * whole Grid (only the Header is parsed).
+		 * 
+		 * @param src the ArcInfoASCII file
+		 * @return the meta data
+		 */
+	public static RasterMetaData getRasterMetaData_from_ArcGridASCII_File(
+			File src) {
+
+		try {
+			ArcGridRaster raster = new ArcGridRaster(new InputStreamReader(
+					new FileInputStream(src)), false);
+			raster.parseHeader();
+			  CoordinateReferenceSystem crs = GeoImportUtil.determineProjection(src);
+			return new RasterMetaData(DataBuffer.TYPE_FLOAT, raster.getNCols(),
+					raster.getNRows(), 0, 0, raster.getXlCorner(), raster
+							.getYlCorner(), raster.getCellSize(),crs);
+		    
+		   } catch (FileNotFoundException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			} catch (IOException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+			return new RasterMetaData(DataBuffer.TYPE_UNDEFINED, 0, 0, 0, 0, 0, 0,
+					0,null);
+	}
+
+	/**
+	 * Runs through every grid cell and checks if the two Grids are equal (based
+	 * on the {@link RasterMetaData} of the first Grid. If the difference is
+	 * smaller than 0.0001 only conversion Warning is given. Output to console
+	 * may be enabled. Writes out warning to sysout, if metaData is not equal,
+	 * but continues checking
+	 * 
+	 * @param a
+	 *            1st grid
+	 * @param b
+	 *            2nd grid
+	 * @param outputToConsole
+	 *            if true the results and some infos are written on System.out
+	 * @return true, if the grids match
+	 */
+	public static boolean checkEqual(WritableGrid a, WritableGrid b,
+			boolean outputToConsole) {
+
+		if (a == null && b == null)
+			return true;
+		if (a == null || b == null)
+			return false;
+
+		//for errors which are probably caused by rounding  
+		float diffTolerance = 1.0e-5f;
+		float maxdiff = 0; // maximum difference found
+		int maxdiffX = 0, maxdiffY = 0; // coordinates of maxdiff
+
+		RasterMetaData metaData = new RasterMetaData(a);
+		if (!metaData.equals(new RasterMetaData(b))) {
+			if (outputToConsole)
+				System.out
+						.println("Warning! Metadata of the two Grids is not equal!");
+		}
+
+		// run through the whole grid
+		float aValue, bValue;
+		float currentdiff;
+		int counter = 0;
+		for (int y = metaData.getMinY(); y < metaData.getHeight()
+				- metaData.getMinY(); y++)
+			for (int x = metaData.getMinX(); x < metaData.getWidth()
+					- metaData.getMinY(); x++) {
+				counter++;
+				aValue = a.getRasterSampleAsFloat(x, y);
+				bValue = b.getRasterSampleAsFloat(x, y);
+				//check equal
+				if (aValue == bValue)
+					continue;
+				if (Float.isNaN(aValue) && Float.isNaN(bValue))
+					continue;
+
+				//check for light differences which might indicate conversionErrors
+				currentdiff = Math.abs(aValue - bValue);
+				if (currentdiff < diffTolerance) {
+					if (currentdiff > maxdiff) {
+						maxdiff = currentdiff;
+						maxdiffX = x;
+						maxdiffY = y;
+					}
+					continue;
+				}
+				// else not equal:
+				if (outputToConsole)
+					System.out
+							.println("Warning: Two Grids were not equal at pos ("
+									+ x
+									+ ","
+									+ y
+									+ ") --- first value "
+									+ a.getRasterSampleAsFloat(x, y)
+									+ " and second value "
+									+ b.getRasterSampleAsFloat(x, y));
+				return false;
+			}
+		if (outputToConsole && !(maxdiff == 0))
+			System.out
+					.println("The Gridvalues differ slightly. The maximum Difference is: "
+							+ maxdiff
+							+ " at ("
+							+ maxdiffX
+							+ ","
+							+ maxdiffY
+							+ "). Finished grid compare after "
+							+ counter
+							+ " checks");
+		else if (outputToConsole)
+			System.out
+					.println("Grids found equal after " + counter + " checks");
+		return true;
+	}
+
+
+	/**
+	 * Copies all values from a {@link WritableGrid} into another
+	 * {@link WritableGrid}. Of course the grids must have the same dimensions.
+	 * 
+	 * @param src
+	 * @param target
+	 * @throws UnsupportedOperationException
+	 *             if the dimensions of the grids does not match or one of the
+	 *             grids is null
+	 */
+	public static void copyInto(WritableGrid src, WritableGrid target){
+		if(src==null || target==null)
+			throw new UnsupportedOperationException("Error: One of the grids was null");
+		//check if width and height are matching:
+		if((src.getHeight()!=target.getHeight()) || (src.getWidth()!=target.getWidth()))
+				throw new UnsupportedOperationException("The bounds of the two rasters don't not match! Copy failed!");
+		for(int y=0; y < src.getHeight();y++)
+			for(int x=0; x < src.getWidth(); x++)
+				target.setRasterSample(src.getRasterSample(x,y), x,y);
+		
+	}
+	
+	/**
+	 * Prints the grid to the console (useful for testing).
+	 * 
+	 * @param grid the grid to be printed
+	 * @param spacing the space to be reserved for one cell-value
+	 * @param precision the decimal places to be printed out
+	 * @param name the name will be shown in the heading of the output
+	 */
+	public static void printGrid(WritableGrid grid, int spacing, int precision, String name){
+		//generate format String
+		System.out.println("****************************** " + name +  " ******************************");
+		int width =grid.getWidth();
+		int noOfCells = grid.getWidth() * grid.getHeight();
+		Object[] cellarray = new Object[noOfCells];
+		StringBuffer buffer = new StringBuffer(noOfCells * 9);
+		String singleCellFormatString = "%" + spacing + "." + precision + "f ";
+		buffer.append("%n ");
+		for(int y=0; y < grid.getHeight();y++){
+			for(int x=0; x < grid.getWidth(); x++){
+				buffer.append(singleCellFormatString);
+				cellarray[y*width+x]=grid.getRasterSampleAsFloat(x,y);
+			}
+			buffer.append("%n ");
+		}
+		
+		System.out.printf(buffer.toString(), cellarray);
+	}
+	
+	/**
+	 * Prints the grid to the console (useful for testing).
+	 * Spacing will be 5 and precision will be 2.
+	 * 
+	 * @param grid the grid to be printed
+	 * @param name the name will be shown in the heading of the output
+	 */
+	public static void printGrid(WritableGrid grid, String name){
+		printGrid(grid,5,2,name);
+	}
+	
+	/**
+	 * Prints the grid to the console (useful for testing). 
+	 * Spacing will be 5 and precision will be 2.
+	 * 
+	 * @param grid the grid to be printed
+	 */
+	public static void printGrid(WritableGrid grid){
+		printGrid(grid," ");
+	}
+}

Added: trunk/src/appl/util/XuluFrameAdapter.java
===================================================================
--- trunk/src/appl/util/XuluFrameAdapter.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/util/XuluFrameAdapter.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,53 @@
+package appl.util;
+
+import javax.swing.JPanel;
+
+import edu.bonn.xulu.gui.XuluInternalFrame;
+import java.awt.Dimension;
+
+/**
+ * Makes an XuluInternalFrame out of a {@link JPanel}.
+ * 
+ * @author Dominik Appl
+ */
+public class XuluFrameAdapter extends XuluInternalFrame{
+
+	
+	private final JPanel panel;
+
+
+
+	/**
+	 * Creates the internal Frame
+	 * @param titel the window-title
+	 * @param panel the panel to be displayed in the frame
+	 */
+	public XuluFrameAdapter(String titel, JPanel panel) {
+		super(titel);
+		this.panel = panel;
+		initialize();
+		   
+	}
+
+	
+
+	/**
+	 * This method initializes this
+	 * 
+	 */
+	private void initialize() {
+        this.setSize(new Dimension(panel.getSize().width, panel.getSize().height + 30));
+        this.setClosable(true);
+	    this.setDefaultCloseOperation( HIDE_ON_CLOSE );
+	    this.getContentPane().add(panel);	
+	}
+
+
+
+	@Override
+	public void refresh() {
+		
+		
+	}
+
+}  //  @jve:decl-index=0:visual-constraint="10,10"

Added: trunk/src/appl/util/benchmark/Benchmark.java
===================================================================
--- trunk/src/appl/util/benchmark/Benchmark.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/util/benchmark/Benchmark.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,17 @@
+package appl.util.benchmark;
+
+/**
+ * Simple Interface for Benchmarks. Benchmarks may be used to give the user an
+ * impression of the hardware capabilities.
+ * 
+ * @author Dominik Appl
+ */
+public interface Benchmark {
+	/**
+	 * runs the Benchmark
+	 * 
+	 * @return a rating. The rating should be a positive number and linear in
+	 *         the computing power
+	 */
+	public int bench();
+}

Added: trunk/src/appl/util/benchmark/SimpleBenchmark.java
===================================================================
--- trunk/src/appl/util/benchmark/SimpleBenchmark.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/util/benchmark/SimpleBenchmark.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,127 @@
+package appl.util.benchmark;
+
+import java.awt.Rectangle;
+import java.awt.image.DataBuffer;
+import java.util.Random;
+
+import appl.data.LoadingException;
+import appl.ext.XuluConfig;
+import appl.parallel.data.splittable.SplittableLLProxyGrid;
+import appl.util.RasterMetaData;
+import appl.util.RasterUtil;
+import edu.bonn.xulu.plugin.io.grid.array.WritableGridArrayFactory;
+
+/**
+ * The algorithm simply iterates over a grid. The with and height can be
+ * specified by the {@link XuluConfig} Property
+ * <code>Benchmark.SimpleBench.gridwidth</code>. For each cell the average
+ * over a neighborhood region is calculated. The neighborhoodRange can be
+ * specified by <code>Benchmark.SimpleBench.neighborhood</code>. If the
+ * algorithm reaches the end of the raster it starts again at (0,0). The rating
+ * depends on the number of cells visited in the time (ms) specified by
+ * <code>Benchmark.SimpleBench.time<code>. The number of cells is divided by
+ * <code>Benchmark.SimpleBench.calibrator</code> and then given back as rating.
+ * 
+ * @author Dominik Appl
+ */
+public class SimpleBenchmark implements Benchmark {
+	private SplittableLLProxyGrid inputGrid;
+
+	int runningTime = 10000;
+
+	private int gridwidth = 1000;
+
+	private int neighborhoodRange;
+
+	private double calibrator = 1;
+
+	public int bench() {
+		setUp();
+
+		int cellCount = 0;
+		long startTime = System.currentTimeMillis();
+		Rectangle partition = new Rectangle(0, 0, inputGrid.getWidth(),
+				inputGrid.getHeight());
+		boolean exit = false;
+		for (int step = 0; exit == false; step++) {
+			// the overallsum is simply the sum over all elements
+			float overallSum = 0f;
+			for (int y = 0; y < inputGrid.getHeight(); y++)
+				for (int x = 0; x < inputGrid.getWidth(); x++) {
+					if (System.currentTimeMillis() - startTime > runningTime)
+						exit = true;
+					else
+						cellCount++;
+					float tmp = inputGrid.getRasterSampleAsFloat(x, y);
+					if (!Float.isNaN(tmp))
+						overallSum += tmp;
+					// the local sum is simply the sum over all elements in the
+					// neighborhood
+					float localSum = 0;
+					// number of cells over which the sum is calculated
+					int noOfCells = 0;
+					// for each cell: calculate the sum of all neighbors
+					for (int y2 = y - neighborhoodRange; y2 <= y
+							+ neighborhoodRange; y2++)
+						for (int x2 = x - neighborhoodRange; x2 <= x
+								+ neighborhoodRange; x2++)
+							// check if the coordinates are valid (inside the
+							// grid and not NaN)
+							if (partition.contains(x2, y2))
+								if (!Float.isNaN(inputGrid
+										.getRasterSampleAsFloat(x2, y2))) {
+									localSum += inputGrid
+											.getRasterSampleAsFloat(x2, y2);
+									noOfCells++;
+								}
+
+				}
+		}
+		return (int) (cellCount / calibrator);
+	}
+
+	/**
+	 * The method is used to load grids and to initialize the benchmarks
+	 * configuration.
+	 */
+	private void setUp() {
+		// read config
+		int width = XuluConfig.getXuluConfig().getIntProperty(
+				"Benchmark.SimpleBench.gridwidth");
+		if (width != 0)
+			this.gridwidth = width;
+		// init running time
+		int time = XuluConfig.getXuluConfig().getIntProperty(
+				"Benchmark.SimpleBench.runningtime");
+		if (time != 0)
+			this.runningTime = time;
+		// init calibrator
+		double calibrator = XuluConfig.getXuluConfig().getDoubleProperty(
+				"Benchmark.SimpleBench.calibrator");
+		if (calibrator != 0)
+			this.calibrator = calibrator;
+		// init neighborhoodRange
+		neighborhoodRange = XuluConfig.getXuluConfig().getIntProperty(
+				"Benchmark.SimpleBench.neighborhood");
+		// create input Grid
+		inputGrid = new SplittableLLProxyGrid(new WritableGridArrayFactory(),
+				new RasterMetaData(DataBuffer.TYPE_DOUBLE, gridwidth,
+						gridwidth, 0, 0, 0, 0, 50, null));
+		// load grid (so late loading has no influence on the calculation)
+		try {
+			inputGrid.loadData();
+		} catch (LoadingException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		// fill Grid with random Data
+		Random rand = new Random();
+		for (int y = 0; y < inputGrid.getHeight(); y++)
+			for (int x = 0; x < inputGrid.getWidth(); x++)
+				inputGrid.setGridSample(rand.nextDouble(), x, y);
+	}
+
+	public static void main(String[] args) {
+		System.out.println("Current rating: " + new SimpleBenchmark().bench());
+	}
+}

Added: trunk/src/appl/util/benchmark/package.html
===================================================================
--- trunk/src/appl/util/benchmark/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/util/benchmark/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,5 @@
+<html>
+<body>
+	Provides benchmarking functionality.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/appl/util/package.html
===================================================================
--- trunk/src/appl/util/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/appl/util/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,5 @@
+<html>
+<body>
+	Collection of several usefull classes.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/de/skrueger/xulu/plugin/gnur/GnuRGUI.java
===================================================================
--- trunk/src/de/skrueger/xulu/plugin/gnur/GnuRGUI.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/de/skrueger/xulu/plugin/gnur/GnuRGUI.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,420 @@
+/** GnuR Plugin - A XULU-plugin for applying R-powered statistics on objects in the XULU-datapool.
+    Copyright (C) 2007  Stefan A. Krüger
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/   
+package de.skrueger.xulu.plugin.gnur;
+
+/**
+ * TODO 
+ * Ausführen von .R skripten
+ * Löschen des Workspace!?
+ * Ãœbergabe von Grids
+ * Eingabefeld zu TextFied für mherzeilige Eingaben
+ */
+
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.dnd.DropTarget;
+import java.awt.dnd.DropTargetAdapter;
+import java.awt.dnd.DropTargetDragEvent;
+import java.awt.dnd.DropTargetDropEvent;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JScrollPane;
+
+import org.rosuda.JRI.REXP;
+import org.rosuda.JRI.RList;
+import org.rosuda.JRI.RVector;
+import org.rosuda.JRI.Rengine;
+
+import schmitzm.data.RasterCalculator;
+import schmitzm.data.event.ObjectEvent;
+import schmitzm.data.event.ObjectListener;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyReadAccess;
+import schmitzm.data.property.Property;
+import schmitzm.swing.ManualInputOption;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.DataPool;
+import edu.bonn.xulu.gui.XuluInternalFrame;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+
+public class GnuRGUI extends XuluInternalFrame {
+  /** Speichert eine Referenz auf das Fenster-Objekt, um aus verschachtelten
+   *  Klassen einfach darauf zugreifen zu koennen. */
+  protected final GnuRGUI THIS = this;
+  /** Speichert eine Referenz auf die Xulu-Applikation, in der der Code-Generator
+   *  ausgefuehrt wird. */
+  protected XuluModellingPlatform appl = null;
+  /** Tabelle in der die Eingabe-Raster angegeben werden. */
+  protected RVarsTable            rVarsTable = null;
+  private   RVarsTableModel 	  rVarsTableModel = null;
+  private   JScrollPane           rVarsScrollPane = null;
+
+  /** Eingabefeld fuer die Formel. */
+  protected ManualInputOption.Text rule = null;
+  /** Button to Import the Variables to R from the datapool. */
+  protected JButton importButton = null;
+  /** Button to Export the Variables from R to the datapool. */
+  protected JButton exportButton = null;
+
+  /** Referenz auf den Container des Fensters. */
+  protected Container contentPane = null;
+  /** The RConsole-Panel contains of ab Output- and an Inputfied for R */
+  private RConsolePanel rConsole = null;
+
+  /**
+   * Erzeugt eine neue GUI fuer den {@link RasterCalculator}.
+   * @param appl Instanz der Xulu-Applikation, in der der Rechner
+   *             ausgefuehrt wird
+   */
+  public GnuRGUI(XuluModellingPlatform appl) {
+    super("GNU-R toolbox");
+    this.appl = appl;
+
+    this.setVisible(false);
+    this.setSize( new Dimension(500,400) );
+    this.setClosable(true);
+    this.setDefaultCloseOperation( HIDE_ON_CLOSE );
+    this.getContentPane().setLayout( new GridBagLayout() );
+    contentPane  = this.getContentPane();
+    initGUI();
+    refresh();
+
+    // Listener auf den Datenpool setzen, damit Auswahlfelder automatisch
+    // aktualisiert werden
+    appl.getDataPool().addObjectListener( new ObjectListener() {
+      public void performObjectEvent(ObjectEvent e) {
+        if ( e instanceof DataPool.DataPoolChangeEvent )
+          refresh();
+      }
+    });
+  }
+
+  /**
+   * Initalisiert die GUI des Fensters.
+   */
+  protected void initGUI() {
+	// Input-Raster-Tabelle
+	rVarsTableModel = new RVarsTableModel(appl);
+	rVarsTable = new RVarsTable(rVarsTableModel);
+	rVarsTable.setToolTipText("Simply do drang and drop");
+	rVarsTable.setPreferredScrollableViewportSize( new Dimension(400,200));
+	rVarsScrollPane = rVarsTable.createScrollPane();
+	// Formel
+	rule = new ManualInputOption.Text("Rule:", true);
+	rule
+		.setToolTipText("Insert your arithmetical rule here (Use arithmetical operators, constants and #1, #2, ... as raster reference identifier)");
+	// Button zum Starten
+	importButton = new JButton("Import");
+	importButton.addActionListener(new ActionListener() {
+	    public void actionPerformed(ActionEvent e) {
+		importRVars();
+		// After Import of vars into R, show all vars..
+		rConsole.sendToConsole("ls()");
+	    }
+	});
+
+	exportButton = new JButton("Export");
+	exportButton.addActionListener(new ActionListener() {
+	    public void actionPerformed(ActionEvent e) {
+		exportRVars();
+	    }
+	});
+
+	// Drag & Drop fuer RVars
+	DropTarget dropTarget = new DropTarget(appl.getMainFrame(),
+		new DropTargetAdapter() {
+		    public void dragEnter(DropTargetDragEvent e) {
+
+			// Pruefen, ob mind, ein akzeptables Objekt im Datenpool
+                        // selektiert ist
+			Object[] selObjects = appl.getMainFrame()
+				.getDataPoolFrame().getSelectedObjects();
+			for (Object obj : selObjects) {
+			    try {
+				RVarAdapter.createFrom((Property) obj, true);
+        			return;
+			    } catch (PropertytypeNotConvertableToRVar ee) {
+				// ee.printStackTrace();
+				System.out.println("Not convertable..");
+			    } 
+			    System.out.println(obj.getClass());
+			}
+			// Reject drop, if nothing convertible was found.
+			e.rejectDrag();
+		    }
+
+		    public void drop(DropTargetDropEvent e) {
+			Object[] selObjects = appl.getMainFrame()
+				.getDataPoolFrame().getSelectedObjects();
+
+			for (Object obj : selObjects) {
+			    // rVarsTableModel.addRVariable(
+				    //RVarAdapter.createFrom(obj, false)  );
+			    refresh();
+			}
+		    }
+		});
+
+	rVarsTable.setDropTarget(dropTarget);
+	rVarsScrollPane.setDropTarget(dropTarget);
+
+	/*
+         * The R-Console Window
+         */
+	try {
+	    rConsole = new RConsolePanel();
+	    rConsole.init();
+	} catch (IOException e1) {
+	    e1.printStackTrace();
+	}
+
+	// Komponenten in Fenster anordnen
+	contentPane.add(new JLabel("Input/Output-Rasters (use context menu or simply drag rasters from xulu data pool):"), new GridBagConstraints(
+		0, 0, 2, 1, 0, 0,
+		GridBagConstraints.NORTHWEST,
+		GridBagConstraints.HORIZONTAL, 
+		new Insets(5, 10, 0,10), 0, 0));
+	
+	contentPane.add(rVarsScrollPane, new GridBagConstraints(
+		0, 1, 2, 3, 0.1, 0.1, 
+		GridBagConstraints.CENTER, 
+		GridBagConstraints.BOTH,
+		new Insets(0, 10, 5, 10), 0, 0));
+
+	contentPane.add(rConsole, new GridBagConstraints(
+		0, 4, 2, 2, 0.5, 0.5,
+		GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, 
+		new Insets(0, 10, 5, 10), 0, 0));
+
+	contentPane.add(importButton, new GridBagConstraints(
+		0, 6, 1, 1, 0.0, 0, 
+		GridBagConstraints.WEST, 
+		GridBagConstraints.NONE,
+		new Insets(0, 10, 5, 10), 0, 0));
+	contentPane.add(exportButton, new GridBagConstraints(
+		1, 6, 1, 1, 0.0, 0, 
+		GridBagConstraints.WEST, 
+		GridBagConstraints.NONE,
+		new Insets(0, 10, 5, 10), 0, 0));
+    }
+
+
+/**
+ * Aktualisiert die Auswahl-Felder auf Basis des Datenpools.
+ */
+  public void refresh() {
+    // Aktualisierung der Tabelle
+    rVarsTableModel.refreshInputOption();
+    rVarsTableModel.fireTableDataChanged();
+  }
+
+
+
+
+  /**
+   */
+  private void exportRVars() {
+		if (rConsole.getREngine() == null) return;
+		System.out.println("Reusing Rengine.. Exporting from R... ");
+		
+		Vector<RVarAdapter> vars = rVarsTableModel.getRVars();
+		for (RVarAdapter rv : vars) {
+			//TODO  rv.fromR( rConsole.getREngine() );
+		}
+  }
+
+  private void importRVars() {
+	Vector<RVarAdapter> vars = rVarsTableModel.getRVars();
+	for (RVarAdapter rv : vars) {
+		rv.toR(rConsole.getREngine());
+	}
+  }
+
+  
+  private void doRstuff(Rengine re) {
+		/* High-level API - do not use RNI methods unless there is no other way
+			to accomplish what you want */
+		try {
+			REXP x;
+			re.eval("data(iris)",false);
+			System.out.println(x=re.eval("iris"));
+			System.out.println(x=re.eval("a <- 2*3"));
+			System.out.println(re.eval("a"));
+			// generic vectors are RVector to accomodate names
+			RVector v = x.asVector();
+			if (v.getNames()!=null) {
+				System.out.println("has names:");
+				for (Enumeration e = v.getNames().elements() ; e.hasMoreElements() ;) {
+					System.out.println(e.nextElement());
+				}
+			}
+			// for compatibility with Rserve we allow casting of vectors to lists
+			RList vl = x.asList();
+			String[] k = vl.keys();
+			if (k!=null) {
+				System.out.println("and once again from the list:");
+				int i=0; while (i<k.length) System.out.println(k[i++]);
+			}			
+			
+			// now for a real dotted-pair list:
+			System.out.println(x=re.eval("pairlist(a=1,b='foo',c=1:5)"));
+			RList l = x.asList();
+			if (l!=null) {
+				int i=0;
+				String [] a = l.keys();
+				System.out.println("Keys:");
+				while (i<a.length) System.out.println(a[i++]);
+				System.out.println("Contents:");
+				i=0;
+				while (i<a.length) System.out.println(l.at(i++));
+			}
+			System.out.println(re.eval("sqrt(36)"));
+		} catch (Exception e) {
+			System.out.println("EX:"+e);
+			e.printStackTrace();
+		}
+		
+		// Part 2 - low-level API - for illustration purposes only!
+		//System.exit(0);
+		
+	    // simple assignment like a<-"hello" (env=0 means use R_GlobalEnv)
+	    long xp1 = re.rniPutString("hello");
+	    re.rniAssign("a", xp1, 0);
+
+	    // Example: how to create a named list or data.frame
+	    double da[] = {1.2, 2.3, 4.5};
+	    double db[] = {1.4, 2.6, 4.2};
+	    long xp3 = re.rniPutDoubleArray(da);
+	    long xp4 = re.rniPutDoubleArray(db);
+	    
+	    // now build a list (generic vector is how that's called in R)
+	    long la[] = {xp3, xp4};
+	    long xp5 = re.rniPutVector(la);
+
+	    // now let's add names
+	    String sa[] = {"a","b"};
+	    long xp2 = re.rniPutStringArray(sa);
+	    re.rniSetAttr(xp5, "names", xp2);
+
+	    // ok, we have a proper list now
+	    // we could use assign and then eval "b<-data.frame(b)", but for now let's build it by hand:       
+	    String rn[] = {"1", "2", "3"};
+	    long xp7 = re.rniPutStringArray(rn);
+	    re.rniSetAttr(xp5, "row.names", xp7);
+	    
+	    long xp6 = re.rniPutString("data.frame");
+	    re.rniSetAttr(xp5, "class", xp6);
+	    
+	    // assign the whole thing to the "b" variable
+	    re.rniAssign("b", xp5, 0);
+	    {
+	        System.out.println("Parsing");
+	        long e=re.rniParse("data(iris)", 1);
+	        System.out.println("Result = "+e+", running eval");
+	        long r=re.rniEval(e, 0);
+	        System.out.println("Result = "+r+", building REXP");
+	        REXP x=new REXP(re, r);
+	        System.out.println("REXP result = "+x);
+	    }
+	    {
+	        System.out.println("Parsing");
+	        long e=re.rniParse("iris", 1);
+	        System.out.println("Result = "+e+", running eval");
+	        long r=re.rniEval(e, 0);
+	        System.out.println("Result = "+r+", building REXP");
+	        REXP x=new REXP(re, r);
+	        System.out.println("REXP result = "+x);
+	    }
+	    {
+	        System.out.println("Parsing");
+	        long e=re.rniParse("names(iris)", 1);
+	        System.out.println("Result = "+e+", running eval");
+	        long r=re.rniEval(e, 0);
+	        System.out.println("Result = "+r+", building REXP");
+	        REXP x=new REXP(re, r);
+	        System.out.println("REXP result = "+x);
+	        String s[]=x.asStringArray();
+	        if (s!=null) {
+	            int i=0; while (i<s.length) { System.out.println("["+i+"] \""+s[i]+"\""); i++; }
+	        }
+	    }
+	    {
+	        System.out.println("Parsing");
+	        long e=re.rniParse("rnorm(10)", 1);
+	        System.out.println("Result = "+e+", running eval");
+	        long r=re.rniEval(e, 0);
+	        System.out.println("Result = "+r+", building REXP");
+	        REXP x=new REXP(re, r);
+	        System.out.println("REXP result = "+x);
+	        double d[]=x.asDoubleArray();
+	        if (d!=null) {
+	            int i=0; while (i<d.length) { System.out.print(((i==0)?"":", ")+d[i]); i++; }
+	            System.out.println("");
+	        }
+	        System.out.println("");
+	    }
+	    {
+	        REXP x=re.eval("1:10");
+	        System.out.println("REXP result = "+x);
+	        int d[]=x.asIntArray();
+	        if (d!=null) {
+	            int i=0; while (i<d.length) { System.out.print(((i==0)?"":", ")+d[i]); i++; }
+	            System.out.println("");
+	        }
+	    }
+
+	    re.eval("print(1:10/3)");
+	    
+	if (false) {
+	    // so far we used R as a computational slave without REPL
+	    // now we start the loop, so the user can use the console
+	    System.out.println("Now the console is yours ... have fun");
+	    re.startMainLoop();
+	} else {
+	    re.end();
+	    System.out.println("end");
+	}    
+	  
+  }
+  
+  private static ListProperty[] getListPropertysFromObject(Object obj){
+	  if ( obj instanceof SingleGrid )
+	      obj = ((SingleGrid)obj).getProperty( SingleGrid.PROP_GRID );
+	    if ( obj instanceof MultiGrid )
+	      obj = ((MultiGrid)obj).getProperty( MultiGrid.PROP_GRIDS );
+
+	    
+	    	    	
+    if ( obj instanceof ListProperty ) {
+        ListPropertyReadAccess a = ((ListProperty)obj).getReadAccess(obj);
+        ListProperty[] lists = new ListProperty[ a.getCount() ];
+        for (int i=0; i<lists.length; i++)
+          lists[i] = (ListProperty)a.getValue(i);
+        a.release();
+        return lists;
+      }
+      return null;
+  }
+
+    
+
+}

Added: trunk/src/de/skrueger/xulu/plugin/gnur/GnuRPlugin.java
===================================================================
--- trunk/src/de/skrueger/xulu/plugin/gnur/GnuRPlugin.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/de/skrueger/xulu/plugin/gnur/GnuRPlugin.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,40 @@
+/** GnuR Plugin - A XULU-plugin for applying R-powered statistics on objects in the XULU-datapool.
+    Copyright (C) 2007  Stefan A. Krüger
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/   
+package de.skrueger.xulu.plugin.gnur;
+
+import edu.bonn.xulu.gui.XuluInternalFrame;
+import edu.bonn.xulu.plugin.appl.AbstractMenuPlugin;
+
+/**
+ * This plugin implements the {@link de.skrueger.xulu.plugin.gnur.GnuRGUI}
+ * into the Xulu-menu "Model".
+ * @author <a href="mailto:stefan at wikisquare.de">Stefan Krueger</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class GnuRPlugin extends AbstractMenuPlugin  {
+  private static final int MODEL_MENU = 1;
+
+  /**
+   * Erzeugt eine neue Plugin-Instanz.
+   */
+  public GnuRPlugin() {
+    super(MODEL_MENU,"Use GNU-R on your datapool");
+  }
+  
+  /**
+   * Erzeugt eine Instanz der Plugin-Applikation {@link GnuRGUI}.
+   */
+  protected XuluInternalFrame createPluginApplication() throws Exception {
+//    return (XuluInternalFrame)LangUtil.loadClass(CALCULATOR_CLASSNAME,appl.getDynamicClassRootDirectory().toURL()).getConstructor(XuluModellingPlatform.class).newInstance(appl);
+    return new GnuRGUI(appl);
+  }
+}

Added: trunk/src/de/skrueger/xulu/plugin/gnur/JRTextArea.java
===================================================================
--- trunk/src/de/skrueger/xulu/plugin/gnur/JRTextArea.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/de/skrueger/xulu/plugin/gnur/JRTextArea.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,57 @@
+/** GnuR Plugin - A XULU-plugin for applying R-powered statistics on objects in the XULU-datapool.
+    Copyright (C) 2007  Stefan A. Krüger
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/   
+package de.skrueger.xulu.plugin.gnur;
+
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.TexturePaint;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+import javax.swing.JTextArea;
+
+public class JRTextArea extends JTextArea {
+	static BufferedImage img = null;
+	TexturePaint texture;
+	boolean fileFound = false;
+	
+	public JRTextArea() {
+		super();
+		if (img == null)	// Open the image if not happened earlier  
+		    try {
+			File file = new File ("rlogo.jpg");
+			System.out.println("name = "+file.getAbsolutePath());
+			img = ImageIO.read( file);
+		    } catch (IOException e) {
+			e.printStackTrace();
+		    }		
+		fileFound = true;
+		// Schrift ausgeben
+		setOpaque(false);
+	}
+	
+	public void paintComponent(Graphics g) {
+		if (fileFound){
+			Graphics2D g2 = (Graphics2D)g;
+			Rectangle rect = new Rectangle(0,0, img.getWidth(null), img.getHeight(null));
+			texture = new TexturePaint(img, rect);
+			g2.setPaint(texture);
+			g.fillRect(0, 0, getWidth(), getHeight());
+			g.drawString("sds", 0, 0);
+		}
+		super.paintComponent(g);
+	}
+	
+}

Added: trunk/src/de/skrueger/xulu/plugin/gnur/PropertytypeNotConvertableToRVar.java
===================================================================
--- trunk/src/de/skrueger/xulu/plugin/gnur/PropertytypeNotConvertableToRVar.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/de/skrueger/xulu/plugin/gnur/PropertytypeNotConvertableToRVar.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,33 @@
+/** GnuR Plugin - A XULU-plugin for applying R-powered statistics on objects in the XULU-datapool.
+    Copyright (C) 2007  Stefan A. Krüger
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/  
+package de.skrueger.xulu.plugin.gnur;
+
+import schmitzm.data.property.Property;
+import schmitzm.data.property.PropertyException;
+
+/**
+ * This Exception is thrown, when the object from the datapool is not convertable to an R object. This can be
+ * due to the structure of the data, or due to the GnuR plugins capabilities.  
+ *
+ * @author Stefan A. Krüger
+ */
+public class PropertytypeNotConvertableToRVar extends PropertyException{
+
+	public PropertytypeNotConvertableToRVar(Property prop) {
+		super(prop, "The Propertytype can not be converted to an R variable.");
+	}
+
+	public PropertytypeNotConvertableToRVar(Property prop, String msg) {
+	    super(prop, msg);
+	}
+
+}

Added: trunk/src/de/skrueger/xulu/plugin/gnur/RConsolePanel.java
===================================================================
--- trunk/src/de/skrueger/xulu/plugin/gnur/RConsolePanel.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/de/skrueger/xulu/plugin/gnur/RConsolePanel.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,322 @@
+/** GnuR Plugin - A XULU-plugin for applying R-powered statistics on objects in the XULU-datapool.
+    Copyright (C) 2007  Stefan A. Krüger
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+package de.skrueger.xulu.plugin.gnur;
+
+import java.awt.Cursor;
+import java.awt.FileDialog;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.io.IOException;
+import java.io.PipedInputStream;
+import java.util.Vector;
+
+import javax.swing.BorderFactory;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+import javax.swing.border.EtchedBorder;
+
+import org.apache.log4j.Logger;
+import org.rosuda.JRI.RMainLoopCallbacks;
+import org.rosuda.JRI.Rengine;
+
+public class RConsolePanel extends JPanel implements RMainLoopCallbacks {
+    Logger log; // TODO .. some smarter logging that System.out
+
+    /** There may only be one REngine for the whole XULU Framework.*/
+    private static Rengine re = null;
+
+    boolean readInput = false;		// Is true when the InputField is ready to be sent to R
+    boolean readInput2 = false;		// Is true when the internal InputField is ready to be sent to R
+
+    // Output from R
+    public JTextArea rOut = new JRTextArea();
+    private JScrollPane cmdOutSp;
+
+    // Inputf to R
+    public JTextArea rCmdIn = new JTextArea(4,80);
+    private JScrollPane cmdInSp;
+
+    // Keeps a list of the last commands entered in R.
+    Vector<String> history    = new Vector<String>();
+    int    historyPos = 0;
+
+    protected int maxLines = 200;
+
+    /* Cursor when waiting for R */
+    Cursor hourglassCursor = new Cursor(Cursor.WAIT_CURSOR);
+    Cursor defaultCursor = new Cursor(Cursor.DEFAULT_CURSOR);
+
+    public RConsolePanel() throws IOException {
+        rOut.setEditable(false);
+        rOut.setRows(200);
+        rOut.setBorder( BorderFactory.createEtchedBorder(EtchedBorder.LOWERED) );
+
+        rCmdIn.addKeyListener(keyL);
+        rCmdIn.setBorder( BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
+
+        setLayout(new GridBagLayout());
+        cmdOutSp = new JScrollPane( rOut );
+	add(  cmdOutSp ,
+        	new GridBagConstraints(
+        		0, 0, 2, 1, 1, 1,
+        		GridBagConstraints.NORTHWEST,
+        		GridBagConstraints.BOTH,
+        		new Insets(5, 0, 2, 0),
+        		0, 0) );
+        cmdInSp = new JScrollPane( rCmdIn );
+        	add(  cmdInSp, new GridBagConstraints(
+        		0, 1, 2, 1, 1, 1,
+        		GridBagConstraints.NORTHWEST,
+        		GridBagConstraints.BOTH,
+        		new Insets(2, 0, 5, 0),
+        		0, 0) );
+    }
+
+    public void init() {
+	if (re == null) {
+	    System.out.println("Creating Rengine (with arguments)");
+            String[] args = new String[1];
+            args[0] = "--no-save";
+            // 1) we pass the arguments from the command line
+            // 2) we won't use the main loop at first, we'll start it later
+            // (that's the "false" as second argument)
+            // 3) the callbacks are implemented by the TextConsole class above
+            re = new Rengine(args, false, this);
+            System.out.println("Rengine created, waiting for R");
+            // the engine creates R is a new thread, so we should wait until
+            // it's ready
+            if (!re.waitForR()) {
+        	System.out.println("Cannot load R");
+    		return;
+    	    }
+    	    re.startMainLoop();
+    	};
+    }
+
+    final KeyListener keyL = new KeyAdapter() {
+        public void keyPressed(KeyEvent ev) {
+
+            if(ev.getKeyCode() == KeyEvent.VK_UP + KeyEvent.CTRL_DOWN_MASK) {
+                if(historyPos > 0) {
+                  String line = history.elementAt(historyPos-1);
+                  historyPos--;
+                  rCmdIn.setText(line);
+                }
+              }
+            else if(ev.getKeyCode() == KeyEvent.VK_DOWN + KeyEvent.CTRL_DOWN_MASK) {
+                if(historyPos < history.size()-1) {
+                  String line = (String)history.elementAt(historyPos+1);
+                  historyPos++;
+                  rCmdIn.setText(line);
+                }
+              }
+            else
+        	// No Up- or Down-key pressed.
+            {
+            String line = rCmdIn.getText();
+            if (    (ev.getModifiers() == KeyEvent.CTRL_MASK)
+        	 && ( ev.getKeyCode() == KeyEvent.VK_ENTER)   ) {
+
+        	// If something worth saving was typed...
+        	if(!("".equals(line) ||
+                     "\n".equals(line) ||
+                     "\n\r".equals(line) ||
+                     "\r\n".equals(line))) {
+                    history.add( line.trim() );
+                }
+
+                if("clear".equals(line)) {
+                    // Wipes the R-Output window.
+                    rOut.setText("");
+                }
+                else
+                {
+                    showLastLine();
+                    readInput = true;
+                }
+            }
+            }
+        }
+    };
+
+    private String throwInCmd;
+
+
+    /**
+     * Scrolls down the ScrollWindow of the ROutput.
+     */
+    public void showLastLine() {
+        SwingUtilities.invokeLater(new Runnable() {
+          public void run() {
+            if (maxLines > 0) {
+              int linesToRemove = rOut.getLineCount() - maxLines;
+              while (linesToRemove < 0 ){
+        	 rOut.setText( "\n" + rOut.getText());
+        	 linesToRemove++;
+              }
+              if (linesToRemove > 0) {
+        	    int index = 0;
+                    for (int i=0; i<linesToRemove; i++) {
+                      index = rOut.getText().indexOf('\n', index) + 1;
+                    }
+                    rOut.setText(rOut.getText().substring(index));
+              } else {
+
+              }
+            }
+          }
+        });
+      }
+
+    class ReaderThread extends Thread {
+        PipedInputStream pi;
+        ReaderThread(PipedInputStream pi) {
+            this.pi = pi;
+        }
+
+        public void run() {
+            final byte[] buf = new byte[1024];
+            try {
+               while (true) {
+                    final int len = pi.read(buf);
+                    if (len == -1) {
+                        break;
+                    }
+                    SwingUtilities.invokeLater(new Runnable() {
+                        public void run() {
+                            rOut.append(new String(buf, 0, len));
+
+                            // Make sure the last line is always visible
+                            rOut.setCaretPosition(rOut.getDocument().getLength());
+
+                            // Keep the text area down to a certain character size
+                            int idealSize = 1000;
+                            int maxExcess = 500;
+                            int excess = rOut.getDocument().getLength() - idealSize;
+                            if (excess >= maxExcess) {
+                                rOut.replaceRange("", 0, excess);
+                            }
+                        }
+                    });
+                }
+            } catch (IOException e) {
+            }
+        }
+    }
+
+    /**
+     * called by the R-Engine, when it want's to print to STDOUT
+     */
+//    @Override
+    public void rWriteConsole(Rengine re, String text) {
+    	rOut.append(text);
+    	showLastLine();
+    }
+
+//    @Override
+    public void rBusy(Rengine re, int which) {
+    	if (which == 1) {
+    		System.out.println("busy");
+    		rCmdIn.setEnabled(false);
+    		setCursor(hourglassCursor);
+    	} else {
+    		rCmdIn.setEnabled(true);
+    		System.out.println("not busy");
+    		setCursor(defaultCursor);
+    		rCmdIn.requestFocus();
+    	}
+    }
+
+//    @Override
+    public String rReadConsole(Rengine re, String prompt, int addToHistory) {
+    	rCmdIn.setEnabled(true);
+    	while ((!readInput) && (!readInput2) ) {
+    		try {
+    			Thread.sleep(100);
+    		} catch (InterruptedException e) {
+    			e.printStackTrace();
+    		}
+    	}
+
+    	String  text = "";
+    	// Input comes from the GNU-R Plugin GUI
+    	if (readInput) {
+    	    readInput=false;
+    	    text = rCmdIn.getText()+"\n";
+    	    rCmdIn.setText("");
+    	}
+    	else if (readInput2) {
+    	    // Sent to R-Console by cmd : public void sendToConsole(String s)
+    	    readInput2 = false;
+    	    text = throwInCmd+"\n";
+    	    throwInCmd = "";
+    	}
+
+    	System.out.print("Sending as Console Input = "+text);
+    	return text;
+    }
+
+    /**
+     * Easy way to send a command to R
+     * The result is shown on the R Console
+     * @param s
+     */
+    public void sendToConsole(String s) {
+	throwInCmd = s;
+	readInput2 = true;
+    }
+
+//    @Override
+    public void rShowMessage(Rengine re, String message) {
+    	rOut.append("rShowMessage \"" + message + "\"");
+    }
+
+//    @Override
+    public String rChooseFile(Rengine re, int newFile) {
+    	FileDialog fd = new FileDialog(new Frame(),
+    			(newFile == 0) ? "Select a file" : "Select a new file",
+    			(newFile == 0) ? FileDialog.LOAD : FileDialog.SAVE);
+    	fd.setVisible(true);
+    	String res = null;
+    	if (fd.getDirectory() != null)
+    		res = fd.getDirectory();
+    	if (fd.getFile() != null)
+    		res = (res == null) ? fd.getFile() : (res + fd.getFile());
+    	return res;
+    }
+
+//    @Override
+    public void rFlushConsole(Rengine re) {
+    }
+
+//    @Override
+    public void rLoadHistory(Rengine re, String filename) {
+    }
+
+    public void rSaveHistory(Rengine re, String filename) {
+    	System.out.println("Maybe I want to export the stuff here!?");
+    }
+
+    /**
+     * Returns the static R-Engine
+     */
+    public Rengine getREngine() {
+        return re;
+    }
+}

Added: trunk/src/de/skrueger/xulu/plugin/gnur/RVar.java
===================================================================
--- trunk/src/de/skrueger/xulu/plugin/gnur/RVar.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/de/skrueger/xulu/plugin/gnur/RVar.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,103 @@
+package de.skrueger.xulu.plugin.gnur;
+
+import org.rosuda.JRI.REXP;
+import org.rosuda.JRI.Rengine;
+
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.data.property.ValueProperty;
+
+/**
+ * Link between datapool and R-Engine 
+ * @author stefan
+ */
+
+public class RVar {
+	/**
+	 * Soll diese Datenstruktur in die R Engine importiert und-/oder aus der 
+	 * Engine heraus exportiert werden?  
+	 */
+	private Boolean exp = true;
+	private Boolean imp = true;
+
+	private ValueProperty prop = null;
+	private String RVarName = null;
+
+	public RVar ( ValueProperty prop) throws PropertytypeNotConvertableToRVar {
+		if (prop instanceof ScalarProperty) {
+			this.prop = prop;
+			RVarName = prop.getName().replaceAll(" ", "_");
+		} else {
+			throw new PropertytypeNotConvertableToRVar( prop );
+		}
+	}
+	
+	public Boolean isExport() {
+		return exp;
+	}
+	
+	public Boolean isImport() {
+		return imp;
+	}
+
+	
+	/**
+	 * @return the name of the variabl ein the R environment
+	 */
+	public String getRName() {
+		return RVarName;
+	}
+	
+
+	/**
+	 * Set the name that will reference the R-variable inside the RVar.
+	 * TODO: Check for doubles, name validity
+	 * @param rname
+	 */
+	public void setRName(String rname) {
+		RVarName = rname.replace(" ", "_");
+	}
+
+	/**
+	 * @return the name of the object in the datapool
+	 */
+	public String getName() {
+		return prop.getName();
+	}
+
+	public boolean toR(Rengine re) {
+		REXP x;
+		
+		if (!isImport()) return false;
+		
+		if (prop instanceof ScalarProperty) {
+			Integer val = prop.getOneTimeReadAccess().getValueAsInt();
+			String expr = getRName() + " <- " + val;
+			re.eval(expr);
+			return true;
+		} else {
+			System.out.println("Can't import this var!"+getName());
+			return false;
+		}
+	}
+	
+
+	public boolean fromR(Rengine re) {
+		REXP x;
+		
+		if (!isExport()) return false;
+		
+		if (prop instanceof ScalarProperty) {
+			String expr = getRName();
+			REXP eval = re.eval(expr);
+			System.out.println(eval);
+			Double val = eval.asDouble();
+			prop.getOneTimeWriteAccess().setValue(val.intValue());
+			System.out.println(getName()+" now has value "+val.intValue());
+			return true;
+		} else {
+			System.out.println("Can't export this var!"+getName());
+			return false;
+		}
+	}
+	
+}

Added: trunk/src/de/skrueger/xulu/plugin/gnur/RVarAdapter.java
===================================================================
--- trunk/src/de/skrueger/xulu/plugin/gnur/RVarAdapter.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/de/skrueger/xulu/plugin/gnur/RVarAdapter.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,88 @@
+package de.skrueger.xulu.plugin.gnur;
+
+import org.rosuda.JRI.Rengine;
+
+import schmitzm.data.property.MatrixProperty;
+import schmitzm.data.property.Property;
+import schmitzm.data.property.ScalarProperty;
+
+/**
+ * Link between datapool and R-Engine
+ * @author stefan
+ */
+
+public abstract class RVarAdapter {
+	/**
+	 * Soll diese Datenstruktur in die R Engine importiert und-/oder aus der
+	 * Engine heraus exportiert werden?
+	 */
+	private Boolean exp = true;
+	private Boolean imp = true;
+
+	protected Property prop = null;
+	private String RVarName = null;
+
+	/**
+	 *
+	 * @param obj
+	 * @param testOnly	if true, than only check if Property is compatible-.. otherwise throw PropertytypeNotConvertableToRVarException
+	 * @throws PropertytypeNotConvertableToRVar
+	 */
+	static public RVarAdapter createFrom ( Property obj, boolean testOnly) throws PropertytypeNotConvertableToRVar {
+		if (obj instanceof ScalarProperty) {
+		    System.out.print("Scalprop");
+		    if (!testOnly) return new RVarScalar( (ScalarProperty)obj );
+		} else if (obj instanceof MatrixProperty) {
+		    System.out.print("MatrixProp");
+		    if (!testOnly) return new RVarMatrix( (MatrixProperty)obj );
+		} else {
+			throw new PropertytypeNotConvertableToRVar( obj );
+		}
+		return null;
+	}
+
+	public Boolean isExport() {
+		return exp;
+	}
+
+	public Boolean isImport() {
+		return imp;
+	}
+
+
+	/**
+	 * @return the name of the variabl ein the R environment
+	 */
+	public String getRName() {
+		return RVarName;
+	}
+
+
+	/**
+	 * Set the name that will reference the R-variable inside the RVar.
+	 * TODO: Check for doubles, name validity
+	 * @param rname
+	 */
+	public void setRName(String rname) {
+		RVarName = rname.replace(" ", "_");
+	}
+
+	/**
+	 * @return the name of the object in the datapool
+	 */
+	public String getName() {
+		return prop.getName();
+	}
+
+	public abstract void toR(Rengine re);
+
+	public abstract void fromR(Rengine re);
+
+	protected RVarAdapter(Property prop) {
+	    super();
+	    this.prop = prop;
+
+	    // Change name of var so that its R-sytax-proof.
+	    RVarName = prop.getName().replaceAll(" ", "_");
+	}
+}

Added: trunk/src/de/skrueger/xulu/plugin/gnur/RVarMatrix.java
===================================================================
--- trunk/src/de/skrueger/xulu/plugin/gnur/RVarMatrix.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/de/skrueger/xulu/plugin/gnur/RVarMatrix.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,139 @@
+package de.skrueger.xulu.plugin.gnur;
+
+import org.rosuda.JRI.REXP;
+import org.rosuda.JRI.Rengine;
+
+import schmitzm.data.property.MatrixProperty;
+
+public class RVarMatrix extends RVarAdapter {
+    
+    MatrixProperty prop = (MatrixProperty) super.prop;
+    private Class cType;		// Class/type of the MatrixProperties' values
+    int[] size;				// Getting the size of the matrix in X and Y direction
+    
+    protected RVarMatrix(MatrixProperty prop) {
+	super(prop);
+	cType = prop.getType();
+	size =  prop.getSize();;
+	System.out.println("MatrixProp created...");
+    }
+
+    @Override
+    /**
+     * Export a matrix from the R environment into a MatrixProperty
+     * @author Stefan A. Krüger
+     */    
+    public void fromR(Rengine re) {
+	if (!isImport()) return;
+	
+	// So far we can only handle two-dimensional matrixes.
+	int dims = prop.getDimension(); 
+	if (dims != 2) {
+	    throw new PropertytypeNotConvertableToRVar(prop,"Sorry. So far the GNU-R plugin can only handle two-dimensional matrixes.");
+	}
+
+	
+    	REXP ex = re.eval( getRName() );
+    	if ((cType == Integer.class) || (cType == Short.class) || (cType == Float.class) ) {
+    	    double ee[][] = ex.asMatrix();
+    	    if (ee==null) 
+    		throw new PropertytypeNotConvertableToRVar(prop, cType.toString() + " - error was not expected."); 
+    	    	System.out.println("len von ee[] = "+ee.length);
+    		System.out.println("ee[1] = "+ee[1]);
+    		
+    	    	// Filling the PropertyMatrix with the double-matrix from R
+    	    	for (int x = 0; x < size[0]; x++)  {
+    	    	    for (int y = 0; y < size[1]; y++)  {
+    	    		Double d = Double.valueOf(ee[x][y]);
+    	    		if ( cType == Float.class ) prop.getOneTimeWriteAccess().setValue( d.floatValue(), x, y );
+    	    		if ( cType == Double.class ) prop.getOneTimeWriteAccess().setValue( d, x, y );
+    	    		if ( cType == Integer.class ) prop.getOneTimeWriteAccess().setValue( Integer.valueOf( d.intValue()), x, y );
+    	    		if ( cType == Short.class ) prop.getOneTimeWriteAccess().setValue( Integer.valueOf( d.shortValue()), x, y );
+    	    	    }
+    	    	}
+    	    	return;
+    	} else
+        if (cType == String.class) {
+            throw new PropertytypeNotConvertableToRVar(prop, cType.toString() + " - cant import that type from R. Ask the programmer kindly to implement it.");
+        } else {
+            throw new PropertytypeNotConvertableToRVar(prop, cType.toString() + " - cant import that type from R. Sorry.");
+        }
+    	
+//    	// Filling the PropertyMatrix fomr a 1-dim object-array
+//    	for (int x = 0; x < size[0]; x++)  {
+//    	    for (int y = 0; y < size[1]; y++)  {
+//    		// System.out.println( prop.getOneTimeReadAccess().getValue( x,y ) );
+//    		int idx = y + (x*size[1]);
+//    		prop.getOneTimeWriteAccess().setValue( longarray[idx], x, y );
+//    	    }
+//    	}
+    	
+    }
+
+
+    
+    
+    
+    @Override
+    /**
+     * Import a MatrixProperty into the R environment
+     */
+    public void toR(Rengine re) {
+	if (!isExport()) return;
+	
+	// So far we can only handle two-dimensional matrixes.
+	int dims = prop.getDimension(); 
+	if (dims != 2) {
+	    throw new PropertytypeNotConvertableToRVar(prop,"Sorry. So far the GNU-R plugin can only handle two-dimensional matrixes.");
+	}
+	
+    	// Filling a 1-dim object-array
+    	Object longarray[] = new Object [ size[0] * size[1] ];
+    	for (int x = 0; x < size[0]; x++)  {
+    	    for (int y = 0; y < size[1]; y++)  {
+    		// System.out.println( prop.getOneTimeReadAccess().getValue( x,y ) );
+    		int idx = y + (x*size[1]);
+    		longarray[idx] = prop.getOneTimeReadAccess().getValueAsInt( x,y );
+    	    }
+    	}
+    	// System.out.println ("Length of the longarray = " + longarray.length );
+    	
+    	// LongArray referenze in R 
+        long xpLA = -1;
+        
+    	// Check which types we can import into R:
+        
+    	if ((cType == Integer.class) || (cType == Short.class)) {
+    	    // Converting object-array to int[]
+    	    int[] aa = new int[longarray.length];
+    	    for (int i = 0; i<longarray.length-1; i++) {
+    		aa[i] = (Integer) longarray[i];
+    	    }
+    	    // importing to R
+    	    xpLA = re.rniPutIntArray(  aa );
+    	} else 
+        if (cType == Float.class) {
+    	    double[] aa = new double[longarray.length];
+    	    for (int i = 0; i<longarray.length-1; i++) {
+    		aa[i] = (Double) longarray[i];
+    	    }
+    	    // importing to R
+    	    xpLA = re.rniPutDoubleArray( aa );
+        } else
+        if (cType == String.class) {
+            String[] aa = new String[longarray.length];
+    	    for (int i = 0; i<longarray.length-1; i++) {
+    		aa[i] = (String) longarray[i];
+    	    }
+    	    // importing to R
+	    xpLA = re.rniPutStringArray( aa );
+        } else {
+            throw new PropertytypeNotConvertableToRVar(prop, cType.toString() + " - cant convert that type to R. Sorry.");
+        }
+    		
+
+    	// Convert xpLA to a R-matrix
+    	re.rniAssign( getRName(), xpLA, 0);
+    	re.eval( getRName()+"<-matrix ( "+getRName()+","+size[0]+" ) ");
+    }
+}

Added: trunk/src/de/skrueger/xulu/plugin/gnur/RVarScalar.java
===================================================================
--- trunk/src/de/skrueger/xulu/plugin/gnur/RVarScalar.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/de/skrueger/xulu/plugin/gnur/RVarScalar.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,41 @@
+package de.skrueger.xulu.plugin.gnur;
+
+import org.rosuda.JRI.REXP;
+import org.rosuda.JRI.Rengine;
+
+import schmitzm.data.property.ScalarProperty;
+
+public class RVarScalar extends RVarAdapter{
+    
+    ScalarProperty prop = (ScalarProperty) super.prop;
+
+    public RVarScalar( ScalarProperty prop) {
+	super(prop );
+	System.out.println("Scalarprop created...\n");
+    }
+    
+    @Override
+    public void toR(Rengine re) {
+    	REXP x;
+    	if (!isImport()) return;
+    	
+    	Integer val = prop.getOneTimeReadAccess().getValueAsInt();
+    	String expr = getRName() + " <- " + val;
+    	re.eval(expr);
+    }
+
+    @Override
+    public void fromR(Rengine re) {
+	if (!isExport()) return;
+
+	REXP x;
+        
+        String expr = getRName();
+        REXP eval = re.eval(expr);
+        System.out.println(eval);
+        Double val = eval.asDouble();
+        prop.getOneTimeWriteAccess().setValue(val.intValue());
+        System.out.println(getRName()+" now has value "+val.intValue());
+    }
+    
+}

Added: trunk/src/de/skrueger/xulu/plugin/gnur/RVarSingleGrid.java
===================================================================
--- trunk/src/de/skrueger/xulu/plugin/gnur/RVarSingleGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/de/skrueger/xulu/plugin/gnur/RVarSingleGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,36 @@
+package de.skrueger.xulu.plugin.gnur;
+
+import org.rosuda.JRI.Rengine;
+
+import schmitzm.data.property.Property;
+
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+
+public class RVarSingleGrid extends RVarAdapter {
+    
+//    SingleGrid grid = (SingleGrid) super.prop;
+//
+//    protected RVarSingleGrid(SingleGrid grid) {
+////	super(grid);
+//    }
+
+    protected RVarSingleGrid(Property prop) {
+	super(prop);
+	// TODO Auto-generated constructor stub
+    }
+
+    @Override
+    public void fromR(Rengine re) {
+
+    }
+
+    @Override
+    /**
+     * 
+     */
+    public void toR(Rengine re) {
+	
+
+    }
+
+}

Added: trunk/src/de/skrueger/xulu/plugin/gnur/RVarsTable.java
===================================================================
--- trunk/src/de/skrueger/xulu/plugin/gnur/RVarsTable.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/de/skrueger/xulu/plugin/gnur/RVarsTable.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,12 @@
+package de.skrueger.xulu.plugin.gnur;
+
+import schmitzm.swing.table.MutableTable;
+import schmitzm.swing.table.MutableTableModel;
+
+public class RVarsTable extends MutableTable {
+
+	public RVarsTable(MutableTableModel model) {
+		super(model);
+	}
+
+}

Added: trunk/src/de/skrueger/xulu/plugin/gnur/RVarsTableModel.java
===================================================================
--- trunk/src/de/skrueger/xulu/plugin/gnur/RVarsTableModel.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/de/skrueger/xulu/plugin/gnur/RVarsTableModel.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,153 @@
+package de.skrueger.xulu.plugin.gnur;
+
+import java.util.Vector;
+
+import schmitzm.data.event.ObjectEvent;
+import schmitzm.data.event.ObjectListener;
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.geotools.gui.GeotoolsGUIUtil;
+import schmitzm.swing.SelectionInputOption;
+import schmitzm.swing.table.AbstractMutableTableModel;
+import schmitzm.swing.table.MutableTableModel;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.DataPool;
+
+///////////////////////////////////////////////////////////////////
+//////////////   TableModel for the DnD-Tabel der R Variables  //////////////
+///////////////////////////////////////////////////////////////////
+
+class RVarsTableModel extends AbstractMutableTableModel {
+  /** Speichert die in der Tabelle gespeicherten Raster */
+	protected Vector<RVarAdapter> objects = new Vector<RVarAdapter>();
+  
+  /** Speichert die Instanz der Xulu-Applikation. */
+  protected XuluModellingPlatform appl = null;
+  /** Eingabe-Option fuer ein einzelnes Objekt. */
+  protected SelectionInputOption.Combo objectInputOption = null;
+
+  /** Flag, ob sich der Inhalt des Datenpools geaendert hat und die Arrays
+   *  {@link #fitObjects} und {@link #fitObjectNames} aktualisiert werden
+   *  muessen */
+  protected boolean  dataPoolChanged = true;
+  /** Passende Objekte im Datenpool */
+  protected Object[] fitObjects = null;
+  /** Bezeichnungen der passenden Objekte im Datenpool */
+  protected String[] fitObjectNames = null;
+
+  /**
+   * Erzeugt ein neues Tabellen-Modell.
+   * @param appl Instanz der Xulu-Applikation
+   * @param rowIndexPrefix Praefix, das den Zeilen-Indizes vorangestellt wird
+   */
+  public RVarsTableModel(XuluModellingPlatform appl) {
+    super();
+    this.appl = appl;
+    objectInputOption = new SelectionInputOption.Combo(getColumnName(1),true);
+    refreshInputOption();
+    // Listener auf den Datenpool setzen, damit das Auswahlfeld aktualisiert
+    // werden kann (wenn notwendig)
+    appl.getDataPool().addObjectListener( new ObjectListener() {
+      public void performObjectEvent(ObjectEvent e) {
+        if ( e instanceof DataPool.DataPoolChangeEvent ) {
+          dataPoolChanged = true;
+        }
+      }
+    });
+  }
+
+  /**
+   * Liefert die Spaltennamen der Tabelle.
+   */
+  @Override
+  public String[] createColumnNames() {
+    return new String[] {null,"Datapool-Object","Names in R","Import","Export"};
+  }
+
+  /**
+   * Ruft {@link #determineFitObjectsAndNames()}, wenn das {@link #dataPoolChanged}-Flag
+   * auf {@code true} steht und setzt das Flag zurueck.
+   */
+  protected void refreshFitObjects() {
+    if ( dataPoolChanged )
+      determineFitObjectsAndNames();
+    dataPoolChanged = false;
+  }
+
+  /**
+   * Aktualisiert das Dialog-Auswahlfeld, in dam alle passenden Objekte
+   * aus dem Datenpool vorgeblendet werden.
+   */
+  protected void refreshInputOption() {
+    refreshFitObjects();
+    objectInputOption.setSelectionObjects(fitObjects,fitObjectNames);
+  }
+
+  /**
+   * Wird aufgerufen, wenn sich der Inhalt des Xulu-Datenpools aendert.
+   * Muss die Arrays {@link #fitObjects} und {@link #fitObjectNames} mit
+   * allen passenden Objekten des Datenpools und deren Bezeichnungen
+   * befuellen.
+   */
+  protected void determineFitObjectsAndNames() {
+}
+
+
+  /**
+   * Loescht eine Tabellenzeile.
+   * @param row Zeilenindex (beginnend bei 0)
+   */
+  public void performRemoveRow(int row) {
+    objects.remove(row);
+  }
+
+  /**
+   * Macht nichts, da in der Tabelle keine Daten veraendert werden koennen.
+   * @param row Zeilenindex (beginnend bei 0)
+   * @param col Spaltenindex (beginnend bei 0)
+   */
+  public void performChangeData(int row, int col) {
+  }
+
+  /**
+   * Liefert die Anzahl an Zeilen.
+   */
+  public int getRowCount() {
+    return objects.size();
+  }
+
+  /**
+   * Liefert den Inhalt einer Tabellenzelle.
+   * @param row Zeilenindex (beginnend bei 0)
+   * @param col Spaltenindex (beginnend bei 0)
+   */
+  public Object getValueAt(int row, int col) {
+    switch ( col ) {
+      case 0: return row;
+      case 1: return objects.elementAt(row).getRName(); // TODO 
+      case 2: return objects.elementAt(row).getRName();
+      case 3: return objects.elementAt(row).isImport();
+      case 4: return objects.elementAt(row).isExport();
+    }
+    return null;
+  }
+
+
+public void performAddRow() {
+	System.out.println("?!");
+}
+
+
+public void addRVariable(RVarAdapter rv) {
+	objects.add(rv);
+	refreshFitObjects();
+}
+
+/**
+ * Returns the 
+ * @return
+ */
+public Vector<RVarAdapter> getRVars() {
+	return objects;
+}
+
+}

Added: trunk/src/de/skrueger/xulu/plugin/gnur/Rcode/funGeneric.r
===================================================================
--- trunk/src/de/skrueger/xulu/plugin/gnur/Rcode/funGeneric.r	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/de/skrueger/xulu/plugin/gnur/Rcode/funGeneric.r	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,39 @@
+### generic functions
+
+### ============================================================================
+### set start working directory automatic
+locPath <- function (dest=c('data','SatData', 'model', 'model.data', 'prog')) {
+  dest <- match.arg(dest)
+  switch(dest, 
+         data = directory <- c("i:/Benin","M:/4_Research/Benin_Daten"), 
+         SatData = directory <- c("F:","M:/4_Research/Benin_Daten"),
+         model = directory <- c("e:/Xulu-100m/statistics","M:/4_Research/Xulu"),
+         model.data = directory <- c("e:/database_modelling","M:/4_Research/LUCC_Modelling/database_modelling"), 
+         prog = directory <- c("Y:/6_Programming/R","D:/6_Programming/R") )
+
+  # look if directory at home is available and set path apropriately
+  if (!is.na(file.info(directory[2])$isdir)){locdrive = directory[2]} else {locdrive <- directory[1]}
+  locdrive <- paste(locdrive,"/",sep="")
+  return(locdrive)
+}
+
+### path to base path for R script files, e.g. this generic function file
+locPathP <- function () {
+  DirUni <- "Y:/6_Programming"
+  DirHome <- "D:/6_Programming"
+  if (!is.na(file.info(DirHome)$isdir)){locdrive = DirHome} else {locdrive <- DirUni}
+  locdrive <- paste(locdrive,"/",sep="")
+  return(locdrive)
+}
+
+### ============================================================================
+### copy content of graphic device to a postscript file
+### file is located in working directory
+### works best if ps is given the width and height of the current device
+
+### the option  onefile=F is essential to have the bounding box -> LATEX!
+
+psFile <- function(file="Rplot.eps", dim, ...) {
+        dev.copy2eps(file=file, width=dim[1], height=dim[2],
+        horizontal = FALSE, onefile=F, paper = "special", ...)
+}

Added: trunk/src/de/skrueger/xulu/plugin/gnur/Rcode/functions.R
===================================================================
--- trunk/src/de/skrueger/xulu/plugin/gnur/Rcode/functions.R	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/de/skrueger/xulu/plugin/gnur/Rcode/functions.R	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,240 @@
+#########################################################################
+################# function definitions  #################################
+#########################################################################
+
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+###                        File operations                                 
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ 
+# --------------------------------------------------------------
+### sort filelist
+### args:
+### 1. List of input files
+### 2. seperator string. where to split the numbers from mai file name
+
+sort.filelist <- function (FileList, s="_") {
+  f=strsplit(FileList, s)
+  v=numeric()
+  # extract number element out of list, which is simulation year
+  for (i in 1:length(f)){v=c(v,f[[i]][2])}
+  v=as.numeric(v)
+  # sort years with index values
+  vs=sort(v, index.return=T)
+  # apply sortet year list to Filelist
+  FileList.sort = FileList[vs[[2]]]
+  return(FileList.sort)
+}
+
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+###                        Read ASCII GRID data                            
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+### ---------------------------------------------------------------------
+### read several ascii grid into list                                   
+### ---------------------------------------------------------------------
+
+read.grd <- function (FileList, n=length(FileList), path="") {
+  #test for right / in path string
+  if (path!="" & length(grep("/$",path))>0) path=path else {path=paste(path,"/",sep="")} 
+  
+  grid.lst = list()
+  for (i in 1:n) {
+    grid.lst[[i]] <- read.asciigrid(paste(path,FileList[i],sep=""), as.image=T )
+    
+  }
+  names(grid.lst) <- FileList
+  return(grid.lst)
+}
+
+
+### ---------------------------------------------------------------------
+### read several ascii grid into one dataframe ONLY DATA!                 
+### ---------------------------------------------------------------------
+
+read.asciigrid.df <- function(GridList, nPixels) {
+  for (i in 1:length(GridList)) {
+    InData = read.asciigrid(GridList[i], as.image=T )
+    InData = as.numeric(InData$z)
+    if (length(na.omit(InData)) != nPixels ) {
+      print("amount of pixel values doesn't match!!!!!")
+      print(GridList[i])
+      }
+    if (i==1) {
+      ascii.df = as.data.frame(InData)
+      }
+    else {  
+    ascii.df = cbind(ascii.df,InData) 
+      }
+    }
+}
+
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+###                        Sampling functions                            
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+# ---------------------------------------------------------------------
+# balanced sampling of lc pixels
+# ---------------------------------------------------------------------
+
+
+balanced.sampling <- function(dataframe, lc.type, max_samp) {
+
+  dataframe$lu <- ifelse (dataframe[[1]] == lc.type, 1, 0)
+
+  dataframe.S1 = subset(dataframe, lu==1)
+  
+  if (sum(dataframe.S1$lu, na.rm = T) > 2000) {
+    RandomList = runif(max_samp,min=1, max=length(dataframe.S1$lu))
+    dataframe.S1 = dataframe.S1[RandomList,]
+  }
+  
+  # set maximum sampling amount to number of cases if <2000
+  if (sum(dataframe$lu, na.rm = T) < 2000) {
+    print (c("LU type", lc.type, "has", sum(dataframe$lu, na.rm = T), "occurances, do balanced sampling"))
+    max_samp = sum(dataframe$lu, na.rm = T)
+    }
+    
+  dataframe.S0 = subset(dataframe, lu==0)
+   RandomList = runif(max_samp,min=1, max=length(dataframe.S0$lu))
+  dataframe.S0 = dataframe.S0[RandomList,]
+
+  dataframe.S = rbind(dataframe.S1,dataframe.S0)
+  colnames(dataframe.S) <- colnames(dataframe)
+  return(dataframe.S)
+  }
+
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+###                 write results from logit model to file                 
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+# ---------------------------------------------------------------------
+# write AUV values to file
+# ---------------------------------------------------------------------
+
+WriteAUC <- function (fitstep, BeninData, i) {
+  pred = prediction(fitted(fitstep),as.vector(BeninData$lu))
+  # ---------------------------------------------------------------------
+  # compute AUC
+  # ---------------------------------------------------------------------
+  auc = performance(pred, measure="auc")
+  # auc is object of class performance, data stored in slots
+  # to access slots (and datas) use @ (in Newsletter 4/1 is said
+  # don't use it but I don't know an other way
+  aucValue = auc at y.values[[1]]
+  write (paste("AUC for LC no",i, ":", aucValue, sep=" "), outputRegEval, append=TRUE)
+}
+
+
+# ---------------------------------------------------------------------
+# write betas in a CLUE-S compatible file
+# ---------------------------------------------------------------------
+
+WriteCoefClue <- function(fitstep, outRegressionFile, i, description="new run") {
+  coef <- summary(fitstep)$coefficients
+  betas <- as.vector(coef[,1])
+  # insert number of dforces
+  betas <- append(betas, length(betas)-1 , after=1)
+  # insert number of landcover class
+  betas <- append(betas, i, after=0)
+  # insert second collumn for dforce id
+  betas <- cbind(betas, "") [, c(1,2)]
+  # match dforce id of coef list with value list above
+  res_dforces_names <- as.data.frame(dimnames(coef)[[1]])
+  res_dforces <- merge(dforce, res_dforces_names, by=1, sort=FALSE)
+  # insert dforce id into second collumn
+  z <- length(dimnames(coef)[[1]]) -1
+  for (j in 1:z) {
+  	betas[j+3,2] <- res_dforces$dforce_number[j]
+  }
+  if (i == 0) {
+    write("\n----------------------------------",outRegressionFile,append=TRUE) 
+    write(description,outRegressionFile,append=TRUE) 
+  }
+  write(t(betas), outRegressionFile, ncolumns=2, append=TRUE)
+}
+
+
+# ---------------------------------------------------------------------
+# write betas in a XULU compatible file
+# ---------------------------------------------------------------------
+
+WriteCoefXulu <- function(fitstep, outeval, i , description="new run") {
+  coef <- summary(fitstep)$coefficients
+  betas <- as.vector(coef[,1])
+
+  coef.val <- numeric(length=length(dforce_number)+1 )
+
+  # assign intercept
+  coef.val[1] = betas[1]
+  # assign coef
+  # get position (index) of df name
+  df.pos = match(dimnames(coef)[[1]][-1], dforce_name)
+  # assign the coef at appropriate postition in vector
+  coef.val[df.pos+1] = betas[-1]
+  # insert semicolon
+  coef.val = paste(coef.val, ";", sep="")
+  if (i==0) {
+     write(paste("--------------- (", description, ")", sep=""),outeval,append=TRUE) 
+     #write(description,outeval,append=TRUE) 
+  }
+  write(paste("\n ----- LC ",i, " ------", sep=""),outeval,append=TRUE) 
+  write(coef.val, outeval, ncolumns=length(dforce_number)+1, append=TRUE)
+}
+
+
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+###                    Plot results from logit model                       
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+# ---------------------------------------------------------------------
+# plot fitted values from logistic regression model
+# ---------------------------------------------------------------------
+
+plot.fitted <- function(FileList, fitted.data, dataset, numrows=580, numcols=539) {
+
+  InData = read.asciigrid(FileList[1], as.image=T )
+  # convert data matrix to numeric
+  v=as.numeric(InData$z)
+  ## get index of data values
+  x=which(v>=0)
+  # calculate probabilities for whole data set (if subset used)
+  prd=predict(fitted.data, newdata=dataset, type="response")
+  prd=na.omit(prd)
+  ## assign new values to x position
+  v[x]=prd
+  # transform it back to matrix
+  v=matrix(v,  nrow=numrows, ncol=numcols)
+  # get matrix back to image
+  predict.grid = InData
+  predict.grid$z = v
+  image(predict.grid, col=terrain.colors(24))
+  legend.entries = seq(0,1, by=1/10,digits=1)
+  legend("bottomright",legend=legend.entries, fill=terrain.colors(11))
+
+}
+
+### color ramp
+### -> see colorRampPalette function and RColorBrewer
+
+#image(grid.prob[[2]], col=rainbow(24, start=0, end=2/6))
+#
+#colorRamp.redblue <- function (n) 
+#{
+#    x <- ramp(seq(0, 1, length = n))
+#    rgb(x[, 1], x[, 2], x[, 3], max = 255)
+#}
+#
+#
\ No newline at end of file

Added: trunk/src/de/skrueger/xulu/plugin/gnur/Rcode/logit_regression_all_v1.3.R
===================================================================
--- trunk/src/de/skrueger/xulu/plugin/gnur/Rcode/logit_regression_all_v1.3.R	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/de/skrueger/xulu/plugin/gnur/Rcode/logit_regression_all_v1.3.R	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,266 @@
+########################################################################
+########################################################################
+# Skript to calculate logit regression for landcover analysis
+# make random subset of input data to minimize computation time 
+# input: datafile prepared with CLUS-S file conversion tool
+# output: ascii file ready to use as alloc.1 in CLUE-S
+# adapt the following parameters:
+# - path to files and filenames
+# - look if colnames are all acoorect!
+# - Subset of data to use (exclude irrelevant predictors and cover classes)
+# CHANGES:
+#
+# Version 1.3:
+# - mehr automatismen, um daten anderer Konfiguration zu verarbeiten
+#   z.B. Daten in 100m und für Xulu -> LN muss nicht bei 0 anfangen
+# Version 1.2:
+# - balanced sampling also for small classes: 
+#   equal samples of 0 and 1 (tip from Peter V.)
+#
+# Version 1.1:
+# - extract certain methods to functions (write different values)
+# 
+# Version 1.0:
+# - read data automaticaly from directory and assign colnames from filenames
+# 
+
+########################################################################
+########################################################################
+ 
+
+# load libraries
+library(MASS)
+library(ROCR)
+library(sp)
+
+#######################################################################
+# read functions
+#######################################################################
+source(paste(locPath(dest="prog"),"CLUE-S/functions.R", sep=""))
+
+# ---------------------------------------------------------------------
+# define path to data
+# ---------------------------------------------------------------------                             
+setwd(locPath(dest="model"))
+
+outputRegressionFile = "R_coefficients_lc.txt" 
+outputRegXulu = "R_coefficients_xulu.txt"
+outputRegEval = "R_regression_evaluation_all.txt"
+
+# ---------------------------------------------------------------------
+# import landcover data and driving forces into R
+# import data are output from CLUE-S conversion tool
+# ---------------------------------------------------------------------
+
+# read directly from ASCII GRID
+# take care the NO MINUS signs are pressent in file names!!
+# replace with underscores
+extension <- ".txt"
+FileList = list.files(pattern = paste("\\",extension,"$",sep=""))
+#FileList = list.files(pattern = "\\.txt$")
+FileList = FileList[-which(FileList == "ac_orig_all.asc")]
+
+# read ascii data into dataframe and test if all have same pixel amount
+BeninData = read.asciigrid.df(FileList, 1434056 )  #for 250m resolution: 229863
+
+# write colnames (filename) to dataframe
+# delete file name extension
+FileListN = gsub(extension,"",FileList)
+# replace undescore in variable name by .
+FileListN = gsub("_", ".",FileListN)
+colnames(BeninData)=FileListN
+
+# convert to factor levels
+BeninData$soil = factor(BeninData$soil)
+BeninData$tpi = factor(BeninData$tpi)
+
+# resort df that lc data are first collumn
+#BeninData = BeninData[c(8,1:7,9:length(BeninData))]
+BeninData = data.frame(BeninData$lc2000, subset(BeninData, select= -lc2000))
+#colnames(BeninData[1]) <- "lc.2000"        # funktiniert nicht!
+## muss names(BeninData)[1]="lc.2000" sein! # colname ist Benindata.lc.2000
+                                            # alle folgenden stellen ändern
+                                            # in glm etc.
+  
+  
+
+# ---------------------------------------------------------------------
+# PRE-FORMATING OF DATA
+# ---------------------------------------------------------------------
+# create list of colnames
+# ---------------------------------------------------------------------
+
+# get number of fields in dataset
+numLUClasses <- max(BeninData[[1]], na.rm = T)
+# 
+LuClasses <- seq(min(BeninData[[1]], na.rm = T) , max(BeninData[[1]], na.rm = T))
+
+# get number of fields in dataset
+numData = length(BeninData)
+
+# create dataframe with driving force names and id numbers
+# due to factor levels it is not possible to take the clomanes 
+# of the dataframe.
+
+
+dforce_name = vector()
+for (i in 2:length(BeninData)) {
+  if (is.factor(BeninData[[i]])){
+    #print ("factor")
+    factor.range <- range(as.numeric(levels(BeninData[[5]])))
+    for (j in factor.range[1]+1 : factor.range[2]){ 
+      dforce_name = append(dforce_name, paste(colnames(BeninData[i]),j, sep=""))
+    }
+  }
+  else {
+  dforce_name = append(dforce_name, colnames(BeninData[i]))
+  }
+}
+dforce_number <- seq(0,length(dforce_name)-1)
+dforce <- data.frame(dforce_name, dforce_number)
+
+
+
+
+########################################################################
+# Logistic regression with random subset of data
+# SELECT BETWEEN THE FOLLLOWING METHODS TO SUBSET DATA11
+########################################################################
+
+# ---------------------------------------------------------------------
+# fit binary logistic model to lc data
+# loop that goes through all landcover types and calculate
+# regression parameters with subset of data and stepwise
+# regression
+# 
+# leave out first list in data_benin as this is AgricChange
+# ---------------------------------------------------------------------
+
+
+# start loop with all LC classes
+i=1
+for (i in LuClasses) {
+  print("---------------------------") # leerzeile
+  print(paste("calculation on landcover no:", i, sep=" "))
+
+	# balanced sampling of data
+	BeninDataS = balanced.sampling(BeninData, i, 25000)  
+	
+	# load data from previous sampling:
+  load(list.files(pattern = paste("BeninDataSampleLc", i,sep="")))
+  
+  # save sample
+	#save(BeninDataS, file=paste("BeninDataSampleLc", i, "_", Sys.Date(), ".Rdata", sep=""), compress=T)
+	
+  # --------------------------------------------------------------
+	# do logitis regression fit
+	# --------------------------------------------------------------
+  #fit0 <- glm(lu ~ bev2000 + d.road.2000 +d.village  , family=binomial, 
+  #  data=subset(BeninDataS, select=c(-BeninData.lc.2000.f,  -d.a.area.1991, -d.f.area.2000)))
+  
+  
+  fit <- assign(paste("fit_lc", i, sep=""), glm(lu ~ . , family=binomial, 
+    data=subset(BeninDataS, select=c(-BeninData.lc2000)) ))
+
+  # --------------------------------------------------------------
+  # do stepwise selection of coefficients
+  # --------------------------------------------------------------   
+	fitstep <- assign(paste("step_lc", i, sep=""), stepAIC(fit, direction="both"))
+	
+	
+	# write results to file
+  #WriteCoefClue(fit0, outputRegressionFile, i, "25000 samples, only lc0, selected df")
+  WriteCoefXulu(fitstep, outputRegXulu, i,)
+  #WriteAUC(fitstep, BeninDataS, i)
+  
+}
+
+#######################################################################
+############ plot fitted value as image
+####################################################################### 
+
+## plot.fitted(FileList, fitted object, data to predict, numrows(grid), numcols) 
+
+plot.fitted(FileList, fitstep, BeninData)  
+
+
+#######################################################################
+# plot log curve data 
+#######################################################################
+
+# ---------------------------------------------------------------------
+# real data:
+# ---------------------------------------------------------------------
+fit1 <- glm(lu ~ CostDist , family=binomial, data=BeninDataS[-1])
+coef = fit1$coef
+
+# ---------------------------------------------------------------------
+# manual calculation of response values
+# ---------------------------------------------------------------------
+logistW = exp(coef[1:1]+(coef[2:2]*BeninDataS$DistRoad))/(1 + exp(coef[1:1]+(coef[2:2]*BeninDataS$DistRoad)))
+plot(BeninDataS$DistRoad,logistW)
+lines(BeninDataS$DistRoad, predict(fit1, type="response"))
+
+# use function predict to calculate response values
+p=predict(fit1, type="response")
+d1=data.frame(BeninDataS$CostDist, p)
+ord=order(d1$p, decreasing = TRUE)
+d1=d1[ord,]
+plot(d1), type="line")
+
+# ---------------------------------------------------------------------   
+#easyest possibility to plot fitted log curve:
+# ---------------------------------------------------------------------
+plot(BeninDataS$CostDist, fit1$fitted)
+
+d1 = BeninDataS$CostDist
+d2 = fit1$fitted
+plot(d2)
+d = data.frame(d1,d2)
+plot(d)
+
+# ---------------------------------------------------------------------
+# test with artificial data
+# ---------------------------------------------------------------------
+fit1 <- glm(lu ~ DistRoad , family=binomial, data=BeninDataS[-1])
+d1 = seq(0, 50000, 50)
+logistW = exp(coef[1:1]+(coef[3:3]*d1))/(1 + exp(coef[1:1]+(coef[3:3]*d1)))
+plot(d1,logistW)
+lines(d1, predict(fit1, data.frame(DistRoad = d1, lc = rep(1, length(d1))), type="response"))
+
+
+#######################################################################
+# caculate some performance measures
+#######################################################################
+
+# ---------------------------------------------------------------------
+# pseudo R² McFadden
+# ---------------------------------------------------------------------
+r = 1-(step$deviance/step$null.deviance)
+
+
+# ---------------------------------------------------------------------
+# calculate ROC curve
+# ---------------------------------------------------------------------
+
+pred = prediction(fitted(fitstep),as.vector(fitstep$data$lu))
+perf <- performance(pred, measure = "tpr", x.measure = "fpr")
+
+# magnify graph
+par.olf <- par(cex=1.5)
+plot(perf, col="red", lwd=3)
+par(par.old)
+
+# ---------------------------------------------------------------------
+# compute AUC
+# ---------------------------------------------------------------------
+
+auc = performance(pred, measure="auc")
+# auc is object of class performance, data stored in slots
+# to access slots (and datas) use @ (in Newsletter 4/1 is said don't use it
+# but I don't know an other way
+aucValue = auc at y.values[[1]]
+print(aucValue)
+write (paste("AUC for",colnames(BeninData[1]), ":", aucValue,sep=" "), outputRegEval)
+
+

Added: trunk/src/de/skrueger/xulu/plugin/gnur/SwingIO.java
===================================================================
--- trunk/src/de/skrueger/xulu/plugin/gnur/SwingIO.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/de/skrueger/xulu/plugin/gnur/SwingIO.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,362 @@
+package de.skrueger.xulu.plugin.gnur;
+/*
+ * Copyright (c) 2003-2004, KNOPFLERFISH project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials
+ *   provided with the distribution.
+ *
+ * - Neither the name of the KNOPFLERFISH project nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.awt.BorderLayout;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Label;
+import java.awt.Panel;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedOutputStream;
+import java.io.PrintStream;
+import java.util.Vector;
+
+import javax.swing.JPanel;
+import javax.swing.JScrollBar;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.SwingUtilities;
+
+
+public class SwingIO extends JPanel {
+
+  JTextArea  text;
+  JTextField tfCmd;
+
+  int p0 = -1;
+  int p1 = 0;
+
+  String last = "";
+
+  InputStream origIn;
+  PrintStream origOut;
+  PrintStream origErr;
+
+  PipedOutputStream textSource;
+
+  TextReader       in;
+  PrintStream      out;
+
+  JPanel panel;
+  JScrollPane scroll;
+  Label  cmdLabel;
+
+  Vector history    = new Vector();
+  int    historyPos = 0;
+
+  StringBuffer lineBuff = new StringBuffer();
+
+  boolean bGrabbed = false;
+
+  int maxLines = new Integer(System.getProperty("org.knopflerfish.desktop.console.maxlines", "5000")).intValue();
+
+  void setSystemIO() {
+
+    boolean bDebugClass = "true".equals(System.getProperty("org.knopflerfish.framework.debug.classloader", "false"));
+
+    if(!bDebugClass) {
+      if(!bGrabbed) {
+        try {
+
+          origIn  = System.in;
+          origOut = System.out;
+          origErr = System.err;
+
+          //    System.setIn(in);
+          System.setOut(new PrintStream(out));
+          System.setErr(new PrintStream(out));
+
+          bGrabbed = true;
+
+        } catch (Exception e) {
+          bGrabbed = false;
+        }
+      }
+    }
+  }
+
+  void restoreSystemIO() {
+
+    //    synchronized(grabLock)
+      {
+      if(bGrabbed) {
+        try {
+          if(origIn != null) {
+            System.setIn(origIn);
+          }
+          if(origOut != null) {
+            System.setOut(origOut);
+          }
+          if(origIn != null) {
+            System.setErr(origErr);
+          }
+//          ConsoleSwing.log(LogService.LOG_DEBUG, "...restored system I/O");
+          bGrabbed = false;
+        } catch (Exception e) {
+  //        ConsoleSwing.log(LogService.LOG_ERROR, "Failed to restore IO", e);
+        }
+      }
+
+    }
+
+  }
+
+
+  public SwingIO() {
+    super(new BorderLayout());
+
+    panel = this;
+
+    try {
+      text = new JTextArea("", 8, 80);
+      text.setEditable(false);
+      String bootText =
+        "Knopflerfish OSGi console. Copyright (c) 2004 Knopflerfish.";
+
+      // See if we're using the knopflerfish framework. If so, grab
+      // the boot string from the startup class
+      try {
+        Class mainClazz = Class.forName("org.knopflerfish.framework.Main");
+        bootText        = (String)mainClazz.getField("bootText").get(null);
+      } catch (Throwable e) {
+        bootText        = "";
+        //  e.printStackTrace();
+        // anything else defaults to the std boot text above
+      }
+      text.setText(bootText +
+       "\n\n" +
+       "Type 'help' for help or 'alias' for a list of common commands\n\n");
+      scroll = new JScrollPane(text,
+                               JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+                               JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+
+      tfCmd = new JTextField();
+
+      final KeyListener keyL = new KeyAdapter() {
+          public void keyPressed(KeyEvent ev) {
+            if(ev.getKeyCode() == KeyEvent.VK_UP) {
+              if(historyPos > 0) {
+                String line = (String)history.elementAt(historyPos-1);
+                historyPos--;
+                tfCmd.setText(line);
+              }
+            } else if(ev.getKeyCode() == KeyEvent.VK_DOWN) {
+              if(historyPos < history.size()-1) {
+                String line = (String)history.elementAt(historyPos+1);
+                historyPos++;
+                tfCmd.setText(line);
+              }
+            } else if(ev.getKeyCode() == KeyEvent.VK_ENTER) {
+              String line = tfCmd.getText();
+              if(!("".equals(line) ||
+                   "\n".equals(line) ||
+                   "\n\r".equals(line) ||
+                   "\r\n".equals(line))) {
+                history.addElement(line);
+                historyPos = history.size();
+              }
+              if("clear".equals(line)) {
+                clear();
+              } else if("quit".equals(line)) {
+//                org.knopflerfish.bundle.desktop.swing
+//                  .Activator.desktop.stopFramework();
+              } else {
+                // Try simple command expansion first
+                if(line.startsWith("!") && line.length() > 1) {
+                  String s2 = line.substring(1);
+                  String bestStr = "";
+                  for(int i = 0; i < history.size(); i++) {
+                    String s = (String)history.elementAt(i);
+                    if(s.startsWith(s2) || s.length() >= bestStr.length()) {
+                      bestStr = s;
+                    }
+                  }
+                  if(!"".equals(bestStr)) {
+                    line = bestStr;
+                  }
+                }
+
+                // ..and send to console via inputstream
+                String s = line + "\r\n";
+                text.append(s);
+                showLastLine();
+                if(in != null) {
+                  in.print(s);
+                  in.flush();
+                }
+              }
+              tfCmd.setText("");
+            }
+          }
+        };
+
+      tfCmd.addKeyListener(keyL);
+
+      // move focus away from text output to text input
+      // in key press
+      text.addKeyListener(new  KeyAdapter() {
+          public void keyPressed(KeyEvent ev) {
+            int modifiers = ev.getModifiers();
+
+            // Don't steal special key events like CTRL-C
+            if(modifiers == 0) {
+              tfCmd.requestFocus();
+            }
+          }
+
+        });
+
+      out = new PrintStream(new TextAreaOutputStream(this, text));
+
+      GridBagLayout gridbag = new GridBagLayout();
+      GridBagConstraints c = new GridBagConstraints();
+
+      panel.add(scroll,         BorderLayout.CENTER);
+
+      Panel cmdPanel = new Panel(new BorderLayout());
+
+      cmdLabel = new Label("> ");
+      cmdPanel.add(cmdLabel,        BorderLayout.WEST);
+      cmdPanel.add(tfCmd,           BorderLayout.CENTER);
+
+      panel.add(cmdPanel,        BorderLayout.SOUTH);
+
+
+      reinit();
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+
+
+  void clear() {
+    text.setText("");
+  }
+
+  void showLastLine() {
+    SwingUtilities.invokeLater(new Runnable() {
+      public void run() {
+        if (maxLines > 0) {
+          int linesToRemove = text.getLineCount() - maxLines;
+          int index = 0;
+          if (linesToRemove > 0) {
+            for (int i=0; i<linesToRemove; i++) {
+              index = text.getText().indexOf('\n', index) + 1;
+            }
+            text.setText(text.getText().substring(index));
+          }
+        }
+
+        JScrollBar bar = scroll.getVerticalScrollBar();
+        if(bar != null) {
+          int v = bar.getMaximum();
+          bar.setValue(v*2);
+        }
+      }
+    });
+  }
+
+  Font font;
+
+  synchronized void reinit() {
+    font = new Font("Areal", Font.PLAIN, 20);
+
+//    text.setBackground(Config.parseColor(1));
+//    text.setForeground(Config.parseColor(2));
+    text.setFont(font);
+
+    tfCmd.setBackground(text.getBackground());
+    tfCmd.setForeground(text.getForeground());
+    tfCmd.setFont(text.getFont());
+
+    cmdLabel.setBackground(text.getBackground());
+    cmdLabel.setForeground(text.getForeground());
+    cmdLabel.setFont(text.getFont());
+  }
+
+  void start() {
+    stop();
+    in         = new TextReader();
+    setVisible(true);
+      setSystemIO();
+  }
+
+  void stop() {
+    restoreSystemIO();
+    setVisible(false);
+    if(in != null) {
+      in.close();
+      in = null;
+    }
+  }
+
+
+  public class TextAreaOutputStream extends OutputStream {
+
+  	  JTextArea     text;
+  	  SwingIO        swingIO;
+  	  StringBuffer buff = new StringBuffer();
+
+  	  TextAreaOutputStream(SwingIO swingIO, JTextArea text) {
+  	    this.swingIO = swingIO;
+  	    this.text  = text;
+  	  }
+
+  	  public void flush() {
+  	    text.append(buff.toString());
+  	    buff.setLength(0);
+  	  }
+
+  	  public void write(int b) {
+  	    char c = (char)b;
+  	    if(c == '\r') {
+  	    } else if(c == '\n') {
+  	      text.append(buff.toString() + "\n");
+  	      buff.setLength(0);
+  	      swingIO.showLastLine();
+  	    } else {
+  	      buff.append(c);
+  	    }
+  	  }
+  	}
+}
+
+

Added: trunk/src/de/skrueger/xulu/plugin/gnur/TextReader.java
===================================================================
--- trunk/src/de/skrueger/xulu/plugin/gnur/TextReader.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/de/skrueger/xulu/plugin/gnur/TextReader.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,138 @@
+package de.skrueger.xulu.plugin.gnur;
+/*
+ * Copyright (c) 2003-2004, KNOPFLERFISH project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials
+ *   provided with the distribution.
+ *
+ * - Neither the name of the KNOPFLERFISH project nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.io.IOException;
+import java.io.Reader;
+
+
+
+public class TextReader extends Reader {
+
+  StringBuffer sb = new StringBuffer();
+
+  Object  lock     = new Object();
+  Object  waitLock = new Object();
+
+  public TextReader() {
+  }
+
+  public int available() {
+    if(sb == null) {
+      throw new RuntimeException("Stream closed");
+    }
+    System.out.println("read available=" + sb.length());
+    return sb.length();
+  }
+
+  public void close() {
+    flush();
+    sb = null;
+  }
+  
+  public void mark(int readlimit) {
+  }
+
+  
+  public boolean markSupported() {
+    return false;
+  }
+
+  public void reset() {
+  }
+
+  public long skip(long n) {
+    if(sb == null) {
+      throw new RuntimeException("Stream closed");
+    }
+    sb.delete(0, (int)Math.max(n, sb.length()));
+    return sb.length();
+  }
+ 
+  public void print(String s) {
+    if(sb == null) {
+      throw new RuntimeException("Stream closed");
+    }
+    sb.append(s);
+    if(s.length() > 0) {
+      flush();
+    }
+  }
+
+  void flush() {
+    synchronized(waitLock) {
+      waitLock.notifyAll();
+    }
+  }
+
+  char[] buf = new char[1];
+
+  public int read() throws IOException {
+    if(-1 != read(buf, 0, 1)) {
+      return buf[0];
+    }
+    
+    return -1;
+  }
+
+  public int read(char[] b) throws IOException {
+    return read(b, 0, b.length);
+  }
+
+  public int read(char[] cbuf, int off, int len) throws IOException {
+    synchronized(waitLock) {
+      if(sb == null) {
+	throw new RuntimeException("Stream closed");
+      }
+      if(len == 0) {
+	return 0;
+      }
+      try {
+	while(sb == null || len > sb.length()) {
+	  waitLock.wait();
+	}
+      } catch(InterruptedException e) {
+	throw new IOException(e.getMessage());
+      }
+      
+      int i   = 0;
+      while(i < len) {
+	cbuf[off + i] = sb.charAt(i);
+	i++;
+      }
+      sb.delete(0, i);
+      return len;
+    }
+  }
+}
\ No newline at end of file

Added: trunk/src/de/skrueger/xulu/plugin/gnur/testsomethong.java
===================================================================
--- trunk/src/de/skrueger/xulu/plugin/gnur/testsomethong.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/de/skrueger/xulu/plugin/gnur/testsomethong.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,22 @@
+package de.skrueger.xulu.plugin.gnur;
+
+import java.io.File;
+
+import javax.swing.JFrame;
+
+public class testsomethong {
+
+	/**
+	 * @param args
+	 */
+	public static void main(String[] args) {
+		JFrame frame = new JFrame();
+		
+		frame.getContentPane().add( new JRTextArea());
+		frame.pack();
+		frame.setVisible(true);
+		
+
+	}
+
+}

Added: trunk/src/edu/bonn/xulu/XuluModellingPlatform.java
===================================================================
--- trunk/src/edu/bonn/xulu/XuluModellingPlatform.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/XuluModellingPlatform.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,697 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu;
+
+import javax.swing.UIManager;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Vector;
+import java.util.TreeSet;
+import java.util.SortedSet;
+import java.util.Locale;
+import java.io.FileInputStream;
+import java.io.File;
+import java.io.PrintStream;
+
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+import schmitzm.lang.SortableVector;
+import schmitzm.swing.SwingUtil;
+import schmitzm.swing.SwingWorker;
+import schmitzm.swing.ExceptionDialog;
+import schmitzm.geotools.GTUtil;
+import schmitzm.lang.ResourceProvider;
+import schmitzm.lang.DefaultComparator;
+import schmitzm.geotools.io.GeoImportUtil;
+
+import edu.bonn.xulu.gui.XuluMainFrame;
+import edu.bonn.xulu.gui.XuluStartingFrame;
+import edu.bonn.xulu.appl.XuluComponent;
+import edu.bonn.xulu.appl.XuluComponentUtil;
+import edu.bonn.xulu.appl.DataPool;
+import edu.bonn.xulu.appl.XuluRegistry;
+import edu.bonn.xulu.appl.XuluRegistryReader;
+import edu.bonn.xulu.appl.VisualisationManager;
+import edu.bonn.xulu.appl.ModelControlManager;
+import edu.bonn.xulu.appl.EventManager;
+import edu.bonn.xulu.appl.XuluPlugin;
+import edu.bonn.xulu.appl.XuluConstants;
+import edu.bonn.xulu.plugin.appl.DataScriptInterpreter_Basic;
+import edu.bonn.xulu.plugin.appl.XuluRegistryReader_BasicAscii;
+
+import appl.ext.XuluConfig;
+
+/**
+ * Diese Klasse implementiert das Hauptprogramm der Xulu-Modeling-Platform.
+ * Beim Starten koennen folgende Kommandozeilenparameter angegeben werden:
+ * <ul>
+ * <li><code>? | /? | -? | -h | h | --help</code><br>
+ *     Zeigt eine Hilfe zu den Kommandozeilenparametern an.</li>
+ * <li><code>-kso</code><br>
+ *     Haelt den Start-Dialog offen, bis "OK" gedrueckt wird.</li>
+ * <li><code>-nogui</code><br>
+ *     Xulu-GUI wird <b>nicht</b> gestartet! Dies macht nur Sinn, wenn autom.
+ *     ein Skript gestartet wird oder die Xulu-Applikation per Konstruktor
+ *     aus einer anderen Applikation instanziiert wird.</li>
+ * <li><code>-noplugin</code><br>
+ *     Ignoriert die in der Xulu-Registry angegebene Autostart-Funktion fuer
+ *     Plugins.</li>
+ * <li><code>-r <i>path</i></code><br>
+ *     Setzt das Start-Verzeichnis (Root) fuer die Instanz, in dem die Registry- und
+ *     XuluProperties-Dateien zu finden sind (Standard: Start-Verzeichnis).</li>
+ * <li><code>-w <i>path</i></code><br>
+ *     Setzt das Arbeitsverzeichnis fuer die Instanz.</li>
+ * <li><code>-l <i>language</i></code><br>
+ *     Setzt die Sprache fuer die GUI. Muss ein ISO-639 Code sein.</li>
+ * <li><code>-rf <i>filepath</i></code><br>
+ *     Setzt die zu Beginn einzulesende Registry-Datei (Default: <code>registry.xif</code>)</li>
+ * <li><code>-rr <i>package.class</i></code><br>
+ *     Setzt den RegistryReader, der zum Einlesen der Registry verwendet wird.
+ *     Muss eine ueber einen Standard-Konstruktor instanziierbare Subklasse
+ *     von {@link XuluRegistryReader} sein (Default: {@link XuluRegistryReader_BasicAscii}.</li>
+ * <li><code>-d <i>path</i></code><br>
+ *     Setzt den Suchpfad (Classpath) fuer die dynamisch zu aktualisierenden Klassen
+ *     (zur Zeit nur Modell-Klassen, also das Paket <code>edu.bonn.xulu.plugin.model</code>).
+ *     Standardmaessig wird das Verzeichnis <code>classes_dyn</code>
+ *     unterhalb des Xulu-Programmverzeichnisses verwendet.<br>
+ *     <b>Bemerke:</b><br>
+ *     Dieses Verzeichnis darf <b>kein</b> Bestandteil des CLASSPATH der JVM
+ *     sein, in der Xulu gestartet wird, da ansonsten das dynamische
+ *     Aktualisieren veraenderter Klassen nicht funktioniert!</li>
+ * <li><code>-s <i>filepath</i></code><br>
+ *     Fuehrt nach dem Initialisieren automatisch die durch ';' getrennten Skripte aus</li>
+ * </ul>
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class XuluModellingPlatform implements XuluComponent {
+
+  /** Liste aller in Xulu verwendeten {@link ResourceProvider} */
+  public static final SortableVector<ResourceProvider> RESOURCE_BUNDLES = new SortableVector<ResourceProvider>();
+  static {
+    // Resource Bundles aus Standard-Paketen umlenken
+    schmitzm.swing.SwingUtil.RESOURCE.resetResourceBundle(XuluConstants.EXTENTION_BUNDLE,"schmitzm.swing");
+    schmitzm.geotools.gui.GeotoolsGUIUtil.RESOURCE.resetResourceBundle(XuluConstants.EXTENTION_BUNDLE,"schmitzm.gt");
+    schmitzm.jfree.JFreeChartUtil.RESOURCE.resetResourceBundle(XuluConstants.EXTENTION_BUNDLE,"schmitzm.jfree");
+    schmitzm.data.DataUtil.RESOURCE.resetResourceBundle(XuluConstants.EXTENTION_BUNDLE,"schmitzm.data");
+    // Resource Bundles in Liste sammeln
+    registerResourceProvider(schmitzm.swing.SwingUtil.RESOURCE);
+    registerResourceProvider(schmitzm.geotools.gui.GeotoolsGUIUtil.RESOURCE);
+    registerResourceProvider(schmitzm.jfree.JFreeChartUtil.RESOURCE);
+    registerResourceProvider(schmitzm.data.DataUtil.RESOURCE);
+  }
+
+  private static boolean keepStartFrameOpen = false;
+  private        boolean startGUI = true;
+  private        boolean autostartPlugins = true;
+
+  private boolean packFrame = false;
+
+  // Art und Weise die Registry einzulesen
+  // ACHTUNG: NACH AENDERUG AUCH DIE JAVADOC OBEN ANPASSEN
+  private File               registryFile   = new File("registry.xif");
+  private XuluRegistryReader registryReader = new XuluRegistryReader_BasicAscii();
+
+  // Xulu-Komponenten
+  private DataPool             dataPool       = null;
+  private XuluRegistry         registry       = null;
+  private VisualisationManager visManager     = null;
+  private ModelControlManager  modelManager   = null;
+  private EventManager         eventManager   = null;
+  // Haupt-GUI
+  private XuluMainFrame        mainFrame      = null;
+
+  // Programm-Parameter
+  private File                 startDir    = new File(".");
+  private File                 pluginDir    = new File("plugin");
+  private File                 workDir     = new File(".");
+  private File                 dynClassDir = null;
+  private File                 startupScriptFiles[] = null;
+
+  /**
+   * Erzeugt eine neue Instanz der Xulu-Modelling-Platform.
+   */
+  public XuluModellingPlatform() {
+    this( new String[0] );
+  }
+
+  /**
+   * Erzeugt eine neue Instanz der Xulu-Modelling-Platform.
+   * @param args Kommandozeilenparameter
+   */
+  public XuluModellingPlatform(String[] args) {
+    this(args,null);
+  }
+
+  private void giveStatus(String text, PrintStream stream) {
+    if (stream == null)
+      return;
+    stream.print(text);
+  }
+
+  /**
+   * Erzeugt eine neue Instanz der Xulu-Modelling-Platform.
+   * @param args       Kommandozeilenparameter
+   * @param infoStream Stream in den Status-Meldungen geschrieben werden, die
+   *                   ueber den Fortschritt der Initialisierung Auskunft geben
+   */
+  public XuluModellingPlatform(String[] args, PrintStream infoStream) {
+    //this.dynClassDir = new File("classes_dyn");
+    try {
+      this.dynClassDir = new File(ClassLoader.getSystemResource("").toURI());
+    } catch(Exception err) {
+      throw new RuntimeException(err);
+    }
+    
+    giveStatus("Reading command line parameters...",infoStream);
+    interpreteCommandLineParameters(args);
+    giveStatus(" done.\n",infoStream);
+
+    //Reading config file (automaticly loaded from File 'XuluProperties'
+    appl.ext.XuluConfig.getXuluConfig( startDir );
+
+    // Datenpool erzeugen und initialisieren
+    giveStatus("Creating xulu data pool...",infoStream);
+    this.dataPool = new DataPool();
+    giveStatus(" done.\n",infoStream);
+
+    // Registry erzeugen
+    giveStatus("Creating xulu registry...",infoStream);
+    this.registry = new XuluRegistry();
+    giveStatus(" done.\n",infoStream);
+
+    // Visualisierungsmanager erzeugen und initialisieren
+    giveStatus("Creating xulu visualisation manager...",infoStream);
+    this.visManager = new VisualisationManager();
+    giveStatus(" done.\n",infoStream);
+
+    // Manager fuer Modell-Kontrollkomponenten erzeugen und initialisieren
+    giveStatus("Creating xulu model manager...",infoStream);
+    this.modelManager = new ModelControlManager();
+    giveStatus(" done.\n",infoStream);
+
+    // Manager fuer Ereignisse erzeugen und initialisieren
+    giveStatus("Creating xulu event manager...",infoStream);
+    this.eventManager = new EventManager(this);
+    giveStatus(" done.\n",infoStream);
+
+    // MainFrame erzeugen und initialisieren
+    if ( startGUI ) {
+      giveStatus("Creating xulu main window...",infoStream);
+      this.mainFrame = new XuluMainFrame(this);
+      //Frames Ueberpruefen, die voreingestellte Groesse haben
+      //Frames packen, die nutzbare bevorzugte Groesseninformationen enthalten, z.B. aus ihrem Layout
+      if (packFrame)
+        mainFrame.pack();
+      else
+        mainFrame.validate();
+      SwingUtil.centerFrameOnScreen(mainFrame);
+      mainFrame.setVisible(true);
+      mainFrame.arrangeInnerFrames();
+      giveStatus(" done.\n",infoStream);
+    }
+
+    // Registry einlesen
+    giveStatus("Reading xulu registry file...",infoStream);
+    try {
+      FileInputStream fileIn = new FileInputStream(registryFile);
+      registryReader.readRegistry(this,fileIn,registry);
+      fileIn.close();
+    } catch (Exception err) {
+      System.err.println("Fehler beim Initialisieren der XuluRegistry: "+err);
+    }
+    giveStatus(" done.\n",infoStream);
+
+    // RecentImports und RecentScripts aus Properties lesen
+    registry.getRecentImports().loadFromXuluProperties(this);
+    registry.getRecentScripts().loadFromXuluProperties(this);
+    // Standard-CRS aus Properties lesen
+    giveStatus("Read default CRS from XULU properties...",infoStream);
+    String defaultCRS = XuluConfig.getXuluConfig().getProperty("General.DefaultCRS");
+    CoordinateReferenceSystem crs = defaultCRS != null ? GTUtil.createCRS(defaultCRS) : null;
+    if ( crs != null )  {
+      GeoImportUtil.DEFAULT_CRS = crs;
+      giveStatus(" done.\n",infoStream);
+    } else {
+      giveStatus(" failt!\n",infoStream);
+    }
+
+
+    // Autostart-Plugins starten
+    // --> WICHTIG: sollte VOR dem Ausfuehren der Start-Skripte stattfinden,
+    //              damit das LoggerPlugin bereits gestartet ist (fuer
+    //              Meldungen waehrend der Start-Skripte!)
+    if ( this.autostartPlugins ) {
+      XuluPlugin[] autostartPlugin = registry.getAutostartPlugins();
+      giveStatus("Executing Autostart-Plugins...",infoStream);
+      for (int i=0; autostartPlugin != null && i<autostartPlugin.length; i++ )
+        autostartPlugin[i].execute(this);
+      giveStatus(" done.\n",infoStream);
+    }
+
+    // Start the scripts
+    if (startupScriptFiles != null)
+      for (File file : startupScriptFiles) {
+        if (file != null) {
+          giveStatus("Executing script " + file.getName() + "...", infoStream);
+          try {
+            FileInputStream fileIn = new FileInputStream(file);
+            new DataScriptInterpreter_Basic().execute(fileIn, this);
+            fileIn.close();
+          }
+          catch (Exception err) {
+            System.err.println("Error while executing startup script: " + err);
+          }
+          giveStatus(" done.\n", infoStream);
+        }
+      }
+
+  }
+
+  /**
+   * Zerstoert die Instanz der Xulu-Anwendung in dem ein
+   * {@link System#exit(int) System.exit(0)} ausgefuehrt wird. Zuvor werden
+   * folgende Komponenten zerstoert:
+   * <ul>
+   * <li>{@linkplain DataPool#dispose() Daten-Pool}</li>
+   * <li>{@linkplain ModelControlManager#dispose() Model-Control-Manager}</li>
+   * <li>{@linkplain VisualisationManager#dispose() Visualisation-Manager}</li>
+   * <li>{@linkplain XuluMainFrame#dispose() GUI-Hauptfenster}</li>
+   * </ul>
+   */
+  public void dispose() {
+    XuluComponentUtil.checkDisposed(this);
+    registry.getRecentImports().storeToXuluProperties(this);
+    registry.getRecentScripts().storeToXuluProperties(this);
+    XuluConfig.getXuluConfig().store();
+    if ( modelManager != null )
+      modelManager.removeAll();
+    modelManager = null;
+    if ( visManager != null )
+      visManager.removeAll();
+    visManager = null;
+    if ( dataPool != null )
+      dataPool.dispose();
+    dataPool = null;
+    if ( mainFrame != null )
+      mainFrame.dispose();
+    mainFrame = null;
+    if ( startGUI )
+      System.exit(0);
+  }
+
+  /**
+   * Prueft, ob die Xulu-Anwendung zerstoert ist.
+   * @see #dispose()
+   */
+  public boolean isDisposed() {
+    return getRegistry() == null;
+  }
+
+  /**
+   * Liefert das Startverzeichnis der Xulu-Applikation.
+   */
+  public File getStartingDirectory() {
+    return startDir;
+  }
+
+  /**
+   * Liefert das CLASSPATH-Verzeichnis unterhalb dessen die Klassen zu finden
+   * sind, die dynamisch in Xulu geladen werden koennen.<br>
+   * <b>Bemerkung:</b><br>
+   * Dieses Verzeichnis darf <b>nicht</b> im CLASSPATH der JVM enthalten sein,
+   * in der Xulu ausgefuehrt wird!!
+   */
+  public File getDynamicClassRootDirectory() {
+    return dynClassDir;
+  }
+
+  /**
+   * Setzt das CLASSPATH-Verzeichnis unterhalb dessen die Klassen zu finden
+   * sind, die dynamisch in Xulu geladen werden koennen.<br>
+   * <b>Bemerkung:</b><br>
+   * Dieses Verzeichnis darf <b>nicht</b> im CLASSPATH der JVM enthalten sein,
+   * in der Xulu ausgefuehrt wird!!
+   */
+  public void setDynamicClassRootDirectory(File searchPath) {
+    dynClassDir = searchPath;
+  }
+
+  /**
+   * Liefert das Verzeichnis ('{@code plugin}' unterhalb des Start-Verzeichnisses)
+   * in dem von Plugins benoetigte Dateien abgelegt werden.
+   */
+  public File getPluginDirectory() {
+    return pluginDir;
+  }
+
+  /**
+   * Liefert das Arbeitsverzeichnis der Xulu-Applikation.
+   */
+  public File getWorkingDirectory() {
+    return workDir;
+  }
+
+  /**
+   * Setzt das Arbeitsverzeichnis der Xulu-Applikation.
+   */
+  public void setWorkingDirectory(File workDir) {
+    if ( !workDir.isDirectory() || !workDir.exists() )
+      throw new RuntimeException("Working directory must be a directory and must exist!");
+    this.workDir = workDir;
+  }
+
+  /**
+   * Liefert den Datenpool der Xulu-Instanz.
+   */
+  public DataPool getDataPool() {
+    return dataPool;
+  }
+
+  /**
+   * Liefert die Registry der Xulu-Instanz.
+   */
+  public XuluRegistry getRegistry() {
+      return registry;
+  }
+
+  /**
+   * Liefert den Verwaltungsmanager fuer die Visualisierungstool-Instanzen.
+   */
+  public VisualisationManager getVisualisationManager() {
+      return visManager;
+  }
+
+  /**
+   * Liefert den Verwaltungsmanager fuer die Modell-Kontroll-Komponenten.
+   */
+  public ModelControlManager getModelControlManager() {
+      return modelManager;
+  }
+
+  /**
+   * Liefert den Verwaltungsmanager fuer die Modell-Kontroll-Komponenten.
+   */
+  public EventManager getEventManager() {
+      return eventManager;
+  }
+
+  /**
+   * Liefert das Hauptfenster der Xulu-Instanz.
+   */
+  public XuluMainFrame getMainFrame() {
+      return mainFrame;
+  }
+
+  /**
+   * Interpretiert die Kommandozeilen-Parameter, die fuer die Xulu-Instanz
+   * relevant sind.
+   * Dies sind:
+   * <ul>
+   * <li><code>-r <i>path</i></code><br>
+   *     Setzt das Start-Verzeichnis (Root) fuer die Instanz, in dem die Registry- und
+   *     XuluProperties-Dateien zu finden sind.</li>
+   * <li><code>-w <i>path</i></code><br>
+   *     Setzt das Arbeitsverzeichnis fuer die Instanz.</li>
+   * <li><code>-rf <i>path</i></code><br>
+   *     Bestimmt die einzulesende Registry-Datei.</li>
+   * <li><code>-rr <i>package.class</i></code><br>
+   *     Bestimmt die Art, die Registry-Datei einzulesen. <i>package.class</i> muss eine
+   *     Unterklasse von {@link XuluRegistryReader} sein und einen Standard-Konstruktor
+   *     besitzen.</li>
+   * <li><code>-d <i>path</i></code><br>
+   *     Setzt den Suchpfad (Classpath) fuer die dynamisch zu ladenen Klassen (zur Zeit
+   *     nur Modell-Klassen). Standardmaessig wird das Verzeichnis <code>classes_dyn</code>
+   *     unterhalb des Xulu-Programmverzeichnisses verwendet.<br>
+   *     <b>Bemerke:</b><br>
+   *     Dieses Verzeichnis darf <b>kein</b> Bestandteil des CLASSPATH der JVM
+   *     sein, in der Xulu gestartet wird, da ansonsten das dynamische
+   *     Aktualisieren veraenderter Klassen nicht funktioniert!</li>
+   * <li><code>-s <i>path<i></code><br>
+   *     Fuehrt die angegebenen durch ';' getrennten Scripte beim Starten aus. </li>
+   * <li><code>-nogui</code><br>
+   *     Verhindert, dass die Xulu-GUI gestartet wird. Dies macht nur Sinn, wenn autom.
+   *     ein Skript gestartet wird oder die Xulu-Applikation per Konstruktor
+   *     aus einer anderen Applikation instanziiert wird.</li>
+   * <li><code>-noplugin</code><br>
+   *     Ignoriert die in der Xulu-Registry angegebene Autostart-Funktion fuer
+   *     Plugins.</li>
+   * </ul>
+   */
+  private void interpreteCommandLineParameters(String[] args) {
+    for (int i=0; args!=null && i<args.length; i++) {
+      // bereits verarbeitete Argumente ignorieren
+      if ( args[i] == null )
+        continue;
+
+       // Angabe des Root-Verzeichnisses
+       // -r <path>
+       if ( args[i].equalsIgnoreCase("-r") )
+         try {
+           startDir = new File(args[i+1]);
+           i++;
+           continue;
+         } catch (Exception err) {
+           System.err.println("Invalid Argument: After -w a valid path is expected");
+           continue;
+         }
+        // Angabe des Arbeitsverzeichnisses
+        // -w <path>
+        if ( args[i].equalsIgnoreCase("-w") )
+          try {
+            setWorkingDirectory( new File(args[i+1]) );
+            i++;
+            continue;
+          } catch (Exception err) {
+            System.err.println("Invalid Argument: After -w a valid path is expected");
+            continue;
+          }
+       //Angabe von Startup-Skripten
+       // -s <file>
+       if ( args[i].equalsIgnoreCase("-s") )
+         try {
+             //splitte nach den einzelnen files
+        	 String[] fileNames = args[i+1].split(";");
+        	 startupScriptFiles = new File[fileNames.length];
+        	 for (int j = 0; j < fileNames.length; j++) {
+				startupScriptFiles [j] = new File(fileNames[j]);
+			}
+           i++;
+           continue;
+         } catch (Exception err) {
+           System.err.println("Invalid Argument: After -s a valid paths sperated by ';' are expected");
+           continue;
+         }
+        // Angabe der Registry-Datei
+        // -rf <file>
+        if ( args[i].equalsIgnoreCase("-rf") )
+         try {
+           registryFile = new File( args[i+1] );
+           i++;
+           continue;
+         } catch (Exception err) {
+           System.err.println("Invalid Argument: After -rf a valid path is expected");
+           continue;
+         }
+         // Angabe des Registry-Readers
+         // -r <package.class>
+         if ( args[i].equalsIgnoreCase("-rr") )
+          try {
+            registryReader = (XuluRegistryReader)Class.forName(args[i+1]).newInstance();
+            i++;
+            continue;
+          } catch (InstantiationException err) {
+            System.err.println("Invalid Argument: Subclass of XuluRegistryReader needs a default constructor");
+            continue;
+          } catch (Exception err) {
+            System.err.println("Invalid Argument: After -rr a subclass of XuluRegistryReader is expected");
+            continue;
+          }
+          // Angabe des Such-Pfades fuer dynamische Klassen
+          // -d <path>
+          if ( args[i].equalsIgnoreCase("-d") )
+           try {
+             setDynamicClassRootDirectory( new File(args[i+1]) );
+             i++;
+             continue;
+           } catch (Exception err) {
+             System.err.println("Invalid Argument: After -d a valid path is expected");
+             continue;
+           }
+         // Flag, dass keine GUI gestartet wird
+         if ( args[i].equalsIgnoreCase("-nogui") ) {
+           this.startGUI = false;
+           continue;
+         }
+         // Flag, dass keine Plugins gestartet werden
+         if ( args[i].equalsIgnoreCase("-noplugin") ) {
+           this.autostartPlugins = false;
+           continue;
+         }
+     System.err.println("Unknown Argument: "+args[i]);
+   }
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Starter-Methoden
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Interpretiert die Kommandozeilen-Parameter, die statisch relevant sind.
+   * Dies sind:
+   * <ul>
+   * <li><code>? | /? | -? | -h | h | --help</code><br>
+   *     Zeigt eine Hilfe zu den Kommandozeilenparametern an.</li>
+   * <li><code>-kso</code><br>
+   *     Haelt das Startup-Fenster nach dem Xulu-Start offen.</li>
+   * <li><code>-l <i>language</i></code><br>
+   *     Setzt die Sprache der GUI. <i>language</i> muss ein ISO-639 Code sein.</li>
+   * </ul>
+   */
+  private static void interpreteStaticCommandLineParameters(String[] args) {
+    for (int i=0; args!=null && i<args.length; i++) {
+        // Parameter-Hilfe
+        // ? -? /? h -h --help
+        if ( args[i].startsWith("?")  || args[i].startsWith("-?") ||
+             args[i].startsWith("/?") ||
+             args[i].equalsIgnoreCase("h") || args[i].equalsIgnoreCase("-h") ||
+             args[i].equalsIgnoreCase("--help") ) {
+          showParameterHelp();
+          args[i] = null; // Argument als verarbeitet kennzeichnen
+          System.exit(0);
+        }
+        // Angabe der Sprache
+        // -l <language>
+        if ( args[i].equalsIgnoreCase("-l") )
+          try {
+            Locale.setDefault( new Locale(args[i+1]) );
+            i++;
+            // Argumente als verarbeitet kennzeichnen
+            args[i-1] = null;
+            args[i] = null;
+            continue;
+          } catch (Exception err) {
+            System.err.println("Invalid Argument: After -l a valid ISO-639 code is expected");
+            continue;
+          }
+        // Start-Up-Fenster offen halten
+        if ( args[i].equalsIgnoreCase("-kso") ) {
+          keepStartFrameOpen = true;
+          args[i] = null; // Argument als verarbeitet kennzeichnen
+        }
+    }
+  }
+
+  private static void showParameterHelp() {
+    System.out.println("\nUsage: java [jre commands] edu.bonn.xulu.XuluModellingPlatform [Xulu commands]");
+    System.out.println("Xulu commands:  ? | /? | -?       Shows this help message");
+    System.out.println("               -h |  h | --help   Shows this help message");
+    System.out.println("               -kso       gs        Keeps the starting frame open.");
+    System.out.println("               -r <path>          Sets the starting (root) directory to <path>");
+    System.out.println("               -w <path>          Sets the working directory to <path>");
+    System.out.println("               -l <language>      Sets the language for the application");
+    System.out.println("                                  Note:");
+    System.out.println("                                  <language> must be a lowercase two-letter");
+    System.out.println("                                  ISO-639 code and the corresponding");
+    System.out.println("                                  ResourceBundle classes must be implemented.");
+    System.out.println("                                  Currently 'de' and 'en' are supported.");
+    System.out.println("               -rf <filepath>     Sets the path to xulu registry file.");
+    System.out.println("               -rr <class>        Sets the class to read the xulu registry");
+    System.out.println("                                  Note:");
+    System.out.println("                                  <class> must be a subclass of XuluRegistryReader");
+    System.out.println("                                  and have a default constructor.");
+    System.out.println("                                  A full class name (package.class) must be specified.");
+    System.out.println("               -d <path>          Sets the directory where the dynamic (reloadable)");
+    System.out.println("                                  classes are located.");
+    System.out.println("                                  Note:");
+    System.out.println("                                  <path> is not allowed to be a part of the CLASSPATH!");
+    System.out.println("               -s <path>          Executes the given datapool scipt after xulu start.");
+    System.out.println("               -nogui             Avoids starting the Xulu GUI. This makes only sence,");
+    System.out.println("                                  if a script is executed automatically or the");
+    System.out.println("                                  XuluModellingPlatform class is instanciated manually");
+    System.out.println("                                  by another application.");
+    System.out.println("               -noplugin          Ignores the autostart functionality specified for");
+    System.out.println("                                  plugins in the Xulu registry.");
+    System.out.println();
+  }
+
+  /**
+   * Startet die Xulu-Anwendungung.
+   * @param args Kommandozeilenparameter
+   */
+  public static void main(final String[] args) {
+    try {
+      if( XuluConfig.getXuluConfig().getBooleanProperty("General.useSystemLookAndFeel") )
+        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+
+      interpreteStaticCommandLineParameters(args);
+
+      // Waehrend die Xulu-Applikation (im Hintergrund) gestartet wird, wird
+      // ein Fenster angezeigt, in dem die Initialisierungsphasen angezeigt
+      // werden
+      SwingWorker.Work initWork = new SwingWorker.Work() {
+        public Object execute() {
+          new XuluModellingPlatform(args,((XuluStartingFrame)getSwingWorker().getDialog()).getPrintStream());
+          return null;
+        }
+        public void performError(Throwable err) {
+          err.printStackTrace();
+          super.performError(err);
+          System.exit(-1);
+        }
+      };
+      SwingWorker startingWindow = new SwingWorker(initWork,new XuluStartingFrame()) {
+        // wenn der Start-Dialog abgebrochen wird, wird die komplette
+        // Applikation abgebrochen
+        public void terminate() {
+          System.exit(0);
+        }
+      };
+      // Ueber den Kommandozeilenparameter -kso wird das Start-Fenster
+      // offen gehalten und nicht automatisch geschlossen
+      startingWindow.setKeepOpen( keepStartFrameOpen );
+      startingWindow.start();
+
+      // Begruessungsmeldung im Xulu-Fenster
+      System.out.println("Start XULU by");
+      System.out.println("   java [jre commands] edu.bonn.xulu.XuluModellingPlatform --help");
+      System.out.println("to see available command line parameters.\n");
+    } catch(Throwable e) {
+      e.printStackTrace();
+      ExceptionDialog.show(e);
+      System.exit(-1);
+    }
+  }
+
+  /**
+   * Fuegt einen {@link ResourceProvider} in die Liste der in Xulu verwendeten
+   * ResourceProvider ein.
+   * @param rp ein ResourceProvider
+   */
+  public static void registerResourceProvider(ResourceProvider rp) {
+    RESOURCE_BUNDLES.add(rp);
+  }
+
+  /**
+   * Erzeugt einen {@link ResourceProvider} unterhalb von {@link XuluConstants#LOCALES_BASE}
+   * ({@code locales}) und fuegt ihn in die Liste der in Xulu verwendeten
+   * ResourceProvider ein.
+   * @param bundleName    Name des Bundles
+   * @param defaultLocale Standard-SPrache des Bundles
+   * @see XuluConstants#LOCALES_BASE
+   */
+  public static ResourceProvider registerResourceProvider(String bundleName, Locale defaultLocale) {
+    ResourceProvider rp = new ResourceProvider(LOCALES_BASE+"."+bundleName,defaultLocale);
+    registerResourceProvider( rp );
+    return rp;
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/appl/AbstractCommandInterpreter.java
===================================================================
--- trunk/src/edu/bonn/xulu/appl/AbstractCommandInterpreter.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/AbstractCommandInterpreter.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,99 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.appl;
+
+import java.io.*;
+import schmitzm.lang.OperationCanceledException;
+import edu.bonn.xulu.*;
+import edu.bonn.xulu.appl.*;
+
+/**
+ * Diese Klasse bildet eine Basis-Implementierung eines {@link ScriptInterpreter}.
+ * Sie basiert darauf, dass die {@linkplain Command Befehle} zunaechst alle
+ * aus einem InputStream eingelesen und danach hintereinander ausgefuehrt
+ * werden. Implementierungen dieser Klasse brauchen lediglich noch das
+ * Einlesen der Befehle aus dem Stream implementieren. Das Ausfuehren (mit
+ * entsprechenden Status-Meldungen) uebernimmt diese Oberklasse.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class AbstractCommandInterpreter extends AbstractScriptInterpreter {
+  /** Speichert die Anzahl an Fehlern, die fuer das Skript aufgetreten sind.*/
+  protected int errorCount = 0;
+  /** Speichert den Namen des Skript-Interpreters. */
+  protected String name = "";
+  /** Speichert die Xulu-Instanz fuer die das Skript ausgefuehrt wird. */
+  protected XuluModellingPlatform appl = null;
+
+  /**
+   * Fuehrt ein Script aus.
+   * @param in   Eingabe-Stream in dem das Skript zu finden ist.
+   * @param appl Applikation, in der das Skript auszufuehren ist
+   */
+  public void execute(InputStream in, XuluModellingPlatform appl) {
+    this.appl = appl;
+    errorCount = 0;
+    Command[] command = readCommands(in);
+    System.out.println("\nStart executing script...");
+    for (int i=0; i<command.length; i++) {
+      System.out.print(">>>> "+command[i].getDescription()+"...");
+      try {
+        command[i].execute(appl);
+        System.out.println(" done!");
+      } catch (OperationCanceledException err) {
+        // Wirft eine Operation eine solche Exception, wird die komplette
+        // Script-Ausfuehung abgebrochen
+        System.out.println(" failed!");
+        System.out.println("Script canceled with "+errorCount+" errors...\n");
+        return;
+      } catch (Exception err) {
+        errorCount++;
+        System.out.println(" failed!");
+        System.out.println(err);
+      }
+
+    }
+    System.out.println("Script finished with "+errorCount+" errors...\n");
+  }
+
+  /**
+   * Liest ein Skript ein und erzeugt daraus eine Reihe von Befehlen.
+   * @param in Eingabe-Stream in dem das Skript zu finden ist
+   */
+  protected abstract Command[] readCommands(InputStream in);
+
+  /**
+   * Diese Interface beschreibt einen unter der Xulu-Plattform ausfuehrbaren
+   * Befehl.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  protected static interface Command {
+    /**
+     * Fuehrt den Befehl aus.
+     * @param appl Applikation unter der der Befehl auszufuehren ist
+     * @exception java.lang.Exception wenn ein Fehler bei der Ausfuehrung aufritt
+     */
+    public void execute(XuluModellingPlatform appl) throws Exception;
+    /**
+     * Liefert eine Beschreibung, was der Befehl macht.
+     */
+    public String getDescription();
+
+    /**
+     * Prueft, ob alle Parameter korrekt gesetzt sind. Ggf. wird eine Exception
+     * geworfen.
+     */
+    public void check() throws RuntimeException;
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/appl/AbstractHandler.java
===================================================================
--- trunk/src/edu/bonn/xulu/appl/AbstractHandler.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/AbstractHandler.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,39 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.appl;
+
+/**
+ * Diese Klasse bildet eine Basis-Implementierung eines {@link Handler}.
+ * Diese implementiert die Verwaltung der {@link HandlerFactory}, die fuer
+ * den Handler zustaendig ist.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class AbstractHandler implements Handler {
+  /** Speichert die Factory, die fuer den Handler zustaendig ist. */
+  protected HandlerFactory factory = null;
+
+  /**
+   * Erzeugt einen neuen Handler.
+   * @param fac Factory, die fuer den Handler zustaendig ist.
+   */
+  public AbstractHandler(HandlerFactory fac) {
+    this.factory = fac;
+  }
+
+  /**
+   * Liefert die Factory, die fuer den Handler zustaendig ist.
+   */
+  public HandlerFactory getFactory() {
+    return factory;
+  }
+}

Added: trunk/src/edu/bonn/xulu/appl/AbstractManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/appl/AbstractManager.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/AbstractManager.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,251 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.appl;
+
+import java.util.Vector;
+
+import schmitzm.lang.DuplicateException;
+import schmitzm.data.event.AbstractObjectTraceable;
+import schmitzm.data.event.ObjectChangeEvent;
+import schmitzm.data.event.Invoker;
+
+// Nur fuer Doku
+import schmitzm.data.event.ObjectListener;
+
+/**
+ * Diese Klasse stellt einen allgemeinen Manager dar. Dieser dient dazu,
+ * Komponenten, denen ein grafisches Fenster zugeordnet ist, in einer Liste zu
+ * verwalten. z.B.
+ * <ul>
+ * <li>Visualisierungstools</li>
+ * <li>Modell-Instanzen</li>
+ * <li>...</li>
+ * </ul>
+ * Aus diesem Grund muessen die Objekte, bestimmte Anforderungen erfuellen, die
+ * durch das Interface {@link AbstractManager.ContentType} spezifiziert werden.<br>
+ * Der Manager fungiert als <code>AbstractObjectTraceable</code>, so dass
+ * {@link ObjectListener} angeschlossen werden koennen, welche automatisch durch
+ * ein {@link AbstractManager.ChangeEvent} informiert werden, wenn sich der
+ * Inhalt des Managers aendert.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class AbstractManager extends AbstractObjectTraceable implements XuluComponent {
+  /** Speichert den Inhalt des Managers. */
+  protected Vector content = new Vector<ContentType>();
+  /** Speichert, ob in dem Manager mehrere gleiche Objekte erlaubt sind */
+  protected boolean duplAllowed = true;
+
+  /**
+   * Erzeugt einen neuen (leeren) Manager.
+   * @param duplAllowed steuert, ob Duplikate im Manager erlaubt sind
+   */
+  public AbstractManager(boolean duplAllowed) {
+    this.duplAllowed = duplAllowed;
+  }
+
+  /**
+   * Erzeugt einen neuen (leeren) Manager, der Duplikate erlaubt.
+   */
+  public AbstractManager() {
+    this(true);
+  }
+
+  /**
+   * Prueft, ob im Manager Objekte mit der gleichen Bezeichnung erlaubt sind.
+   */
+  public boolean getDuplicatedAllowed() {
+    return this.duplAllowed;
+  }
+
+  /**
+   * Zerstoert den Manager und alle darin enthaltenen Komponenten.
+   */
+  public void dispose() {
+    this.removeAll();
+    content = null;
+  }
+
+  /**
+   * Prueft, ob der Manager zerstoert ist.
+   * @see #dispose()
+   */
+  public boolean isDisposed() {
+    return content == null;
+  }
+
+  /**
+   * Liefert die Anzahl an aktuell registrierten Komponenten.
+   */
+  public int getCount() {
+    XuluComponentUtil.checkDisposed(this);
+    return content.size();
+  }
+
+  /**
+   * Liefert eine registrierte Komponente.
+   * @param index Listen-Index
+   */
+  public ContentType get(int index) {
+    XuluComponentUtil.checkDisposed(this);
+    return (ContentType)content.get(index);
+  }
+
+  /**
+   * Liefert alle registrierte Komponenten als Array.
+   * @return leerer Array falls keine Komponenten im Manager registriert sind.
+   */
+  public ContentType[] getAll() {
+    XuluComponentUtil.checkDisposed(this);
+    return (ContentType[])content.toArray(new ContentType[0]);
+  }
+
+  /**
+   * Fuegt dem Manager eine Komponente hinzu. Das Fenster dieser
+   * Komponente wird noch nicht angezeigt!
+   * @param comp neue Komponente
+   */
+  public void add(ContentType comp) {
+    add(comp,false);
+  }
+
+  /**
+   * Fuegt dem Manager eine Komponente hinzu.
+   * @param comp neue Komponente
+   * @param visible bestimmt, ob die Komponente (bzw. deren Fenster) direkt
+   *                angezeigt wird
+   */
+  public void add(ContentType comp, boolean visible) {
+    XuluComponentUtil.checkDisposed(this);
+    checkComponentAndError(comp);
+
+    if ( !duplAllowed )
+      checkDuplicateAndError(comp);
+
+    if ( content.add( comp ) )
+      fireEvent( new ChangeEvent(this,null,comp) );
+    comp.setVisible(visible);
+  }
+
+  /**
+   * Entfernt eine Komponente aus dem Manager. Zuvor wird diese
+   * komplett geschlossen.
+   * @param comp zu schliessende Komponente
+   * @see ContentType#close()
+   */
+  public void remove(ContentType comp) {
+    XuluComponentUtil.checkDisposed(this);
+    if ( content.remove(comp) )
+      fireEvent( new ChangeEvent(this,comp,null) );
+    comp.setVisible(false);
+    comp.close();
+  }
+
+  /**
+   * Entfernt alle Komponenten aus dem Manager. Zuvor werden diese
+   * komplett geschlossen.
+   * @see ContentType#close()
+   */
+  public void removeAll() {
+    while( getCount() > 0 )
+      remove(0);
+  }
+
+  /**
+   * Entfernt eine Komponente aus dem Manager. Zuvor wird diese
+   * komplett geschlossen.
+   * @param index Listen-Index
+   * @see ContentType#close()
+   */
+  public void remove(int index) {
+    XuluComponentUtil.checkDisposed(this);
+    remove( (ContentType)content.elementAt(index) );
+  }
+
+  /**
+   * Prueft, ob es bereits ein Objekt im Manager gibt, das dem uebergebenen
+   * gleicht (diese Implementierung prueft auf die {@code equals(.)}.Methode).
+   * Ist dies der Fall, wird eine {@link DuplicateException} geworfen.
+   * @param cont Objekt auf das geprueft wird
+   */
+  protected void checkDuplicateAndError(ContentType cont) {
+    ContentType[] content = getAll();
+    for (ContentType c : content)
+      if ( c == null && cont == null ||
+           c != null && c.equals( cont ) )
+        throw new DuplicateException("Duplicate Object in AbstractManager",c,cont);
+  }
+
+  /**
+   * Diese Methode prueft, ob der Inhalt fuer die konkrete Implementierung
+   * zulaessig ist.
+   * @param cont ContentType
+   */
+  public abstract void checkComponentAndError(ContentType cont);
+
+  /**
+   * Dieses Interface definiert Mindestanforderungen, die die Komponenten
+   * erfuellen muessen, die in dem Manager verwaltet werden sollen.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static interface ContentType {
+    /**
+     * Zeigt die Komponente (deren Fenster an) oder verbirgt sie.
+     */
+    public void setVisible(boolean visible);
+
+    /**
+     * Prueft, ob die Komponente (deren Fenster) aktuell angezeigt wird.
+     */
+    public boolean isVisible();
+
+    /**
+     * Liefert die Bezeichnung der Komponente. Hiermit wird die Komponente
+     * in einer grafischen Darstellung (Tabelle) identifiziert.
+     */
+    public String getTitle();
+
+    /**
+     * Setzt die Bezeichnung der Komponente. Hiermit wird die Komponente
+     * in einer grafischen Darstellung (Tabelle) identifiziert.
+     */
+    public void setTitle(String newTitle);
+
+    /**
+     * Schliesst die Komponente komplett. Alle internen Ressourcen sollten
+     * freigegeben werden.
+     */
+    public void close();
+  }
+
+  /**
+   * Diese Ereignis wird erzeugt (und an alle {@link ObjectListener}
+   * gesendet), wenn sich der Inhalt des Managers aendert (eine Instanz hingefuegt
+   * oder entfernt wurde).
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class ChangeEvent extends ObjectChangeEvent {
+    /**
+     * Erzeugt ein neues Ereignis.
+     * @param manager  Manager, der sich geaendert hat
+     * @param oldComp  alte Komponente (<code>null</code> falls
+     *                 eine Komponente hinzugefuegt wurde)
+     * @param newComp  neue Komponente (<code>null</code> falls
+     *                 eine Komponente entfernt wurde)
+     */
+    public ChangeEvent(AbstractManager manager, Object oldComp, Object newComp) {
+      super( new Invoker(manager, new Invoker(oldComp)), oldComp, newComp );
+    }
+  }
+}

Added: trunk/src/edu/bonn/xulu/appl/AbstractScriptInterpreter.java
===================================================================
--- trunk/src/edu/bonn/xulu/appl/AbstractScriptInterpreter.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/AbstractScriptInterpreter.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,42 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.appl;
+
+import java.io.*;
+
+import edu.bonn.xulu.*;
+import edu.bonn.xulu.appl.*;
+
+/**
+ * Diese Klasse bildet eine Basis-Implementierung eines {@link ScriptInterpreter}.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class AbstractScriptInterpreter implements ScriptInterpreter {
+  /** Speichert den Namen des Skript-Interpreters. */
+  protected String name = "";
+
+  /**
+   * Liefert die Bezeichnung des Skript-Interpreter.
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Setzt die Bezeichnung fuer den Skript-Interpreter
+   * @param name neue Bezeichnung
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+}

Added: trunk/src/edu/bonn/xulu/appl/AbstractXuluPlugin.java
===================================================================
--- trunk/src/edu/bonn/xulu/appl/AbstractXuluPlugin.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/AbstractXuluPlugin.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,88 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.appl;
+
+import schmitzm.lang.AbstractNamedObject;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.XuluPlugin;
+
+/**
+ * Diese Klasse stellt eine Basis-Implementierung von {@link XuluPlugin} dar.
+ * Unterklassen muessen lediglich noch die {@link XuluPlugin#execute(XuluModellingPlatform)}-Methode
+ * implementieren und darin das {@link #started}-Flag pruefen, damit das
+ * Plugin beendet werden kann.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class AbstractXuluPlugin extends AbstractNamedObject implements XuluPlugin {
+  /** Speichert, ob das Plugin gestartet ist oder nicht. */
+  protected boolean started = false;
+  /** Speichert, ob die Plugin-GUI angezeigt wird. */
+  protected boolean visible = false;
+  /** Speichert, ob die Plugin eine GUI besitzt. */
+  protected boolean hasGUI = false;
+  /** Speichert, ob die Xulu-Instanz, in der das Plugin ausgefuehrt wird. */
+  protected XuluModellingPlatform appl = null;
+
+  /**
+   * Erzeugt eine neue Plugin-Instanz.
+   * @param hasGUI gibt an, ob das Plugin eine GUI besitzt.
+   */
+  public AbstractXuluPlugin(boolean hasGUI) {
+    super();
+    this.hasGUI = hasGUI;
+  }
+
+  /**
+   * Startet die Ausfuehrung des Plugins. Diese Basis-Implementierung speichert
+   * lediglich die Xulu-Instanz in der globalen Variable {@link #appl}.
+   * Unterklassen muessen diese Methode ueberschreiben <b>und die
+   * {@code super.execute(.)}-Methode aufrufen</b>.
+   * @param appl Instanz der Xulu-Applikation
+   */
+  public void execute(XuluModellingPlatform appl) {
+    this.appl = appl;
+  }
+
+  /**
+   * Stoppt die Ausfuehrung des Plugins. Diese Basis-Implementierung setzt
+   * lediglich das {@link #started}-Flag auf {@code false}.
+   */
+  public void stop() {
+    this.started = false;
+  }
+
+  /**
+   * Prueft, ob das Plugin gestartet ist.
+   * @return Wert des {@link #started}-Flag
+   */
+  public boolean isStarted() {
+    return started;
+  }
+
+  /**
+   * Prueft, ob die Plugin-GUI angezeigt wird.
+   * @return Wert des {@link #visible}-Flag
+   */
+  public boolean isVisible() {
+    return visible;
+  }
+
+  /**
+   * Zeigt die Plugin-GUI an oder verbirgt sie. Diese Basis-Implementierung
+   * setzt lediglich das Flag {@code #visible}. Macht nichts, wenn das Plugin keine
+   * GUI besitzt.
+   */
+  public void setVisible(boolean visible) {
+    this.visible = hasGUI && visible;
+  }
+}

Added: trunk/src/edu/bonn/xulu/appl/DataPool.java
===================================================================
--- trunk/src/edu/bonn/xulu/appl/DataPool.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/DataPool.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,370 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.appl;
+
+import java.util.Vector;
+import java.util.Random;
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+import schmitzm.data.event.AbstractObjectTraceable;
+import schmitzm.data.event.ObjectListener;
+import schmitzm.data.event.AbstractObjectEvent;
+import schmitzm.data.event.ObjectEvent;
+import schmitzm.data.event.NameChangeEvent;
+import schmitzm.data.event.Invoker;
+
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.data.DuplicateXuluObjectIDException;
+import edu.bonn.xulu.data.DuplicateXuluObjectNameException;
+
+/**
+ * Diese Klasse stellt den Xulu-Datenpool dar, in dem saemtliche (globalen)
+ * Daten fuer die Modellierung verwaltet werden.<br>
+ * Die Objekte werden in einer {@link java.util.Hashtable} verwaltet und sind
+ * durch eine eindeutige ID ansprechbar.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class DataPool extends AbstractObjectTraceable implements XuluComponent {
+  /** Zufallsgenerator */
+  private static final Random RANDOM = new Random();
+  /** Enthaelt alle <code>DataPool</code>-Instanzen. */
+  private static Vector pools = new Vector();
+
+  /** Enthaelt den Inhalt des Datenpools */
+  private Hashtable content = null;
+
+  /** Enthaelt einen {@link ObjectListener} der auf interne Veraenderungen
+   *  der Datenpool-Objekte horcht */
+  private ObjectListener objectListener = null;
+
+  /** Flag, ob sich mehrere Objekte mit demselben Namen im Datenpool
+   *  befinden duerfen */
+  private boolean duplNamesAllowed = false;
+  /** Flag, ob beim Einfuegen eines neuen Objekte bestehende Objekte mit dem
+   *  gleichen Namen automatisch aus dem Datenpool entfernt werden. Ist nur
+   *  relevant, wenn Duplikate verboten sind.
+   *  @see #duplNamesAllowed */
+  private boolean autoOverwriteDuplNames = false;
+
+  /**
+   * Erzeugt eine neue Datenpool-Instanz.
+   * @param cap initiale Kapazitaet des Pools
+   */
+  public DataPool(int cap) {
+    pools.add(this);
+    this.content = new Hashtable(cap);
+    final DataPool dummyPool = this;
+    this.objectListener = new ObjectListener() {
+      public void performObjectEvent(ObjectEvent e) {
+        if ( e instanceof NameChangeEvent )
+          fireEvent( new DataPoolChangeEvent(dummyPool,e.getSource(),DataPoolChangeEvent.OBJECT_NAME_CHANGED) );
+      }
+    };
+  }
+
+  /**
+   * Erzeugt einen neuen Datenpool. Dieser hat die initiale Groesse von
+   * 50 Objekten.
+   */
+  public DataPool() {
+    this(50);
+  }
+
+  /**
+   * Zerstoert den Datenpool und alle darin enthaltenen Objekte.
+   * @see XuluObject#dispose()
+   */
+  public void dispose() {
+    XuluComponentUtil.checkDisposed(this);
+    Enumeration e = asEnumeration();
+    while( e.hasMoreElements() ) {
+      XuluObject o = (XuluObject)e.nextElement();
+      removeObject(o);
+      o.dispose();
+    }
+  }
+
+  /**
+   * Prueft, ob der Datenpool zerstoert ist.
+   * @see #dispose()
+   */
+  public boolean isDisposed() {
+    return content == null;
+  }
+
+  /**
+   * Liefert die Anzahl an Objekten im Datenpool.
+   */
+  public int getSize() {
+    XuluComponentUtil.checkDisposed(this);
+    return content.size();
+  }
+
+  /**
+   * Liefert den Inhalt des Datenpools als Liste.
+   */
+  public Enumeration asEnumeration() {
+    XuluComponentUtil.checkDisposed(this);
+    return content.elements();
+  }
+
+  /**
+   * Liefert ein Objekt aus dem Datenpool.
+   * @param id ID des Objekts im Datenpool
+   * @return <code>null</code> falls es im Pool kein Objekt mit dieser
+   *         ID gibt
+   */
+  public XuluObject getObject(long id) {
+    XuluComponentUtil.checkDisposed(this);
+    return (XuluObject)content.get(id);
+  }
+
+  /**
+   * Liefert Objekte aus dem Datenpool.
+   * @param name Bezeichnung des Objekts im Datenpool
+   * @return ein leerer Array falls es im Pool keine Objekte mit dieser
+   *         Bezeichnung gibt
+   */
+  public XuluObject[] getObjects(String name) {
+    Vector outObjects = new Vector();
+    Enumeration e = asEnumeration();
+    for (;e.hasMoreElements();) {
+      XuluObject o = (XuluObject)e.nextElement();
+      if ( o.getDescription() != null && o.getDescription().equals(name) )
+        outObjects.add(o);
+    }
+    return (XuluObject[])outObjects.toArray(new XuluObject[0]);
+  }
+
+  /**
+   * Liefert alle Objekte aus dem Datenpool, die Instanzen eines bestimmten
+   * Typs sind.
+   * @param type zu suchende Typ
+   * @return leerer Array, falls es keine solchen Objekte gibt
+   */
+  public XuluObject[] getObjects(Class type) {
+    Vector outObjects = new Vector();
+    Enumeration e = asEnumeration();
+    for (;e.hasMoreElements();) {
+      XuluObject o = (XuluObject)e.nextElement();
+      if ( o != null && type.isInstance(o) )
+        outObjects.add(o);
+    }
+    return (XuluObject[])outObjects.toArray(new XuluObject[0]);
+  }
+
+  /**
+   * Prueft, ob im Pool ein Objekt vorhanden ist.
+   * @param id ID des Objekts
+   */
+  public boolean contains(long id) {
+    return getObject(id) != null;
+  }
+
+  /**
+   * Prueft, ob im Pool ein Objekt vorhanden ist.
+   * @param name Bezeichnung des Objekts
+   */
+  public boolean contains(String name) {
+    return getObjects(name).length > 0;
+  }
+  
+  /**
+   * Erstellt eine fuer den Datenpool eindeutige Bezeichnung.
+   * Enthaelt der Datenpool bereits ein Objekt mit der angegeben
+   * Bezeichnung, wird ein Index an die Bezeichnung angehaengt.
+   * @param baseName Basis-Bezeichnung
+   */
+  public String createUniqueDescription(String baseName) {
+    String newName = baseName;
+    for (int i=2; contains(newName); i++)
+      newName = baseName + " ("+i+")";
+    return newName;
+  }
+
+  /**
+   * Fuegt dem Datenpool ein Objekt hinzu. Erzeugt ein <code>DataPoolChangeEvent</code>
+   * fuer das neue Objekt.
+   * @see DataPoolChangeEvent#OBJECT_ADDED
+   * @exception DuplicateXuluObjectIDException falls im Datenpool bereits ein Objekt
+   *            mit der gleichen Objekt-ID existiert
+   * @exception DuplicateXuluObjectNameException falls die Duplikat-Eigenschaft
+   *            abgeschaltet ist und im Datenpool bereits ein Objekt mit der
+   *            gleichen Objekt-Beschreibung existiert
+   */
+  public void addObject(XuluObject object) {
+    XuluComponentUtil.checkDisposed(this);
+    if ( contains(object.getID()) )
+      throw new DuplicateXuluObjectIDException(object,"DataPool already contains an object with ID "+object.getID());
+
+    // Sind doppelte Namen verboten, wird geprueft, ob es bereits Objekte
+    // mit dem Namen im Datenpool gibt
+    if ( !duplNamesAllowed ) {
+      XuluObject[] obj = getObjects(object.getDescription());
+      // Wenn kein AutoOverwrite, wird die Einfuege-Operation zurueckgewiesen
+      if ( obj.length > 0 && !autoOverwriteDuplNames )
+        throw new DuplicateXuluObjectNameException(object,"DataPool already contains object '"+object.getDescription()+"'");
+      for (XuluObject o : obj)
+        removeObject(o);
+    }
+    content.put(object.getID(),object);
+    object.addObjectListener( objectListener );
+    fireEvent( new DataPoolChangeEvent(this,object,DataPoolChangeEvent.OBJECT_ADDED) );
+  }
+
+  /**
+   * Entfernt ein Objekt aus dem Datenpool. Erzeugt ein <code>DataPoolChangeEvent</code>
+   * fuer das entfernte Objekt. Existiert das Objekt nicht im DatenPool, geschieht
+   * nichts (es wird auch kein Event erzeugt).
+   * @param object zu entfernendes Xulu-Objekt
+   * @see DataPoolChangeEvent#OBJECT_REMOVED
+   */
+  public void removeObject(XuluObject object) {
+    removeObject( object.getID() );
+  }
+
+  /**
+   * Entfernt ein Objekt aus dem Datenpool. Erzeugt ein <code>DataPoolChangeEvent</code>
+   * fuer das entfernte Objekt. Existiert im DatenPool kein Objekt mit der ID,
+   * geschieht nichts (es wird auch kein Event erzeugt).<br>
+   * <b>Bemerke:</b><br>
+   * Durch das Loeschen des Objekts wird dieses noch nicht zerstoert. Hierdurch
+   * kann es einfach in eine andere Datenpool-Instanz eingefuegt werden!
+   * @param id ID des Xulu-Objekts im Datenpool
+   * @see DataPoolChangeEvent#OBJECT_REMOVED
+   */
+  public void removeObject(long id) {
+    XuluComponentUtil.checkDisposed(this);
+    XuluObject object = (XuluObject)content.remove(id);
+    object.removeObjectListener( objectListener );
+    if ( object != null )
+      fireEvent( new DataPoolChangeEvent(this,object,DataPoolChangeEvent.OBJECT_REMOVED) );
+  }
+
+  /**
+   * Prueft, ob sich mehrere Objekte mit demselben Namen im Datenpool
+   * befinden duerfen.
+   * @see #setAutoOverwriteDuplicateNames(boolean)
+   */
+  public boolean getDuplicateNamesAllowed() {
+    return this.duplNamesAllowed;
+  }
+
+  /**
+   * Bestimmt, ob sich mehrere Objekte mit demselben Namen im Datenpool
+   * befinden duerfen.<br>
+   * Wird diese Eigenschaft auf {@code false} gesetzt haengt es von der
+   * {@link #setAutoOverwriteDuplicateNames(boolean) autoOverwriteDuplNames}-Eigenschaft
+   * ab, ob eine Einfuege-Operation zurueckgewiesen wird, oder das bestehende Objekt
+   * automatisch entfernt wird.<br>
+   * Standardwert: {@code false}
+   * @param duplAllowed wenn {@code true}, koennen mehrere Objekte mit demselben
+   *                    Namen im Datenpool vorkommen
+   */
+  public void setDuplicateNamesAllowed(boolean duplAllowed) {
+    this.duplNamesAllowed = duplAllowed;
+  }
+
+  /**
+   * Prueft, ob beim Einfuegen eines neuen Objekte bestehende Objekte mit dem
+   * gleichen Namen automatisch aus dem Datenpool entfernt werden ({@code true}),
+   * oder die Einfuege-Operation zurueckgewiesen wird ({@code false}).
+   * Diese Eigenschaft ist nur relevant, wenn Duplikate verboten sind. <br>
+   * Standardwert: {@code false}
+   * @see #getDuplicateNamesAllowed() */
+  public boolean getAutoOverwrideDuplicateNames() {
+    return this.autoOverwriteDuplNames;
+  }
+
+  /**
+   * Bestimmt, ob beim Einfuegen eines neuen Objekte bestehende Objekte mit dem
+   * gleichen Namen automatisch aus dem Datenpool entfernt werden ({@code true}),
+   * oder die Einfuege-Operation zurueckgewiesen wird ({@code false}).
+   * Diese Eigenschaft ist nur relevant, wenn Duplikate verboten sind.<br>
+   * Standardwert: {@code false}
+   * @see #setDuplicateNamesAllowed(boolean) */
+  public void setAutoOverwriteDuplicateNames(boolean autoOverwrite) {
+    this.autoOverwriteDuplNames = autoOverwrite;
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Statische Methoden
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob die angegebene ID bereits in irgendeinem Datenpool fuer
+   * ein Objekt verwendet wird.
+   */
+  private static boolean checkUnused(long id) {
+    for (int i=0; i<pools.size(); i++)
+      if ( ((DataPool)pools.elementAt(i)).contains(id) )
+        return false;
+    return true;
+  }
+
+  /**
+   * Generiert eine Objekt-ID, die (ueber alle <code>DataPool</code>-Instanzen!)
+   * eindeutig ist.
+   */
+  public static long generateUniqueID() {
+    long newID = 0;
+    while( !checkUnused( newID = System.currentTimeMillis() % RANDOM.nextInt() ) );
+    return newID;
+  }
+
+  /**
+   * Diese Ereignis wird erzeugt (und an alle {@link schmitzm.data.event.ObjectListener}
+   * gesendet), wenn sich der Inhalt des Datenpools aendert (ein Objekt hingefuegt
+   * oder entfernt wurde).
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class DataPoolChangeEvent extends AbstractObjectEvent {
+    /**
+     * Ereignis-Typ, der anzeigt, dass ein Objekt hinzugefuegt wurde.
+     */
+    public static final int OBJECT_ADDED = 30;
+
+    /**
+     * Ereignis-Typ, der anzeigt, dass ein Objekt entfernt wurde.
+     */
+    public static final int OBJECT_REMOVED = 40;
+
+    /**
+     * Ereignis-Typ, der anzeigt, dass ein Objekt seinen Namen geaendert hat.
+     */
+    public static final int OBJECT_NAME_CHANGED = 50;
+
+    /**
+     * Erzeugt ein neues Ereignis.
+     * @param pool DataPool der sich geaendert hat
+     * @param obj  Xulu-Objekt, das betroffen ist
+     * @param type Zeigt an, was mit dem Objekt geschehen ist.
+     */
+    public DataPoolChangeEvent(DataPool pool, XuluObject obj, int type) {
+      this(pool,new Invoker(obj), type );
+    }
+
+    /**
+     * Erzeugt ein neues Ereignis.
+     * @param pool   DataPool der sich geaendert hat
+     * @param source betroffene Objekt-Kette
+     * @param type   Zeigt an, was mit dem Objekt geschehen ist.
+     */
+    public DataPoolChangeEvent(DataPool pool, Invoker source, int type) {
+      super( new Invoker( pool, source ), type );
+    }
+  }
+
+}
+

Added: trunk/src/edu/bonn/xulu/appl/EventHandler.java
===================================================================
--- trunk/src/edu/bonn/xulu/appl/EventHandler.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/EventHandler.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,160 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.appl;
+
+import schmitzm.data.event.ObjectEvent;
+import edu.bonn.xulu.appl.AbstractManager;
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.model.XuluModel;
+import edu.bonn.xulu.XuluModellingPlatform;
+
+/**
+ * Ein EventHandler stellt eine Zuordnung her zwischen
+ * <ol>
+ *   <li>einem Objekt</li>
+ *   <li>einem Ereignis-Typ</li>
+ *   <li>einer {@linkplain Handler Ereignis-Routine} (Handler)
+ * </ol>
+ * Loest das Objekt ein Ereignis vom spezifizierten Typ aus, so wird der
+ * Handler ausgefuehrt.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class EventHandler implements AbstractManager.ContentType {
+  /** Objekt, auf dessen Ereignisse gelauscht wird. */
+  protected Object object = null;
+  /** Ereignis, auf das reagiert wird. */
+  protected Class<ObjectEvent> eventType = null;
+  /** Handler, der ausgefuehrt wird, wenn {@link #object} ein Ereignis
+   *  vom Typ {@link #eventType} ausloest. */
+  protected Handler handler;
+
+  // Fuer AbstractManager.ContentType
+  private XuluModellingPlatform appl    = null;
+  private boolean               visible = false;
+  private String                title   = "";
+
+  /**
+   * Erzeugt einen neuen Event-Handler.
+   * @param object    Objekt, das beobachtet wird
+   * @param eventType Ereignis-Typ auf den reagiert werden soll (muss eine
+   *                  Subklasse von {@link ObjectEvent} sein)
+   * @param handler   Handler der ausgefuehrt werden soll
+   * @param appl      Xulu-Applikation in der der Handler ausgefuehrt wird
+   */
+  public EventHandler(Object object, Class eventType, Handler handler, XuluModellingPlatform appl) {
+    if ( !ObjectEvent.class.isAssignableFrom(eventType) )
+      throw new IllegalArgumentException("Subclass of ObjectEvent expected for eventType!");
+    this.object    = object;
+    this.eventType = eventType;
+    this.handler   = handler;
+    this.appl      = appl;
+    // Titel initialisieren
+    if (object == null)
+      title = "*";
+    else if (object instanceof XuluObject)
+      title = ((XuluObject)object).getDescription();
+    else if (object instanceof XuluModel)
+      title = ((XuluModel)object).getName();
+    else
+      title = "untitled";
+  }
+
+  /**
+   * Erzeugt einen neuen Event-Handler. Dieser beobachtet kein bestimmtes
+   * Objekt, sondern ist global.
+   * @param eventType Ereignis-Typ auf den reagiert werden soll (muss eine
+   *                  Subklasse von {@link ObjectEvent} sein)
+   * @param handler   Handler der ausgefuehrt werden soll
+   * @param appl      Xulu-Applikation in der der Handler ausgefuehrt wird
+   */
+  public EventHandler(Class eventType, Handler handler, XuluModellingPlatform appl) {
+    this(null,eventType,handler,appl);
+  }
+
+  /**
+   * Liefert das Objekt, das beobachtet wird.
+   */
+  public Object getObject() {
+    return object;
+  }
+
+  /**
+   * Liefert den Ereignistyp, auf den der Handler ausgefuehrt werden soll.
+   */
+  public Class<ObjectEvent> getEventType() {
+    return eventType;
+  }
+
+  /**
+   * Liefert den Handler, der ausgefuehrt werden soll, wenn das beobachtete Objekt
+   * das Ereignis ausloest.
+   */
+  public Handler getHandler() {
+    return handler;
+  }
+
+  /**
+   * Prueft, ob es sich um einen Event-Handler handelt, der fuer <i>alle</i>
+   * Objekte zustaendig ist.
+   */
+  public boolean isGlobal() {
+    return object == null;
+  }
+
+
+  ///////////////////////////////////////////////////////////////////
+  //////// Implementierung von AbstractManager.ContentType  /////////
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Fordert die HandlerFactory auf, den Handler zu veraendern.
+   */
+  public void setVisible(boolean visible) {
+    if ( visible && this.getHandler().getFactory()!=null ) {
+      this.visible = true;
+      this.getHandler().getFactory().modifyHandler( appl, getHandler() );
+    }
+    this.visible = false;
+
+  }
+
+  /**
+   * Liefert <code>true</code> falls der Handler durch die Factory gerade
+   * veraendert wird.
+   */
+  public boolean isVisible() {
+    return visible;
+  }
+
+  /**
+   * Liefert die Bezeichnung des Objekts fuer das der Event-Handler zustaendig
+   * ist.
+   */
+  public String getTitle() {
+    return title;
+  }
+
+  /**
+   * Setzt die Bezeichnung der Komponente. Hiermit wird die Komponente
+   * in einer grafischen Darstellung (Tabelle) identifiziert.
+   */
+  public void setTitle(String newTitle) {
+    this.title = newTitle;
+  }
+
+  /**
+   * Schliesst den EventHandler.
+   */
+  public void close() {
+
+  }
+}

Added: trunk/src/edu/bonn/xulu/appl/EventManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/appl/EventManager.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/EventManager.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,339 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.appl;
+
+import java.util.Vector;
+import java.util.Enumeration;
+
+import schmitzm.data.event.ObjectEvent;
+import schmitzm.data.event.ObjectListener;
+import schmitzm.data.event.ObjectTraceable;
+import schmitzm.data.event.ObjectChangeEvent;
+import schmitzm.data.event.GeneralObjectChangeEvent;
+import schmitzm.data.event.NameChangeEvent;
+import schmitzm.data.event.ObjectCloseEvent;
+
+import schmitzm.lang.HashtableWithCollisionList;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.DataPool;
+import edu.bonn.xulu.appl.EventHandler;
+import edu.bonn.xulu.model.XuluModel;
+import edu.bonn.xulu.model.event.ModelListener;
+import edu.bonn.xulu.model.event.ModelEvent;
+import edu.bonn.xulu.gui.ModelControlFrame;
+
+import edu.bonn.xulu.plugin.appl.VisualisationHandlerFactory;
+import edu.bonn.xulu.plugin.appl.FileExportHandlerFactory;
+
+// nur fuer Doku
+import edu.bonn.xulu.plugin.appl.VisualisationHandler;
+import edu.bonn.xulu.appl.ModelControlManager;
+import edu.bonn.xulu.appl.Handler;
+
+/**
+ * Ueber den Xulu-Event-Manager werden verschiedene Reaktionen auf Ereignisse
+ * bestimmter Komponenten innerhalb Xulu-Applikation gesteuert.<br>
+ * Hierzu koppelt sich der Event-Manager als Listener an den {@linkplain DataPool Xulu-Datenpool}
+ * und den {@linkplain ModelControlManager Xulu-Modell-Manager}. Sobald von diesen
+ * ein neues Objekt/Modell gemeldet wird, koppelt sich der Modell-Manager
+ * auch an dieses neue Objekt/Modell und kann somit im Folgenden auf saemtliche
+ * Ereignisse dieses Objekts reagieren (mit einem Handler).<br>
+ * Der Event-Manager unterscheidet zwei Arten von {@linkplain EventHandler Event-Handlern}.
+ * <ol>
+ *   <li><b>Objekt-Event-Handler</b>: Der zugehoerige {@link Handler} wird
+ *       ausgefuerhrt, wenn ein bestimmtes Objekt/Modell ein bestimmtes Ereignis
+ *       ausloest.</li>
+ *   <li><b>globale Event-Handler</b>: Nicht an ein spezielles Objekt gebunden. Der
+ *       zugehoerige {@link Handler} wird ausgefuerhrt, unabhaengig davon,
+ *       welches Objekt/Modell das entsprechende Ereignis initiiert</li>
+ * </ol>
+ * Neben fest definierten Event-Handlern besteht fuer den Anwender die Moeglichkeit,
+ * ueber die GUI des Event-Managers eigene Event-Handler zu spezifizieren.
+ * Zur Zeit ist ein Handler implementiert, mit dem ein Visualisierungsupdate
+ * fuer ein bestimmtes Objekt vorgenommen werden kann (siehe {@link VisualisationHandler}).
+ * @todo Handler zum automatisierten Speichern eines Objekts
+ * @todo HandlerFactory-Klassen ueber Xulu-Registry anstelle des statischen Arrays
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class EventManager extends AbstractManager implements ObjectListener, ModelListener {
+  private XuluModellingPlatform appl = null;
+
+  /** Speichert die globalen Event-Handler, die fuer alle Objekte gueltig sind. */
+  protected Vector globalEventHandler = null;
+//  protected HashtableWithCollisionList globalEventHandler = null;
+
+  /** Speichert die objekt-spezifischen Event-Handler. */
+  protected HashtableWithCollisionList objectEventHandler = null;
+
+  /** Speichert die zur Verfuegung stehenden Handler. */
+  protected HandlerFactory[] handler = new HandlerFactory[] {
+      new VisualisationHandlerFactory( XuluConstants.XULUGUI_RES.getString("VisualisationUpdate") ),
+      new FileExportHandlerFactory( XuluConstants.XULUGUI_RES.getString("FileExport") )
+  };
+
+  /** Speichert die zur Verfuegung stehenden Objekt-Ereignisse. */
+  private static final Class<ObjectEvent>[] objectEvents = new Class[] {
+      GeneralObjectChangeEvent.class,
+      ObjectChangeEvent.class,
+      ObjectCloseEvent.class,
+      NameChangeEvent.class
+  };
+
+  /**
+   * Erzeugt den Event-Manager.
+   * @param appl Xulu-Applikation in der die Event-Handler ausgefuehrt werden
+   */
+  public EventManager(XuluModellingPlatform appl) {
+    super();
+
+    globalEventHandler = new Vector(); //new HashtableWithCollisionList<Class<ObjectEvent>,EventHandler>();
+    objectEventHandler = new HashtableWithCollisionList<Object,EventHandler>();
+    initGlobalEventHandler();
+
+    this.appl = appl;
+    appl.getDataPool().addObjectListener(this);
+    appl.getModelControlManager().addObjectListener(this);
+  }
+
+  /**
+   * Zerstoert den Event-Manager. Durch den Aufruf von
+   * <code>super.dispose()</code> werden zunaechst alle Objekte (Event-Handler)
+   * aus dem Event-Manager entfernt ({@link #remove(AbstractManager.ContentType)}).
+   * Anschliessend werden die Kopplungen zu allen Xulu-Objekten und -Modellen
+   * entfernt, sowie die Kopplung zum {@linkplain DataPool Daten-Pool}
+   * und {@linkplain ModelControlManager Modell-Manager}.
+   */
+  public void dispose() {
+    super.dispose();
+
+    // Listener von allen Datenpool-Objekten entfernen
+    Enumeration list = appl.getDataPool().asEnumeration();
+    while( list.hasMoreElements() )
+      ((ObjectTraceable)list.nextElement()).removeObjectListener(this);
+
+    // Listener von allen Modellen entfernen
+    ModelControlFrame[] modelFrame = appl.getModelControlManager().getAll();
+    for (int i=0; i<modelFrame.length; i++)
+      modelFrame[i].getModel().removeModelListener(this);
+
+    // Listener von Datenpool und Modell-Manager entfernen
+    appl.getDataPool().removeObjectListener(this);
+    appl.getModelControlManager().removeObjectListener(this);
+  }
+
+  /**
+   * Prueft (fuer add/remove), ob es sich einem Objekt um einen {@link EventHandler} handelt.
+   */
+  public void checkComponentAndError(AbstractManager.ContentType comp) {
+    if ( !(comp instanceof EventHandler) )
+      throw new UnsupportedOperationException(getClass().getSimpleName().concat(" can not manage instances of ").concat(comp.getClass().getName()));
+  }
+
+  /**
+   * Fuegt dem Event-Manager einen Event-Handler hinzu.
+   * @param comp {@linkplain EventHandler Event-Handler}
+   */
+  public void add(AbstractManager.ContentType comp) {
+    super.add(comp);
+    // Auch in die Hash-Tabelle einfuegen
+    EventHandler eh = (EventHandler)comp;
+    if ( eh.isGlobal() )
+      globalEventHandler.add(eh);
+    else
+      objectEventHandler.add(eh.getObject(),eh);
+  }
+
+  /**
+   * Entfernt einen Event-Handler aus dem Event-Manager.
+   * @param comp {@linkplain EventHandler Event-Handler}
+   */
+  public void remove(AbstractManager.ContentType comp) {
+    super.remove(comp);
+    // Auch aus den Hash-Tabelle einfuegen
+    EventHandler eh = (EventHandler)comp;
+    if ( eh.isGlobal() )
+      globalEventHandler.remove(eh);
+    else
+      objectEventHandler.remove(eh.getObject(),eh);
+  }
+
+  /**
+   * Liefert alle Factorys, die fuer die Erzeugung von Event-Handlern zur
+   * Verfuegung stehen.
+   */
+  public HandlerFactory[] getHandlerFactories() {
+    return handler.clone();
+  }
+
+  /**
+   * Liefert alle Ereignis-Typen, die fuer ein bestimmtes Objekt zur Verfuegung stehen.
+   */
+  public Class[] getEventTypes(Object obj) {
+    if ( obj instanceof XuluModel )
+      return ((XuluModel) obj).getEvents().clone();
+    if ( obj instanceof ObjectTraceable )
+      return this.objectEvents.clone();
+    return new Class[0];
+  }
+
+
+  /**
+   * Verarbeitet saemtliche Ereignisse.
+   * @param e ein Ereignis.
+   */
+  public void performObjectEvent(ObjectEvent e) {
+    ///////////////////  DATENPOOL //////////////////////
+    // Objekt dem Datenpool hinzugefuegt
+    if ( e instanceof DataPool.DataPoolChangeEvent && e.getType() ==  DataPool.DataPoolChangeEvent.OBJECT_ADDED ) {
+      performDatapoolObjectAdded(e.getSource().getRoot());
+      return;
+    }
+    // Objekt dem Datenpool entfernt
+    if ( e instanceof DataPool.DataPoolChangeEvent && e.getType() ==  DataPool.DataPoolChangeEvent.OBJECT_REMOVED ) {
+      performDatapoolObjectRemoved(e.getSource().getRoot());
+      return;
+    }
+
+    ///////////////////  MODELL-MANAGER //////////////////////
+    if ( e instanceof ModelControlManager.ChangeEvent ) {
+      // Modell dem Modell-Manager hinzugefuegt
+      if ( ((ModelControlManager.ChangeEvent)e).getOldValue() == null ) {
+        performModelAdded( ((ModelControlFrame)((ModelControlManager.ChangeEvent)e).getNewValue()).getModel() );
+        return;
+      }
+      // Modell aus dem Modell-Manager entfernt
+      if ( ((ModelControlManager.ChangeEvent)e).getNewValue() == null ) {
+        performModelRemoved( ((ModelControlFrame)((ModelControlManager.ChangeEvent)e).getOldValue()).getModel() );
+        return;
+      }
+
+    }
+
+    /////////////////// OBJEKT  //////////////////////
+    // globale Handler ausfuehren
+    Vector list = globalEventHandler; //(Vector)globalEventHandler.get(e.getClass());
+    for (int i=0; list!=null && i<list.size(); i++) {
+      EventHandler eh = (EventHandler)list.elementAt(i);
+      if ( eh.getEventType().isAssignableFrom(e.getClass()) )
+           eh.getHandler().execute(e);
+    }
+    // objektspezifische Handler ausfuehren
+    list = (Vector)objectEventHandler.get(e.getSource().getRoot());
+    for (int i=0; list!=null && i<list.size(); i++) {
+      EventHandler eh = (EventHandler)list.elementAt(i);
+      if ( eh.getObject() == e.getSource().getRoot() && eh.getEventType().isAssignableFrom(e.getClass()) )
+        eh.getHandler().execute(e);
+    }
+  }
+
+  /**
+   * Ruft lediglich {@link #performObjectEvent(ObjectEvent)} auf.
+   * @param e ein Ereignis.
+   */
+  public void performModelEvent(ModelEvent e) {
+    this.performObjectEvent(e);
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  /////  Methoden fuer die Ereignisbehandlung im Event-Manager  /////
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Erzeugt die globalen EventHandler, die automatisch fuer alle
+   * Modelle/Objekte gueltig sind.<br>
+   * Zur Zeit macht diese Methode nichts!
+   */
+  private void initGlobalEventHandler() {
+//    add( new EventHandler(
+//      schmitzm.data.event.ObjectChangeEvent.class,
+//      new Handler() {
+//        public HandlerFactory getFactory() {
+//          return null;
+//        }
+//
+//        public void execute(ObjectEvent e) {
+//          System.out.println("Test: "+e.getSource().getRoot()+" > "+e.getClass().getSimpleName());
+//        }
+//
+//        public void close() {
+//
+//        }
+//      },
+//      appl
+//    ));
+  }
+
+  /**
+   * Wird dem Datenpool ein Objekt hinzugefuegt, koppelt sich der Event-Manager
+   * automatisch als Listener an dieses Objekt.
+   * @param obj neues Objekt im Datenpool
+   */
+  private void performDatapoolObjectAdded(Object obj) {
+    // Event-Manager ankoppeln
+    if ( obj instanceof ObjectTraceable )
+      ((ObjectTraceable)obj).addObjectListener(this);
+  }
+
+  /**
+   * Wird ein Objekt aus dem Datenpool geloescht, entkoppelt sich der Event-Manager
+   * von diesem Objekt und loescht alle mit dem Objekt verknuepften Event-Handler.
+   * @param obj aus dem Datenpool geloschtes Objekt
+   */
+  private void performDatapoolObjectRemoved(Object obj) {
+    // alle EventHandler entfernen!
+    Vector list = (Vector)objectEventHandler.get(obj);
+    if ( list != null )
+      list = (Vector)list.clone();
+
+    for (int i=0; list!=null && i<list.size(); i++) {
+      EventHandler eh = (EventHandler)list.elementAt(i);
+      if ( eh.getObject().equals(obj) )
+        remove(eh);
+    }
+
+    // Event-Manager abkoppeln
+    if ( obj instanceof ObjectTraceable )
+      ((ObjectTraceable)obj).removeObjectListener(this);
+  }
+
+  /**
+   * Wird dem Modell-Manager ein Modell hinzugefuegt, koppelt sich der Event-Manager
+   * automatisch als Listener an dieses Modell.
+   * @param model neues Modell im Modell-Manager
+   */
+  private void performModelAdded(XuluModel model) {
+    // Event-Manager ankoppeln
+    model.addModelListener(this);
+  }
+
+  /**
+   * Wird ein Modell aus dem Modell-Manager entfernt, entkoppelt sich der Event-Manager
+   * von diesem Modell und loescht alle mit dem Modell verknuepften Event-Handler.
+   * @param model aus dem Modell-Manager entferntes Modell.
+   */
+  private void performModelRemoved(XuluModel model) {
+    // alle EventHandler entfernen!
+    Vector list = (Vector)objectEventHandler.get(model);
+    if ( list!=null )
+      list = (Vector)list.clone();
+    for (int i=0; list!=null && i<list.size(); i++) {
+      EventHandler eh = (EventHandler)list.elementAt(i);
+      if ( eh.getObject().equals(model) )
+        remove(eh);
+    }
+
+    // Event-Manager abkoppeln
+    model.removeModelListener(this);
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/appl/Handler.java
===================================================================
--- trunk/src/edu/bonn/xulu/appl/Handler.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/Handler.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,45 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.appl;
+
+import schmitzm.data.event.ObjectEvent;
+
+/**
+ * Ein Handler beschreibt eine konkrete Reaktion auf ein Ereignis. Diese ist jedoch
+ * unabhaengig von einem bestimmten Ereignis oder Ereignis-Typ definiert. Deshalb kann
+ * ein Handler prinzipiell "alles" sein, z.B. auch die Loeschung eines Objekts aus
+ * dem Datenpool oder das Beenden der XULU-Applikation.<br>
+ * Aus diesem Grund gehoert zu einer Handler-Implementierung immer eine
+ * {@linkplain HandlerFactory Handler-Factory} (mit entsprechender GUI), ueber
+ * die der Anwender das Neu-Erstellen und Abaendern eines Handlers vornehmen kann.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public interface Handler {
+  /**
+   * Schliesst den Handler.
+   */
+  public void close();
+
+
+  /**
+   * Fuehrt den Handler aus. Diese Methode <b>muss</b> damit umgehen koennen,
+   * das das uebergebene Ereignis <code>null</code> ist!
+   * @param e Ereignis fuer das der Handler ausgefuehrt wird (kann <code>null</code> sein!).
+   */
+  public void execute(ObjectEvent e);
+
+  /**
+   * Liefert die Factory, die fuer den Handler zustaendig ist.
+   */
+  public HandlerFactory getFactory();
+}

Added: trunk/src/edu/bonn/xulu/appl/HandlerFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/appl/HandlerFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/HandlerFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,39 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.appl;
+
+import edu.bonn.xulu.io.Factory;
+import edu.bonn.xulu.XuluModellingPlatform;
+
+/**
+ * Diese Klasse stellt eine Factory fuer einen {@link Handler} dar. Die Factory
+ * ist dafuer verantwortlich, dem Anwender Dialoge zur Verfuegung zu stellen,
+ * mit denen ein neuer Handler erzeugt und bestehende Handler abgeaendert werden
+ * koennen.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public interface HandlerFactory extends Factory {
+  /**
+   * Erzeugt einen neuen Handler.
+   * @param appl Instanz der Xulu-Applikation
+   */
+  public Handler createHandler(XuluModellingPlatform appl);
+
+  /**
+   * Veraendert einen bestehenden Handler. Hierzu soll ein entsprechender
+   * Anwender-Dialog bereitgestellt werden.
+   * @param appl    Instanz der Xulu-Applikation
+   * @param handler Handler, der veraendert werden soll
+   */
+  public void modifyHandler(XuluModellingPlatform appl, Handler handler);
+}

Added: trunk/src/edu/bonn/xulu/appl/ModelControlManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/appl/ModelControlManager.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/ModelControlManager.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,64 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.appl;
+
+import java.util.Vector;
+
+import edu.bonn.xulu.model.XuluModel;
+import edu.bonn.xulu.appl.AbstractManager;
+import edu.bonn.xulu.gui.ModelControlFrame;
+
+// nur fuer Doku
+import schmitzm.data.event.ObjectListener;
+import schmitzm.data.event.AbstractObjectTraceable;
+
+/**
+ * Der ModelManager verwaltet alle in der Xulu-Modelling-Platform aktiven
+ * Modell-Instanzen durch eine Liste der zugehoerigen {@linkplain ModelControlFrame Kontrollfenster}.<br>
+ * Der Manager fungiert als {@link AbstractObjectTraceable},
+ * so dass {@link ObjectListener} angeschlossen werden
+ * koennen, welche automatisch durch ein {@link AbstractManager.ChangeEvent}
+ * informiert werden, wenn sich der Inhalt des Managers aendert.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class ModelControlManager extends AbstractManager {
+  /**
+   * Erzeugt einen neuen (leeren) ModelManager.
+   */
+  public ModelControlManager() {
+    super(false);
+    this.content = new Vector<ModelControlFrame>();
+  }
+
+  /**
+   * Prueft, ob eine Komponente im ModelManager verwaltet werden
+   * kann.
+   * @param comp Komponente
+   * @exception UnsupportedOperationException falls es sich bei der Komponente
+   *            nicht um eine Instanz von {@link ModelControlFrame} handelt
+   */
+  public void checkComponentAndError(AbstractManager.ContentType comp) {
+    if (! (comp instanceof ModelControlFrame))
+      throw new UnsupportedOperationException(getClass().getSimpleName().concat(
+          " can not manage instances of ").concat(comp.getClass().getName()));
+  }
+
+  /**
+   * Liefert alle registrierte Modell-Kontroll-Fenster als Array.
+   * @return leerer <code>ModelControlFrame[]</code>-Array falls keine Instanzen
+   *         im Manager registriert sind.
+   */
+  public ModelControlFrame[] getAll() {
+    return (ModelControlFrame[])content.toArray(new ModelControlFrame[0]);
+  }
+}

Added: trunk/src/edu/bonn/xulu/appl/RecentImports.java
===================================================================
--- trunk/src/edu/bonn/xulu/appl/RecentImports.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/RecentImports.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,137 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.appl;
+
+import java.io.File;
+import org.apache.log4j.Logger;
+
+import appl.ext.XuluConfig;
+import schmitzm.lang.LimitedVector;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.io.IODefinition;
+import edu.bonn.xulu.io.ImportFactory;
+
+
+/**
+ * Diese Klasse stellt eine Liste der letzten in Xulu vorgenommenen Import-Operationen
+ * dar.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class RecentImports extends LimitedVector<IODefinition.ImportDefinition> {
+  private final Logger LOG = Logger.getLogger(this.getClass().getName());
+
+  private static final String KEY_PREFIX  = "RecentImports.";
+  private static final String KEY_MAXLOAD = KEY_PREFIX + "MAXLOAD";
+  private static final String KEY_SIZE = KEY_PREFIX + "SIZE";
+  private static final String KEY_FACTORY = ".FACTORY";
+  private static final String KEY_SOURCE  = ".SOURCE";
+
+  /**
+   * Erzeugt eine neue leere Liste, in der letzten Importe abgelegt werden.
+   * @param maxLoad maximale Groesse der Liste
+   */
+  public RecentImports(int maxLoad) {
+    super(maxLoad);
+  }
+
+  /**
+   * Laed die Liste der zuletzt vorgenommenen Import-Operationen aus den
+   * Xulu-Properties.
+   * @param appl Xulu-Instanz
+   * @see XuluConfig
+   */
+  public void loadFromXuluProperties(XuluModellingPlatform appl) {
+    XuluConfig config = XuluConfig.getXuluConfig();
+    // MaxLoad-Wert einlesen
+    int maxLoad = config.getIntProperty(KEY_MAXLOAD);
+    if (maxLoad <= 0) {
+      maxLoad = 10;
+      config.setIntProperty(KEY_MAXLOAD,maxLoad);
+    }
+    clear();
+    setMaxLoad(maxLoad);
+
+    // Anzahl an Elementen einlesen
+    int size = config.getIntProperty(KEY_SIZE);
+    if (size <= 0)
+      config.setIntProperty(KEY_SIZE,0);
+
+    // Import-Definitionan einlesen
+    for (int i=0; i<size; i++) {
+      // Name der Factory ermitteln
+      String facName = config.getProperty(KEY_PREFIX + i + KEY_FACTORY);
+      ImportFactory[] impFac = appl.getRegistry().getImportFactories(facName);
+      if ( impFac.length <= 0 ) {
+        LOG.error("Warning [RecentImports]: No import factory with name '"+facName+"' registered in Xulu-Registry");
+        continue;
+      }
+      // Source-Objekte einlesen
+      String[] impSourceName = config.getMultiProperty(KEY_PREFIX + i + KEY_SOURCE);
+      if ( impSourceName.length <= 0 ) {
+        LOG.error("Warning [RecentImports]: No source objects found in Xulu properties for recent import "+i);
+        continue;
+      }
+
+      // Import-Quellen erstellen (ES WIRD ANGENOMMEN, DASS ES SICH BEI
+      // DEN QUELL-OBJEKTEN UM DATEIEN HANDELT!!)
+      Object impSource = null;
+      if ( Object[].class.isAssignableFrom( impFac[0].getImportSourceType() ) ) {
+        impSource = new File[ impSourceName.length ];
+        for (int j=0; j<impSourceName.length; j++)
+          ((File[])impSource)[j] = new File(impSourceName[j]);
+      } else
+        impSource =  new File(impSourceName[0]);
+
+      // Import-Definition erstellen
+      add( new IODefinition.ImportDefinition(impSource,impFac[0],appl.getRegistry()) );
+    }
+  }
+
+  /**
+   * Speichert die Liste der zuletzt vorgenommenen Import-Operationen in den
+   * Xulu-Properties.
+   * @param appl Xulu-Instanz
+   * @see XuluConfig
+   */
+  public void storeToXuluProperties(XuluModellingPlatform appl) {
+    XuluConfig config = XuluConfig.getXuluConfig();
+    config.removeAll(KEY_PREFIX);
+    // MaxLoad-Wert speichern
+    config.setProperty(KEY_MAXLOAD,String.valueOf(getMaxLoad()));
+    // Anzahl an Elementen speichern
+    config.setProperty(KEY_SIZE,String.valueOf(size()));
+    // Import-Definitionan speichern
+    for (int i=0; i<size(); i++) {
+      IODefinition.ImportDefinition impDef = elementAt(i);
+      // Name der Factory
+      String facName = impDef.getFactory().getName();
+      // Quell-Objekte in String konvertieren (ES WIRD ANGENOMMEN, DASS ES
+      // SICH BEI DEN QUELL-OBJEKTEN UM DATEIEN HANDELT!!)
+      Object   impSource = impDef.getIOObject();
+      String[] impSourceName = null;
+      if ( impSource instanceof File )
+        impSourceName = new String[] { ((File)impSource).getAbsolutePath() };
+      else if ( impSource instanceof File[] ) {
+        impSourceName = new String[ ((File[])impSource).length ];
+        for (int j=0; j<impSourceName.length; j++)
+          impSourceName[j] = ((File[])impSource)[j].getAbsolutePath();
+      } else {
+        LOG.error("Warning [RecentImports]: Can not store recent import "+i+" in Xulu properties (import source is no file)");
+        continue;
+      }
+      // Import-Definition speichern
+      config.setProperty(KEY_PREFIX + i + KEY_FACTORY, facName);
+      config.setMultiProperty(KEY_PREFIX + i + KEY_SOURCE, impSourceName);
+    }
+  }
+}

Added: trunk/src/edu/bonn/xulu/appl/RecentScripts.java
===================================================================
--- trunk/src/edu/bonn/xulu/appl/RecentScripts.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/RecentScripts.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,126 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.appl;
+
+import java.io.File;
+import org.apache.log4j.Logger;
+
+import appl.ext.XuluConfig;
+import schmitzm.lang.LimitedVector;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.io.IODefinition;
+import edu.bonn.xulu.appl.ScriptInterpreter;
+
+
+/**
+ * Diese Klasse stellt eine Liste der letzten in Xulu ausgefuehrten Skripte
+ * dar.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class RecentScripts extends LimitedVector<ScriptInterpreter.ScriptExecutionDefinition> {
+  private final Logger LOG = Logger.getLogger(this.getClass().getName());
+
+  private static final String KEY_PREFIX  = "RecentScripts.";
+  private static final String KEY_MAXLOAD = KEY_PREFIX + "MAXLOAD";
+  private static final String KEY_SIZE = KEY_PREFIX + "SIZE";
+  private static final String KEY_FACTORY = ".FACTORY";
+  private static final String KEY_SOURCE  = ".SOURCE";
+
+  /**
+   * Erzeugt eine neue leere Liste, in der letzten Skripte abgelegt werden.
+   * @param maxLoad maximale Groesse der Liste
+   */
+  public RecentScripts(int maxLoad) {
+    super(maxLoad);
+  }
+
+  /**
+   * Laed die Liste der zuletzt ausgefuehrten Skripte aus den
+   * Xulu-Properties.
+   * @param appl Xulu-Instanz
+   * @see XuluConfig
+   */
+  public void loadFromXuluProperties(XuluModellingPlatform appl) {
+    XuluConfig config = XuluConfig.getXuluConfig();
+    // MaxLoad-Wert einlesen
+    int maxLoad = config.getIntProperty(KEY_MAXLOAD);
+    if (maxLoad <= 0) {
+      maxLoad = 10;
+      config.setIntProperty(KEY_MAXLOAD,maxLoad);
+    }
+    clear();
+    setMaxLoad(maxLoad);
+
+    // Anzahl an Elementen einlesen
+    int size = config.getIntProperty(KEY_SIZE);
+    if (size <= 0)
+      config.setIntProperty(KEY_SIZE,0);
+
+    // Skript-Definitionan einlesen
+    for (int i=0; i<size; i++) {
+      // Name des Skript-Interpreter ermitteln
+      String interpreterName = config.getProperty(KEY_PREFIX + i + KEY_FACTORY);
+      ScriptInterpreter[] interpreter = appl.getRegistry().getScriptInterpreter(interpreterName);
+      if ( interpreter.length <= 0 ) {
+        LOG.error("Warning [RecentScripts]: No script interpreter with name '"+interpreterName+"' registered in Xulu-Registry");
+        continue;
+      }
+      // Quell-Datei ermitteln
+      String scriptSourceName = config.getProperty(KEY_PREFIX + i + KEY_SOURCE);
+      if ( scriptSourceName == null ) {
+        LOG.error("Warning [RecentScripts]: No source file found in Xulu properties for recent import "+i);
+        continue;
+      }
+
+      // Skript-Quellen erstellen (ES WIRD ANGENOMMEN, DASS ES SICH BEI
+      // DEN SKRIPT-OBJEKTEN UM DATEIEN HANDELT!!)
+      File scriptSource = new File(scriptSourceName);
+
+      // Skript-Definition erstellen
+      add( new ScriptInterpreter.ScriptFileExecutionDefinition(scriptSource,interpreter[0]) );
+    }
+  }
+
+  /**
+   * Speichert die Liste der zuletzt ausgefuehrten Skripte in den
+   * Xulu-Properties.
+   * @param appl Xulu-Instanz
+   * @see XuluConfig
+   */
+  public void storeToXuluProperties(XuluModellingPlatform appl) {
+    XuluConfig config = XuluConfig.getXuluConfig();
+    config.removeAll(KEY_PREFIX);
+    // MaxLoad-Wert speichern
+    config.setProperty(KEY_MAXLOAD,String.valueOf(getMaxLoad()));
+    // Anzahl an Elementen speichern
+    config.setProperty(KEY_SIZE,String.valueOf(size()));
+    // Skript-Definitionan speichern
+    for (int i=0; i<size(); i++) {
+      ScriptInterpreter.ScriptExecutionDefinition scriptDef = elementAt(i);
+      // Name des Skript-Interpreters
+      String interpreterName = scriptDef.getScriptInterpreter().getName();
+      // Skript-Quelle speichern (ES WIRD ANGENOMMEN, DASS ES SICH BEI
+      // DER SKRIPT-QUELLE UM EINE DATEI HANDELT!!)
+      String scriptSourceName = null;
+      if ( scriptDef instanceof ScriptInterpreter.ScriptFileExecutionDefinition )
+        scriptSourceName = ((ScriptInterpreter.ScriptFileExecutionDefinition)scriptDef).getScriptSource().getAbsolutePath();
+      else {
+        LOG.error("Warning [RecentImports]: Can not store recent import "+i+" in Xulu properties (import source is no file)");
+        continue;
+      }
+      // SkriptDefinition speichern
+      config.setProperty(KEY_PREFIX + i + KEY_FACTORY, interpreterName);
+      config.setProperty(KEY_PREFIX + i + KEY_SOURCE, scriptSourceName);
+    }
+  }
+}

Added: trunk/src/edu/bonn/xulu/appl/ScriptInterpreter.java
===================================================================
--- trunk/src/edu/bonn/xulu/appl/ScriptInterpreter.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/ScriptInterpreter.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,156 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.appl;
+
+import java.io.InputStream;
+import java.io.File;
+import java.io.FileInputStream;
+
+import schmitzm.lang.NamedObject;
+import schmitzm.lang.AbstractNamedObject;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.io.IODefinition;
+
+/**
+ * Ein <code>ScriptInterpreter</code> fuehrt eine Reihe von Befehlen
+ * in einer Xulu-Umgebung aus. Die Befehle erhaelt er ueber einen Eingabe-Stream.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public interface ScriptInterpreter extends NamedObject {
+  /**
+   * Fuehrt ein Script aus.
+   * @param in   Eingabe-Stream in dem das Skript zu finden ist.
+   * @param appl Applikation, in der das Skript auszufuehren ist
+   * @exception java.lang.Exception wenn ein Fehler bei der Ausfuehrung aufritt
+   */
+  public void execute(InputStream in, XuluModellingPlatform appl) throws Exception;
+
+  ///////////////////////////////////////////////////////////////////
+  ////////////////   Script-Ausfuehungs-Definition   ////////////////
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse stellt die Definition einer Script-Ausfuehrung dar.
+   * Die besteht aus einem {@link ScriptInterpreter} und einem Quell-Objekt
+   * aus dem der {@link ScriptInterpreter} das Script einliest.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static abstract class ScriptExecutionDefinition extends AbstractNamedObject {
+    /** Speichert das Quell-Objekt, aus dem das Script gelesen wird. */
+    protected Object source = null;
+    /** Speichert den {@link ScriptInterpreter}, der das Objekt einliest. */
+    protected ScriptInterpreter interpreter = null;
+
+    /**
+     * Erzeugt eine neue Import-Definition.
+     * @param source      Objekt aus dem das Script eingelesen wird; z.B. eine Datei
+     * @param interpreter {@link ScriptInterpreter} der das Script einliest
+     */
+    public ScriptExecutionDefinition(Object source, ScriptInterpreter interpreter) {
+      if ( source == null )
+        throw new IllegalArgumentException("null-source not allowed!");
+      if ( interpreter == null )
+        throw new IllegalArgumentException("null-interpreter not allowed!");
+      this.source = source;
+      this.interpreter = interpreter;
+      setName( toString() );
+    }
+
+    /**
+     * Liefert den Script-Interpreter, die das Script einliest.
+     */
+    public ScriptInterpreter getScriptInterpreter() {
+      return interpreter;
+    }
+
+    /**
+     * Liefert den Quell-Objekt, aus dem das Script eingelesen wird.
+     */
+    public Object getScriptSource() {
+      return source;
+    }
+
+    /**
+     * Liefert einen Stream zum Quell-Objekt.
+     */
+    public abstract InputStream getSourceAsStream() throws Exception;
+
+
+    /**
+     * Fuehrt das durch die {@code ScriptDefinition} definitierten Script
+     * aus.
+     * @param appl Xulu-Instanz unter der das Script ausgefuehrt wird.
+     * @throws Exception
+     */
+    public void execute(XuluModellingPlatform appl) throws Exception {
+      getScriptInterpreter().execute( getSourceAsStream(),appl );
+    }
+
+    /**
+     * Vergleicht die {@code ScriptExecutionDefinition} mit einer anderen.
+     * Beide sind gleich, gdw. beide den gleichen {@link ScriptInterpreter}
+     * und die gleiche Script-Quelle enthalten.
+     * @param o andere {@code IODefinition}
+     */
+    public boolean equals(Object o) {
+      return o != null &&
+             o instanceof ScriptExecutionDefinition &&
+             ((ScriptExecutionDefinition)o).getScriptInterpreter().equals( getScriptInterpreter() ) &&
+             ((ScriptExecutionDefinition)o).getScriptSource().equals( getScriptSource() );
+    }
+  }
+
+  /**
+   * Diese Klasse stellt die Definition einer Script-Ausfuehrung dar.
+   * Die besteht aus einem {@link ScriptInterpreter} und einer Quell-Datei
+   * aus der der {@link ScriptInterpreter} das Script einliest.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class ScriptFileExecutionDefinition extends ScriptExecutionDefinition {
+    /**
+     * Erzeugt eine neue Import-Definition.
+     * @param sourceFile  Datei aus der das Script eingelesen wird
+     * @param interpreter {@link ScriptInterpreter} der das Script einliest
+     */
+    public ScriptFileExecutionDefinition(File sourceFile, ScriptInterpreter interpreter) {
+      super(sourceFile,interpreter);
+      this.setName(sourceFile.getAbsolutePath());
+    }
+
+    /**
+     * Liefert die Quell-Datei, aus der das Script eingelesen wird.
+     */
+    public File getScriptSource() {
+      return (File)source;
+    }
+
+    /**
+     * Setzt das Xulu-Arbeitsverzeichnis auf das der Script-Datei und fuehrt
+     * das Skript aus.
+     * @param appl Xulu-Instanz unter der das Script ausgefuehrt wird.
+     */
+    public void execute(XuluModellingPlatform appl) throws Exception {
+      appl.setWorkingDirectory( getScriptSource().getParentFile() );
+      super.execute(appl);
+    }
+
+    /**
+     * Liefert einen {@link FileInputStream} zur Quell-Datei.
+     */
+    public FileInputStream getSourceAsStream() throws Exception {
+      return new FileInputStream( getScriptSource() );
+    }
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/appl/ScriptablePlugin.java
===================================================================
--- trunk/src/edu/bonn/xulu/appl/ScriptablePlugin.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/ScriptablePlugin.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,37 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.appl;
+
+import java.util.Vector;
+
+import schmitzm.lang.NamedObject;
+import edu.bonn.xulu.XuluModellingPlatform;
+
+/**
+ * This class extends the XuluPlugin interface in order to support easy
+ * scripting operations on plugins. The commands may be forwarded by the {@link edu.bonn.xulu.plugin.appl.DataScriptInterpreter_Basic}.
+ * 
+ * @see XuluPlugin
+ * 
+ * @author Dominik Appl
+ */
+public interface ScriptablePlugin extends XuluPlugin {
+
+    /**
+     * Executes scripting commands in XuluPlugins.
+     * 
+     * @param commandLines Each String in the array represents one commandLine
+     * 
+     * @exception UnsupportedOperationException will be thrown if there is an error.
+     */
+    public void executeScript(String[] commandLines) throws UnsupportedOperationException;
+}

Added: trunk/src/edu/bonn/xulu/appl/VisualisationManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/appl/VisualisationManager.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/VisualisationManager.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,66 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.appl;
+
+import java.util.Vector;
+
+import edu.bonn.xulu.appl.VisualisationTool;
+import edu.bonn.xulu.appl.AbstractManager;
+
+// nur fuer Doku
+import schmitzm.data.event.ObjectListener;
+import schmitzm.data.event.AbstractObjectTraceable;
+
+/**
+ * Der VisualisationManager verwaltet saemtliche in der Xulu-Applikation
+ * <u>instanziierten</u> Visualisierungstools. An dieser Stelle ist der
+ * Unterschied zu den in der Xulu-Registry registierten Tools zu bemerken.
+ * Waehrend in der Registry nur die Klassen der Visualisierungstools
+ * hinterlegt werden, verwaltet der VisualisationManager deren Instanzen
+ * (also die einzelenen Fenster).<br>
+ * Der VisualisationManager fungiert als <code>AbstractObjectTraceable</code>,
+ * so dass {@link ObjectListener} angeschlossen werden
+ * koennen, welche automatisch durch ein {@link AbstractManager.ChangeEvent}
+ * informiert werden, wenn sich der Inhalt des VisualisationManagers aendert.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class VisualisationManager extends AbstractManager {
+
+  /**
+   * Erzeugt einen neuen (leeren) Visualisierungsmanager.
+   */
+  public VisualisationManager() {
+    this.content = new Vector<VisualisationTool>();
+  }
+
+  /**
+   * Prueft, ob eine Komponente im Visualisierungsmanager verwaltet werden
+   * kann.
+   * @param comp Komponente
+   * @exception UnsupportedOperationException falls es sich bei der Komponente
+   *            nicht um eine Instanz von {@link VisualisationTool} handelt
+   */
+  public void checkComponentAndError(ContentType comp) {
+    if ( !(comp instanceof VisualisationTool) )
+      throw new UnsupportedOperationException(getClass().getSimpleName().concat(" can not manage instances of ").concat(comp.getClass().getName()));
+  }
+
+  /**
+   * Liefert alle registrierte Visualisierungstool-Instanzen als Array.
+   * @return leerer <code>VisualisationTool[]</code>-Array falls keine Instanzen
+   *         im Manager registriert sind.
+   */
+  public VisualisationTool[] getAll() {
+    return (VisualisationTool[])content.toArray(new VisualisationTool[0]);
+  }
+}

Added: trunk/src/edu/bonn/xulu/appl/VisualisationTool.java
===================================================================
--- trunk/src/edu/bonn/xulu/appl/VisualisationTool.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/VisualisationTool.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,94 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.appl;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.VisualisationUpdateListener;
+
+/**
+ * Dieses Interface bildet die Grundlage fuer verschiedenste Visualisierungstools.
+ * <b>Wichtig:</b><br>
+ * Damit eine Implementierung dieser Klasse in der Xulu-Modelling-Platform
+ * verwendet werden kann, <u>muss</u> sie einen Standard-Konstruktor
+ * implementieren!!
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public interface VisualisationTool extends AbstractManager.ContentType {
+  /**
+   * Initialisiert das Visualisierungstools. Sollte nur einmal und unmittelbar
+   * nach der Instanziierung aufgerufen werden.
+   * @param appl Xulu-Instanz fuer die das Visualisierungstool erzeugt wurde 
+   */
+  public void initialize(XuluModellingPlatform appl);
+
+  /**
+   * Zeigt oder verbirgt das Fenster des Visualisierungstools.
+   */
+  public void setVisible(boolean visible);
+
+  /**
+   * Prueft, ob das Fenster des Visualisierungstools aktuell angezeigt wird.
+   */
+  public boolean isVisible();
+
+  /**
+   * Prueft, ob ein Objekt durch das Tool visualisiert werden kann.
+   */
+  public boolean isVisualisable(Object obj);
+
+  /**
+   * Prueft, ob Instanzen einer Klasse durch das Tool visualisiert werden kann.
+   */
+  public boolean isVisualisable(Class c);
+
+  /**
+   * Visualisiert ein Objekt. Beinhaltet das Visualisierungstool mehrere Fenster,
+   * so muss es ueber einen Anwender-Dialog selbst erfragen, in welchem
+   * Fenster/Layer das Objekt dargestellt werden soll.
+   * @param obj  darzustellendes Objekt
+   * @param desc Erlaeuterung, die im Vis.Tool zu dem Objekt angezeigt werden kann
+   * @return <code>false</code>, falls das Objekt nicht dargestellt werden kann
+   */
+  public boolean add(Object obj, String desc);
+
+  /**
+   * Entfernt die Visualisierung eines Objekts.
+   * @param obj  zu entfernendes Objekt
+   * @return <code>false</code>, falls das Objekt nicht entfernt werden kann, z.B.
+   *         weil es nicht (mehr) dargestellt wird.
+   */
+  public boolean remove(Object obj);
+
+  /**
+   * Aktualisiert die Visualisierung eins Objekts.
+   * @param obj  zu aktualisierendes Objekt
+   * @return <code>false</code>, falls das Objekt nicht aktualisiert werden kann, z.B.
+   *         weil es nicht (mehr) dargestellt wird.
+   */
+  public boolean update(Object obj);
+
+  /**
+   * Schliesst das Visualisierungstool und alle darin enthaltenen Fenster/Layer.
+   */
+  public void close();
+
+  /**
+   * Liefert eine Beschreibung fuer die Instanz des Visualisierungstools.
+   */
+  public String getTitle();
+
+  /**
+   * Liefert eine Beschreibung fuer die Instanz des Visualisierungstools.
+   */
+  public void setTitle(String desc);
+}

Added: trunk/src/edu/bonn/xulu/appl/VisualisationUpdateListener.java
===================================================================
--- trunk/src/edu/bonn/xulu/appl/VisualisationUpdateListener.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/VisualisationUpdateListener.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,108 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.appl;
+
+import schmitzm.data.event.ObjectListener;
+import schmitzm.data.event.ObjectEvent;
+import schmitzm.data.event.ObjectChangeEvent;
+import schmitzm.data.event.ObjectCloseEvent;
+
+import edu.bonn.xulu.appl.VisualisationTool;
+
+/**
+ * Zwischen Xulu-Datenobjekt ("source") und visualisiertem Objekt ("visObject")
+ * besteht in der Regel ein Unterschied, da das Datenobjekt meist nicht direkt
+ * dargestellt werden kann. Es wird ein eigenes Objekt für die Visualisierung
+ * erstellt. Diese Klasse stellt hierfuer die Schnittstelle zwischen dem
+ * allgemeinem Objekt und dessen Visualisierungsobjekt dar.<br>
+ * Während ein Visualisierungstool fuer die Darstellung von vielen Objekten
+ * verantwortlich ist, besteht eine 1:1-Beziehung zwischen einem Objekt und
+ * einem <code>VisualisationUpdateListener</code>. M.a.W.: Ein Visualisierungstool
+ * (PlugIn) muss für jedes dargestellte Objekt einen <code>VisualisationUpdateListener</code>
+ * verwalten. U.U. können einem Objekt aber auch mehrere VisualisationUpdateListener
+ * zugeordnet werden.<br>
+ * Der <code>VisualisationUpdateListener</code> ist stark Tool-abhaengig und
+ * sollte als innere Klasse des jeweiligen Visualisierungstools implementiert werden.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class VisualisationUpdateListener {//implements ObjectListener {
+  /** Speichert das Visualisierungstool, in dem das Objekt dargestellt wird. */
+  protected VisualisationTool visTool = null;
+  /** Speichert das darzustellende Objekt */
+  protected Object visObject = null;
+
+//  /** Speichert, ob die automatische Aktualisierung (wenn ein Objekt sich
+//   *  aendert) aktiviert ist. Default: <code>true</code> **/
+//  private   boolean autoRefresh = false;
+
+  /**
+   * Erzeugt einen neuen Listener.
+   * @param tool Visualisierungstool, an den der Listener angeschlossen ist
+   * @param obj  Objekt, welches durch diesen Listener dargestellt wird
+   */
+  public VisualisationUpdateListener(VisualisationTool tool, Object obj) {
+    this.visTool   = tool;
+    this.visObject = obj;
+  }
+
+//  /**
+//   * Verarbeitet ein <code>ObjectEvent</code>. Handelt es sich um ein
+//   * {@link schmitzm.data.event.ObjectChangeEvent}, wird bei aktiviertem
+//   * AutoRefresh ein {@link #refresh()} aufgerufen.<br>
+//   * Bei einem {@link schmitzm.data.event.ObjectCloseEvent}
+//   * wird immer {@link #close()} initiiert.
+//   */
+//  public void performObjectEvent(ObjectEvent e) {
+//    if ( autoRefreshEnabled() && e instanceof ObjectChangeEvent && e.getSource().contains( getSourceObject() ) )
+//      refresh();
+//    if ( e instanceof ObjectCloseEvent )
+//      close();
+//  }
+
+  /**
+   * Liefert das Objekt, das durch diesen <code>VisualisationUpdateListener</code>
+   * visualisiert wird.
+   */
+  public Object getSourceObject() {
+    return this.visObject;
+  }
+
+//  /**
+//   * Setzt den Modus fuer die automatische Aktualisierung der Visualisierung.
+//   * Ist diese aktiviert erfolgt bei einem {@link schmitzm.data.event.ObjectChangeEvent}
+//   * automatisch ein {@link #refresh()}. Standardmaessig ist sie deaktiviert!
+//   */
+//  public void setAutoRefresh(boolean autoRefresh) {
+//    this.autoRefresh = autoRefresh;
+//  }
+//
+//  /**
+//   * Prueft, ob die automatische Aktualisierung der Visualisierung aktiviert ist.
+//   * @see #setAutoRefresh(boolean)
+//   */
+//  public boolean autoRefreshEnabled() {
+//    return autoRefresh;
+//  }
+
+  /**
+   * Aktualisiert die Darstellung des Objekts.
+   */
+  public abstract void refresh();
+
+  /**
+   * Schliesst den VisualisationUpdateListener und entfernt die Darstellung
+   * aus dem Visualisierungstool.
+   */
+  public abstract void close();
+
+}

Added: trunk/src/edu/bonn/xulu/appl/XuluComponent.java
===================================================================
--- trunk/src/edu/bonn/xulu/appl/XuluComponent.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/XuluComponent.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,30 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.appl;
+
+/**
+ * Dieses Interface sollten alle Haupt-Komponenten implementieren, die in die
+ * Xulu-Applikation eingebettet werden.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public interface XuluComponent extends XuluConstants {
+  /**
+   * Zerstoert die Komponente.
+   */
+  public void dispose();
+
+  /**
+   * Prueft, ob die Komponente zerstoert ist.
+   */
+  public boolean isDisposed();
+}

Added: trunk/src/edu/bonn/xulu/appl/XuluComponentUtil.java
===================================================================
--- trunk/src/edu/bonn/xulu/appl/XuluComponentUtil.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/XuluComponentUtil.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,29 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.appl;
+
+/**
+ * Diese Klasse stellt allgemeine Hilftsmethoden fuer Xulu-Komponenten zur
+ * Verfuegung.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class XuluComponentUtil {
+  /**
+   * Prueft, ob eine Xulu-Komponente zerstoert ist.
+   * @exception RuntimeException falls die Komponente zerstoert ist
+   */
+  public static void checkDisposed(XuluComponent comp) {
+    if ( comp.isDisposed() )
+      throw new RuntimeException("This instance of "+comp.getClass().getSimpleName()+" is disposed");
+  }
+}

Added: trunk/src/edu/bonn/xulu/appl/XuluConstants.java
===================================================================
--- trunk/src/edu/bonn/xulu/appl/XuluConstants.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/XuluConstants.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,71 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.appl;
+
+import java.io.File;
+import javax.swing.ImageIcon;
+import java.util.Locale;
+
+import schmitzm.lang.ResourceProvider;
+import schmitzm.swing.SwingUtil;
+import edu.bonn.xulu.XuluModellingPlatform;
+
+// nur fuer Doku
+
+/**
+ * Dieses Interface enthaelt Kostanten fuer die Xulu-Modelling-Platform.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public interface XuluConstants {
+  /** Versionsnummer der Xulu-Modelling-Platform. **/
+  public static final String VERSION = "1.7.7";
+  /** Versionsdatum der Xulu-Modelling-Platform. **/
+  public static final String VERSION_DATE = "2008-07-03";
+  /** Verzeichnis, in dem Icons und Uebersetzungen hinterlegt sind. */
+  public static final String RESOURCE_DIR = "resource";
+  /** Verzeichnis, in dem Icons hinterlegt sind. */
+  public static final String ICONS_DIR = RESOURCE_DIR+File.separatorChar+"icons";
+  /** Icon, das fuer Xulu-Fenster verwendet wird. */
+  public static final ImageIcon XULU_ICON      = new ImageIcon(ICONS_DIR+File.separatorChar+"xulu_icon.png");
+  /** Xulu-Logo, das auf dem Start-Fenster angezeigt wird. */
+  public static final ImageIcon XULU_INFOICON  = new ImageIcon(ICONS_DIR+File.separatorChar+"xulu_info.png");
+  /** Xulu-Logo, das auf dem Info-Fenster angezeigt wird. */
+  public static final ImageIcon XULU_STARTICON = new ImageIcon(ICONS_DIR+File.separatorChar+"xulu_start.png");
+
+  /** Enthaelt eine Referenz auf die Standard-Swing-Ressourcen des Package
+   *  {@code schmitzm.swing}.
+   *  @see SwingUtil#RESOURCE */
+  public static final ResourceProvider SWING_RES = SwingUtil.RESOURCE;
+
+  /** Enthaelt den Basis-Pfad (in Punkt-Notation, basierend auf dem Classpath)
+   *  der Xulu-spezifischen Ressourcen.<br>
+   *  Konstant: {@code locales} (Verzeichnis unterhalb von {@code <xulu_main>/resource)}*/
+  public static final String LOCALES_BASE = "locales";
+
+  /** Pfad (in Punkt-Notation), auf den die Bundles aus Standard-Paketen umgelenkt
+   *  werden. Konstant: {@code locales.StandardBundleExtension}
+   *  @see #LOCALES_BASE */
+  public static final String EXTENTION_BUNDLE = XuluConstants.LOCALES_BASE+".StandardBundleExtension";
+
+  /** Enthaelt eine Referenz auf die Xulu-spezifischen Ressourcen fuer
+   *  die Haupt-Applikation. */
+  public static final ResourceProvider XULUGUI_RES = XuluModellingPlatform.registerResourceProvider("XuluMainAppl",Locale.ENGLISH);
+
+  /** Enthaelt eine Referenz auf die Xulu-spezifischen Ressourcen fuer
+   *  die Fehlermeldungen in der Haupt-Applikation. */
+  public static final ResourceProvider XULUERR_RES = XuluModellingPlatform.registerResourceProvider("XuluMainError",Locale.ENGLISH);
+
+  /** Enthaelt eine Referenz auf die Xulu-spezifischen Ressourcen fuer
+   *  die Visualisierungs-Plugins. */
+  public static final ResourceProvider XULU_VIS_RES = XuluModellingPlatform.registerResourceProvider("XuluVisualisationTool",Locale.ENGLISH);
+}

Added: trunk/src/edu/bonn/xulu/appl/XuluPlugin.java
===================================================================
--- trunk/src/edu/bonn/xulu/appl/XuluPlugin.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/XuluPlugin.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,51 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.appl;
+
+import schmitzm.lang.NamedObject;
+import edu.bonn.xulu.XuluModellingPlatform;
+
+/**
+ * Diese Klasse stellt die Schnittstelle zu Xulu-Plugins dar. Implementierungen
+ * muessen einen <b>parameterlosen Konstruktor</b> implementieren, damit das Plugin
+ * in der Xulu-Applikation verwendet werden kann!!
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public interface XuluPlugin extends NamedObject {
+
+  /**
+   * Startet die Ausfuehrung des Plugins.
+   * @param appl Instanz der Xulu-Applikation
+   */
+  public void execute(XuluModellingPlatform appl);
+
+  /**
+   * Stoppt die Ausfuehrung des Plugins.
+   */
+  public void stop();
+
+  /**
+   * Prueft, ob das Plugin gestartet ist.
+   */
+  public boolean isStarted();
+
+  /**
+   * Zeigt die GUI zur Plugin-Konfiguration an oder verbirgt sie.
+   */
+  public void setVisible(boolean visible);
+
+  /**
+   * Prueft, ob die GUI zur Plugin-Konfiguration angezeigt wird.
+   */
+  public boolean isVisible();
+}

Added: trunk/src/edu/bonn/xulu/appl/XuluRegistry.java
===================================================================
--- trunk/src/edu/bonn/xulu/appl/XuluRegistry.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/XuluRegistry.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,948 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.appl;
+
+import java.util.Vector;
+import java.util.Hashtable;
+
+import schmitzm.lang.NamedObject;
+import schmitzm.lang.LimitedVector;
+import schmitzm.data.event.AbstractObjectTraceable;
+import schmitzm.data.event.ObjectListener;
+import schmitzm.data.event.ObjectEvent;
+import schmitzm.data.event.ObjectChangeEvent;
+import schmitzm.data.event.Invoker;
+import edu.bonn.xulu.io.IODefinition;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.io.TypeMapping;
+import edu.bonn.xulu.appl.ScriptInterpreter;
+import edu.bonn.xulu.appl.VisualisationTool;
+import edu.bonn.xulu.appl.XuluPlugin;
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.model.XuluModel;
+
+
+/**
+ * In der Xulu-Registry werden alle dynamischen Komponenten registriert,
+ * die in der Xulu-Applikation verwendet werden sollen. Hierzu zaehlen
+ * <ul>
+ * <li><b><u>Datentypen</u></b><br>
+ *     alle Datentyp die im Xulu-Datenpool verwaltet werden koennen
+ *     (Subklassen von {@link XuluObject})</li>
+ * <li><b><u>DefaultFactorys</u></b><br>
+ *     alle Factorys, die Standard-Instanzen der Datentypen erzeugen</li>
+ * <li><b><u>ImportFactorys</u></b><br>
+ *     alle Factorys, die Instanzen der Datentypen importieren</li>
+ * <li><b><u>ExportFactorys</u></b><br>
+ *     alle Factorys, die Instanzen der Datentypen exportieren</li>
+ * <li><b><u>TypeMappings</u></b><br>
+ *     Zuordnungen, welche welche Factorys fuer einen Datentyp zustaendig sind</li>
+ * <li><b><u>Visualisierungstools</u></b><br>
+ *     alle Tools die Xulu-Daten visualisieren koennen
+ *     (Subklassen von {@link VisualisationTool})</li>
+ * <li><b><u>Modell-Klassen</u></b><br>
+ *     alle Modelle die im Xulu-Daten visualisieren koennen
+ *     (Subklassen von {@link XuluModel})</li>
+ * <li><b><u>Skript-Interpreter</u></b><br>
+ *     alle Klassen die in der Xulu-Anwendung Skripte interpretieren koennen
+ *     (Subklassen von {@link ScriptInterpreter})</li>
+ * <li><b><u>Plugins</u></b><br>
+ *     alle Klassen die in der Xulu-Anwendung als Plugin ausgefuehrt werden
+ *     (Subklassen von {@link XuluPlugin})</li>
+ * </ul>
+ * Daneben bietet die Registry {@linkplain LimitedVector Listen}, in denen
+ * die letzten Daten-Importe, Daten-Exporte und Script-Ausfuehrungen
+ * hinterlegt sind.<br>
+ * <br>
+ * Die Registry fungiert als <code>AbstractObjectTraceable</code>, so dass
+ * {@link ObjectListener} angeschlossen werden koennen, welche automatisch
+ * durch ein {@link XuluRegistry.ChangeEvent} informiert werden, wenn sich der
+ * Inhalt der Registry aendert.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class XuluRegistry extends AbstractObjectTraceable implements XuluComponent {
+  private final XuluRegistry  THIS = this;
+
+  private Vector    dataTypes         = new Vector<Class>();
+  private Vector    defaultFac        = new Vector<InstantiationFactory>();
+  private Vector    importFac         = new Vector<ImportFactory>();
+  private Vector    exportFac         = new Vector<ExportFactory>();
+  private Hashtable typeMappings      = new Hashtable<Class,TypeMapping>();
+  private Vector    visTools          = new Vector<Class>();
+  private Vector    modelClasses      = new Vector<Class>();
+  private Vector    scriptInterpreter = new Vector<ScriptInterpreter>();
+  private Vector    xuluPlugins       = new Vector<XuluPlugin>();
+  private Vector    autostartPlugins  = new Vector<XuluPlugin>();
+  private boolean   disposed          = false;
+
+  // History der Importe, Skripte, ...
+  private RecentImports recentImports = new RecentImports(10);
+  private RecentScripts recentScripts = new RecentScripts(10);
+
+  // Proxy-Listener, der die Ereignisse der recentImports, recentExports, ...
+  // an die der Registry angeschlossenen Listener weiterleitet
+  private ObjectListener listenerProxy = new ObjectListener() {
+    public void performObjectEvent(ObjectEvent e) {
+      e.expandSource(THIS);
+      fireEvent( e );
+    }
+  };
+
+  /**
+   * Erzeugt eine neue (leere) Registry.
+   */
+  public XuluRegistry() {
+    recentImports.addObjectListener( listenerProxy );
+    recentImports.setDuplicatedAllowed(false);
+    recentScripts.addObjectListener( listenerProxy );
+    recentScripts.setDuplicatedAllowed(false);
+  }
+
+  /**
+   * Zerstoert den Manager und alle darin enthaltenen Komponenten.
+   */
+  public void dispose() {
+    XuluComponentUtil.checkDisposed(this);
+    dataTypes.removeAllElements();
+    defaultFac.removeAllElements();
+    importFac.removeAllElements();
+    exportFac.removeAllElements();
+    typeMappings.clear();
+    visTools.removeAllElements();
+    modelClasses.removeAllElements();
+    scriptInterpreter.removeAllElements();
+    xuluPlugins.removeAllElements();
+    disposed = true;
+  }
+
+  /**
+   * Prueft, ob der Manager zerstoert ist.
+   * @see #dispose()
+   */
+  public boolean isDisposed() {
+    return disposed;
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Allgemeine Methoden
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Ueberschreibt {@link AbstractObjectTraceable#createGeneralEvent()}, damit
+   * ein {@link XuluRegistry.ChangeEvent XuluRegistry.ChangeEvent} zurueckgegeben wird.
+   */
+  protected ChangeEvent createGeneralEvent() {
+    return new ChangeEvent(this,null,null);
+  }
+
+  /**
+   * Fuegt ein Object in einen Vector ein.
+   */
+  private boolean register(Object o, Vector vector) {
+    XuluComponentUtil.checkDisposed(this);
+    if (vector.contains(o))
+      return false;
+    boolean ret = vector.add(o);
+    this.fireEvent( new ChangeEvent(this,null,o) );
+    return ret;
+  }
+
+  /**
+   * Entfernt ein Object aus einem Vector.
+   * Ist das Objekt nicht im Vector vorhanden wird nichts gemacht und
+   * <code>false</code> zurueckgegeben.
+   */
+  private boolean unregister(Object o, Vector vector) {
+    XuluComponentUtil.checkDisposed(this);
+    if (!vector.contains(o))
+      return false;
+    boolean ret = vector.remove(o);
+    this.fireEvent( new ChangeEvent(this,o,null) );
+    return ret;
+  }
+
+  /**
+   * Ersetzt ein Object in einem Vector durch ein anderes.
+   * Ist das <code>o1</code> nicht im Vector vorhanden wird nichts gemacht und
+   * <code>false</code> zurueckgegeben.
+   */
+  private boolean replace(Object o1, Object o2, Vector vector) {
+    XuluComponentUtil.checkDisposed(this);
+    int idx = vector.indexOf(o1);
+    if ( idx < 0 )
+      return false;
+    vector.set(idx,o2);
+    this.fireEvent( new ChangeEvent(this,o1,o2) );
+    return true;
+  }
+
+  /**
+   * Prueft, ob ein Object in einem Vector enthalten ist.
+   */
+  private boolean contains(Object o, Vector vector) {
+    XuluComponentUtil.checkDisposed(this);
+    return vector.contains(o);
+  }
+
+  /**
+   * Prueft, ob diese angegebene Klasse zulaessig ist.
+   */
+  private void checkClass(Class c) {
+    if ( c == null )
+      throw new UnsupportedOperationException("null-Classes are not allowed!");
+  }
+
+  /**
+   * Registriert ein Objekt. Dieses wird (wenn moeglich) fuer alle
+   * folgenden Punkte registriert:
+   * <ul>
+   * <li><code>DefaultFactory</code></li>
+   * <li><code>ImportFactory</code></li>
+   * <li><code>ExportFactory</code></li>
+   * <li><code>TypeMapping</code></li>
+   * <li><code>VisualisationTool</code></li>
+   * <li><code>Skript-Interpreter</code></li>
+   * </ul>
+   * @param obj ein beliebiges Objekt
+   * @return <code>true</code> wenn mindestens eine neue Registrierung
+   *         erfolgt ist
+   */
+  public boolean register(Object obj) {
+    XuluComponentUtil.checkDisposed(this);
+
+    boolean ret = false;
+    if ( obj instanceof Class && XuluObject.class.isAssignableFrom((Class)obj) )
+      ret |= registerDataType((Class)obj);
+    if ( obj instanceof InstantiationFactory )
+      ret |= registerDefaultFactory((InstantiationFactory)obj);
+    if ( obj instanceof ImportFactory )
+      ret |= registerImportFactory((ImportFactory)obj);
+    if ( obj instanceof ExportFactory )
+      ret |= registerExportFactory((ExportFactory)obj);
+    if ( obj instanceof TypeMapping )
+      ret |= registerTypeMapping((TypeMapping)obj);
+    if ( obj instanceof Class && VisualisationTool.class.isAssignableFrom((Class)obj) )
+      ret |= registerVisualisationTool((Class)obj);
+    if ( obj instanceof ScriptInterpreter )
+      ret |= registerScriptInterpreter((ScriptInterpreter)obj);
+
+    return ret;
+  }
+
+  /**
+   * Liefert alle Objekte eines Arrays, die eine bestimmte Bezeichnung (oder
+   * Klassennamen) haben.
+   * @param source Eingabe-Array
+   * @param name Bezeichnung
+   * @param outArray Ausgabe-Array (kann ein leerer Array sein!)
+   */
+  private static NamedObject[] findObjectsByName(NamedObject[] source, String name, Object[] outArray) {
+    Vector out = new Vector();
+    for (int i=0; i<source.length; i++)
+      if ( source[i].getName().equals(name) ||
+           source[i].getClass().getName().equals(name) ||
+           source[i].getClass().getSimpleName().equals(name) )
+        out.add(source[i]);
+    return (NamedObject[])out.toArray(outArray);
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Datentypen
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob diese angegebene Klasse als Datentyp zulaessig ist.
+   */
+  private void checkTypeClass(Class c) {
+    checkClass(c);
+    if ( !XuluObject.class.isAssignableFrom( c ) )
+      throw new UnsupportedOperationException( "Only subclasses of ".concat(XuluObject.class.getName()).concat(" can be registered as data types!") );
+  }
+
+  /**
+   * Registriert einen Datentyp. Hierfuer koennen nur (Sub)Klassen von
+   * {@link edu.bonn.xulu.data.XuluObject} angegeben werden.
+   * @param type Datentyp
+   * @return <code>false</code> falls der Datentyp bereits registriert ist
+   * @exception java.lang.UnsupportedOperationException falls der angegebene
+   *            Typ nicht einem {@link edu.bonn.xulu.data.XuluObject}
+   *            entspricht
+   */
+  public boolean registerDataType(Class type) {
+    checkTypeClass(type);
+    return register(type,dataTypes);
+  }
+
+  /**
+   * Entfernt die Registrierung eines Datentyps.
+   * @param type Datentyp
+   * @return <code>false</code> falls der Datentyp nicht registriert war
+   */
+  public boolean unregisterDataType(Class type) {
+    return unregister(type,dataTypes);
+  }
+
+  /**
+   * Ersetzt die Registrierung eines Datentyps durch einen anderen.
+   * @param typeOld zu ersetzender Datentyp
+   * @param typeNew neuer Datentyp
+   * @return <code>false</code> falls <code>typeOld</code> nicht registriert war
+   *         und deshalb keine Ersetzung moeglich ist
+   * @exception java.lang.UnsupportedOperationException falls der neue
+   *            Typ nicht einem {@link edu.bonn.xulu.data.XuluObject}
+   *            entspricht
+   */
+  public boolean replaceDataType(Class typeOld, Class typeNew) {
+    checkTypeClass(typeNew);
+    return replace(typeOld,typeNew,dataTypes);
+  }
+
+  /**
+   * Prueft, ob ein Datentyp registriert ist.
+   */
+  public boolean isDataTypeRegistered(Class type) {
+    return contains(type,dataTypes);
+  }
+
+  /**
+   * Liefert alle registrierten Datentypen.
+   */
+  public Class[] getDataTypes() {
+    XuluComponentUtil.checkDisposed(this);
+    return (Class[])dataTypes.toArray(new Class[0]);
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Standard-Factories
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Registriert eine Standard-Factory.
+   * @param fac Factory
+   * @return <code>false</code> falls die Factory bereits registriert ist
+   */
+  public boolean registerDefaultFactory(InstantiationFactory fac) {
+    return register(fac,defaultFac);
+  }
+
+  /**
+   * Entfernt die Registrierung einer Standard-Factory.
+   * @param fac Factory
+   * @return <code>false</code> falls die Factory nicht registriert war
+   */
+  public boolean unregisterDefaultFactory(InstantiationFactory fac) {
+    return unregister(fac,defaultFac);
+  }
+
+  /**
+   * Ersetzt die Registrierung einer Standard-Factory durch eine andere.
+   * @param facOld zu ersetzende Factory
+   * @param facNew neue Factory
+   * @return <code>false</code> falls <code>facOld</code> nicht registriert war
+   *         und deshalb keine Ersetzung moeglich ist
+   */
+  public boolean replaceDefaultFactory(InstantiationFactory facOld, InstantiationFactory facNew) {
+    return replace(facOld,facNew,defaultFac);
+  }
+
+  /**
+   * Prueft, ob eine Standard-Factory registriert ist.
+   */
+  public boolean isDefaultFactoryRegistered(InstantiationFactory fac) {
+    return contains(fac,defaultFac);
+  }
+
+  /**
+   * Liefert alle registrierten Standard-Factorys.
+   */
+  public InstantiationFactory[] getDefaultFactories() {
+    XuluComponentUtil.checkDisposed(this);
+    return (InstantiationFactory[])defaultFac.toArray(new InstantiationFactory[0]);
+  }
+
+  /**
+   * Liefert alle Default-Factorys, die einen bestimmten Namen besitzen.
+   * @param name Bezeichnung der Factory
+   * @return ein leerer <code>DeafultFactory</code>-Array, falls zu der Bezeichnung
+   *         keine Factory registriert ist
+   */
+  public InstantiationFactory[] getDefaultFactories(String name) {
+    return (InstantiationFactory[])findObjectsByName(getDefaultFactories(),name,new InstantiationFactory[0]);
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Import-Factories
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Registriert eine Import-Factory.
+   * @param fac Factory
+   * @return <code>false</code> falls die Factory bereits registriert ist
+   */
+  public boolean registerImportFactory(ImportFactory fac) {
+    return register(fac,importFac);
+  }
+
+  /**
+   * Entfernt die Registrierung einer Import-Factory.
+   * @param fac Factory
+   * @return <code>false</code> falls die Factory nicht registriert war
+   */
+  public boolean unregisterImportFactory(ImportFactory fac) {
+    return unregister(fac,importFac);
+  }
+
+  /**
+   * Ersetzt die Registrierung einer Import-Factory durch eine andere.
+   * @param facOld zu ersetzende Factory
+   * @param facNew neue Factory
+   * @return <code>false</code> falls <code>facOld</code> nicht registriert war
+   *         und deshalb keine Ersetzung moeglich ist
+   */
+  public boolean replaceImportFactory(ImportFactory facOld, ImportFactory facNew) {
+    return replace(facOld,facNew,importFac);
+  }
+
+  /**
+   * Prueft, ob eine Import-Factory registriert ist.
+   */
+  public boolean isImportFactoryRegistered(ImportFactory fac) {
+    return contains(fac,importFac);
+  }
+
+  /**
+   * Liefert alle registrierten Import-Factorys.
+   */
+  public ImportFactory[] getImportFactories() {
+    XuluComponentUtil.checkDisposed(this);
+    return (ImportFactory[])importFac.toArray(new ImportFactory[0]);
+  }
+
+  /**
+   * Liefert alle Import-Factorys, die einen bestimmten Namen besitzen.
+   * @param name Bezeichnung der Factory
+   * @return ein leerer <code>ImportFactory</code>-Array, falls zu der Bezeichnung
+   *         keine Factory registriert ist
+   */
+  public ImportFactory[] getImportFactories(String name) {
+    return (ImportFactory[])findObjectsByName(getImportFactories(),name,new ImportFactory[0]);
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Export-Factories
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Registriert eine Export-Factory.
+   * @param fac Factory
+   * @return <code>false</code> falls die Factory bereits registriert ist
+   */
+  public boolean registerExportFactory(ExportFactory fac) {
+    return register(fac,exportFac);
+  }
+
+  /**
+   * Entfernt die Registrierung einer Export-Factory.
+   * @param fac Factory
+   * @return <code>false</code> falls die Factory nicht registriert war
+   */
+  public boolean unregisterExportFactory(ExportFactory fac) {
+    return unregister(fac,exportFac);
+  }
+
+  /**
+   * Ersetzt die Registrierung einer Export-Factory durch eine andere.
+   * @param facOld zu ersetzende Factory
+   * @param facNew neue Factory
+   * @return <code>false</code> falls <code>facOld</code> nicht registriert war
+   *         und deshalb keine Ersetzung moeglich ist
+   */
+  public boolean replaceExportFactory(ExportFactory facOld, ExportFactory facNew) {
+    return replace(facOld,facNew,exportFac);
+  }
+
+  /**
+   * Prueft, ob eine Export-Factory registriert ist.
+   */
+  public boolean isExportFactoryRegistered(ExportFactory fac) {
+    return contains(fac,exportFac);
+  }
+
+  /**
+   * Liefert alle registrierten Export-Factorys.
+   */
+  public ExportFactory[] getExportFactories() {
+    XuluComponentUtil.checkDisposed(this);
+    return (ExportFactory[])exportFac.toArray(new ExportFactory[0]);
+  }
+
+  /**
+   * Liefert alle Export-Factorys, die einen bestimmten Namen besitzen.
+   * @param name Bezeichnung der Factory
+   * @return ein leerer <code>ExportFactory</code>-Array, falls zu der Bezeichnung
+   *         keine Factory registriert ist
+   */
+  public ExportFactory[] getExportFactories(String name) {
+    return (ExportFactory[])findObjectsByName(getExportFactories(),name,new ExportFactory[0]);
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Type-Mappings
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Registriert ein TypeMapping. War bereits ein TypeMapping fuer den
+   * entsprechenden Datentyp registriert, wird das bestehende TypeMapping
+   * ersetzt.<br>
+   * Sind die darin enthaltenen Komponenten (Datentyp, Factorys, ...) noch
+   * nicht registriert, werden diese ebenfalls in die XuluRegistry aufgenommen.
+   * @param mapping TypeMapping
+   * @return <code>true</code>
+   */
+  public boolean registerTypeMapping(TypeMapping mapping) {
+    // Alle Komponenten des Mappings registrieren
+    registerDataType(mapping.getType());
+    registerDefaultFactory(mapping.getDefaultFactory());
+    ImportFactory[] iFac = mapping.getImportFactories();
+    for (int i=0; i<iFac.length; i++)
+      registerImportFactory(iFac[i]);
+    ExportFactory[] eFac = mapping.getExportFactories();
+    for (int i=0; i<eFac.length; i++)
+      registerExportFactory(eFac[i]);
+    // Wenn alle Komponenten erfolgreich registriert wurden, wird
+    // das TypeMapping registriert
+    typeMappings.put(mapping.getType(),mapping);
+    this.fireEvent( new ChangeEvent(this,null,mapping) );
+    return true;
+  }
+
+  /**
+   * Entfernt die Registrierung eines TypeMappings.
+   * @param mapping TypeMapping
+   * @return <code>false</code> falls das TypeMapping nicht registriert war
+   */
+  public boolean unregisterTypeMapping(TypeMapping mapping) {
+    XuluComponentUtil.checkDisposed(this);
+    if ( typeMappings.remove(mapping.getType()) != null ) {
+      fireEvent( new ChangeEvent(this,mapping,null) );
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * Ersetzt die Registrierung eines TypeMappings durch ein anderes.
+   * @param mapOld zu ersetzendes TypeMapping
+   * @param mapNew neues TypeMapping
+   * @return <code>false</code> falls <code>mapOld</code> nicht registriert war
+   *         und deshalb keine Ersetzung moeglich ist
+   */
+  public boolean replaceTypeMapping(TypeMapping mapOld, TypeMapping mapNew) {
+    // Da die Hashtable keine feste Reihenfolge impliziert, entspricht
+    // replace(TypeMapping,TypeMapping) einfach dem Entfernen und Hinzufuegen
+    // Die Methode wird nur der Vollstaendigkeit halber implementiert.
+    if ( !unregisterTypeMapping(mapOld) )
+      return false;
+    return registerTypeMapping(mapNew);
+  }
+
+  /**
+   * Prueft, ob ein TypeMapping (fuer den Datentyp) registriert ist.
+   */
+  public boolean isTypeMappingRegistered(TypeMapping mapping) {
+    XuluComponentUtil.checkDisposed(this);
+    return typeMappings.containsKey(mapping.getType());
+  }
+
+  /**
+   * Liefert alle registrierten TypeMappings.
+   */
+  public TypeMapping[] getTypeMappings() {
+    XuluComponentUtil.checkDisposed(this);
+    return (TypeMapping[])typeMappings.values().toArray(new TypeMapping[0]);
+  }
+
+  /**
+   * Liefert ein TypeMapping aus der Xulu-Registry.
+   * @param type Datentyp
+   * @return <code>null</code> falls zu dem Datentyp kein TypeMapping registriert
+   *         ist
+   */
+  public TypeMapping getTypeMapping(Class type) {
+    XuluComponentUtil.checkDisposed(this);
+    return (TypeMapping)typeMappings.get(type);
+  }
+
+  /**
+   * Liefert eine Datentyp-Factory aus der Xulu-Registry.
+   * @param type Datentyp
+   * @return <code>null</code> falls zu dem Datentyp kein TypeMapping registriert
+   *         ist
+   */
+  public InstantiationFactory getDefaultFactory(Class type) {
+    TypeMapping tm = getTypeMapping(type);
+    return tm==null ? null : tm.getDefaultFactory();
+  }
+
+  /**
+   * Liefert alle Import-Factorys zu einem Datentyp.
+   * @param type Datentyp
+   * @return ein leerer <code>ImportFactory</code>-Array, falls zu dem Datentyp
+   *         kein TypeMapping registriert ist
+   */
+  public ImportFactory[] getImportFactories(Class type) {
+    TypeMapping tm = getTypeMapping(type);
+    return tm==null ? new ImportFactory[0] : tm.getImportFactories();
+  }
+
+  /**
+   * Liefert eine Export-Factory aus der Xulu-Registry.
+   * @param type Datentyp
+   * @return ein leerer <code>ExportFactory</code>-Array, falls zu dem Datentyp
+   *         kein TypeMapping registriert ist
+   */
+  public ExportFactory[] getExportFactories(Class type) {
+    TypeMapping tm = getTypeMapping(type);
+    return tm==null ? new ExportFactory[0] : tm.getExportFactories();
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Visualisierungs-Tools
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob diese angegebene Klasse als Visualisierungstool zulaessig ist.
+   */
+  private void checkVisualisationToolClass(Class c) {
+    checkClass(c);
+    if ( !VisualisationTool.class.isAssignableFrom( c ) )
+      throw new UnsupportedOperationException( "Only subclasses of ".concat(VisualisationTool.class.getName()).concat(" can be registered as visualisation tool!") );
+    // Pruefen, ob Klasse einen Standard-Konstruktor hat
+    try {
+      c.getConstructor();
+    } catch ( Exception err ) {
+      throw new UnsupportedOperationException( "Visualisation tool must have a default constructor!" );
+    }
+  }
+
+  /**
+   * Registriert ein Visualisierungstool.
+   * @param toolClass Visualisierungstool
+   * @return <code>false</code> falls das Visualisierungstool bereits registriert ist
+   */
+  public boolean registerVisualisationTool(Class toolClass) {
+    checkVisualisationToolClass(toolClass);
+    return register(toolClass,visTools);
+  }
+
+  /**
+   * Entfernt die Registrierung eines Visualisierungstool.
+   * @param toolClass Visualisierungstool
+   * @return <code>false</code> falls das Visualisierungstool nicht registriert war
+   */
+  public boolean unregisterVisualisationTool(Class toolClass) {
+    return unregister(toolClass,visTools);
+  }
+
+  /**
+   * Ersetzt die Registrierung eines Visualisierungstools durch ein andere.
+   * @param toolOld zu ersetzendes Visualisierungstool
+   * @param toolNew neues Visualisierungstool
+   * @return <code>false</code> falls <code>toolOld</code> nicht registriert war
+   *         und deshalb keine Ersetzung moeglich ist
+   */
+  public boolean replaceVisualisationTool(Class toolOld, Class toolNew) {
+    checkVisualisationToolClass(toolNew);
+    return replace(toolOld,toolNew,visTools);
+  }
+
+  /**
+   * Prueft, ob eine Visualisierungstool registriert ist.
+   */
+  public boolean isVisualisationToolRegistered(Class toolClass) {
+    return contains(toolClass,visTools);
+  }
+
+  /**
+   * Liefert alle registrierten Visualisierungstools.
+   */
+  public Class[] getVisualisationTools() {
+    XuluComponentUtil.checkDisposed(this);
+    return (Class[])visTools.toArray(new Class[0]);
+  }
+
+  /**
+   * Diese Ereignis wird erzeugt (und an alle {@link schmitzm.data.event.ObjectListener}
+   * gesendet), wenn sich der Inhalt der Xulu-Registrierung aendert (ein Objekt hingefuegt,
+   * entfernt oder ersetzt wurde).
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class ChangeEvent extends ObjectChangeEvent {
+    /**
+     * Erzeugt ein neues Ereignis.
+     * @param registry XuluRegistry, die sich geaendert wird
+     * @param oldObj   altes Objekt (<code>null</code> falls ein Registry-Objekt
+     *                 hinzugefuegt wurde)
+     * @param newObj   neues Objekt (<code>null</code> falls ein Registry-Objekt
+     *                 geloescht wurde)
+     */
+    public ChangeEvent(XuluRegistry registry, Object oldObj, Object newObj) {
+      super( new Invoker(registry, new Invoker(oldObj)), oldObj, newObj );
+    }
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Modell-Klassen
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob diese angegebene Klasse als Modell zulaessig ist.
+   */
+  private void checkModelClass(Class c) {
+    checkClass(c);
+    if ( !XuluModel.class.isAssignableFrom( c ) )
+      throw new UnsupportedOperationException( "Only subclasses of ".concat(XuluModel.class.getName()).concat(" can be registered as model!") );
+    // Pruefen, ob Klasse einen Standard-Konstruktor hat
+    try {
+      c.getConstructor();
+    } catch ( Exception err ) {
+      throw new UnsupportedOperationException( "Model class must have a default constructor!" );
+    }
+  }
+
+  /**
+   * Registriert eine Modellklasse.
+   * @param modelClass Modellklasse
+   * @return <code>false</code> falls die Modellklasse bereits registriert ist
+   */
+  public boolean registerModelClass(Class modelClass) {
+    checkModelClass(modelClass);
+    return register(modelClass,modelClasses);
+  }
+
+  /**
+   * Entfernt die Registrierung einer Modellklasse.
+   * @param modelClass Modellklasse
+   * @return <code>false</code> falls die Modellklasse nicht registriert war
+   */
+  public boolean unregisterModelClass(Class modelClass) {
+    return unregister(modelClass,modelClasses);
+  }
+
+  /**
+   * Ersetzt die Registrierung einer Modellklasse durch eine andere.
+   * @param modelOld zu ersetzende Modellklasse
+   * @param modelNew neue Modellklasse
+   * @return <code>false</code> falls <code>modelOld</code> nicht registriert war
+   *         und deshalb keine Ersetzung moeglich ist
+   */
+  public boolean replaceModelClass(Class modelOld, Class modelNew) {
+    checkModelClass(modelNew);
+    return replace(modelOld,modelNew,modelClasses);
+  }
+
+  /**
+   * Prueft, ob eine Modellklasse registriert ist.
+   */
+  public boolean isModelClassRegistered(Class modelClass) {
+    return contains(modelClass,modelClasses);
+  }
+
+  /**
+   * Liefert alle registrierten Modellkassen.
+   */
+  public Class[] getModelClasses() {
+    XuluComponentUtil.checkDisposed(this);
+    return (Class[])modelClasses.toArray(new Class[0]);
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Skript-Interpreter
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Registriert einen Skript-Interpreters.
+   * @param interpreter {@link ScriptInterpreter}-Instanz
+   * @return <code>false</code> falls die Klasse bereits registriert ist
+   */
+  public boolean registerScriptInterpreter(ScriptInterpreter interpreter) {
+    return register(interpreter,scriptInterpreter);
+  }
+
+  /**
+   * Entfernt die Registrierung eines Skript-Interpreters.
+   * @param interpreter {@link ScriptInterpreter}-Instanz
+   * @return <code>false</code> falls die Klasse nicht registriert war
+   */
+  public boolean unregisterScriptInterpreter(ScriptInterpreter interpreter) {
+    return unregister(interpreter,scriptInterpreter);
+  }
+
+  /**
+   * Ersetzt die Registrierung einer Skript-Interpreters durch einen andere.
+   * @param interpreterOld zu ersetzender Skript-Interpreter
+   * @param interpreterNew neuer Skript-Interpreter
+   * @return <code>false</code> falls <code>interpreterOld</code> nicht registriert war
+   *         und deshalb keine Ersetzung moeglich ist
+   */
+  public boolean replaceScriptInterpreter(ScriptInterpreter interpreterOld, ScriptInterpreter interpreterNew) {
+    return replace(interpreterOld,interpreterNew,scriptInterpreter);
+  }
+
+  /**
+   * Prueft, ob ein Skript-Interpreter registriert ist.
+   */
+  public boolean isScriptInterpreterRegistered(ScriptInterpreter interpreter) {
+    return contains(interpreter,scriptInterpreter);
+  }
+
+  /**
+   * Liefert alle registrierten Skript-Interpreter.
+   */
+  public ScriptInterpreter[] getScriptInterpreter() {
+    XuluComponentUtil.checkDisposed(this);
+    return (ScriptInterpreter[])scriptInterpreter.toArray(new ScriptInterpreter[0]);
+  }
+
+  /**
+   * Liefert alle Skript-Interpreter, die einen bestimmten Namen besitzen.
+   * @param name Bezeichnung des Skript-Interpreter
+   * @return ein leerer <code>Skript-Interpreter</code>-Array, falls zu der Bezeichnung
+   *         kein Skript-Interpreter registriert ist
+   */
+  public ScriptInterpreter[] getScriptInterpreter(String name) {
+    return (ScriptInterpreter[])findObjectsByName(getScriptInterpreter(),name,new ScriptInterpreter[0]);
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Xulu-Plugins
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Registriert ein Xulu-Plugin.
+   * @param plugin {@link XuluPlugin}-Instanz
+   * @return <code>false</code> falls die Klasse bereits registriert ist
+   */
+  public boolean registerPlugin(XuluPlugin plugin) {
+    return register(plugin, xuluPlugins);
+  }
+
+  /**
+   * Entfernt die Registrierung eines Xulu-Plugins. Wenn das
+   * Plugin auch als Autostart-Plugin registriert war, wird dieses ebenfalls
+   * entfernt.
+   * @param plugin {@link XuluPlugin}-Instanz
+   * @return <code>false</code> falls die Klasse nicht registriert war
+   */
+  public boolean unregisterPlugin(XuluPlugin plugin) {
+    unregisterAutostartPlugin(plugin);
+    return unregister(plugin,xuluPlugins);
+  }
+
+  /**
+   * Ersetzt die Registrierung eines Xulu-Plugins durch eine andere. Wenn das
+   * Plugin auch als Autostart-Plugin registriert war, wird dieses ebenfalls
+   * ersetzt.
+   * @param pluginOld zu ersetzendes Plugin
+   * @param pluginNew neues Plugin
+   * @return <code>false</code> falls <code>pluginOld</code> nicht registriert war
+   *         und deshalb keine Ersetzung moeglich ist
+   */
+  public boolean replacePlugin(XuluPlugin pluginOld, XuluPlugin pluginNew) {
+    replaceAutostartPlugin(pluginOld, pluginNew);
+    return replace(pluginOld, pluginNew, xuluPlugins);
+  }
+
+  /**
+   * Prueft, ob ein Plugin registriert ist.
+   */
+  public boolean isPluginRegistered(XuluPlugin plugin) {
+    return contains(plugin, xuluPlugins);
+  }
+
+  /**
+   * Liefert alle registrierten Xulu-Plugins.
+   */
+  public XuluPlugin[] getPlugins() {
+    XuluComponentUtil.checkDisposed(this);
+    return (XuluPlugin[]) xuluPlugins.toArray(new XuluPlugin[0]);
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Autostart-Plugins
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Registriert ein Xulu-Plugin als Autostart-Plugin. Wenn noch nicht
+   * registriert, wird es (automatisch) auch in die Liste der Xulu-Plugins
+   * aufgenommen.
+   * @param plugin {@link XuluPlugin}-Instanz
+   * @return <code>false</code> falls das Plugin bereits registriert ist
+   */
+  public boolean registerAutostartPlugin(XuluPlugin plugin) {
+    registerPlugin(plugin);
+    return register(plugin, autostartPlugins);
+  }
+
+  /**
+   * Entfernt die Registrierung eines Xulu-Plugins als Autostart-Plugin.
+   * Als "normalen" Plugin bleibt es jedoch registriert.
+   * @param plugin {@link XuluPlugin}-Instanz
+   * @return <code>false</code> falls die Klasse nicht registriert war
+   */
+  public boolean unregisterAutostartPlugin(XuluPlugin plugin) {
+    return unregister(plugin,autostartPlugins);
+  }
+
+  /**
+   * Ersetzt die Registrierung eines Xulu-Plugins als Autostart-Plugin
+   * durch eine andere.
+   * @param pluginOld zu ersetzendes Plugin
+   * @param pluginNew neues Plugin
+   * @return <code>false</code> falls <code>pluginOld</code> nicht registriert war
+   *         und deshalb keine Ersetzung moeglich ist
+   */
+  public boolean replaceAutostartPlugin(XuluPlugin pluginOld, XuluPlugin pluginNew) {
+    boolean success = replace(pluginOld, pluginNew, autostartPlugins);
+    // Wenn die Ersetzung erfolgreich war, das neue Plugin auch in die
+    // Liste der normalen Plugins aufnehmen
+    if ( success )
+      registerPlugin(pluginNew);
+    return success;
+  }
+
+  /**
+   * Prueft, ob ein Plugin als Autostart-Plugin registriert ist.
+   */
+  public boolean isAutostartPluginRegistered(XuluPlugin plugin) {
+    return contains(plugin, autostartPlugins);
+  }
+
+  /**
+   * Liefert alle registrierten Autostart-Plugins.
+   */
+  public XuluPlugin[] getAutostartPlugins() {
+    XuluComponentUtil.checkDisposed(this);
+    return (XuluPlugin[]) autostartPlugins.toArray(new XuluPlugin[0]);
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  ///////////////   Letzte Importe, Exporte, ...   //////////////////
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Liefert eine Liste, in der die letzten Daten-Importe hinterlegt werden.
+   */
+  public RecentImports getRecentImports() {
+    return recentImports;
+  }
+
+  /**
+   * Liefert eine Liste, in der die letzten Script-Aufrufe hinterlegt werden.
+   */
+  public RecentScripts getRecentScripts() {
+    return recentScripts;
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/appl/XuluRegistryReader.java
===================================================================
--- trunk/src/edu/bonn/xulu/appl/XuluRegistryReader.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/XuluRegistryReader.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,51 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.appl;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+/**
+ * Dieses Interface bildet die Basis fuer eine Klasse, die die XuluRegistry
+ * einlesen kann.
+ * @see edu.bonn.xulu.appl.XuluRegistry
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public interface XuluRegistryReader {
+  /**
+   * Erweitert eine bestehende XuluRegistry. Bestehende Eintraege werden
+   * ueberschrieben. Ist die uebergebene Registy <code>null</code> wird
+   * eine neue (leere) Instanz erstellt.
+   * @param appl     Instanz der Xulu-Applikation fuer die die Registry eingelesen
+   *                 werden soll
+   * @param input    Eingabe-Stream aus dem die Registry-Daten gelesen werden
+   * @param registry XuluRegistry die erweitert werden soll (kan <code>null</code> sein
+   * @return Instanz der XuluRegistry, die erstellt oder erweitert wurde
+   * @throws java.io.IOException falls ein Fehler beim Einlesen auftritt
+   */
+  public XuluRegistry readRegistry(XuluModellingPlatform appl, InputStream input, XuluRegistry registry) throws IOException;
+
+  /**
+   * Erstellt eine neue XuluRegistry und befuellt diese.
+   * @param appl     Instanz der Xulu-Applikation fuer die die Registry eingelesen
+   *                 werden soll
+   * @param input    Eingabe-Stream aus dem die Registry-Daten gelesen werden
+   * @return Instanz der XuluRegistry, die erstellt wurde
+   * @throws java.io.IOException falls ein Fehler beim Einlesen auftritt
+   */
+  public XuluRegistry readRegistry(XuluModellingPlatform appl, InputStream input) throws IOException;
+
+}

Added: trunk/src/edu/bonn/xulu/appl/package.html
===================================================================
--- trunk/src/edu/bonn/xulu/appl/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/appl/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,9 @@
+<html>
+<body>
+	Dieses Paket enthält Verwaltungsklassen für die Xulu-Modelling-Plattform.
+	Hierzu zählen u.a. der {@linkplain edu.bonn.xulu.appl.DataPool Daten-Pool} zur
+	Daten-Verwaltung und die {@linkplain edu.bonn.xulu.appl.XuluRegistry Xulu-Registry},
+	in der alle dynamischen Komponenten der Modelling-Plattform (z.B. Datentypen und Factorys)
+	abgelegt werden.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/edu/bonn/xulu/data/AbstractXuluObject.java
===================================================================
--- trunk/src/edu/bonn/xulu/data/AbstractXuluObject.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/data/AbstractXuluObject.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,342 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.data;
+
+import java.util.Enumeration;
+
+import edu.bonn.xulu.appl.DataPool;
+import schmitzm.data.property.PropertySet;
+import schmitzm.data.property.Properties;
+import schmitzm.data.property.Property;
+import schmitzm.data.property.PropertyType;
+import schmitzm.data.event.AbstractObjectTraceable;
+import schmitzm.data.event.ObjectEvent;
+import schmitzm.data.event.ObjectChangeEvent;
+import schmitzm.data.event.ObjectCloseEvent;
+import schmitzm.data.event.NameChangeEvent;
+import schmitzm.data.event.ObjectListener;
+import schmitzm.data.event.Invoker;
+// nur fuer Doku
+import schmitzm.data.ObjectStructure;
+import schmitzm.data.property.ValuePropertyType;
+
+
+/**
+ * Diese Klasse bildet die Basisimplementierung eines Xulu-Datenobjekts. Diese
+ * stellen die Objekte dar, die im {@link DataPool Xulu-Datenpool} verwaltet
+ * werden koennen.
+ * <code>AbstractXuluObject</code> ist <b>fest</b> aus einer Menge an Properties
+ * zusammengesetzt, welche in einem {@link schmitzm.data.property.PropertySet}
+ * verwaltet werden. Diese sind von der jeweiligen Implementierung (im
+ * Konstruktor) festzulegen. Moeglichkeiten, dynamisch Eigenschaften hinzufuegen
+ * oder zu entfernen besteht nicht. Hierzu kann {@link DynamicXuluObject} genutzt
+ * werden.<br>
+ * Jedes Xulu-Datenobjekt erhaelt (automatisch) bei der Erzeugung eine ID, mit
+ * der es im Datenpool (sogar ueber alle Datenpool-Instanzen!) eindeutig
+ * identifiziert werden kann ({@link DataPool#generateUniqueID()}).
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class AbstractXuluObject extends AbstractObjectTraceable implements XuluObject {
+  /** Zaehlt die Instanzen fuer die Default-Beschreibung */
+  private static int instanceNo = 0;
+
+  /** Speichert die Eigenschaften des Xulu-Objekts. Darf nicht mit einem neuen
+   *  <code>PropertySet</code> belegt werden (<code>final</code>),
+   *  da es mit einem {@link ObjectListener} belegt wurde, der auf Aenderungen
+   *  an dem <code>PropertySet</code> reagiert (jeder hinzugefuegten Eigenschaft
+   *  wird ein {@link ObjectListener} hinzugefuegt, damit das <code>XuluObject</code>
+   *  Aenderungen an seinen Properties mitbekommt und ggf. weiterleiten kann).*/
+  protected final PropertySet propSet = new PropertySet();
+
+  /** Flag das anzeigt, dass das Objekt zerstoert ist. */
+  private boolean disposed = false;
+
+  /** Beschreibung fuer den Xulu-Datenpool */
+  private String desc = "";
+
+  /** eindeutige ID mit der das Datenobjekt im Datenpool identifizierbar ist */
+  private long id = 0;
+
+  /**
+   * Lauscht auf Aenderungen an den Properties und propagiert diese an
+   * alle Listener auf dem <code>XuluObject</code> weiter */
+  protected ObjectListener propertyChangeListener = null;
+
+  ///////////////////////////////////////////////////////////////////
+  // Konstruktoren
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Erzeugt eine neue <code>XuluObject</code>-Instanz.
+   * @param desc Beschreibung, welche im Datenpool angezeigt wird (wird
+   *         <code>null</code> uebergeben, wird eine Standardbeschreibung
+   *         erzeugt)
+   */
+  public AbstractXuluObject(String desc) {
+    instanceNo++; // Anzahl an Instanzen zaehlen (nur fuer Default-Beschreibung!)
+    // Standard-Beschreibung generieren
+    if ( desc == null )
+      desc = this.getClass().getSimpleName().concat(String.valueOf(instanceNo));
+    setDescription(desc);
+
+    this.id = DataPool.generateUniqueID();
+
+    // Listener achtet auf Aenderungen (an Eigenschaften des XuluObject)
+    // und propagiert diese an die Listener des XuluObject weiter
+    this.propertyChangeListener = new ObjectListener() {
+      public void performObjectEvent(ObjectEvent e) {
+        propagateDeeperEvent(e);
+      }
+    };
+
+    // Listener achtet darauf, ob dem XuluObject eine Property hingefuegt
+    // oder entfernt wird
+    this.propSet.addObjectListener( new ObjectListener() {
+      public void performObjectEvent(ObjectEvent e) {
+        if ( e instanceof ObjectChangeEvent ) {
+          ObjectChangeEvent oce = (ObjectChangeEvent)e;
+          // Property wurde entfernt > Listener entfernen
+          if ( oce.getNewValue() == null )
+            ((Property)oce.getOldValue()).removeObjectListener(propertyChangeListener);
+          // Property wurde hinzugefuegt > Listener hinzufuegen
+          if ( oce.getOldValue() == null )
+            ((Property)oce.getNewValue()).addObjectListener(propertyChangeListener);
+        }
+      }
+    });
+
+  }
+
+  /**
+   * Erweitert die Ereigniskette eines Events, das von einem Unterobjekt
+   * erhalten wurde, und gibt es an alle Listener weiter.
+   */
+  private void propagateDeeperEvent(ObjectEvent e) {
+    e.expandSource(this);
+    fireEvent(e);
+  }
+
+  /**
+   * Erzeugt eine neue <code>XuluObject</code>-Instanz. Diese erhaelt eine Default-Beschreibung,
+   * bestehend aus dem Klassennamen und einer laufenden Nummer.
+   */
+  public AbstractXuluObject() {
+    this(null);
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Implementierung von XuluObject
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Liefert die Beschreibung des Xulu-Objekts fuer den Datenpool.
+   */
+  public String getDescription() {
+    return this.desc;
+  }
+
+  /**
+   * Setzt die Beschreibung des Xulu-Objekts fuer den Datenpool. Aendert sich
+   * der Name, wird ein {@link NameChangeEvent} an alle Listener weitergeleitet.
+   * @param desc Beschreibung fuer das Objekt
+   */
+  public void setDescription(String desc) {
+    if ( desc == null || desc.trim().equals("") )
+      throw new XuluDataException("Object description can not be empty!");
+    String oldDesc = getDescription();
+    this.desc = desc;
+    if ( !desc.equals(oldDesc) )
+      this.fireEvent( new NameChangeEvent( new Invoker(this),oldDesc,desc ) );
+  }
+
+  /**
+   * Liefert die Beschreibung des Xulu-Objekts fuer den Datenpool. Synonym fuer
+   * {@link #getDescription()}.
+   */
+  public String getName() {
+    return getDescription();
+  }
+
+  /**
+   * Setzt die Beschreibung des Xulu-Objekts fuer den Datenpool. Synonym fuer
+   * {@link #setDescription(String)}.
+   * @param desc Beschreibung fuer das Objekt
+   */
+  public void setName(String desc) {
+    setDescription(desc);
+  }
+
+
+  /**
+   * Liefert die ID, mit der das Objekt in allen Datenpools eindeutig
+   * angesprochen werden kann.
+   */
+  public long getID() {
+    return this.id;
+  }
+
+  /**
+   * Zerstoert das Xulu-Objekt, indem alle seine Properties zerstoert
+   * werden. Unterklassen sollten diese Methode ueberschreiben, wenn
+   * weitere Ressourcen bei der Zerstoerung des Objekts oder seiner
+   * Propertys notwendig sind!!
+   * @see Property#dispose()
+   */
+  public void dispose() {
+    this.fireEvent( new ObjectCloseEvent(new Invoker(this)) );
+    Property[] prop = getProperties();
+    for (int i=0; i<prop.length; i++)
+      prop[i].dispose();
+    disposed = true;
+  }
+
+  /**
+   * Prueft, ob das Objekt zerstoert ist.
+   */
+  public boolean isDisposed() {
+    return disposed;
+  }
+
+  /**
+   * Prueft, ob aktuell auf eine Property des Xulu-Objekts zugegriffen
+   * wird.
+   */
+  public boolean isAccessed() {
+    Property[] prop = getProperties();
+    for (int i=0; i<prop.length; i++)
+      if (prop[i].hasAccess())
+        return true;
+    return false;
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Implementierung von Properties
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Liefert die Anzahl an Eigenschaften des Xulu-Objekts.
+   */
+  public int getPropertyCount() {
+    return propSet.getPropertyCount();
+  }
+
+  /**
+   * Liefert die Eigenschaften des Xulu-Objekts als Array.
+   */
+  public Property[] getProperties() {
+    return propSet.getProperties();
+  }
+
+  /**
+   * Liefert alle Eigenschaften des Xulu-Objekts, die einem bestimmten
+   * Typ angehoeren. Als Typ kann sowohl ein bestimmter <code>Property</code>-Untertyp
+   * angegeben werden (z.B. {@link schmitzm.data.property.ListProperty}),
+   * als auch ein Objekt-Typ (Typ den eine Property aufnehmen kann; z.B.
+   * <code>int.class</code>).<br>
+   * Da die Methode wiederum eine <code>Properties</code>-Instanz liefert,
+   * lassen sich recht einfach verschiedene Filter hintereinander anwenden:<br>
+   * <br>
+   * <center><code>
+   * Properties.getProperties(ListProperty.class).getProperties(int.class).getPropertyNames()
+   * </code></center>
+   * <br>
+   * liefert z.B. die Namen aller Listen-Eigenschaften, die <code>int</code>-Werte
+   * aufnehmen koennen.
+   */
+  public Properties getProperties(Class type) {
+    return propSet.getProperties(type);
+  }
+
+  /**
+   * Liefert die Namen aller Eigenschaften des Xulu-Objekts.
+   */
+  public String[] getPropertyNames() {
+    return propSet.getPropertyNames();
+  }
+
+  /**
+   * Liefert die Typen aller Eigenschaften des Xulu-Objekts.
+   */
+  public PropertyType[] getPropertyTypes() {
+    return propSet.getPropertyTypes();
+  }
+
+  /**
+   * Liefert eine bestimmte Eigenschaft des Xulu-Objekts.
+   * @param name Name der Eigenschaft
+   * @return <code>null</code> falls das Xulu-Objekt keine Eigenschaft dieses
+   *         Namens enthaelt
+   */
+  public Property getProperty(String name) {
+    return propSet.getProperty(name);
+  }
+
+  /**
+   * Prueft, ob das Xulu-Objekt eine bestimmte Eigenschaft enthaelt.
+   * @param name Name der Eigenschaft
+   */
+  public boolean containsProperty(String name) {
+    return propSet.containsProperty(name);
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Implementierung von ObjectStructure
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Liefert <code>true</code>.
+   */
+  public boolean isStructureNamed() {
+    return true;
+  }
+
+  /**
+   * Liefert die Bezeichnung des Xulu-Objekts.
+   * @see #getDescription()
+   */
+  public String getStructureName() {
+    return getDescription();
+  }
+
+  /**
+   * Liefert die Anzah1 an Properties des Xulu-Objekt.
+   * @see #getPropertyCount()
+   */
+  public int getAttrCount() {
+    return propSet.getAttrCount();
+  }
+
+  /**
+   * Liefert eine Liste, in der genau so viele Elemente enthaelt, wie das
+   * Xulu-Objekt Eigenschaften hat. Alle Listen-Elemente sind vom Typ
+   * {@link ObjectStructure}.
+   */
+  public Enumeration<ObjectStructure> getAttrTypes() {
+    return propSet.getAttrTypes();
+  }
+
+  /**
+   * Vergleicht die Struktur der Property mit einer anderen auf Gleichheit.
+   * @param object eine anderes {@link ObjectStructure}-Objekt
+   * @see ValuePropertyType#equalsInStructure(Object)
+   */
+  public boolean equalsInStructure(Object object) {
+    return propSet.equalsInStructure(object);
+  }
+
+  /**
+   * Liefert <code>false</code>, da ein Xulu-Objekt von jeder Eigenschaft
+   * immer nur eine Instanz enthaelt.
+   */
+  public boolean containsMultipleValues() {
+    return false;
+  }
+
+
+}

Added: trunk/src/edu/bonn/xulu/data/DuplicateXuluObjectIDException.java
===================================================================
--- trunk/src/edu/bonn/xulu/data/DuplicateXuluObjectIDException.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/data/DuplicateXuluObjectIDException.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,48 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.data;
+
+/**
+ * Dieser Fehler wird immer dann geworfen, wenn beim Einfuegen in den Xulu-Datenpool
+ * bereits ein Objekt mit der gleichen ID im Datenpool existiert.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class DuplicateXuluObjectIDException extends XuluDataException {
+  private long duplID = 0;
+
+  /**
+   * Erzeugt eine neue Fehlermeldung.
+   * @param object betroffenes Xulu-Objekt
+   * @param desc   Fehlermeldung
+   */
+  public DuplicateXuluObjectIDException(XuluObject object, String desc) {
+    super(object,desc);
+    this.duplID = object.getID();
+  }
+
+  /**
+   * Erzeugt eine neue Fehlermeldung.
+   * @param object betroffenes Xulu-Objekt
+   */
+  public DuplicateXuluObjectIDException(XuluObject object) {
+    this(object,"");
+  }
+
+  /**
+   * Liefert die XuluObject-ID, die den Fehler ausgeloest hat.
+   */
+  public long getDuplicateID() {
+    return duplID;
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/data/DuplicateXuluObjectNameException.java
===================================================================
--- trunk/src/edu/bonn/xulu/data/DuplicateXuluObjectNameException.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/data/DuplicateXuluObjectNameException.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,47 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.data;
+
+/**
+ * Dieser Fehler wird immer dann geworfen, wenn beim Einfuegen in den Xulu-Datenpool
+ * bereits ein Objekt mit der gleichen Namen im Datenpool existiert.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class DuplicateXuluObjectNameException extends XuluDataException {
+  private String duplName = "";
+
+  /**
+   * Erzeugt eine neue Fehlermeldung.
+   * @param object betroffenes Xulu-Objekt
+   * @param desc   Fehlermeldung
+   */
+  public DuplicateXuluObjectNameException(XuluObject object, String desc) {
+    super(object,desc);
+    this.duplName = object.getDescription();
+  }
+
+  /**
+   * Erzeugt eine neue Fehlermeldung.
+   * @param object betroffenes Xulu-Objekt
+   */
+  public DuplicateXuluObjectNameException(XuluObject object) {
+    this(object,"");
+  }
+
+  /**
+   * Liefert die XuluObject-Bezeichnung, die den Fehler ausgeloest hat.
+   */
+  public String getDuplicateName() {
+    return duplName;
+  }
+}

Added: trunk/src/edu/bonn/xulu/data/DynamicXuluObject.java
===================================================================
--- trunk/src/edu/bonn/xulu/data/DynamicXuluObject.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/data/DynamicXuluObject.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,174 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.data;
+
+import schmitzm.data.property.PropertySet;
+import schmitzm.data.property.Properties;
+import schmitzm.data.property.Property;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+
+/**
+ * Diese Klasse bildet die Basisimplementierung eines <u>dynamischen</u>
+ * Xulu-Datenobjekts. Diesem koennen Eigenschaften
+ * ({@link schmitzm.data.property.Property Propertys}) hinzugefuegt oder
+ * entfernt werden.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class DynamicXuluObject extends AbstractXuluObject {
+  /**
+   * Factory, die Standard-Instanzen von <code>DynamicXuluObject</code>
+   * erzeugt.
+   */
+  public static final InstantiationFactory DEFAULT_FACTORY = new DefaultFactory();
+
+  /**
+   * Erzeugt ein dynamisches Xulu-Objekt.
+   * @param desc    Beschreibung fuer den Datenpool
+   * @param propSet Eigenschaften aus denen das Objekt zusammengesetzt ist
+   */
+  public DynamicXuluObject(String desc, PropertySet propSet) {
+    super(desc);
+    // Struktur kopieren
+    // Bemerke: this.propSet = propSet geht nicht mehr, da Variable
+    //                         da this.propSet als final deklariert ist!
+    Property[] prop = propSet.getProperties();
+    for (int i=0; i<prop.length; i++)
+      this.propSet.addProperty(prop[i]);
+
+  }
+
+  /**
+   * Erzeugt ein dynamisches Xulu-Objekt. Dieses besitzt noch keine
+   * Eigenschaften.
+   * @param desc    Beschreibung fuer den Datenpool
+   */
+  public DynamicXuluObject(String desc) {
+    this(desc,new PropertySet());
+  }
+
+  /**
+   * Erzeugt ein dynamisches Xulu-Objekt. Diesem wird eine Default-Beschreibung
+   * fuer den Datenpool zugewiesen.
+   * @param propSet Eigenschaften aus denen das Objekt zusammengesetzt ist
+   */
+  public DynamicXuluObject(PropertySet propSet) {
+    this(null,propSet);
+  }
+
+  /**
+   * Erzeugt ein dynamisches Xulu-Objekt. Dieses besitzt noch keine Eigenschaften
+   * und ihm wird eine Default-Beschreibung fuer den Datenpool zugewiesen.
+   */
+  public DynamicXuluObject() {
+    this(new PropertySet());
+  }
+
+
+  /**
+   * Fuegt dem Xulu-Objekt eine Eigenschaft hinzu. Dabei wird auf Eindeutigkeit
+   * des Namens geachtet!
+   * @param prop Eigenschaft
+   * @exception schmitzm.data.property.PropertyException falls das Xulu-Objekt
+   *            bereits eine Eigenschaft dieses Namens besitzt
+   */
+  public void addProperty(Property prop) {
+    propSet.addProperty(prop);
+  }
+
+  /**
+   * Entfernt eine Eigenschaft aus dem Xulu-Objekt (sofern diese existiert).<br>
+   * <b>Die entfernte Eigenschaft wird mittels {@link Property#dispose()}
+   * vollstaendig zerstoert.</b>
+   * @param name Name der Eigenschaft
+   */
+  public void removeProperty(String name) {
+    Property p = propSet.removeProperty(name);
+    if ( p != null ) p.dispose();
+  }
+
+  /**
+   * Entfernt eine Eigenschaft aus der Menge.
+   * Falls die Menge eine solche Eigenschaft nicht besitzt, passiert nichts.<br>
+   * <b>Die entfernte Eigenschaft wird mittels {@link Property#dispose()}
+   * vollstaendig zerstoert.</b>
+   * @param prop zu entfernende Eigenschaft
+   */
+  public void removeProperty(Property prop) {
+    removeProperty(prop.getName());
+  }
+
+  /**
+   * Entfernt Eigenschaften aus der Menge. Falls die Menge eine dieser
+   * Eigenschaften nicht enthaelt, passiert fuer die entsprechende Eigenschaft
+   * nichts.<br>
+   * <b>Alle entfernten Eigenschaften werden mittels {@link Property#dispose()}
+   * vollstaendig zerstoert.</b>
+   * @param prop zu entfernende Eigenschaft
+   */
+  public void removeProperties(Properties prop) {
+    Property[] p = propSet.removeProperties(prop).getProperties();
+    for (int i=0; i < p.length; i++)
+      p[i].dispose();
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Implementierung von InstantiationFactory
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse implementiert eine Standard-Instanz-Factory fuer
+   * {@link DynamicXuluObject}.
+   * @see edu.bonn.xulu.data.DynamicXuluObject#DEFAULT_FACTORY
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class DefaultFactory extends AbstractFactory implements InstantiationFactory {
+    /**
+     * Liefert <code>DynamicXuluObject.class</code> als die Klasse, die
+     * von {@link #newInstance(boolean)} instanziiert wird.
+     */
+    public Class getInstanceType() {
+      return DynamicXuluObject.class;
+    }
+
+    /**
+     * Erzeugt eine neue leere Instanz von {@link DynamicXuluObject}.
+     * @param dialog wird nicht beachtet, da kein Dialog zum erzeugen einer
+     *               leeren Standard-Instanz benoetigt wird
+     */
+    public DynamicXuluObject newInstance(boolean dialog) {
+      return new DynamicXuluObject();
+    }
+
+    /**
+     * Erzeugt ein dynamisches Xulu-Objekt, das dieselben Eigenschaften hat,
+     * wie die Vorlage. Der Inhalt der Eigenschaften wird jedoch nicht kopiert.
+     * @param dialog siehe {@link #newInstance(boolean)}
+     * @param sample Vorlage
+     * @exception IllegalArgumentException falls es sich bei der Vorlage nicht
+     *            um eine <code>Properties</code>-Instanz handelt
+     */
+    public DynamicXuluObject newInstance(boolean dialog, Object sample) {
+      if ( sample == null )
+        throw new IllegalArgumentException(this.getClass().getSimpleName().concat(" can not create an instance of ").concat(getInstanceType().getSimpleName()).concat(" from null") );
+      if ( !Properties.class.isAssignableFrom(sample.getClass()) )
+        throw new IllegalArgumentException(this.getClass().getSimpleName().concat(" can not create an instance of ").concat(getInstanceType().getSimpleName()).concat(" from ").concat(sample.getClass().getName()) );
+
+      Property[] prop = ((Properties)sample).getProperties();
+      DynamicXuluObject newObj = newInstance(dialog);
+      for (int i=0; i<prop.length; i++)
+        newObj.addProperty( prop[i].cloneStructure() );
+      return newObj;
+    }
+  }
+}

Added: trunk/src/edu/bonn/xulu/data/XuluDataException.java
===================================================================
--- trunk/src/edu/bonn/xulu/data/XuluDataException.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/data/XuluDataException.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,57 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.data;
+
+/**
+ * Dieser Fehler wird immer dann geworfen, wenn ein Fehler mit einem
+ * Xulu-Datenobjekt auftritt.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class XuluDataException extends RuntimeException {
+  private XuluObject data = null;
+
+  /**
+   * Erzeugt eine neue Fehlermeldung.
+   * @param object betroffenes Xulu-Objekt
+   * @param desc   Fehlermeldung
+   */
+  public XuluDataException(XuluObject object, String desc) {
+    super(desc);
+    this.data = object;
+  }
+
+  /**
+   * Erzeugt eine neue Fehlermeldung.
+   * @param object betroffenes Xulu-Objekt
+   */
+  public XuluDataException(XuluObject object) {
+    this(object,"");
+  }
+
+  /**
+   * Erzeugt eine neue Fehlermeldung ohne Zusammenhang zu einem
+   * <code>XuluObject</code>.
+   * @param desc   Fehlermeldung
+   */
+  public XuluDataException(String desc) {
+    this(null,desc);
+  }
+
+  /**
+   * Liefert das Objekt, das den Fehler ausgeloest hat.
+   */
+  public XuluObject getXuluData() {
+    return data;
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/data/XuluObject.java
===================================================================
--- trunk/src/edu/bonn/xulu/data/XuluObject.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/data/XuluObject.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,77 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.data;
+
+import schmitzm.data.property.Properties;
+import schmitzm.data.property.Property;
+import schmitzm.data.property.PropertySet;
+import schmitzm.data.event.ObjectTraceable;
+import schmitzm.lang.NamedObject;
+
+import edu.bonn.xulu.appl.XuluComponent;
+
+/**
+ * Diese Interface bildet die Oberklasse fuer alle vom Xulu-Datenpool
+ * verwaltbare Datentypen. Es dient in der Hauptsache dazu, alle notwendigen
+ * Interfaces zusammenzufassen.<br>
+ * Darueber hinaus spezifiziert es einige weitere Funktionen, die fuer die
+ * Verwaltung des Datenpools wichtig sind.<br>
+ * Eine Basis-Implementierung stellt die Klasse {@link AbstractXuluObject} zur
+ * Verfuegung. Hiervon sollten neue Xulu-Objekte abgeleitet werden.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public interface XuluObject extends Properties, ObjectTraceable, XuluComponent, NamedObject {
+  /** Name der Eigenschaft, die den Objekt-Style beinhaltet. Es ist nicht
+   *  gewaehrleistet, dass das {@link XuluObject} tatsaechlich eine Eigenschaft
+   *  mit diesem Namen enthaelt. Doch wenn es eine solche bereitstellt, sollte
+   *  sie unter folgendem Einheitlichen Namen angesprochen werden koennen! */
+  public static final String PROP_STYLE = "Style";
+
+  /**
+   * Liefert eine numerische ID, ueber die das Objekt eindeutig im Datenpool
+   * identifiziert wird.
+   */
+  public long getID();
+
+  /**
+   * Liefert eine Beschreibung (Namen) des Objekts. Ueber diese wird das Objekt
+   * dem Anwender gegenueber im Datenpool identifiziert.
+   */
+  public String getDescription();
+
+  /**
+   * Setzt die Beschreibung (Namen) des Objekts. Ueber diese wird das Objekt
+   * dem Anwender gegenueber im Datenpool identifiziert.
+   */
+  public void setDescription(String desc);
+
+  /**
+   * Zerstoert das Objekt und gibt alle internen Ressourcen (z.B. Zugriffsrechte)
+   * wieder frei.
+   */
+  public void dispose();
+
+  /**
+   * Prueft, ob das Objekt "zerstoert" ist.
+   * @see #dispose()
+   */
+  public boolean isDisposed();
+
+  /**
+   * Prueft, ob zur Zeit Zugriffsrechte auf das Objekt (oder seine Properties)
+   * verteilt sind.
+   * @return boolean
+   */
+  public boolean isAccessed();
+
+}

Added: trunk/src/edu/bonn/xulu/data/package.html
===================================================================
--- trunk/src/edu/bonn/xulu/data/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/data/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,9 @@
+<html>
+<body>
+	Dieses Paket enthält Klassen/Interfaces, die für die Xulu-spezifische Datenverwaltung
+	benötigt werden. Hierzu zählen insbesondere die Klassen
+	{@link edu.bonn.xulu.data.XuluObject} und {@link edu.bonn.xulu.data.DynamicXuluObject},
+	von denen alle Objekte abgeleitet werden müssen, wenn sie im Xulu-Datenpool verwaltet werden
+	sollen.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/edu/bonn/xulu/gui/AbstractManagerFrame.java
===================================================================
--- trunk/src/edu/bonn/xulu/gui/AbstractManagerFrame.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/gui/AbstractManagerFrame.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,44 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.gui;
+
+import edu.bonn.xulu.appl.AbstractManager;
+
+/**
+ * Diese Klasse bildet eine abstrakte Oberklasse fuer alle grafischen
+ * Implementierungen des {@link AbstractManager}.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class AbstractManagerFrame extends XuluInternalFrame {
+  /** Speichert die Manager-Instanz, die im Fenster dargestellt wird. */
+  protected AbstractManager manager = null;
+
+  /**
+   * Erzeugt einen neue Instanz des grafischen Manager-Fensters.
+   * @param title   Titel fuer das Fenster
+   * @param manager darzustellender Manager
+   */
+  public AbstractManagerFrame(String title, AbstractManager manager) {
+    super(title);
+    this.manager = manager;
+  }
+
+  /**
+   * Liefert die Objekte, welches aktuell im Manager-Fenster ausgewaehlt sind.
+   * Mit diesen Objekten werden Aktionen durchgefuhrt, wenn ein Kontextmenu
+   * aktiviert wurde.
+   * @return <code>null</code> wenn noch kein Kontextmenue aufgerufen wurde.
+   */
+  public abstract AbstractManager.ContentType[] getSelectedObjects();
+
+}

Added: trunk/src/edu/bonn/xulu/gui/DataPoolFrame.java
===================================================================
--- trunk/src/edu/bonn/xulu/gui/DataPoolFrame.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/gui/DataPoolFrame.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,46 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.gui;
+
+import edu.bonn.xulu.data.XuluObject;
+
+/**
+ * Diese Klasse bildet eine abstrakte Oberklasse fuer alle grafischen
+ * Implementierungen des Xulu-Datenpools.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class DataPoolFrame extends XuluInternalFrame {
+  /**
+   * Erzeugt einen neue Instanz des grafischen Datenpool-Fensters. Dieses hat
+   * den Namen "Xulu-Datenpool".
+   */
+  public DataPoolFrame() {
+    super(XULUGUI_RES.getString("Comp_DataPool"));
+  }
+
+  /**
+   * Liefert alle Objekte, welches aktuell im Datenpool selektiert sind.
+   * Mit diesen Objekten werden Aktionen durchgefuhrt, wenn ein Kontextmenu
+   * aktiviert wurde.
+   * @return <code>null</code> wenn noch kein Kontextmenue aufgerufen wurde.
+   */
+  public abstract Object[] getSelectedObjects();
+
+  /**
+   * Liefert das Objekt, welches aktuell im Datenpool ausgewaehlt ist.
+   * Mit diesem Objekt werden Aktionen durchgefuhrt, wenn ein Kontextmenu
+   * aktiviert wurde.
+   * @return <code>null</code> wenn noch kein Kontextmenue aufgerufen wurde.
+   */
+  public abstract Object getSelectedObject();
+}

Added: trunk/src/edu/bonn/xulu/gui/DataPoolInputOption.java
===================================================================
--- trunk/src/edu/bonn/xulu/gui/DataPoolInputOption.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/gui/DataPoolInputOption.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,100 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.gui;
+
+import schmitzm.swing.BrowseInputOption;
+import schmitzm.swing.TreeSelectionDialog;
+
+import schmitzm.data.property.Property;
+
+import edu.bonn.xulu.appl.DataPool;
+import edu.bonn.xulu.appl.XuluConstants;
+import edu.bonn.xulu.data.XuluObject;
+
+// nur fuer Doku
+import schmitzm.swing.MultipleOptionPane;
+
+/**
+ * Diese Klasse stellt eine Eingabe-Option fuer einen {@link MultipleOptionPane}-Dialog
+ * dar, in der ein Daten-Objekt aus dem {@linkplain DataPool Xulu-Datenpool}
+ * eingegeben werden muss. Hierzu besteht fuer den Anwender die Moeglichkeit,
+ * ueber einen Browse-Dialog aus allen vorhandenen Datenpool-Objekten auszuwaehlen.<br>
+ * <br>
+ * Zur Zeit ist die manuelle Eingabe eines Objekts in das Textfeld der Eingabe-Option
+ * gesperrt (es kann nur gebrowsed werden). Die Methode {@link #convertFromString(String)}
+ * muss noch implementiert werden.
+ * @todo Manuelle Eingabe eines Objekts implementieren
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class DataPoolInputOption extends BrowseInputOption {
+  /** Speichert den Datenpool in den gebrowsed wird. */
+  protected DataPool dataPool = null;
+
+  /**
+   * Erzeugt eine neue Eingabe-Option.
+   * @param dp Datenpool, aus dem ein Objekt angegeben werden soll
+   * @param label Label-Text fuer die Eingabe-Option
+   * @param inputNeeded gibt an, ob eine Eingabe in der Option erforderlich ist
+   * @param defValue Standard-Belegung fuer die Eingabe-Option
+   */
+  public DataPoolInputOption(DataPool dp, String label, boolean inputNeeded, Object defValue) {
+    super(label, inputNeeded, defValue);
+    this.dataPool = dp;
+
+    // Eingabe-Feld sperren (bis Objekterkennung aus manuellem Textstring
+    // implementiert ist!)
+    inpComp.setEnabled(false);
+  }
+
+  /**
+   * Fuehrt die Browse-Aktion aus, wenn der Anwender auf den entsprechenden
+   * Button der Eingabe-Option klickt. Es wird ein Anwender-Dialog angezeigt,
+   * der in einer Baumstruktur alle Datenpool-Objekte zur Auswahl stellt.
+   * @param defValue Standard-Auswahl fuer den Browse-Dialog
+   * @return <code>null</code> wenn der Browse-Dialog abgebrochen wurde
+   * @see TreeSelectionDialog
+   */
+  public Object performBrowse(Object defValue) {
+    TreeSelectionDialog dialog = new TreeSelectionDialog(new DataPoolTreeModel(dataPool,false,"DUMMY"));
+    // Objekt von Anwender abfragen
+    Object[] o = dialog.show(this,XuluConstants.XULUGUI_RES.getString("Object"),false);
+    if ( o == null || o.length < 1 )
+      return null; // Dialog abgebrochen
+    return o[0];
+  }
+
+  /**
+   * <b>Noch nicht implementiert</b><br>
+   * Parst eine textuellen Angabe und liefert ein entsprechendes Objekt aus dem
+   * Datenpool.
+   * @param objectStr String, der das Datenpool-Objekt identifiziert.
+   * @exception UnsupportedOperationException bei <b>jedem</b> Aufruf
+   */
+  public Object convertFromString(String objectStr) {
+    throw new UnsupportedOperationException(XuluConstants.SWING_RES.getString("InvalidInputMess"));
+    // wenn diese Methode implementiert ist, kann auch eine manuelle (textuelle)
+    // Eingabe im Text-Feld erlaubt werden (-> Konstruktor!)
+  }
+
+  /**
+   * Liefert die textuelle Bezeichnung zu einem Datenpool-Objekt.
+   * @param object Datenpool-Objekt
+   */
+  public String convertToString(Object object) {
+    if ( object instanceof XuluObject )
+      return ((XuluObject)object).getDescription();
+    if ( object instanceof Property )
+      return ((Property)object).getName();
+    return object.toString();
+  }
+}

Added: trunk/src/edu/bonn/xulu/gui/DataPoolMenu.java
===================================================================
--- trunk/src/edu/bonn/xulu/gui/DataPoolMenu.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/gui/DataPoolMenu.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,734 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.gui;
+
+import java.io.File;
+
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import javax.swing.JFileChooser;
+import java.util.Vector;
+
+import schmitzm.io.FileOutputStream;
+import schmitzm.io.FileInputStream;
+
+import schmitzm.lang.NamedObject;
+
+import schmitzm.data.property.Property;
+import schmitzm.data.property.AccessViolationException;
+import schmitzm.data.event.ObjectListener;
+import schmitzm.data.event.ObjectEvent;
+import schmitzm.data.event.ObjectTraceable;
+import schmitzm.data.event.GeneralObjectChangeEvent;
+
+import schmitzm.swing.SwingWorker;
+import schmitzm.swing.menu.ActionStructure;
+import schmitzm.swing.menu.ObjectSubMenu;
+import schmitzm.swing.menu.ObjectMenuItem;
+
+import schmitzm.lang.AlreadyHandledException;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.XuluRegistry;
+import edu.bonn.xulu.appl.XuluConstants;
+import edu.bonn.xulu.appl.VisualisationTool;
+import edu.bonn.xulu.appl.VisualisationManager;
+import edu.bonn.xulu.appl.VisualisationUpdateListener;
+import edu.bonn.xulu.io.IODefinition;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.io.FactoryCanceledException;
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.data.XuluDataException;
+
+/**
+ * Diese Klasse stellt eine Menuestruktur fuer die Verwaltung des Datenpool
+ * zur Verfuegung.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class DataPoolMenu extends ObjectSubMenu implements XuluConstants {
+  /** Aktion steht fuer die Auswahl des "Neu"-Untermenues. */
+  public static final int ACTION_NEW       = 1;
+  /** Aktion steht fuer die Auswahl des "Import"-Untermenues. */
+  public static final int ACTION_IMPORT    = 2;
+  /** Aktion steht fuer die Auswahl des "Export"-Untermenues. */
+  public static final int ACTION_EXPORT    = 4;
+  /** Aktion steht fuer die Auswahl des "Display"-Untermenues. */
+  public static final int ACTION_DISPLAY   = 8;
+  /** Aktion steht fuer die Auswahl des Menu-Punkt "Display | Aktualisieren". */
+  public static final int ACTION_ACTUALIZE = 16;
+  /** Aktion steht fuer die Auswahl des Menu-Punkt "Kopieren". */
+  public static final int ACTION_COPY = 32;
+  /** Aktion steht fuer die Auswahl des Menu-Punkt "Löschen". */
+  public static final int ACTION_DELETE = 64;
+  /** Aktion steht fuer die Auswahl des Menu-Punkt "Import | Neu importieren" und
+   *  "Export | Neu exportieren". */
+  public static final int ACTION_RECENTIO = 128;
+
+  private XuluModellingPlatform appl = null;
+
+  /**
+   * Erzeugt ein neues Aktionsmenue fuer den Xulu-Datenpool.
+   * @param appl          Instanz der Xulu-Applikation
+   * @param dataPoolFrame DatenPool-Fenster auf dem das Menu aufgerufen wird
+   *                      (wird benoetigt, um die darin selektieren Objekte zu
+   *                      referenzieren, auf denen die Menu-Aktionen ausgefuehrt
+   *                      werden sollen)
+   */
+  public DataPoolMenu(final XuluModellingPlatform appl, DataPoolFrame dataPoolFrame) {
+    super(XULUGUI_RES.getString("Menu_DataPool"),ACTION_NONE,null,new DataPoolMenuListener(appl,dataPoolFrame),false);
+
+    add( new DataPoolSubMenu_New(this,itemActionListener,appl.getRegistry(),true) );
+    add( new ObjectMenuItem(XULUGUI_RES.getString("Menu_DataPool_Del"),itemActionListener,ACTION_DELETE,this) );
+    add( new DataPoolSubMenu_Import(this,itemActionListener,appl.getRegistry(), true));
+    add( new DataPoolSubMenu_Export(this,itemActionListener,appl.getRegistry(),true) );
+    addSeparator();
+    add( new DataPoolSubMenu_Display(this,itemActionListener,appl.getRegistry(),appl.getVisualisationManager(),true) );
+
+
+    ObjectListener updateListener = new ObjectListener() {
+      public void performObjectEvent(ObjectEvent e) {
+//        if ( e instanceof XuluRegistry.ChangeEvent ||
+//             e instanceof VisualisationManager.ChangeEvent )
+        if ( e.getSource().contains( appl.getRegistry() ) ||
+             e.getSource().contains( appl.getVisualisationManager() ) )
+          reorganize();
+    }};
+
+    this.appl = appl;
+    appl.getRegistry().addObjectListener( updateListener );
+    appl.getVisualisationManager().addObjectListener( updateListener );
+  }
+
+  public void reorganize() {
+    super.reorganize();
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // Untermenue zur Darstellung von Klassennamen
+  /////////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse stellt ein allgemeines Untermenue fuer die Auflistung von
+   * Objekten dar. Angezeigt wird der jeweilige Klassenname. Den einzelnen
+   * Menue-Eintraegen wird kein eigener ActionCode zugeordnet,
+   * sondern lediglich {@link ActionStructure#ACTION_NONE}.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class DataPoolSubMenu_ObjectClasses extends ObjectSubMenu {
+    /** Speichert die angezeigten Objekte. */
+    protected Object[] object = null;
+
+    /**
+     * Erzeugt ein Untermenue.
+     * @param name               Anzeigename des Menues
+     * @param actionCode         ActionCode fuer das Menue (nicht fuer die Eintraege!)
+     * @param parent             Ãœbergeordnete Aktions-Struktur
+     * @param itemActionListener wird den Menuepunkten zugeordnet und verarbeitet
+     *                           deren Auswahl
+     * @param object             Objekte die dargestellt werden
+     * @param reorganize         gibt, an ob das Menu bereits zur Instanziierung
+     *                           komplett (mit allen Untermenues) aufgebaut wird
+     */
+    public DataPoolSubMenu_ObjectClasses(String name, int actionCode, ActionStructure parent, ActionListener itemActionListener, Object[] object, boolean reorganize) {
+      super(name, actionCode, parent, itemActionListener, false);
+      this.object = object;
+      if (reorganize)
+        reorganize();
+    }
+
+    /**
+     * Reorganisiert das "Display"-Untermenue. Es werden alle
+     * Visualisierungstool-Instanzen geloescht und auf Basis des
+     * Visualisation-Managers neu eingefuegt. Danach werden
+     * alle (etwaigen) Untermenues ("Neu") reorganisiert.
+     */
+    public void reorganize() {
+      // Index des ersten und zweiten Seperators finden
+      int firstSepIdx = -1;
+      int secondSepIdx = -1;
+      for (int i = 0; i < getItemCount(); i++)
+        if ( getItem(i) == null ) {
+          if ( firstSepIdx < 0 )
+            firstSepIdx = i;
+          else {
+            secondSepIdx = i;
+            break;
+          }
+        }
+      // Wenn keine Seperator vorhanden, werden alle Menue-Eintraege
+      // geloescht
+      if ( firstSepIdx < 0 )
+        firstSepIdx = -1;
+      if ( secondSepIdx < 0 )
+        secondSepIdx = getItemCount();
+
+      // erst alle Klassen-Eintraege zwischen dem ersten und zweiten
+      // Seperator loeschen
+      // Beachte: von hinten nach vorne loeschen!!
+      //          Alles zwischen den Seperatorn
+      for (int i = secondSepIdx-1; i > firstSepIdx; i--)
+        if ( getItem(i) instanceof ObjectMenuItem )
+          remove(i);
+
+      // Klassen vorne neu einfuegen
+      for (int i = 0; i < object.length; i++) {
+        String name = object[i].getClass().getSimpleName();
+        if ( object[i] instanceof Class )
+          name = ((Class)object[i]).getSimpleName();
+        else if ( object[i] instanceof NamedObject ) {
+          NamedObject namedObject = (NamedObject)object[i];
+          if ( namedObject != null && namedObject.getName() != null && !namedObject.getName().equals("") )
+            name = namedObject.getName();
+        } 
+        ObjectMenuItem item = new ObjectMenuItem(name,object[i],ActionStructure.ACTION_NONE,this);
+        item.addActionListener( itemActionListener );
+        insert(item, firstSepIdx+1+i);
+      }
+
+      // SubMenus reorganisieren
+      super.reorganize();
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // Untermenue "Neu"
+  /////////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse stellt das Untermenue "Neu" des Datenpool-Menues dar.
+   * Es beinhaltet eine Liste mit den in der Xulu-Registry registrierten
+   * Datentypen und ein {@link DataPoolMenu.DataPoolSubMenu_Import Import-Untermenue}.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class DataPoolSubMenu_New extends DataPoolSubMenu_ObjectClasses {
+    private XuluRegistry registry = null;
+    private ObjectMenuItem copyItem = null;
+
+    /**
+     * Erzeugt ein "Neu"-Untermenue.
+     * @param parent             Ãœbergeordnete Aktions-Struktur
+     * @param itemActionListener wird den Menuepunkten zugeordnet und verarbeitet
+     *                           deren Auswahl
+     * @param registry           Xulu-Registry als Datenbasis
+     * @param reorganize         gibt, an ob das Menu bereits zur Instanziierung
+     *                           komplett (mit allen Untermenues) aufgebaut wird
+     */
+    public DataPoolSubMenu_New(ActionStructure parent, ActionListener itemActionListener, final XuluRegistry registry, boolean reorganize) {
+      super(XULUGUI_RES.getString("Menu_DataPool_New"),ACTION_NEW,parent,itemActionListener,registry.getDataTypes(),false);
+      this.registry = registry;
+      ObjectMenuItem item = new ObjectMenuItem(XULUGUI_RES.getString("Menu_DataPool_New_CopyStr"),null,ACTION_COPY,this);
+      item.addActionListener(itemActionListener);
+      add(item);
+      addSeparator();
+//      addSeparator();
+//      add(new DataPoolSubMenu_Import(this,itemActionListener,registry, false));
+      if (reorganize)
+        reorganize();
+    }
+
+    /**
+     * Ermittelt die Datentypen aus der Registry neu und regorganisiert dann
+     * das Menu.
+     */
+    public void reorganize() {
+      this.object = registry.getDataTypes();
+      super.reorganize();
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // Untermenue "Import"
+  /////////////////////////////////////////////////////////////////////
+
+  /**
+   * Diese Klasse stellt ein Untermenue "Import" dar.
+   * Es beinhaltet eine Liste mit den in der Xulu-Registry registrierten
+   * Import-Factorys.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class DataPoolSubMenu_Import extends DataPoolSubMenu_ObjectClasses {
+    private XuluRegistry registry = null;
+
+    /**
+     * Erzeugt ein "Import"-Untermenue.
+     * @param parent             Ãœbergeordnete Aktions-Struktur
+     * @param itemActionListener wird den Menuepunkten zugeordnet und verarbeitet
+     *                           deren Auswahl
+     * @param registry           Xulu-Registry als Datenbasis
+     * @param reorganize         gibt, an ob das Menu bereits zur Instanziierung
+     *                           komplett (mit allen Untermenues) aufgebaut wird
+     */
+    public DataPoolSubMenu_Import(ActionStructure parent, ActionListener itemActionListener, XuluRegistry registry, boolean reorganize) {
+      super(XULUGUI_RES.getString("Menu_DataPool_Import"), ACTION_IMPORT, parent, itemActionListener, registry.getImportFactories(), false);
+      this.registry = registry;
+      add(new DataPoolSubMenu_RecentIOs(this,XULUGUI_RES.getString("Menu_DataPool_RecentImport"),itemActionListener,registry.getRecentImports(), false));
+      addSeparator();
+      if (reorganize)
+        reorganize();
+    }
+
+    /**
+     * Ermittelt die ImportFactorys aus der Registry neu und regorganisiert dann
+     * das Menu.
+     */
+    public void reorganize() {
+      this.object = registry.getImportFactories();
+      super.reorganize();
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // Untermenue "Export"
+  /////////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse stellt ein Untermenue "Export" dar.
+   * Es beinhaltet eine Liste mit den in der Xulu-Registry registrierten
+   * Export-Factorys.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class DataPoolSubMenu_Export extends DataPoolSubMenu_ObjectClasses {
+    private XuluRegistry registry = null;
+
+    /**
+     * Erzeugt ein "Export"-Untermenue.
+     * @param parent             Ãœbergeordnete Aktions-Struktur
+     * @param itemActionListener wird den Menuepunkten zugeordnet und verarbeitet
+     *                           deren Auswahl
+     * @param registry           Xulu-Registry als Datenbasis
+     * @param reorganize         gibt, an ob das Menu bereits zur Instanziierung
+     *                           komplett (mit allen Untermenues) aufgebaut wird
+     */
+    public DataPoolSubMenu_Export(ActionStructure parent, ActionListener itemActionListener, XuluRegistry registry, boolean reorganize) {
+      super(XULUGUI_RES.getString("Menu_DataPool_Export"), ACTION_EXPORT, parent, itemActionListener, registry.getExportFactories(), false);
+      this.registry = registry;
+//      add(new DataPoolSubMenu_RecentIOs(this,XULUGUI_RES.getString("Menu_DataPool_RecentExport"),itemActionListener,registry.getRecentExports(), false));
+//      addSeparator();
+      if (reorganize)
+        reorganize();
+    }
+
+    /**
+     * Ermittelt die ExportFactorys aus der Registry neu und regorganisiert dann
+     * das Menu.
+     */
+    public void reorganize() {
+      this.object = registry.getExportFactories();
+      super.reorganize();
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // Untermenue "Display"
+  /////////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse stellt ein Untermenue "Display" dar.
+   * Es beinhaltet eine Liste mit den im VisualisationManager instanziierten
+   * Tools, sowie (in einem Untermenue "Neu") alle in Xulu-Registry registrierten
+   * Visualisierungstool-Klassen.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class DataPoolSubMenu_Display extends ObjectSubMenu {
+    private VisualisationManager visManager;
+
+    /**
+     * Erzeugt ein "Display"-Untermenue.
+     * @param parent             Ãœbergeordnete Aktions-Struktur
+     * @param itemActionListener wird den Menuepunkten zugeordnet und verarbeitet
+     *                           deren Auswahl
+     * @param registry           Xulu-Registry als Datenbasis
+     * @param reorganize         gibt, an ob das Menu bereits zur Instanziierung
+     *                           komplett (mit allen Untermenues) aufgebaut wird
+     */
+    public DataPoolSubMenu_Display(ActionStructure parent, ActionListener itemActionListener, final XuluRegistry registry, VisualisationManager visManager, boolean reorganize) {
+      super(XULUGUI_RES.getString("Menu_DataPool_Display"), ACTION_DISPLAY, parent, itemActionListener, false);
+      this.visManager = visManager;
+      // Menuepunkt "Aktualisieren"
+      ObjectMenuItem item = new ObjectMenuItem(XULUGUI_RES.getString("Menu_DataPool_Display_Actualise"),null,ACTION_ACTUALIZE,this);
+      add(item);
+      item.addActionListener(itemActionListener);
+      // Seperator vor und nach den aktiven Visualisierungstools
+      insertSeparator(1);
+      insertSeparator(2);
+      add(new DataPoolSubMenu_ObjectClasses(XULUGUI_RES.getString("Menu_DataPool_Display_New"),ACTION_NEW,this,itemActionListener,registry.getVisualisationTools(), false) {
+        public void reorganize() {
+          this.object = registry.getVisualisationTools();
+          super.reorganize();
+        }
+      });
+      if (reorganize)
+        reorganize();
+    }
+
+    /**
+     * Reorganisiert das "Display"-Untermenue. Es werden alle
+     * Visualisierungstool-Instanzen geloescht und auf Basis des
+     * Visualisation-Managers neu eingefuegt. Danach werden
+     * alle (etwaigen) Untermenues ("Neu") reorganisiert.
+     */
+    public void reorganize() {
+        // erst alle Menue-Eintraege fuer VisualisationTool-Instanzen loeschen
+        for (int i = 0; i < getItemCount(); i++)
+          if ( getItem(i) instanceof ObjectMenuItem && ((ObjectMenuItem)getItem(i)).getObject() instanceof VisualisationTool )
+            remove(i--);
+
+        // VisualisationTool-Instanzen HINTER (!) erstem Seperator einfuegen
+        VisualisationTool[] openTool = (VisualisationTool[])visManager.getAll();
+        for (int i = 0; i < openTool.length; i++) {
+          ObjectMenuItem item = new ObjectMenuItem(openTool[i].getTitle(),openTool[i],ActionStructure.ACTION_NONE,this);
+          item.addActionListener( itemActionListener );
+          insert(item, i+2); // +2 weil darueber "Aktualisieren" und der Seperator
+        }
+
+      // SubMenus reorganisieren
+      super.reorganize();
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // Untermenue "Letzte Dateien"
+  /////////////////////////////////////////////////////////////////////
+
+  /**
+   * Diese Klasse stellt ein Untermenue fuer die letzten Import- oder
+   * Export-Operationen dar.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class DataPoolSubMenu_RecentIOs extends ObjectSubMenu {
+    private Vector<? extends IODefinition> recentIOs = new Vector<IODefinition>();
+
+    /**
+     * Erzeugt ein neues Untermenue.
+     * @param parent             Ãœbergeordnete Aktions-Struktur
+     * @param name               Bezeichnung fuer das Menue
+     * @param itemActionListener wird den Menuepunkten zugeordnet und verarbeitet
+     *                           deren Auswahl
+     * @param recentIOs          Liste der letzten I/O-Operationen, die im Menue
+     *                           dargestellt werden
+     * @param reorganize         gibt, an ob das Menu bereits zur Instanziierung
+     *                           komplett (mit allen Untermenues) aufgebaut wird
+     */
+    public DataPoolSubMenu_RecentIOs(ActionStructure parent, String name, ActionListener itemActionListener, Vector<? extends IODefinition> recentIOs, boolean reorganize) {
+      super(name, ACTION_RECENTIO, parent, itemActionListener, false);
+      this.recentIOs = recentIOs;
+      if (reorganize)
+        reorganize();
+    }
+
+    /**
+     * Reorganisiert das "Letzte Dateien"-Untermenue. Es werden alle Eintraege
+     * geloescht und auf Basis der Datei-Liste neu eingefuegt.
+     */
+    public void reorganize() {
+      // erst alle Menue-Eintraege loeschen
+      removeAll();
+
+      // Alle Imports (mit Factory) einfuegen (der aelteste Import steht
+      // im ersten Element!)
+      for (int i = recentIOs.size()-1; i>=0; i--) {
+        IODefinition ioDef    = recentIOs.elementAt(i);
+        Object       ioObj    = ioDef.getIOObject();
+        // Namen des Menue-Eintrags zusammensetzen
+        // -> Factory-Name + Liste der Quell- bzw. Ziel-Objekte
+        Object[]     ioObjArr = ( ioObj instanceof Object[] ) ? (Object[])ioObj : new Object[] { ioObj };
+        String       itemName = ioDef.getFactory().getName() + " >> ";
+        for (int j=0; j<ioObjArr.length; j++) {
+          if ( j > 0 )
+            itemName += "; ";
+          ioObj = ioObjArr[j];
+          if ( ioObj instanceof File )
+            itemName += ((File)ioObj).getName();
+          else
+            itemName += ioObj.toString();
+        }
+        // Menue-Eintrag soll max. 50 Zeichen lang sein
+        if ( itemName.length() > 75 )
+          itemName = itemName.substring(0,75) + " ... ";
+
+        // Menue-Eintrag erzeugen
+        ObjectMenuItem item = new ObjectMenuItem(itemName, ioDef, ActionStructure.ACTION_NONE, this);
+        item.addActionListener(itemActionListener);
+        add(item);
+      }
+
+      // SubMenus reorganisieren
+      super.reorganize();
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // Listener fuer die Menues, der die entspr. Funktionen implementiert
+  /////////////////////////////////////////////////////////////////////
+
+  /**
+   * Diese Klasse stellt einen Listener dar, der die Aktionen, die im
+   * <code>DataPoolMenu</code> angewaehlt wurden, interpretiert und
+   * durchfuehrt.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  private static class DataPoolMenuListener implements ActionListener {
+    private DataPoolFrame         dataPoolFrame = null;
+    private XuluModellingPlatform appl = null;
+
+    /**
+     * Erzeugt einen Listener fuer das DatenPool-Menue.
+     * @param appl    XuluModellingPlatform-Instanz in der die Aktionen
+     *                ausgefuehrt werden
+     * @param parent  DatenPool-Frame, der das Menue aufruft (benoetigt um
+     *                selektierte Objekte zu referenzieren, auf die die Aktionen
+     *                ausgefuehrt werden sollen)
+     */
+    public DataPoolMenuListener(XuluModellingPlatform appl, DataPoolFrame parentFrame) {
+      this.appl          = appl;
+      this.dataPoolFrame = parentFrame;
+    }
+
+    /**
+     * Verarbeitet die jeweilige Menu-Auswahl und reagiert auf etwaige Fehler
+     * mit einer Meldung.
+     */
+    public void actionPerformed(ActionEvent e) {
+      if (e == null || e.getSource() == null ||
+          ! (e.getSource() instanceof ObjectMenuItem))
+        return;
+
+      ObjectMenuItem item = (ObjectMenuItem) e.getSource();
+      Object menuObject = item.getObject();
+      int menuAction = item.getCompleteActionCode();
+
+
+      try {
+        Object newDataPoolObject = null;
+        // wenn NEU ohne IMPORT >> MenuObject enthaelt DatenTyp
+        //          ohne COPY   >> 1) DefaultFactory aus TypeMapping
+        //                         2) Checken, ob XuluObject erzeugt wird
+        //                         3) Neues Objekt erzeugen und DP hinzufuegen
+        if ( item.compareActions(menuAction, DataPoolMenu.ACTION_NEW) &&
+            !item.compareActions(menuAction, DataPoolMenu.ACTION_IMPORT) &&
+            !item.compareActions(menuAction, DataPoolMenu.ACTION_COPY) &&
+            !item.compareActions(menuAction, DataPoolMenu.ACTION_DISPLAY)) {
+          InstantiationFactory fac = appl.getRegistry().getDefaultFactory((Class)menuObject);
+          if (fac == null)
+            throw new XuluDataException("No TypeMapping found for ".concat(
+                menuObject.getClass().getName()));
+          if (!XuluObject.class.isAssignableFrom(fac.getInstanceType()))
+            throw new XuluDataException("Factory does not create an instance of ".
+                                        concat(XuluObject.class.getName()));
+          newDataPoolObject = fac.newInstance(true);
+          appl.getDataPool().addObject( (XuluObject) newDataPoolObject);
+        }
+
+        // wenn IMPORT >> MenuObject enthaelt ImportDefinition
+        //             >> 1) Checken, ob XuluObject erzeugt wird
+        //                2) Dateiname abfragen
+        //                3) Neues Objekt erzeugen und DP hinzufuegen
+        if ( item.compareActions(menuAction, DataPoolMenu.ACTION_IMPORT) &&
+            !item.compareActions(menuAction, DataPoolMenu.ACTION_RECENTIO)) {
+          ImportFactory fac = (ImportFactory) menuObject;
+          XuluGUIUtil.importObjectsToDataPool(dataPoolFrame,fac,appl);
+        }
+
+        // wenn RECENT IMPORT >> MenuObject enthaelt ImportFactory
+        //                    >> 1) Checken, ob XuluObject erzeugt wird
+        //                       2) Neues Objekt erzeugen und DP hinzufuegen
+        if ( item.compareActions(menuAction, DataPoolMenu.ACTION_IMPORT) &&
+             item.compareActions(menuAction, DataPoolMenu.ACTION_RECENTIO)) {
+          final IODefinition.ImportDefinition impDef = (IODefinition.ImportDefinition) menuObject;
+          final ImportFactory                 fac    = impDef.getFactory();
+          if ( !XuluObject.class.isAssignableFrom(fac.getImportType()) )
+            throw new XuluDataException("Factory does not create an instance of ".concat(XuluObject.class.getName()));
+          SwingWorker.Work work = new SwingWorker.Work() {
+            public Object execute() throws Exception {
+              Object impObj = fac.importObject( XuluGUIUtil.convertImportSourceAsNeeded(fac,impDef.getIOObject()), appl.getRegistry() );
+              XuluGUIUtil.insertObjectToDataPool(dataPoolFrame,impObj,appl.getDataPool(),false,false);
+              // Import wieder an die erste Stelle der Recent-Imports setzen
+              appl.getRegistry().getRecentImports().remove( impDef );
+              appl.getRegistry().getRecentImports().add( impDef );
+              return null;
+            }
+          };
+          new SwingWorker(work,appl.getMainFrame(),XULUGUI_RES.getString("ImportProgressMess"),0.2,0.2).start();
+        }
+
+        // wenn NEU durch COPY >> MenuObject enthaelt ImportFactory
+        //                     >> 1) Checken, ob XuluObject erzeugt wird
+        //                        2) Dateiname abfragen
+        //                        3) Neues Objekt erzeugen und DP hinzufuegen
+        if (item.compareActions(menuAction, DataPoolMenu.ACTION_NEW) &&
+            item.compareActions(menuAction, DataPoolMenu.ACTION_COPY)) {
+          Object selObj = dataPoolFrame.getSelectedObject();
+          if ( selObj != null ) {
+            // Zur Zeit koennen nur komplette Xulu-Objekte kopiert werden
+            if ( !(selObj instanceof XuluObject) )
+              throw new XuluDataException("Zur Zeit koennen nur ganze Xulu-Objekte kopiert werden. Keine einzelnen Eigenschaften!");
+            XuluObject copyFromObj   = (XuluObject)selObj;
+            InstantiationFactory fac = appl.getRegistry().getDefaultFactory(copyFromObj.getClass());
+            newDataPoolObject        = fac.newInstance(true,copyFromObj);
+            // Bezeichnung von kopiertem Objekt uebernehmen
+            XuluObject newXuluObj = (XuluObject)newDataPoolObject;
+            newXuluObj.setDescription("Kopie von ".concat(copyFromObj.getDescription()));
+            // Objekt in Datenpool aufnehmen
+            appl.getDataPool().addObject( newXuluObj );
+          }
+        }
+      } catch (FactoryCanceledException err) {
+        // manueller/gewollter Abbruch der Factory
+      } catch (XuluDataException err) {
+        XuluGUIMessages.showError(dataPoolFrame, err, "Objekt kann nicht erzeugt werden!");
+      } catch (ClassCastException err) {
+        XuluGUIMessages.showError(dataPoolFrame, err,
+            "Der Xulu-Datenpool kann nur XuluObject-Instanzen aufnehmen!");
+      } catch (AlreadyHandledException err) {
+        // Exception wurde bereits verarbeitet
+      } catch (Exception err) {
+        XuluGUIMessages.showError(dataPoolFrame, err);
+      }
+
+
+      // wenn LOESCHEN >> 1) Alle selektieren Xulu-Objekte loeschen
+      if ( item.compareActions(menuAction, DataPoolMenu.ACTION_DELETE) ) {
+        try {
+            // alle selektierten Objekte aus dem Datenpool entfernen und
+            // zerstoeren
+            Object[] obj = dataPoolFrame.getSelectedObjects();
+            for (int i = 0; i < obj.length; i++)
+              if ( obj[i] instanceof XuluObject ) {
+                XuluObject xuluObject = (XuluObject)obj[i];
+                // Wenn zur Zeit noch Zugriffe auf das Objekt bestehen, kann es
+                // nicht geloescht werden
+                if ( xuluObject.isAccessed() )
+                  XuluGUIMessages.showError(dataPoolFrame,"Das Objekt '"+xuluObject.getDescription()+"' kann nicht geloescht werden. Es wird noch darauf zugegriffen!");
+                else {
+                  // Objekt aus Datenpool entfernen
+                  appl.getDataPool().removeObject(xuluObject);
+                  // Objekt aus Visualisierungen loeschen
+                  for (int j = 0; j<appl.getVisualisationManager().getCount(); j++)
+                    ((VisualisationTool)appl.getVisualisationManager().get(j)).remove(xuluObject);
+                  // Objekt zerstoeren
+                  xuluObject.dispose();
+                }
+              }
+            dataPoolFrame.refresh();
+        } catch ( Exception err ){
+          XuluGUIMessages.showError(dataPoolFrame, err);
+        }
+      }
+
+      // wenn EXPORT >> MenuObject enthaelt ExportFactory
+      //             >> 1) Checken, ob Factory die ausgewaehlten XuluObjekte
+      //                   exportieren kann
+      //                2) Dateinamen abfragen
+      //                3) DP-Objekte exportieren
+      if (item.compareActions(menuAction, DataPoolMenu.ACTION_EXPORT)) {
+        ExportFactory fac = (ExportFactory) menuObject;
+        // versuchen, alle selektierten Objekte zu exportieren
+        Object[] obj = dataPoolFrame.getSelectedObjects();
+        for (int i = 0; i < obj.length; i++)
+          try {
+            XuluGUIUtil.exportObjects(dataPoolFrame,obj[i],fac,appl);
+          } catch (XuluDataException err) {
+            String name = obj[i] instanceof XuluObject ? ((XuluObject)obj[i]).getDescription() : ((Property)obj[i]).getName();
+            XuluGUIMessages.showError(dataPoolFrame, err, "Objekt '".concat(name).concat("' konnte nicht exportiert werden werden!"));
+          } catch (AlreadyHandledException err) {
+            // Exception wurde bereits verarbeitet
+          } catch (AccessViolationException err) {
+            XuluGUIMessages.showAccessError(dataPoolFrame, err);
+          } catch (Exception err) {
+            XuluGUIMessages.showError(dataPoolFrame, err);
+          }
+      }
+
+      // wenn DISPAY, aber nicht AKTUALISIEREN
+      //             >> 1) Visualisierungstool bestimmen oder erzeugen
+      //                   MenuObject enthaelt VisualisationTool oder entspr. Klasse
+      //                2) Checken, ob Tool die das ausgewaehlten Objekte
+      //                   darstellen kann
+      //                3) Objekte darstellen
+      if ( item.compareActions(menuAction, DataPoolMenu.ACTION_DISPLAY) &&
+          !item.compareActions(menuAction, DataPoolMenu.ACTION_ACTUALIZE) ) {
+        try {
+          VisualisationTool visTool = null;
+          // VisualisationTool bestimmen oder erzeugen und dem Manager hinzufuegen
+          if (!item.compareActions(menuAction, DataPoolMenu.ACTION_NEW))
+            visTool = (VisualisationTool) menuObject;
+          else {
+            visTool = (VisualisationTool) ( (Class) menuObject).newInstance();
+            visTool.initialize(appl);
+            appl.getVisualisationManager().add(visTool,true);
+          }
+          // versuchen, alle selektierten Objekte darzustellen
+          Object[] obj = dataPoolFrame.getSelectedObjects();
+          for (int i = 0; i < obj.length; i++)
+            try {
+              // Objekte, die nicht darstellbar sind, ignorieren
+//          if ( !visTool.isVisualisable(obj[i]) )
+//            throw new XuluDataException(visTool.getClass().getSimpleName().concat(" can not visualise an instance of ").concat(obj[i].getClass().getName()));
+              String desc = "neues Objekt";
+              if ( obj[i] instanceof XuluObject )
+                desc =  ((XuluObject)obj[i]).getDescription();
+              visTool.add(obj[i], desc);
+// add-Methode liefert keinen UpdateListener mehr!!
+//              VisualisationUpdateListener updateListener = visTool.add(obj[i], desc);
+//              // wenn es sich um ein "verfolgbares" Objekt handelt,
+//              // den Listener zuordnen
+//              if ( obj[i] instanceof ObjectTraceable )
+//                ((ObjectTraceable)obj[i]).addObjectListener(updateListener);
+
+            }
+            catch (AlreadyHandledException err) {
+              // Exception wurde bereits verarbeitet
+            }
+            catch (AccessViolationException err) {
+              XuluGUIMessages.showAccessError(dataPoolFrame, err);
+            }
+            catch (Exception err) {
+              XuluGUIMessages.showError(dataPoolFrame, err);
+            }
+        } catch ( Exception err ){
+            XuluGUIMessages.showError(dataPoolFrame, err);
+        }
+      }
+
+      // wenn DISPAY und AKTUALISIEREN
+      //             >> 1) Visualisierungstool bestimmen oder erzeugen
+      //                   MenuObject enthaelt VisualisationTool oder entspr. Klasse
+      //                2) Checken, ob Tool die das ausgewaehlten Objekte
+      //                   darstellen kann
+      //                3) Objekte darstellen
+      if ( item.compareActions(menuAction, DataPoolMenu.ACTION_DISPLAY) &&
+           item.compareActions(menuAction, DataPoolMenu.ACTION_ACTUALIZE) ) {
+        try {
+            // versuchen, alle selektierten Objekte zu aktualisieren
+            Object[] obj = dataPoolFrame.getSelectedObjects();
+            for (int i = 0; i < obj.length; i++)
+              for (int j = 0; j<appl.getVisualisationManager().getCount(); j++)
+                ((VisualisationTool)appl.getVisualisationManager().get(j)).update(obj[i]);
+//              if ( obj[i] instanceof ObjectTraceable ) {
+//                ObjectListener[] visListener = ( (ObjectTraceable) obj[i]).getObjectListener(VisualisationUpdateListener.class);
+//                for (int j=0; j<visListener.length; j++)
+//                  ((VisualisationUpdateListener)visListener[j]).refresh();
+//              }
+        } catch ( Exception err ){
+            XuluGUIMessages.showError(dataPoolFrame, err);
+        }
+      }
+    }
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/gui/DataPoolMenu.sav
===================================================================
--- trunk/src/edu/bonn/xulu/gui/DataPoolMenu.sav	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/gui/DataPoolMenu.sav	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,392 @@
+package edu.bonn.xulu.gui;
+
+import java.awt.event.ActionListener;
+
+import schmitzm.data.io.Factory;
+
+import schmitzm.swing.menu.ActionStructure;
+import schmitzm.swing.menu.ObjectSubMenu;
+import schmitzm.swing.menu.ObjectMenuItem;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.XuluRegistry;
+import edu.bonn.xulu.appl.VisualisationTool;
+
+/**
+ * Diese Klasse stellt eine Menuestruktur fuer die Verwaltung des Datenpool
+ * zur Verfuegung.
+ * @author <a href="mailto:schmitzm at bonn.edu">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class DataPoolMenu extends ObjectSubMenu {
+  /** Aktion steht fuer die Auswahl des "Neu"-Untermenues. */
+  public static final int ACTION_NEW       = 1;
+  /** Aktion steht fuer die Auswahl des "Import"-Untermenues. */
+  public static final int ACTION_IMPORT    = 2;
+  /** Aktion steht fuer die Auswahl des "Export"-Untermenues. */
+  public static final int ACTION_EXPORT    = 4;
+  /** Aktion steht fuer die Auswahl des "Display"-Untermenues. */
+  public static final int ACTION_DISPLAY   = 8;
+  /** Aktion steht fuer die Auswahl des Menu-Punkt "Display | Aktualisieren". */
+  public static final int ACTION_ACTUALIZE = 16;
+
+
+  /**
+   * Erzeugt ein neues Aktionsmenue fuer den Xulu-Datenpool.
+   * @param appl Instanz der Xulu-Applikation
+   */
+  public DataPoolMenu(XuluModellingPlatform appl, ActionListener listener) {
+    super("Daten-Pool",ACTION_NONE,null,listener,false);
+
+    add( new DataPoolSubMenu_New(this,itemActionListener,appl.getRegistry(),true) );
+//    add( new DataPoolSubMenu_Import(this,itemActionListener,appl.getRegistry(),true) );
+    add( new DataPoolSubMenu_Export(this,itemActionListener,appl.getRegistry(),true) );
+    add( new DataPoolSubMenu_Display(this,itemActionListener,appl.getRegistry(),true) );
+  }
+
+
+
+  /////////////////////////////////////////////////////////////////////
+  // Untermenue zur Darstellung von Klassennamen
+  /////////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse stellt ein allgemeines Untermenue fuer die Auflistung von
+   * Klassen dar.
+   * @author <a href="mailto:schmitzm at bonn.edu">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class DataPoolSubMenu_ObjectClasses extends ObjectSubMenu {
+    /** Speichert die angezeigten Klassen. */
+    protected Object[] object = null;
+
+    /**
+     * Erzeugt ein "Display"-Untermenue.
+     * @param parent             Übergeordnete Aktions-Struktur
+     * @param itemActionListener wird den Menuepunkten zugeordnet und verarbeitet
+     *                           deren Auswahl
+     * @param registry           Xulu-Registry als Datenbasis
+     * @param reorganize         gibt, an ob das Menu bereits zur Instanziierung
+     *                           komplett (mit allen Untermenues) aufgebaut wird
+     */
+    public DataPoolSubMenu_ObjectClasses(String name, int actionCode, ActionStructure parent, ActionListener itemActionListener, Object[] object, boolean reorganize) {
+      super(name, actionCode, parent, itemActionListener, false);
+      this.object = object;
+      if (reorganize)
+        reorganize();
+    }
+
+    /**
+     * Reorganisiert das "Display"-Untermenue. Es werden alle
+     * Visualisierungstool-Instanzen geloescht und auf Basis des
+     * Visualisation-Managers neu eingefuegt. Danach werden
+     * alle (etwaigen) Untermenues ("Neu") reorganisiert.
+     */
+    public void reorganize() {
+        // erst alle Klassen-Eintraege loeschen
+        for (int i = 0; i < getItemCount(); i++)
+          if ( getItem(i) instanceof ObjectMenuItem && ((ObjectMenuItem)getItem(i)).getObject() instanceof Class)
+            remove(i);
+
+        // Klassen vorne neu einfuegen
+        for (int i = 0; i < object.length; i++) {
+          String name = object[i] instanceof Class ? ((Class)object[i]).getSimpleName() : object[i].getClass().getSimpleName();
+          ObjectMenuItem item = new ObjectMenuItem(name,object[i],ActionStructure.ACTION_NONE,this);
+          item.addActionListener( itemActionListener );
+          insert(item, i);
+        }
+
+      // SubMenus reorganisieren
+      super.reorganize();
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // Untermenue "Neu"
+  /////////////////////////////////////////////////////////////////////
+//  /**
+//   * Diese Klasse stellt das Untermenue "Neu" des Datenpool-Menues dar.
+//   * Es beinhaltet eine Liste mit den in der Xulu-Registry registrierten
+//   * Datentypen und ein {@link DataPoolMenu.DataPoolSubMenu_Import Import-Untermenue}.
+//   * @author <a href="mailto:schmitzm at bonn.edu">Martin Schmitz</a> (University of Bonn/Germany)
+//   * @version 1.0
+//   */
+//  public static class DataPoolSubMenu_New extends ObjectSubMenu {
+//    private XuluRegistry registry;
+//
+//    /**
+//     * Erzeugt ein "Neu"-Untermenue.
+//     * @param parent             Übergeordnete Aktions-Struktur
+//     * @param itemActionListener wird den Menuepunkten zugeordnet und verarbeitet
+//     *                           deren Auswahl
+//     * @param registry           Xulu-Registry als Datenbasis
+//     * @param reorganize         gibt, an ob das Menu bereits zur Instanziierung
+//     *                           komplett (mit allen Untermenues) aufgebaut wird
+//     */
+//    public DataPoolSubMenu_New(ActionStructure parent, ActionListener itemActionListener, XuluRegistry registry, boolean reorganize) {
+//      super("Neu",ACTION_NEW,parent,itemActionListener,false);
+//      this.registry = registry;
+//      insertSeparator(0);
+//      add(new DataPoolSubMenu_Import(this,itemActionListener,registry, false));
+//      if (reorganize)
+//        reorganize();
+//    }
+//
+//    /**
+//     * Reorganisiert das "Neu"-Untermenue. Zunaecht werden alle Datentyp-Eintraege
+//     * geloescht und auf Basis der Xulu-Registry neu eingefuegt. Danach werden
+//     * alle Untermenues reorganisiert.
+//     */
+//    public void reorganize() {
+//      // erst alle normalen Menue-Eintraege loeschen
+//      for (int i = 0; i < getItemCount(); i++)
+//        if ( getItem(i) instanceof ObjectMenuItem )
+//          remove(i);
+//
+//      // Datentypen vorne neu einfuegen
+//      Class[] dataType = registry.getDataTypes();
+//      for (int i = 0; i < dataType.length; i++) {
+//        ObjectMenuItem item = new ObjectMenuItem(dataType[i].getSimpleName(),dataType[i],ActionStructure.ACTION_NONE,this);
+//        item.addActionListener( itemActionListener );
+//        insert(item, i);
+//      }
+//
+//      // SubMenus reorganisieren
+//      super.reorganize();
+//    }
+//  }
+
+  /**
+   * Diese Klasse stellt das Untermenue "Neu" des Datenpool-Menues dar.
+   * Es beinhaltet eine Liste mit den in der Xulu-Registry registrierten
+   * Datentypen und ein {@link DataPoolMenu.DataPoolSubMenu_Import Import-Untermenue}.
+   * @author <a href="mailto:schmitzm at bonn.edu">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class DataPoolSubMenu_New extends DataPoolSubMenu_ObjectClasses {
+    private XuluRegistry registry;
+
+    /**
+     * Erzeugt ein "Neu"-Untermenue.
+     * @param parent             Übergeordnete Aktions-Struktur
+     * @param itemActionListener wird den Menuepunkten zugeordnet und verarbeitet
+     *                           deren Auswahl
+     * @param registry           Xulu-Registry als Datenbasis
+     * @param reorganize         gibt, an ob das Menu bereits zur Instanziierung
+     *                           komplett (mit allen Untermenues) aufgebaut wird
+     */
+    public DataPoolSubMenu_New(ActionStructure parent, ActionListener itemActionListener, XuluRegistry registry, boolean reorganize) {
+      super("Neu",ACTION_NEW,parent,itemActionListener,registry.getDataTypes(),false);
+      this.registry = registry;
+      insertSeparator(0);
+      add(new DataPoolSubMenu_Import(this,itemActionListener,registry, false));
+      if (reorganize)
+        reorganize();
+    }
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Gemeinsame Methoden fuer FactoryMenu-Klassen
+  ///////////////////////////////////////////////////////////////////
+//  /**
+//   * Reorganisiert ein Factory-Untermenue. Hierzu werden alle Menue-Eintraege
+//   * geloescht und danach wieder eingefuegt.
+//   * @param menu zu reorganisierendes (Factory-)Menue
+//   * @param fac  Factorys, die neu eingefuegt werden
+//   */
+//  private static void reorganizeFactoryMenu(ObjectSubMenu menu, Factory[] fac) {
+//    menu.removeAll();
+//    for (int i = 0; i < fac.length; i++) {
+//      ObjectMenuItem item = new ObjectMenuItem(fac[i].getClass().getSimpleName(),fac[i],ACTION_IMPORT,menu);
+//      item.addActionListener( menu.getItemActionListener() );
+//      menu.insert(item, i);
+//    }
+//  }
+
+  /////////////////////////////////////////////////////////////////////
+  // Untermenue "Import"
+  /////////////////////////////////////////////////////////////////////
+//  /**
+//   * Diese Klasse stellt ein Untermenue "Import" dar.
+//   * Es beinhaltet eine Liste mit den in der Xulu-Registry registrierten
+//   * Import-Factorys.
+//   * @author <a href="mailto:schmitzm at bonn.edu">Martin Schmitz</a> (University of Bonn/Germany)
+//   * @version 1.0
+//   */
+//  public static class DataPoolSubMenu_Import extends ObjectSubMenu {
+//    private XuluRegistry registry;
+//
+//    /**
+//     * Erzeugt ein "Import"-Untermenue.
+//     * @param parent             Übergeordnete Aktions-Struktur
+//     * @param itemActionListener wird den Menuepunkten zugeordnet und verarbeitet
+//     *                           deren Auswahl
+//     * @param registry           Xulu-Registry als Datenbasis
+//     * @param reorganize         gibt, an ob das Menu bereits zur Instanziierung
+//     *                           komplett (mit allen Untermenues) aufgebaut wird
+//     */
+//    public DataPoolSubMenu_Import(ActionStructure parent, ActionListener itemActionListener, XuluRegistry registry, boolean reorganize) {
+//      super("Import", ACTION_IMPORT, parent, itemActionListener, false);
+//      this.registry = registry;
+//      if (reorganize)
+//        reorganize();
+//    }
+//
+//    /**
+//     * Reorganisiert das "Import"-Untermenue. Zunaecht werden alle Factory-Eintraege
+//     * geloescht und auf Basis der Xulu-Registry neu eingefuegt. Danach werden
+//     * alle (etwaigen) Untermenues reorganisiert.
+//     */
+//    public void reorganize() {
+//      reorganizeFactoryMenu(this,registry.getImportFactories());
+//      // SubMenus reorganisieren
+//      super.reorganize();
+//    }
+//  }
+
+  /**
+   * Diese Klasse stellt ein Untermenue "Import" dar.
+   * Es beinhaltet eine Liste mit den in der Xulu-Registry registrierten
+   * Import-Factorys.
+   * @author <a href="mailto:schmitzm at bonn.edu">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class DataPoolSubMenu_Import extends DataPoolSubMenu_ObjectClasses {
+    /**
+     * Erzeugt ein "Import"-Untermenue.
+     * @param parent             Übergeordnete Aktions-Struktur
+     * @param itemActionListener wird den Menuepunkten zugeordnet und verarbeitet
+     *                           deren Auswahl
+     * @param registry           Xulu-Registry als Datenbasis
+     * @param reorganize         gibt, an ob das Menu bereits zur Instanziierung
+     *                           komplett (mit allen Untermenues) aufgebaut wird
+     */
+    public DataPoolSubMenu_Import(ActionStructure parent, ActionListener itemActionListener, XuluRegistry registry, boolean reorganize) {
+      super("Import", ACTION_IMPORT, parent, itemActionListener, registry.getImportFactories(), false);
+      if (reorganize)
+        reorganize();
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // Untermenue "Export"
+  /////////////////////////////////////////////////////////////////////
+//  /**
+//   * Diese Klasse stellt ein Untermenue "Export" dar.
+//   * Es beinhaltet eine Liste mit den in der Xulu-Registry registrierten
+//   * Export-Factorys.
+//   * @author <a href="mailto:schmitzm at bonn.edu">Martin Schmitz</a> (University of Bonn/Germany)
+//   * @version 1.0
+//   */
+//  public static class DataPoolSubMenu_Export extends ObjectSubMenu {
+//    private XuluRegistry registry;
+//
+//    /**
+//     * Erzeugt ein "Export"-Untermenue.
+//     * @param parent             Übergeordnete Aktions-Struktur
+//     * @param itemActionListener wird den Menuepunkten zugeordnet und verarbeitet
+//     *                           deren Auswahl
+//     * @param registry           Xulu-Registry als Datenbasis
+//     * @param reorganize         gibt, an ob das Menu bereits zur Instanziierung
+//     *                           komplett (mit allen Untermenues) aufgebaut wird
+//     */
+//    public DataPoolSubMenu_Export(ActionStructure parent, ActionListener itemActionListener, XuluRegistry registry, boolean reorganize) {
+//      super("Export", ACTION_EXPORT, parent, itemActionListener, false);
+//      this.registry = registry;
+//      if (reorganize)
+//        reorganize();
+//    }
+//
+//    /**
+//     * Reorganisiert das "Export"-Untermenue. Zunaecht werden alle Factory-Eintraege
+//     * geloescht und auf Basis der Xulu-Registry neu eingefuegt. Danach werden
+//     * alle (etwaigen) Untermenues reorganisiert.
+//     */
+//    public void reorganize() {
+//      reorganizeFactoryMenu(this,registry.getExportFactories());
+//      // SubMenus reorganisieren
+//      super.reorganize();
+//    }
+//  }
+
+  /**
+   * Diese Klasse stellt ein Untermenue "Export" dar.
+   * Es beinhaltet eine Liste mit den in der Xulu-Registry registrierten
+   * Export-Factorys.
+   * @author <a href="mailto:schmitzm at bonn.edu">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class DataPoolSubMenu_Export extends DataPoolSubMenu_ObjectClasses {
+    /**
+     * Erzeugt ein "Export"-Untermenue.
+     * @param parent             Übergeordnete Aktions-Struktur
+     * @param itemActionListener wird den Menuepunkten zugeordnet und verarbeitet
+     *                           deren Auswahl
+     * @param registry           Xulu-Registry als Datenbasis
+     * @param reorganize         gibt, an ob das Menu bereits zur Instanziierung
+     *                           komplett (mit allen Untermenues) aufgebaut wird
+     */
+    public DataPoolSubMenu_Export(ActionStructure parent, ActionListener itemActionListener, XuluRegistry registry, boolean reorganize) {
+      super("Export", ACTION_EXPORT, parent, itemActionListener, registry.getExportFactories(), false);
+      if (reorganize)
+        reorganize();
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////
+  // Untermenue "Display"
+  /////////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse stellt ein Untermenue "Display" dar.
+   * Es beinhaltet eine Liste mit den im VisualisationManager instanziierten
+   * Tools, sowie (in einem Untermenue "Neu") alle in Xulu-Registry registrierten
+   * Visualisierungstool-Klassen.
+   * @author <a href="mailto:schmitzm at bonn.edu">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class DataPoolSubMenu_Display extends ObjectSubMenu {
+    private XuluRegistry registry;
+
+    /**
+     * Erzeugt ein "Display"-Untermenue.
+     * @param parent             Übergeordnete Aktions-Struktur
+     * @param itemActionListener wird den Menuepunkten zugeordnet und verarbeitet
+     *                           deren Auswahl
+     * @param registry           Xulu-Registry als Datenbasis
+     * @param reorganize         gibt, an ob das Menu bereits zur Instanziierung
+     *                           komplett (mit allen Untermenues) aufgebaut wird
+     */
+    public DataPoolSubMenu_Display(ActionStructure parent, ActionListener itemActionListener, XuluRegistry registry, boolean reorganize) {
+      super("Display", ACTION_DISPLAY, parent, itemActionListener, false);
+      this.registry = registry;
+      insertSeparator(0);
+      add(new DataPoolSubMenu_ObjectClasses("Neu",ACTION_NEW,this,itemActionListener,registry.getVisualisationTools(), false));
+      if (reorganize)
+        reorganize();
+    }
+
+    /**
+     * Reorganisiert das "Display"-Untermenue. Es werden alle
+     * Visualisierungstool-Instanzen geloescht und auf Basis des
+     * Visualisation-Managers neu eingefuegt. Danach werden
+     * alle (etwaigen) Untermenues ("Neu") reorganisiert.
+     */
+    public void reorganize() {
+        // erst alle normalen Menue-Eintraege loeschen
+        for (int i = 0; i < getItemCount(); i++)
+          if ( getItem(i) instanceof ObjectMenuItem )
+            remove(i);
+
+        // VisualisationTool-Instanzen vorne neu einfuegen
+        VisualisationTool[] openTool = new VisualisationTool[0]; // visManager.getVisualisationTools();
+        for (int i = 0; i < openTool.length; i++) {
+          ObjectMenuItem item = new ObjectMenuItem(openTool[i].getTitle(),openTool[i],ActionStructure.ACTION_NONE,this);
+          item.addActionListener( itemActionListener );
+          insert(item, i);
+        }
+
+      // SubMenus reorganisieren
+      super.reorganize();
+    }
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/gui/DataPoolTreeModel.java
===================================================================
--- trunk/src/edu/bonn/xulu/gui/DataPoolTreeModel.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/gui/DataPoolTreeModel.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,192 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.gui;
+
+import javax.swing.tree.TreeModel;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeNode;
+import java.util.Enumeration;
+
+import schmitzm.data.property.Property;
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.MatrixProperty;
+import schmitzm.data.property.Properties;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.ListPropertyReadAccess;
+
+import schmitzm.data.event.ObjectListener;
+import schmitzm.data.event.ObjectEvent;
+import schmitzm.swing.tree.EmptyNode;
+import schmitzm.swing.tree.ContentNode;
+
+import edu.bonn.xulu.appl.DataPool;
+import edu.bonn.xulu.data.XuluObject;
+
+/**
+ * Diese Klasse stellt ein TreeModel fuer den {@link edu.bonn.xulu.appl.DataPool} dar.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class DataPoolTreeModel extends DefaultTreeModel {
+  private DataPool dataPool               = null;
+  private boolean  editable               = false;
+  private ObjectListener dataPoolListener = null;
+
+  /**
+   * Erzeugt ein neues Daten-Modell fuer einen Datenpool.
+   * @param dp Instanz eines Xulu-Datenpools
+   * @param editable bestimmt, ob die Baum-Eintraege editierbar sein duerfen
+   * @param rootName Bezeichnung fuer den Wurzelknoten
+   */
+  public DataPoolTreeModel(DataPool dp, boolean editable, String rootName) {
+    super( new EmptyNode(rootName) );
+    this.dataPool = dp;
+    this.editable = editable;
+    reorganize();
+    this.dataPoolListener = new ObjectListener() {
+      public void performObjectEvent(ObjectEvent e) {
+        DataPool.DataPoolChangeEvent dpEvent = (DataPool.DataPoolChangeEvent)e;
+        switch (dpEvent.getType()) {
+          // Objekt wurde hinzugefuegt
+          case DataPool.DataPoolChangeEvent.OBJECT_ADDED:
+            add( (XuluObject)dpEvent.getSource().getRoot() );
+            break;
+          // Objekt wurde entfernt
+          case DataPool.DataPoolChangeEvent.OBJECT_REMOVED:
+            remove( (XuluObject)dpEvent.getSource().getRoot() );
+            break;
+        }
+        reload();
+      }
+    };
+    dataPool.addObjectListener( dataPoolListener );
+  }
+
+  /**
+   * Zerstoert das Tree-Model.
+   */
+  public void finalize() throws Throwable {
+    dataPool.removeObjectListener( dataPoolListener );
+    super.finalize();
+  }
+
+  /**
+   * Baut den Baum komplett neu auf.
+   */
+  public void reorganize() {
+    ((EmptyNode)getRoot()).removeAllChildren();
+    // Fuer alle Xulu-Objekte einen Knoten einfuegen
+    for ( Enumeration e = dataPool.asEnumeration(); e.hasMoreElements(); )
+      add( (XuluObject)e.nextElement() );
+    reload();
+  }
+
+  /**
+   * Fuegt dem Baum auf der Root-Ebene ein Xulu-Objekt hinzu.
+   * @param obj hinzuzufuegendes Xulu-Objekt
+   */
+  public void add(XuluObject obj) {
+    ((EmptyNode)getRoot()).add( new XuluObjectNode(obj,editable) );
+  }
+
+  /**
+   * Entfernt ein Xulu-Objekt aus der Root-Ebene des Baums.
+   * @param obj zu entfernendes Xulu-Objekt
+   */
+  public void remove(XuluObject obj) {
+    // Knoten des Objekts suchen und entfernen
+    for (int i=0; i<((TreeNode)getRoot()).getChildCount();i++) {
+      ContentNode child = (ContentNode) ((EmptyNode)getRoot()).getChildAt(i);
+      if ( child.getUserObject() == obj )
+        ((EmptyNode)getRoot()).remove( i-- );
+    }
+  }
+
+  /**
+   * Diese Klasse stellt einen Baum-Knoten fuer ein {@link Properties}-Objekt dar.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  private class PropertiesNode extends ContentNode {
+    public PropertiesNode(Properties obj, boolean editable) {
+      super(obj,editable);
+      Property[] prop = obj.getProperties();
+      for (int i=0; i<prop.length; i++)
+        this.add( new PropertyNode(prop[i]) );
+    }
+  }
+
+  /**
+   * Diese Klasse stellt einen Baum-Knoten fuer ein {@link XuluObject}-Objekt dar.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  private class XuluObjectNode extends PropertiesNode {
+    public XuluObjectNode(XuluObject obj, boolean editable) {
+      super(obj,editable);
+    }
+
+    // bei Aenderung aendert sich der Name des Objekts
+    public void setUserObject(Object newValue) {
+      if ( newValue instanceof String && getUserObject() instanceof XuluObject )
+        ((XuluObject)getUserObject()).setDescription( (String)newValue );
+    }
+
+    // Xulu-Objekte haben eine spezielle Beschreibung
+    public String toString() {
+      return ((XuluObject)getUserObject()).getDescription();
+    }
+  }
+
+
+  /**
+   * Diese Klasse stellt einen Baum-Knoten fuer ein {@link Property}-Objekt dar.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  private class PropertyNode extends ContentNode {
+    public PropertyNode(Property prop) {
+      super(prop,prop.getName(),false);
+      if ( prop instanceof ScalarProperty )
+        expandNode(this,((ScalarProperty)prop).getOneTimeReadAccess().getValue(),"");
+      if ( prop instanceof ListProperty ) {
+        ListPropertyReadAccess lpa = ((ListProperty)prop).getReadAccess(this);
+        EmptyNode node = new EmptyNode("List["+prop.getPropertyType().getType().getSimpleName()+"] >> "+lpa.getCount());
+        for (int i=0; i<lpa.getCount(); i++)
+          expandNode(node,lpa.getValue(i),(i+1)+". ");
+        lpa.release();
+        add( node );
+      }
+      if ( prop instanceof MatrixProperty ) {
+        MatrixProperty m = (MatrixProperty)prop;
+        EmptyNode node = new EmptyNode(m.getSizeText()+"-Matrix["+prop.getPropertyType().getType().getSimpleName()+"]");
+        add( node );
+      }
+    }
+
+    private void expandNode(DefaultMutableTreeNode node, Object o, String namePrefix) {
+      if (o instanceof Property)
+        node.add(new PropertyNode( (Property) o));
+      else if (o instanceof Properties)
+        node.add(new PropertiesNode( (Properties) o, false));
+      else if (o != null)
+        node.add(new ContentNode(o,namePrefix+o.getClass().getSimpleName(),false));
+      else
+        node.add(new EmptyNode());
+    }
+
+
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/gui/ModelContentManagerContainer.java
===================================================================
--- trunk/src/edu/bonn/xulu/gui/ModelContentManagerContainer.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/gui/ModelContentManagerContainer.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,222 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.gui;
+
+import java.awt.Container;
+import java.awt.Color;
+import javax.swing.BoxLayout;
+import javax.swing.SpringLayout;
+import java.util.Enumeration;
+import java.util.Collection;
+import java.util.Vector;
+
+import schmitzm.swing.SpringUtilities;
+
+import schmitzm.data.property.Properties;
+import schmitzm.data.property.Property;
+import schmitzm.data.event.ObjectListener;
+import schmitzm.data.event.ObjectEvent;
+import schmitzm.data.event.NameChangeEvent;
+import schmitzm.swing.SelectionInputOption;
+
+import edu.bonn.xulu.appl.DataPool;
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.model.ModelContentManager;
+import edu.bonn.xulu.model.ModelResource;
+
+
+/**
+ * Diese Klasse stellt eine Container dar, ueber den die im Datenpool befindlichen
+ * Objekte den benoetigten Ressourcen eines Modells (siehe {@link ModelContentManager})
+ * durch den Anwender zugeordnet werden koennen.<br>
+ * Manuelle Eingaben (in Form eines Textfeldes) sind nicht moeglich. Fuer jede
+ * Ressource gibt es ein Auswahlfeld, in dem ein (passendes) Xulu-Objekt aus
+ * dem Datenpool oder eine seiner Propertys selektiert werden koennen.<br>
+ * Die Ressourcen werden nach folgender Regel farbig markiert:
+ * <ul>
+ * <li>Eingabe-Ressource >> GRUEN</li>
+ * <li>Ausgabe-Ressource >> BLAU</li>
+ * <li>Ein- und Ausgabe-Ressource >> ROT</li>
+ * <li>Temporaere Ressource >> ORANGE</li>
+ * </ul>
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class ModelContentManagerContainer extends Container {
+  /** Speichert eine Referenz auf den ContentManager */
+  protected ModelContentManager contManager = null;
+  /** Speichert eine Referenz auf den Datenpool */
+  protected DataPool dataPool = null;
+
+  private SelectionInputOption[] inputOption = null;
+  private ObjectListener         objectListener = null;
+
+  /**
+   * Erzeugt einen neuen Container.
+   * @param contentManager ModelContentManager, dem Daten zugeordnet werden
+   * @param dataPool       DatenPool, aus dem die Daten stammen
+   */
+  public ModelContentManagerContainer(ModelContentManager contentManager, DataPool dataPool) {
+    super();
+    this.contManager = contentManager;
+    this.dataPool    = dataPool;
+//    this.setLayout( new BoxLayout(this,BoxLayout.Y_AXIS) );
+    this.setLayout( new SpringLayout() );
+    // Auswahl-Optionen fuer Ressourcen erzeugen
+    this.inputOption = new SelectionInputOption[contManager.getResourceCount()];
+    for (int i=0; i<inputOption.length; i++) {
+      inputOption[i] = new SelectionInputOption.Combo(
+          "["+(i+1)+"] "+contManager.getResource(i).getDesc(),
+          !contManager.getResource(i).isNullable()
+      );
+      // je nach Kategorie erhaelt die Ressource eine andere Farbe
+      inputOption[i].getInputComponent().setBackground(
+          getColorForResource( contManager.getResource(i) )
+      );
+      // InputOption hinzufuegen
+      this.add(inputOption[i]);
+    }
+    // Komponenten in Form eines Grids anordnen
+    int cols = (inputOption.length-1) / 9   + 1; // max. 9 Zeilen pro Spalte
+    int rows = (inputOption.length-1) / cols + 1;
+    SpringUtilities.makeCompactGrid(this,rows,cols,0,0,10,10);
+
+    // Auswahl-Optionen fuer Ressourcen befuellen
+    reorganize();
+
+    // Listener auf den Datenpool, damit die Auswahlfelder automatisch
+    // erweitert/reduziert werden, wenn Objekte in den Datenpool eingefuegt,
+    // daraus entfernt werden, oder ihren Namen aendern
+    objectListener = new ObjectListener() {
+      public void performObjectEvent(ObjectEvent e) {
+        if ( e instanceof DataPool.DataPoolChangeEvent ) {
+          reorganize();
+        }
+      }
+    };
+    dataPool.addObjectListener( objectListener );
+  }
+
+  /**
+   * Liefert die Farb-Codierung fuer eine Ressource. Sub-Klassen koennen diese
+   * Methode ueberschreiben, um die Farb-Codierung zu aendern.
+   */
+  protected Color getColorForResource(ModelResource resource) {
+    if ( resource.isCategory( ModelResource.CATEGORY_TEMP ) )
+        return Color.ORANGE;
+    if ( resource.isCategoryAll( ModelResource.CATEGORY_INPUT | ModelResource.CATEGORY_OUTPUT) )
+        return Color.RED;
+    if ( resource.isCategoryAll( ModelResource.CATEGORY_INPUT ) )
+      return Color.GREEN;
+    if ( resource.isCategoryAll( ModelResource.CATEGORY_OUTPUT ) )
+      return Color.BLUE;
+    return Color.WHITE;
+  }
+  /**
+   * Zerstoert den Container.
+   */
+  public void dispose() {
+    this.removeAll();
+    dataPool.removeObjectListener(objectListener);
+  }
+
+  /**
+   * Deaktiviert den Container und alle darin enthalten Optionen.
+   */
+  public void setEnabled(boolean enabled) {
+    super.setEnabled(enabled);
+    for (int i=0; i<this.getComponentCount(); i++)
+      this.getComponent(i).setEnabled(enabled);
+  }
+
+  /**
+   * Belegt ein Ressourcen-Auswahlfeld mit einem Objekt.
+   * @param i          Nummer der Ressource
+   * @param objectName Im Auswahlfeld angezeigter Objekt-Name
+   */
+  public void setResourceByName(int i, String objectName) {
+    inputOption[i].setSelectedDisplayItem(objectName);
+  }
+
+  /**
+   * Belegt ein Ressourcen-Auswahlfeld mit einem Objekt.
+   * @param i      Nummer der Ressource
+   * @param object Passendes Objekt aus dem Datenpool (muss in der Auswahl
+   *               vorhanden sein!)
+   */
+  public void setResourceByObject(int i, Object object) {
+    inputOption[i].setSelectedItem(object);
+  }
+
+  /**
+   * Aktualisiert die Auswahlfelder.
+   */
+  public void reorganize() {
+    Vector         objects = new Vector<Object>();
+    Vector<String> names   = new Vector<String>();
+
+    for (int i=0; i<inputOption.length; i++) {
+      ModelResource resource = contManager.getResource(i);
+
+      objects.clear();
+      names.clear();
+      XuluGUIUtil.determineObjectsFromDataPool(resource,dataPool,objects,names);
+
+      inputOption[i].setSelectionObjects(objects.toArray(),names.toArray(new String[0]));
+    }
+
+    this.validate();
+  }
+
+  /**
+   * Liefert alle in den Eingabe-Optionen ausgewaehlten Objekte des Datenpools.
+   */
+  public Object[] getSelection() {
+    Object[] selection = new Object[contManager.getResourceCount()];
+
+//    //===================================================================
+//    // ZUM TESTEN DES CLUE-MODELLS
+//    // Ressourcen automatisch zuordnen, wenn erste Option nicht zugeordnet ist
+//    if ( contManager instanceof edu.bonn.xulu.plugin.model.ClueModelContentManager &&
+////         inputOption != null &&
+//         inputOption[0].getSelectedIndex() == -1) {
+//      inputOption[ClueModelContentManager.MODELSTEPS].setSelectedItem(      dataPool.getObjects("Clue-Parameter")[0].getProperty("Step Count") );
+//      inputOption[ClueModelContentManager.TOLERANCETYPE].setSelectedItem(   dataPool.getObjects("Clue-Parameter")[0].getProperty("Demand Tolerance Type") );
+//      inputOption[ClueModelContentManager.TOLERANCESINGLE].setSelectedItem( dataPool.getObjects("Clue-Parameter")[0].getProperty("Single Demand Tolerance") );
+//      inputOption[ClueModelContentManager.TOLERANCEAVERAGE].setSelectedItem(dataPool.getObjects("Clue-Parameter")[0].getProperty("Average Demand Tolerance") );
+//      inputOption[ClueModelContentManager.CONVFACTQM].setSelectedItem(      dataPool.getObjects("Clue-Parameter")[0].getProperty("Demand Conversion") );
+//      inputOption[ClueModelContentManager.BASESCENARIO].setSelectedItem(    dataPool.getObjects("Base LU Scenario")[0].getProperty("Grid") );
+//      inputOption[ClueModelContentManager.LUHISTORY].setSelectedItem(       dataPool.getObjects("Base LU History")[0].getProperty("Grid") );
+//      inputOption[ClueModelContentManager.LUCONV].setSelectedItem(          dataPool.getObjects("Clue-Parameter")[0].getProperty("LU Conversion Matrix") );
+//      inputOption[ClueModelContentManager.ELASTICITY].setSelectedItem(      dataPool.getObjects("Clue-Parameter")[0].getProperty("Conversion Elasticity") );
+//      inputOption[ClueModelContentManager.AREARESTR].setSelectedItem(       dataPool.getObjects("Area Restrictions")[0].getProperty("Grid") );
+//      inputOption[ClueModelContentManager.DEMAND].setSelectedItem(          dataPool.getObjects("Clue-Parameter")[0].getProperty("Demand Scenario") );
+//      inputOption[ClueModelContentManager.STATDF].setSelectedItem(          dataPool.getObjects("Static Driving Forces")[0] );
+//      inputOption[ClueModelContentManager.DYNDFTYPES].setSelectedItem(      dataPool.getObjects("Clue-Parameter")[0].getProperty("Dynamic Driving Forces") );
+//      inputOption[ClueModelContentManager.DYNDF].setSelectedItem(           dataPool.getObjects("Dynamic Driving Forces")[0] );
+//      inputOption[ClueModelContentManager.REGRESSION].setSelectedItem(      dataPool.getObjects("Clue-Parameter")[0].getProperty("Regression Results") );
+//      inputOption[ClueModelContentManager.NBHWEIGHTS].setSelectedItem(      dataPool.getObjects("Clue-Parameter")[0].getProperty("Neighborhood Weights") );
+//      inputOption[ClueModelContentManager.NBHSETTINGS].setSelectedItem(     dataPool.getObjects("Clue-Parameter")[0].getProperty("Neighborhood Settings") );
+//      inputOption[ClueModelContentManager.NBHREGRESSION].setSelectedItem(   dataPool.getObjects("Clue-Parameter")[0].getProperty("Neighborhood Regression") );
+//      inputOption[ClueModelContentManager.ACTLU].setSelectedItem(           dataPool.getObjects("Out: Actual LU")[0].getProperty("Grid") );
+//      inputOption[ClueModelContentManager.ACTLUHISTORY].setSelectedItem(    dataPool.getObjects("Out: Actual LU History")[0].getProperty("Grid") );
+//      inputOption[ClueModelContentManager.LUPROB].setSelectedItem(          dataPool.getObjects("Out: LU Probabilities")[0] );
+//      inputOption[ClueModelContentManager.NBHPROB].setSelectedItem(         dataPool.getObjects("Out: Neighborhood Probabilities")[0] );
+//      inputOption[ClueModelContentManager.ITERVAR].setSelectedItem(         dataPool.getObjects("Clue-Parameter")[0].getProperty("Iteration Variables") );
+//      inputOption[ClueModelContentManager.STEPRESULTS].setSelectedItem(     dataPool.getObjects("Out: Step Results")[0] );
+//    }
+    //===================================================================
+    for (int i=0; i<contManager.getResourceCount(); i++)
+      selection[i] = ((SelectionInputOption)getComponent(i)).getValue();
+    return selection;
+  }
+}

Added: trunk/src/edu/bonn/xulu/gui/ModelControlFrame.java
===================================================================
--- trunk/src/edu/bonn/xulu/gui/ModelControlFrame.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/gui/ModelControlFrame.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,76 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.gui;
+
+import javax.swing.JFrame;
+
+import edu.bonn.xulu.model.XuluModel;
+import edu.bonn.xulu.appl.AbstractManager;
+
+
+// nur fuer Doku
+import edu.bonn.xulu.gui.XuluInternalFrame;
+import edu.bonn.xulu.gui.DataPoolFrame;
+import edu.bonn.xulu.gui.RegistryFrame;
+
+/**
+ * Diese Klasse bildet eine abstrakte Oberklasse fuer alle Implementierungen des
+ * Modell-Kontroll-Fensters. Die Modellfenster werden (im Gegensatz z.B. zum
+ * {@linkplain DataPoolFrame Datenpool} oder der {@linkplain RegistryFrame Registry})
+ * nicht in das Hauptfenster der {@linkplain XuluMainFrame Xulu-Applikation}
+ * integriert, sondern stellen unabhaengige Fenster da. Deshalb sind sie keine
+ * Unterklassen von {@link XuluInternalFrame}, sondern von {@link JFrame}.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class ModelControlFrame extends JFrame implements AbstractManager.ContentType {
+  /** Speichert die zugehoerige Xulu-Modell-Instanz */
+  protected XuluModel model = null;
+
+  /**
+   * Erzeugt einen neue Instanz des grafischen Modell-Konroll-Fensters. Dieses
+   * erhaelt als Namen die Bezeichunng des Modells.
+   */
+  public ModelControlFrame(XuluModel model) {
+    super(model.getName());
+    this.model = model;
+  }
+
+  /**
+   * Liefert das dem Kontrollfenster zugeordnete Modell.
+   */
+  public XuluModel getModel() {
+    return this.model;
+  }
+
+  /**
+   * Aktualisiert die grafische Darstellung des internen Kontrollfensters.
+   */
+  public abstract void refresh();
+
+  /**
+   * Prueft, ob zwei Modell-Kontrollfenster gleich sind. Da im ModellManager keine
+   * zwei Modelle den gleichen Namen haben sollen, gelten zwei Modell-Kontrollfenster
+   * bereits als gleich, wenn <b>sie die gleiche Bezeichnung besitzen</b>!
+   * @param o anderes Objekt
+   * @see #getTitle()
+   */
+  public boolean equals(Object o) {
+    if ( !(o instanceof ModelControlFrame) )
+      return false;
+    ModelControlFrame otherFrame = (ModelControlFrame)o;
+    return o != null &&
+         ( this.getTitle() == null && otherFrame.getTitle() == null ||
+           this.getTitle().equals( otherFrame.getTitle() ) );
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/gui/ModelManagerTreeModel.java
===================================================================
--- trunk/src/edu/bonn/xulu/gui/ModelManagerTreeModel.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/gui/ModelManagerTreeModel.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,102 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.gui;
+
+import javax.swing.tree.DefaultTreeModel;
+
+import schmitzm.swing.tree.EmptyNode;
+import schmitzm.swing.tree.ContentNode;
+
+import edu.bonn.xulu.appl.ModelControlManager;
+import edu.bonn.xulu.model.XuluModel;
+
+// nur fuer Doku
+import schmitzm.swing.TreeSelectionDialog;
+
+/**
+ * Diese Klasse stellt ein TreeModel fuer den {@link ModelControlManager Xulu-Modell-Manager}
+ * dar. Zwar handelt es sich bei den Modellen lediglich um eine Liste, die
+ * eigentlich kein Baumstruktur erfordert, jedoch wird das <code>ModelManagerTreeModel</code>
+ * dazu genutzt, Xulu-Datenobjekte und Xulu-Modelle in einem <b>gemeinsamen</b>
+ * Eingabe-Dialog zur Auswahl zu stellen.
+ * @see ObjectOrModelInputOption
+ * @see TreeSelectionDialog
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class ModelManagerTreeModel extends DefaultTreeModel {
+  private ModelControlManager modelManager = null;
+
+  /**
+   * Erzeugt ein neues Daten-Modell fuer einen {@link ModelControlManager Modell-Manager}.
+   * Die Baum-Eintraege sind <b>nicht</b> editierbar.
+   * @param mm Instanz eines Modell-Managers
+   * @param rootName Bezeichnung fuer den Wurzelknoten
+   */
+  public ModelManagerTreeModel(ModelControlManager mm, String rootName) {
+    super( new EmptyNode(rootName) );
+    this.modelManager = mm;
+    reorganize();
+
+//    dp.addObjectListener( new ObjectListener() {
+//      public void performObjectEvent(ObjectEvent e) {
+//        DataPool.DataPoolChangeEvent dpEvent = (DataPool.DataPoolChangeEvent)e;
+//        switch (dpEvent.getType()) {
+//          // Objekt wurde hinzugefuegt
+//          case DataPool.DataPoolChangeEvent.OBJECT_ADDED:
+//            add( (XuluObject)dpEvent.getSource().getRoot() );
+//            break;
+//          // Objekt wurde entfernt
+//          case DataPool.DataPoolChangeEvent.OBJECT_REMOVED:
+//            remove( (XuluObject)dpEvent.getSource().getRoot() );
+//            break;
+//        }
+//        reload();
+//      }
+//    });
+  }
+
+  /**
+   * Baut den Baum komplett neu auf.
+   */
+  public void reorganize() {
+    ((EmptyNode)getRoot()).removeAllChildren();
+    // Fuer alle Modelle einen Knoten einfuegen
+    for ( int i=0; i<modelManager.getCount(); i++ )
+      add( ((ModelControlFrame)modelManager.get(i)).getModel() );
+    reload();
+  }
+
+  /**
+   * Fuegt dem Baum auf der Root-Ebene ein Xulu-Modell hinzu.
+   * @param model hinzuzufuegendes Xulu-Modell
+   */
+  public void add(XuluModel model) {
+    ((EmptyNode)getRoot()).add( new ModelNode(model) );
+  }
+
+
+  /**
+   * Stellt einen Baum-Knoten fuer ein Xulu-Modell dar.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  private class ModelNode extends ContentNode {
+    /**
+     * Erzeugt einen neuen Modell-Knoten
+     * @param model Xulu-Model, das durch den Knoten repraesentiert wird
+     */
+    public ModelNode(XuluModel model) {
+      super(model,model.getName(),false);
+    }
+  }
+}

Added: trunk/src/edu/bonn/xulu/gui/ObjectOrModelInputOption.java
===================================================================
--- trunk/src/edu/bonn/xulu/gui/ObjectOrModelInputOption.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/gui/ObjectOrModelInputOption.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,114 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.gui;
+
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.MutableTreeNode;
+
+import schmitzm.swing.TreeSelectionDialog;
+import schmitzm.swing.tree.EmptyNode;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.DataPool;
+import edu.bonn.xulu.appl.ModelControlManager;
+import edu.bonn.xulu.appl.XuluConstants;
+import edu.bonn.xulu.model.XuluModel;
+
+// nur fuer Doku
+import schmitzm.swing.MultipleOptionPane;
+
+/**
+ * Diese Klasse stellt eine Eingabe-Option fuer einen {@link MultipleOptionPane}-Dialog
+ * dar, in der ein Daten-Objekt aus dem {@linkplain DataPool Xulu-Datenpool}
+ * oder ein Modell aus dem {@linkplain ModelControlManager Xulu-Modell-Manager}
+ * eingegeben werden kann. Hierzu besteht fuer den Anwender die Moeglichkeit,
+ * ueber einen Browse-Dialog aus allen vorhandenen Datenpool-Objekten -und
+ * Modellen auszuwaehlen.<br>
+ * <br>
+ * Zur Zeit ist die manuelle Eingabe eines Objekts in das Textfeld der Eingabe-Option
+ * gesperrt (es kann nur gebrowsed werden). Die Methode {@link #convertFromString(String)}
+ * muss noch implementiert werden.
+ * @todo Manuelle Eingabe eines Objekts implementieren
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class ObjectOrModelInputOption extends DataPoolInputOption {
+  /** Speichert die Xulu-Applikation. */
+  protected XuluModellingPlatform appl = null;
+
+  /**
+   * Erzeugt einen neu Input-Option
+   * @param appl Xulu-Applikation die die Datenbasis (Xulu-Objekte und Modelle) bereitstellt
+   * @param label Beschreibung der Eingabe-Option
+   * @param inputNeeded bestimmt, ob eine Eingabe erforderlich (oder optional) ist
+   * @param defValue Standardwert fuer die Eingabe-Option
+   */
+  public ObjectOrModelInputOption(XuluModellingPlatform appl, String label, boolean inputNeeded, Object defValue) {
+    super(appl.getDataPool(), label, inputNeeded, defValue);
+    this.appl = appl;
+
+    // Eingabe-Feld sperren (bis Objekterkennung aus manuellem Textstring
+    // implementiert ist!)
+    inpComp.setEnabled(false);
+  }
+
+  /**
+   * Fuehrt die Browse-Aktion aus, wenn der Anwender auf den entsprechenden
+   * Button der Eingabe-Option klickt. Es wird ein Anwender-Dialog angezeigt,
+   * der in einer Baumstruktur alle Datenpool-Objekte und Modelle zur Auswahl stellt.
+   * @param defValue Standard-Auswahl fuer den Browse-Dialog (wird <b>nicht</b> genutzt!)
+   * @return <code>null</code> wenn der Browse-Dialog abgebrochen wurde
+   * @see TreeSelectionDialog
+   */
+  public Object performBrowse(Object defValue) {
+    TreeSelectionDialog dialog = new TreeSelectionDialog(new ObjectOrModellChoseTreeModel(appl.getDataPool(), appl.getModelControlManager()));
+    // Objekt von Anwender abfragen
+    Object[] o = dialog.show(this,XuluConstants.XULUGUI_RES.getString("EventObject"),false);
+    if ( o == null || o.length < 1 )
+      return null; // Dialog abgebrochen
+    return o[0];
+  }
+
+  /**
+   * <b>Noch nicht implementiert</b><br>
+   * Parst eine textuellen Angabe und liefert ein entsprechendes Objekt aus dem
+   * Datenpool oder Modell-Manager.
+   * @param objectStr String, der das Datenpool-Objekt (bzw. Modell) identifiziert.
+   * @exception UnsupportedOperationException bei <b>jedem</b> Aufruf
+   */
+  public Object convertFromString(String objectStr) {
+    throw new UnsupportedOperationException(XuluConstants.SWING_RES.getString("InvalidInputMess"));
+  }
+
+  /**
+   * Liefert die textuelle Bezeichnung zu einem Datenpool-Objekt, bzw. Modell.
+   * @param object Datenpool-Objekt oder Xulu-Modell
+   */
+  public String convertToString(Object object) {
+    if ( object instanceof XuluModel )
+      return ((XuluModel)object).getName();
+    return super.convertToString(object);
+  }
+
+  /**
+   * Diese Klasse stellt ein TreeModel dar, in dem es zwei Root-Knoten gibt.
+   * Unterhalb des ersten werden alle Datenpool-Objekte aufgefuehrt und
+   * unterhalb des anderen alle geladenen Modelle.
+   */
+  private static class ObjectOrModellChoseTreeModel extends DefaultTreeModel {
+    public ObjectOrModellChoseTreeModel(DataPool dp, ModelControlManager mm) {
+      super(new EmptyNode("ROOT"));
+      ((EmptyNode)root).add( (MutableTreeNode)new DataPoolTreeModel(dp, false, XuluConstants.XULUGUI_RES.getString("Comp_DataPool")).getRoot());
+      ((EmptyNode)root).add( (MutableTreeNode)new ModelManagerTreeModel(mm, XuluConstants.XULUGUI_RES.getString("Comp_Models")).getRoot());
+    }
+  }
+}

Added: trunk/src/edu/bonn/xulu/gui/RegistryFrame.java
===================================================================
--- trunk/src/edu/bonn/xulu/gui/RegistryFrame.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/gui/RegistryFrame.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,36 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.gui;
+
+/**
+ * Diese Klasse bildet eine abstrakte Oberklasse fuer alle grafischen
+ * Implementierungen der Xulu-Registry.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class RegistryFrame extends XuluInternalFrame{
+  /**
+   * Erzeugt einen neue Instanz des grafischen Registry-Fensters. Dieses hat
+   * den Namen "Xulu-Registry"
+   */
+  public RegistryFrame() {
+    super(XULUGUI_RES.getString("Comp_Registry"));
+  }
+
+//  /**
+//   * Liefert die Objekt, welches aktuell in der Registry Datenpool ausgewaehlt sind.
+//   * Mit diesen Objekten werden Aktionen durchgefuhrt, wenn ein Kontextmenu
+//   * aktiviert wurde.
+//   * @return <code>null</code> wenn noch kein Kontextmenue aufgerufen wurde.
+//   */
+//  public abstract Object[] getSelectedObjects();
+}

Added: trunk/src/edu/bonn/xulu/gui/StatusFrame.java
===================================================================
--- trunk/src/edu/bonn/xulu/gui/StatusFrame.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/gui/StatusFrame.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,64 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.gui;
+
+import java.io.PrintStream;
+import java.io.OutputStream;
+import javax.swing.JMenu;
+import edu.bonn.xulu.XuluModellingPlatform;
+import java.awt.event.ActionListener;
+import schmitzm.swing.event.PopupMenuListener;
+import java.awt.Dimension;
+
+/**
+ * Diese Klasse bildet eine abstrakte Oberklasse fuer alle grafischen
+ * Implementierungen des Status-Fensters.<br>
+ * Darin koennen beliebige Statusmeldungen ausgegeben werden. Dies kann ueber
+ * einzelne Zeilen geschehen ({@link #print(String)}, {@link #println(String)})
+ * oder ueber einen {@link #out PrintStream}. So ist es z.B. auch moeglich
+ * mittels {@link System#setErr(PrintStream)} die Standard-Fehlerausgabe auf
+ * dieses Fenster umzulenken.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class StatusFrame extends XuluInternalFrame {
+  /** Ausgabe-Stream, der an die interne Text-Komponente des Statusfensters gekoppelt ist.
+   *  Ruft sukzessibve {@link #print(String)} fuer jedes in den <code>PrintStream</code>
+   *  geschriebene Zeichen auf.*/
+  public final PrintStream out = new PrintStream(new OutputStream() {
+    public void write(int b) {
+      print( String.valueOf((char)b) );
+    }
+  });
+
+  /**
+   * Erzeugt einen neue Instanz des grafischen Status-Fensters. Dieses hat
+   * den Namen "Status-Ausgaben".
+   */
+  public StatusFrame() {
+    super(XULUGUI_RES.getString("Comp_Log"));
+  }
+
+  /**
+   * Schreibt einen Text in das Statusfenster (ohne anschliessenden Zeilenumbruch!).
+   */
+  public abstract void print(String text);
+
+  /**
+   * Schreibt einen Text mit anschliessendem Zeilenumbruch in das
+   * Statusfenster.
+   */
+  public void println(String text) {
+    print(text);
+    print("\n");
+  }
+}

Added: trunk/src/edu/bonn/xulu/gui/XuluErrorResource.20080424
===================================================================
--- trunk/src/edu/bonn/xulu/gui/XuluErrorResource.20080424	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/gui/XuluErrorResource.20080424	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,76 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.gui;
+
+import schmitzm.lang.HashtableResourceBundle;
+
+/**
+ * Dieses ResourceBundle stellt folgende Objekte fuer die Xulu-GUI zur Verfuegung.
+ * <table align=center border=2 cellpadding=5><code>
+ * <tr><th>Key</th><th>Ressource</th></tr>
+ * <tr><td><code>Access</code></td><td>"Zugriffsrecht"</td></tr>
+ * <tr><td><code>ReadAccess</code></td><td>"Leserecht"</td></tr>
+ * <tr><td><code>WriteAccess</code></td><td>"Schreibrecht"</td></tr>
+ * <tr><td><code>AccessError</code></td><td>"Zugriffsfehler"</td></tr>
+ * <tr><td><code>AccessErrMess_1</code></td><td>"Sie haben (zur Zeit) kein"</td></tr>
+ * <tr><td><code>AccessErrMess_2</code></td><td>"auf dieses Objekt"</td></tr>
+ * <tr><td><code>DataTypeError</code></td><td>"Datentyp-Fehler"</td></tr>
+ * <tr><td><code>TypeConvErrMess</code></td><td>"Typumwandunlung kann nicht vorgenommen werden"</td></tr>
+ * <tr><td><code>InstantiationError</code></td><td>"Instanziierungs-Fehler"</td></tr>
+ * <tr><td><code>InstantiationErrMess</code></td><td>"Klasse muss instanziierbar sein! Abstrakte Klassen oder Interfaces sind nicht zulaessig!"</td></tr>
+ * <tr><td><code>ClassCastError</code></td><td>"Cast-Fehler"</td></tr>
+ * <tr><td><code>InstExpMess_1</code></td><td>"Instanz von"</td></tr>
+ * <tr><td><code>InstExpMess_2</code></td><td>"erwartet!"</td></tr>
+ * <tr><td><code>DataError</code></td><td>"Daten-Fehler"</td></tr>
+ * <tr><td><code>DuplXuluObjectNameMessIntro</code></td><td>"Es gibt bereits ein Datenpool-Objekt"</td></tr>
+ * <tr><td><code>DuplXuluModelNameMessIntro</code></td><td>"Es gibt bereits ein Modell"</td></tr>
+ * <tr><td><code>ClassError</code></td><td>"Klassen-Fehler"</td></tr>
+ * <tr><td><code>ClassNotFoundErrMess</code></td><td>"Die angegebene Klasse konnte nicht gefunden werden"</td></tr>
+ * <tr><td><code>NoEvents</code></td><td>"Keine Ereignisse fuer dieses Objekt verfuegbar!"</td></tr>
+ * <tr><td><code>NoHandler</code></td><td>"Keine Handler fuer dieses Objekt verfuegbar!"</td></tr>
+ * </table>
+ * Diese Ressourcen werden in der Xulu-Standard-GUI verwendet. Fuer die einzelnen
+ * PlugIns sollten eigene ResourceBundles erstellt werden.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class XuluErrorResource extends HashtableResourceBundle {
+  /**
+   * Liefert die (Key/Wert)-Paerchen. Die Keys (erste Dimension) muessen aus Strings
+   * bestehen.
+   */
+  public Object[][] getContents() {
+    return new Object[][] {
+        {"Access","Zugriffsrecht"},
+        {"ReadAccess","Leserecht"},
+        {"WriteAccess","Schreibrecht"},
+        {"AccessError","Zugriffsfehler"},
+        {"AccessErrMess_1","Sie haben (zur Zeit) kein"},
+        {"AccessErrMess_2","auf dieses Objekt"},
+        {"DataTypeError","Datentyp-Fehler"},
+        {"TypeConvErrMess","Typumwandunlung kann nicht vorgenommen werden"},
+        {"InstantiationError","Instanziierungs-Fehler"},
+        {"InstantiationErrMess","Klasse muss instanziierbar sein! Abstrakte Klassen oder Interfaces sind nicht zulaessig!"},
+        {"ClassCastError","Cast-Fehler"},
+        {"InstExpMess_1","Instanz von"},
+        {"InstExpMess_2","erwartet!"},
+        {"DataError","Daten-Fehler"},
+        {"DuplXuluObjectNameMessIntro","Es gibt bereits ein Datenpool-Objekt"},
+        {"DuplModelNameMessIntro","Es gibt bereits ein Modell"},
+        {"ClassError","Klassen-Fehler"},
+        {"ClassNotFoundErrMess","Die angegebene Klasse konnte nicht gefunden werden"},
+        {"NoEvents","Keine Ereignisse für dieses Objekt verfügbar!"},
+        {"NoHandler","Keine Handler für dieses Objekt verfügbar!"}
+    };
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/gui/XuluErrorResource_en.20080424
===================================================================
--- trunk/src/edu/bonn/xulu/gui/XuluErrorResource_en.20080424	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/gui/XuluErrorResource_en.20080424	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,73 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.gui;
+
+
+/**
+ * Dieses ResourceBundle stellt englische Objekte fuer die Xulu-GUI zur Verfuegung.
+ * <table align=center border=2 cellpadding=5><code>
+ * <tr><th>Key</th><th>Ressource</th></tr>
+ * <tr><td><code>Access</code></td><td>"access"</td></tr>
+ * <tr><td><code>ReadAccess</code></td><td>"read access"</td></tr>
+ * <tr><td><code>WriteAccess</code></td><td>"write access"</td></tr>
+ * <tr><td><code>AccessError</code></td><td>"Access violation"</td></tr>
+ * <tr><td><code>AccessErrMess_1</code></td><td>"You don't have"</td></tr>
+ * <tr><td><code>AccessErrMess_2</code></td><td>"to this object at the time"</td></tr>
+ * <tr><td><code>DataTypeError</code></td><td>"Data type error"</td></tr>
+ * <tr><td><code>TypeConvErrMess</code></td><td>"Typ cast not possible"</td></tr>
+ * <tr><td><code>ClassCastError</code></td><td>"Class cast error"</td></tr>
+ * <tr><td><code>InstExpMess_1</code></td><td>"Instance of"</td></tr>
+ * <tr><td><code>InstExpMess_2</code></td><td>"expected!"</td></tr>
+ * <tr><td><code>DataError</code></td><td>"Data error"</td></tr>
+ * <tr><td><code>DuplXuluObjectNameMessIntro</code></td><td>"Datapool already contains an object with name"</td></tr>
+ * <tr><td><code>DuplModelNameMessIntro</code></td><td>"Xulu already contains a model with name"</td></tr>
+ * <tr><td><code>ClassError</code></td><td>"Class error"</td></tr>
+ * <tr><td><code>ClassNotFoundErrMess</code></td><td>"The indicated class could not be found"</td></tr>
+ * <tr><td><code>NoEvents</code></td><td>"No events available for this object!"</td></tr>
+ * <tr><td><code>NoHandler</code></td><td>"No handler available for this object!"</td></tr>
+ * </table>
+ * Diese Ressourcen werden in der Xulu-Standard-GUI verwendet. Fuer die einzelnen
+ * PlugIns sollten eigene ResourceBundles erstellt werden.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class XuluErrorResource_en extends XuluGUIResource {
+  /**
+   * Liefert die (Key/Wert)-Paerchen. Die Keys (erste Dimension) muessen aus Strings
+   * bestehen.
+   */
+  public Object[][] getContents() {
+    return new Object[][] {
+        {"Access","access"},
+        {"ReadAccess","read access"},
+        {"WriteAccess","write access"},
+        {"AccessError","Access violation"},
+        {"AccessErrMess_1","You don't have"},
+        {"AccessErrMess_2","to this object at the time"},
+        {"DataTypeError","Data type error"},
+        {"TypeCastErrMess","Typ cast not possible"},
+        {"InstantiationError","Instantiation error"},
+        {"InstantiationErrMess","Class must be instantiable! Abstact classes or interfaces are not allowed!"},
+        {"ClassCastError","Class cast error"},
+        {"InstExpMess_1","Instance of"},
+        {"InstExpMess_2","expected!"},
+        {"DataError","Data error"},
+        {"DuplXuluObjectNameMessIntro","Datapool already contains an object with name"},
+        {"DuplModelNameMessIntro","Xulu already contains a model with name"},
+        {"ClassError","Class error"},
+        {"ClassNotFoundErrMess","The indicated class could not be found"},
+        {"NoEvents","No events available for this object!"},
+        {"NoHandler","No handler available for this object!"}
+    };
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/gui/XuluGUIMessages.java
===================================================================
--- trunk/src/edu/bonn/xulu/gui/XuluGUIMessages.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/gui/XuluGUIMessages.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,248 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.gui;
+
+import java.awt.Component;
+import javax.swing.JOptionPane;
+import java.util.ResourceBundle;
+import java.io.File;
+
+
+import schmitzm.lang.LangUtil;
+import schmitzm.swing.ExceptionDialog;
+import schmitzm.data.property.AccessViolationException;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.PropertyWriteAccess;
+
+import edu.bonn.xulu.appl.XuluConstants;
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.data.XuluDataException;
+import schmitzm.swing.MultipleOptionPane;
+import javax.swing.JCheckBox;
+
+
+/**
+ * Diese Klasse enthaelt statische Methoden zur Anzeige von GUI-Messages
+ * ({@link javax.swing.JOptionPane}.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class XuluGUIMessages implements XuluConstants {
+  /** Auswahl von {@link #checkFileOverwrite(Component,File,boolean)} und
+   *  {@link #approveFileOverwrite(Component,String,boolean)} */
+  public static enum FileOverrideOption {
+    /** Dialog wurde abgebrochen. */
+    CANCEL,
+    /** Auswahl "Ueberschreiben". */
+    OVERWRITE,
+    /** Auswahl "Immer ueberschreiben". */
+    OVERWRITE_ALL
+  }
+
+  /**
+   * Prueft, ob eine Datei existiert und fordert gegenfalls zum Bestaetigen
+   * des Ueberschreiben auf.
+   * @param parent Uebergeordnete GUI-Komponente fuer die Meldung
+   * @param file zu ueberpruefende Datei
+   * @param owAllOption Flag, ob die Option "Alle ueberschreiben" zur Auswahlt
+   *                    gestellt wird
+   * @return {@link FileOverrideOption#CANCEL} falls der Dialog abgebrochen wurde;
+   *         {@link FileOverrideOption#OVERWRITE} falls das Ueberschreiben
+   *         bestaetigt wurde; {@link FileOverrideOption#OVERWRITE_ALL} falls
+   *         das Ueberschreiben generell bestaetigt wurde
+   */
+  public static FileOverrideOption checkFileOverwrite(Component parent, File file, boolean owAllOption) {
+    if ( !file.exists() )
+      return FileOverrideOption.OVERWRITE;
+    return approveFileOverwrite(parent, file.getName(), owAllOption);
+  }
+
+  /**
+   * Zeigt einen Dialog an, in dem das Ueberschreiben einer Datei bestaetigt
+   * werden muss.
+   * @param parent Uebergeordnete GUI-Komponente fuer die Meldung
+   * @param filename Bezeichnung der Datei
+   * @param owAllOption Flag, ob die Option "Alle ueberschreiben" zur Auswahlt
+   *                    gestellt wird
+   * @return {@link FileOverrideOption#CANCEL} falls der Dialog abgebrochen wurde;
+   *         {@link FileOverrideOption#OVERWRITE} falls das Ueberschreiben
+   *         bestaetigt wurde; {@link FileOverrideOption#OVERWRITE_ALL} falls
+   *         das Ueberschreiben generell bestaetigt wurde
+   */
+  public static FileOverrideOption approveFileOverwrite(Component parent, String filename, boolean owAllOption) {
+    // Fehler-Dialog
+    // --> Abfrage Abbrechen / Ueberschreiben / Immer ueberschreiben
+    String cancelOption = SWING_RES.getString("Cancel");
+    String overwriteOption = SWING_RES.getString("Overwrite");
+    String overwriteAllOption = SWING_RES.getString("OverwriteAll");
+    Object selection = MultipleOptionPane.showMultipleOptionDialog(
+        parent,
+        JOptionPane.WARNING_MESSAGE,
+        SWING_RES.getString("Warning")+"...",
+        SWING_RES.getString("FileExists")+": "+filename,
+        owAllOption ? new String[] {cancelOption, overwriteOption, overwriteAllOption} : new String[] {cancelOption, overwriteOption},
+        cancelOption
+        );
+    // Ueberschreiben
+    if (overwriteOption.equals(selection))
+      return FileOverrideOption.OVERWRITE;
+    // Immer ueberschreiben
+    if (overwriteAllOption.equals(selection))
+      return FileOverrideOption.OVERWRITE_ALL;
+    // Abbrechen
+    return FileOverrideOption.CANCEL;
+  }
+
+  /**
+   * Zeigt eine allgemeine Fehlermeldung (fuer alle "unbekannten" Fehler) an.
+   * @param parent Uebergeordnete GUI-Komponente fuer die Meldung
+   * @param err    Fehler der aufgetreten ist
+   */
+  public static void showError(Component parent, Exception err) {
+    showError(parent,err,null);
+  }
+
+  /**
+   * Zeigt eine allgemeine Fehlermeldung (fuer alle "unbekannten" Fehler) an.
+   * @param parent Uebergeordnete GUI-Komponente fuer die Meldung
+   * @param mess   Fehlerbeschreibung
+   */
+  public static void showError(Component parent, String mess) {
+    showError(parent,null,mess);
+  }
+
+  /**
+   * Zeigt eine allgemeine Fehlermeldung (fuer alle "unbekannten" Fehler) an.
+   * @param parent  Uebergeordnete GUI-Komponente fuer die Meldung
+   * @param err     Fehler der aufgetreten ist
+   * @param addMess Zusaetzliche Fehlermeldung
+   */
+  public static void showError(Component parent, Exception err, String addMess) {
+    String mess = (addMess==null) ? "" : addMess;
+    if ( err!=null && err.getMessage()!=null && !err.getMessage().equals("") ) {
+      if (!mess.equals(""))
+        mess = mess.concat(":  ");
+      mess = mess.concat(err.getMessage());
+    }
+
+    String title = (err!=null) ? err.getClass().getSimpleName() : SWING_RES.getString("Error");
+    ExceptionDialog.show(parent,err,title,addMess);
+  }
+
+  /**
+   * Zeigt eine Fehlermeldung fuer Zugriffsfehler an.
+   * @param parent Uebergeordnete GUI-Komponente fuer die Meldung
+   * @param err    Fehler der aufgetreten ist
+   */
+    public static void showAccessError(Component parent, AccessViolationException err) {
+    String desc = XULUERR_RES.getString("Access");
+    if ( err.getAccess() instanceof PropertyWriteAccess )
+      desc = XULUERR_RES.getString("WriteAccess");
+    if ( err.getAccess() instanceof PropertyReadAccess )
+      desc = XULUERR_RES.getString("ReadAccess");
+
+    ExceptionDialog.show(
+      parent,
+      err,
+      XULUERR_RES.getString("AccessError"),
+      LangUtil.stringConcatWithSep(" ",XULUERR_RES.getString("AccessErrMess_1"),desc,XULUERR_RES.getString("AccessErrMess_2"),"!")
+    );
+
+  }
+
+  /**
+   * Zeigt eine Fehlermeldung fuer Datentyp-Konflikte an.
+   * @param parent Uebergeordnete GUI-Komponente fuer die Meldung
+   * @param err    Fehler der aufgetreten ist
+   */
+  public static void showBaseTypeError(Component parent, NumberFormatException err) {
+    ExceptionDialog.show(
+      parent,
+      err,
+      XULUERR_RES.getString("DataTypeError"),
+      XULUERR_RES.getString("TypeConvErrMess")+"!"
+    );
+  }
+
+  /**
+   * Zeigt eine Fehlermeldung fuer Instanziierungs-Konflikte an.
+   * @param parent Uebergeordnete GUI-Komponente fuer die Meldung
+   * @param err    Fehler der aufgetreten ist
+   */
+  public static void showInstantiationError(Component parent, InstantiationException err) {
+    ExceptionDialog.show(
+      parent,
+      err,
+      XULUERR_RES.getString("InstantiationError"),
+      XULUERR_RES.getString("InstantiationErrMess")
+    );
+  }
+
+  /**
+   * Zeigt eine Fehlermeldung fuer Cast-Konflikte an.
+   * @param parent   Uebergeordnete GUI-Komponente fuer die Meldung
+   * @param err      Fehler der aufgetreten ist
+   * @param expClass Erwartete Klasse
+   */
+  public static void showClassCastError(Component parent, ClassCastException err, Class expClass) {
+    ExceptionDialog.show(
+      parent,
+      err,
+      XULUERR_RES.getString("ClassCastError"),
+      LangUtil.stringConcatWithSep(" ",XULUERR_RES.getString("InstExpMess_1"),expClass.getName(),XULUERR_RES.getString("InstExpMess_2"))
+    );
+  }
+
+  /**
+   * Zeigt eine Fehlermeldung fuer ClassNotFound-Konflikte an.
+   * @param parent   Uebergeordnete GUI-Komponente fuer die Meldung
+   * @param err      Fehler der aufgetreten ist
+   * @param expClass Erwartete Klasse
+   */
+  public static void showClassNotFoundError(Component parent, ClassNotFoundException err, String expClass) {
+    ExceptionDialog.show(
+      parent,
+      err,
+      XULUERR_RES.getString("ClassError"),
+      LangUtil.stringConcat(XULUERR_RES.getString("ClassNotFoundErrMess"),":  ",expClass)
+    );
+  }
+
+  /**
+   * Zeigt eine Fehlermeldung fuer Daten-Konflikte an.
+   * @param parent   Uebergeordnete GUI-Komponente fuer die Meldung
+   * @param err      Fehler der aufgetreten ist
+   */
+  public static void showDataError(Component parent, XuluDataException err) {
+    String mess = "";
+    XuluObject data = err.getXuluData();
+    if ( data != null && !data.getDescription().trim().equals("") )
+      mess = mess.concat(data.getDescription()).concat(":  ");
+    mess = mess.concat(err.getMessage());
+    ExceptionDialog.show(parent,err,XULUERR_RES.getString("DataError"),mess);
+  }
+
+  /**
+   * Zeigt eine Info-Meldung an.
+   * @param parent   Uebergeordnete GUI-Komponente fuer die Meldung
+   * @param mess     Meldung
+   */
+  public static void showInfoMessage(Component parent, String mess) {
+    JOptionPane.showMessageDialog(
+      parent,
+      mess,
+      SWING_RES.getString("Information")+"...",
+      JOptionPane.INFORMATION_MESSAGE
+    );
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/gui/XuluGUIResource.20080424
===================================================================
--- trunk/src/edu/bonn/xulu/gui/XuluGUIResource.20080424	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/gui/XuluGUIResource.20080424	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,158 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.gui;
+
+import schmitzm.lang.HashtableResourceBundle;
+
+/**
+ * Dieses ResourceBundle stellt folgende Objekte fuer die Xulu-GUI zur Verfuegung.
+ * <table align=center border=2 cellpadding=5><code>
+ * <tr><th>Key</th><th>Ressource</th></tr>
+ * <tr><td><code>XuluTitle</code></td><td>"XULU - eXtendable Unified Land Use Modelling Platform"</td></tr>
+ * <tr><td><code>Menu_File</code></td><td>"Datei"</td></tr>
+ * <tr><td><code>Menu_File_Exit</code></td><td>"Beenden"</td></tr>
+ * <tr><td><code>Menu_Model</code></td><td>"Modell"</td></tr>
+ * <tr><td><code>Menu_Model_New</code></td><td>"Neu"</td></tr>
+ * <tr><td><code>Menu_Model_Reload</code></td><td>"Modell-Klasse neu laden"</td></tr>
+ * <tr><td><code>Menu_View</code></td><td>"Ansicht"</td></tr>
+ * <tr><td><code>Menu_View_Arrange</code></td><td>"Fenster anordnen"</td></tr>
+ * <tr><td><code>Menu_View_AutoArrange</code></td><td>"Autom. Fenster-Anordnung"</td></tr>
+ * <tr><td><code>Menu_Scripts</code></td><td>"Skripte"</td></tr>
+ * <tr><td><code>Menu_RecentScripts</code></td><td>"Skript erneut ausführen"</td></tr>
+ * <tr><td><code>Menu_Help</code></td><td>"Hilfe"</td></tr>
+ * <tr><td><code>Menu_Help_Info</code></td><td>"Ãœber..."</td></tr>
+ * <tr><td><code>Menu_Advanced</code></td><td>"Erweitert"</td></tr>
+ * <tr><td><code>Menu_DataPool</code></td><td>"Daten-Pool"</td></tr>
+ * <tr><td><code>Menu_DataPool_Del</code></td><td>"Löschen"</td></tr>
+ * <tr><td><code>Menu_DataPool_New</code></td><td>"Neu"</td></tr>
+ * <tr><td><code>Menu_DataPool_New_CopyStr</code></td><td>"Struktur kopieren"</td></tr>
+ * <tr><td><code>Menu_DataPool_Import</code></td><td>"Import"</td></tr>
+ * <tr><td><code>Menu_DataPool_RecentImport</code></td><td>"Erneut importieren"</td></tr>
+ * <tr><td><code>Menu_DataPool_Export</code></td><td>"Export"</td></tr>
+ * <tr><td><code>Menu_DataPool_RecentExport</code></td><td>"Erneut exportieren"</td></tr>
+ * <tr><td><code>Menu_DataPool_Display</code></td><td>"Display"</td></tr>
+ * <tr><td><code>Menu_DataPool_Display_Actualise</code></td><td>"Aktualisieren"</td></tr>
+ * <tr><td><code>Menu_DataPool_Display_New</code></td><td>"Neu"</td></tr>
+ * <tr><td><code>Comp_DataPool</code></td><td>"Xulu-Datenpool"</td></tr>
+ * <tr><td><code>Comp_Registry</code></td><td>"Xulu-Registry"</td></tr>
+ * <tr><td><code>Comp_Models</code></td><td>"Geladene Modelle"</td></tr>
+ * <tr><td><code>Comp_EventManager</code></td><td>"Ereignis-Manager"</td></tr>
+ * <tr><td><code>Comp_PluginManager</code></td><td>"Plugins"</td></tr>
+ * <tr><td><code>Comp_Log</code></td><td>"Status-Augaben"</td></tr>
+ * <tr><td><code>Comp_Visualisation</code></td><td>"Visualisierungstools"</td></tr>
+ * <tr><td><code>Model</code></td><td>"Modell"</td></tr>
+ * <tr><td><code>DynModel</code></td><td>"Dynamisches Modell"</td></tr>
+ * <tr><td><code>Access</code></td><td>"Zugriffsrecht"</td></tr>
+ * <tr><td><code>ReadAccess</code></td><td>"Leserecht"</td></tr>
+ * <tr><td><code>WriteAccess</code></td><td>"Schreibrecht"</td></tr>
+ * <tr><td><code>ScriptProgressMess</code></td><td>"Skript wird verarbeitet..."</td></tr>
+ * <tr><td><code>ImportProgressMess</code></td><td>"Import wird durchgeführt..."</td></tr>
+ * <tr><td><code>ExportProgressMess</code></td><td>"Export wird durchgeführt..."</td></tr>
+ * <tr><td><code>ModelChoiceMess</code></td><td>"Modell auswählen..."</td></tr>
+ * <tr><td><code>DefaultModelName</code></td><td>"Neues Modell"</td></tr>
+ * <tr><td><code>ModelClassChoiceMess</code></td><td>"Modell-Klasse auswählen..."</td></tr>
+ * <tr><td><code>DynModelChoiceMess</code></td><td>"Dynamisches Modell aus Datenpool auswählen..."</td></tr>
+ * <tr><td><code>ModelReloadSuccessMess</code></td><td>"Modell-Klasse erfolgreich aktualisiert..."</td></tr>
+ * <tr><td><code>Name</code></td><td>"Name"</td></tr>
+ * <tr><td><code>Type</code></td><td>"Typ"</td></tr>
+ * <tr><td><code>Object</code></td><td>"Objekt"</td></tr>
+ * <tr><td><code>Event</code></td><td>"Ereignis"</td></tr>
+ * <tr><td><code>Handler</code></td><td>"Handler"</td></tr>
+ * <tr><td><code>EventObject</code></td><td>"Zu beobachtendes Objekt"</td></tr>
+ * <tr><td><code>VisualisationUpdate</code></td><td>"Visualisierung aktualisieren"</td></tr>
+ * <tr><td><code>UpdateObject</code></td><td>"Darzustellendes Objekt"</td></tr>
+ * <tr><td><code>VisTool</code></td><td>"Visualisierungstool"</td></tr>
+ * <tr><td><code>FileExport</code></td><td>"Datei-Export"</td></tr>
+ * <tr><td><code>ExportSource</code></td><td>"Zu exportierendes Objekt"</td></tr>
+ * <tr><td><code>ExportFactory</code></td><td>"Export-Methode"</td></tr>
+ * <tr><td><code>ExportDest</code></td><td>"Export-Ziel"</td></tr>
+ * <tr><td><code>new</code></td><td>"neu"</td></tr>
+ * <tr><td><code>StartMess</code></td><td>"Starte Xulu"</td></tr>
+ * </table>
+ * <br>
+ * Diese Ressourcen werden in der Xulu-Standard-GUI verwendet. Fuer die einzelnen
+ * PlugIns sollten eigene ResourceBundles erstellt werden.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class XuluGUIResource extends HashtableResourceBundle {
+  /**
+   * Liefert die (Key/Wert)-Paerchen. Die Keys (erste Dimension) muessen aus Strings
+   * bestehen.
+   */
+  public Object[][] getContents() {
+    return new Object[][] {
+        {"XuluTitle","XULU - eXtendable Unified Land Use Modelling Platform"},
+        {"Menu_File","Datei"},
+        {"Menu_File_Exit","Beenden"},
+        {"Menu_Model","Modell"},
+        {"Menu_Model_New","Neu"},
+        {"Menu_Model_Reload","Modell-Klasse neu laden"},
+        {"Menu_View","Ansicht"},
+        {"Menu_View_Arrange","Fenster anordnen"},
+        {"Menu_View_AutoArrange","Autom. Fenster-Anordnung"},
+        {"Menu_Scripts","Skripte"},
+        {"Menu_RecentScripts","Skript erneut ausführen"},
+        {"Menu_Help","Hilfe"},
+        {"Menu_Help_Info","Ãœber..."},
+        {"Menu_Advanced_Preferences","Xulu Einstellungen"},
+        {"Menu_Advanced","Erweitert"},
+        {"Menu_DataPool","Daten-Pool"},
+        {"Menu_DataPool_Del","Löschen"},
+        {"Menu_DataPool_New","Neu"},
+        {"Menu_DataPool_New_CopyStr","Struktur kopieren"},
+        {"Menu_DataPool_Import","Import"},
+        {"Menu_DataPool_RecentImport","Erneut importieren"},
+        {"Menu_DataPool_Export","Export"},
+        {"Menu_DataPool_RecentExport","Erneut exportieren"},
+        {"Menu_DataPool_Display","Visualisieren"},
+        {"Menu_DataPool_Display_Actualise","Aktualisieren"},
+        {"Menu_DataPool_Display_New","Neu"},
+        {"Comp_DataPool","Xulu-Datenpool"},
+        {"Comp_Registry","Xulu-Registry"},
+        {"Comp_Models","Geladene Modelle"},
+        {"Comp_EventManager","Ereignis-Manager"},
+        {"Comp_PluginManager","Plugins"},
+        {"Comp_Log","Status-Ausgaben"},
+        {"Comp_Visualisation","Visualisierungstools"},
+        {"Model","Modell"},
+        {"DynModel","Dynamisches Modell"},
+        {"Access","Zugriffsrecht"},
+        {"ReadAccess","Leserecht"},
+        {"WriteAccess","Schreibrecht"},
+        {"ScriptProgressMess","Skript wird verarbeitet..."},
+        {"ImportProgressMess","Import wird durchgeführt..."},
+        {"ExportProgressMess","Export wird durchgeführt..."},
+        {"ModelChoiceMess","Modell auswählen..."},
+        {"DefaultModelName","Neues Modell"},
+        {"ModelClassChoiceMess","Modell-Klasse auswählen..."},
+        {"DynModelChoiceMess","Dynamisches Modell aus Datenpool auswählen..."},
+        {"ModelReloadSuccessMess","Modell-Klasse erfolgreich aktualisiert..."},
+        {"Name","Name"},
+        {"Type","Typ"},
+        {"Object","Objekt"},
+        {"Event","Ereignis"},
+        {"Handler","Handler"},
+        {"EventObject","Zu beobachtendes Objekt"},
+        {"VisualisationUpdate","Visualisierung aktualisieren"},
+        {"UpdateObject","Darzustellendes Objekt"},
+        {"VisTool","Visualisierungstool"},
+        {"FileExport","Datei-Export"},
+        {"ExportSource","Zu exportierendes Objekt"},
+        {"ExportFactory","Export-Methode"},
+        {"ExportDest","Export-Ziel"},
+        {"new","neu"},
+        {"StartMess","Starte Xulu"}
+    };
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/gui/XuluGUIResource_en.20080424
===================================================================
--- trunk/src/edu/bonn/xulu/gui/XuluGUIResource_en.20080424	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/gui/XuluGUIResource_en.20080424	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,163 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.gui;
+
+import java.util.ResourceBundle;
+import schmitzm.lang.HashtableResourceBundle;
+
+// nur fuer Doku
+import java.util.Locale;
+
+/**
+ * Dieses ResourceBundle stellt englische Objekte fuer die Xulu-GUI zur Verfuegung.
+ * <table align=center border=2 cellpadding=5><code>
+ * <tr><th>Key</th><th>Ressource</th></tr>
+ * <tr><td><code>XuluTitle</code></td><td>"XULU - eXtendable Unified Land Use Modelling Platform"</td></tr>
+ * <tr><td><code>Menu_File</code></td><td>"File"</td></tr>
+ * <tr><td><code>Menu_File_Exit</code></td><td>"Exit"</td></tr>
+ * <tr><td><code>Menu_Model</code></td><td>"Model"</td></tr>
+ * <tr><td><code>Menu_Model_New</code></td><td>"New"</td></tr>
+ * <tr><td><code>Menu_Model_Reload</code></td><td>"Reload model class"</td></tr>
+ * <tr><td><code>Menu_View</code></td><td>"View"</td></tr>
+ * <tr><td><code>Menu_View_Arrange</code></td><td>"Arrange Windows"</td></tr>
+ * <tr><td><code>Menu_View_AutoArrange</code></td><td>"Auto-Arrange"</td></tr>
+ * <tr><td><code>Menu_Scripts</code></td><td>"Scripts"</td></tr>
+ * <tr><td><code>Menu_RecentScripts</code></td><td>"Recent scripts"</td></tr>
+ * <tr><td><code>Menu_Help</code></td><td>"Help"</td></tr>
+ * <tr><td><code>Menu_Help_Info</code></td><td>"About..."</td></tr>
+ * <tr><td><code>Menu_Advanced_Preferences</code></td><td>"Xulu Preferences"</td></tr>
+ * <tr><td><code>Menu_Advanced</code></td><td>"Advanced"</td></tr>
+ * <tr><td><code>Menu_DataPool</code></td><td>"Datapool"</td></tr>
+ * <tr><td><code>Menu_DataPool_Del</code></td><td>"Delete"</td></tr>
+ * <tr><td><code>Menu_DataPool_New</code></td><td>"New"</td></tr>
+ * <tr><td><code>Menu_DataPool_New_CopyStr</code></td><td>"Copy structure"</td></tr>
+ * <tr><td><code>Menu_DataPool_Import</code></td><td>"Import"</td></tr>
+ * <tr><td><code>Menu_DataPool_RecentImport</code></td><td>"Recent imports"</td></tr>
+ * <tr><td><code>Menu_DataPool_Export</code></td><td>"Export"</td></tr>
+ * <tr><td><code>Menu_DataPool_RecentExport</code></td><td>"Recent exports"</td></tr>
+ * <tr><td><code>Menu_DataPool_Display</code></td><td>"Display"</td></tr>
+ * <tr><td><code>Menu_DataPool_Display_Actualise</code></td><td>"Actualise"</td></tr>
+ * <tr><td><code>Menu_DataPool_Display_New</code></td><td>"New"</td></tr>
+ * <tr><td><code>Comp_DataPool</code></td><td>"Xulu-Datenpool"</td></tr>
+ * <tr><td><code>Comp_DataPool</code></td><td>"Xulu Datapool"</td></tr>
+ * <tr><td><code>Comp_Registry</code></td><td>"Xulu Registry"</td></tr>
+ * <tr><td><code>Comp_Models</code></td><td>"Loades Models"</td></tr>
+ * <tr><td><code>Comp_EventManager</code></td><td>"Event Manager"</td></tr>
+ * <tr><td><code>Comp_PluginManager</code></td><td>"Plugins"</td></tr>
+ * <tr><td><code>Comp_Log</code></td><td>"Status Messages"</td></tr>
+ * <tr><td><code>Comp_Visualisation</code></td><td>"Visualisation Tools"</td></tr>
+ * <tr><td><code>Model</code></td><td>"Model"</td></tr>
+ * <tr><td><code>DynModel</code></td><td>"Dynamic Model"</td></tr>
+ * <tr><td><code>Access</code></td><td>"access"</td></tr>
+ * <tr><td><code>ReadAccess</code></td><td>"read access"</td></tr>
+ * <tr><td><code>WriteAccess</code></td><td>"write access"</td></tr>
+ * <tr><td><code>ScriptProgressMess</code></td><td>"Script is working..."</td></tr>
+ * <tr><td><code>ImportProgressMess</code></td><td>"Import in progress..."</td></tr>
+ * <tr><td><code>ExportProgressMess</code></td><td>"Export in progress..."</td></tr>
+ * <tr><td><code>ModelChoiceMess</code></td><td>"Please choose a model..."</td></tr>
+ * <tr><td><code>DefaultModelName</code></td><td>"New model"</td></tr>
+ * <tr><td><code>ModelClassChoiceMess</code></td><td>"Please choose a model class..."</td></tr>
+ * <tr><td><code>DynModelChoiceMess</code></td><td>"Please choose a dynamic model from datapool..."</td></tr>
+ * <tr><td><code>ModelReloadSuccessMess</code></td><td>"Model class reloaded successfully..."</td></tr>
+ * <tr><td><code>Name</code></td><td>"Name"</td></tr>
+ * <tr><td><code>Type</code></td><td>"Type"</td></tr>
+ * <tr><td><code>Object</code></td><td>"Object"</td></tr>
+ * <tr><td><code>Event</code></td><td>"Event"</td></tr>
+ * <tr><td><code>Handler</code></td><td>"Handler"</td></tr>
+ * <tr><td><code>EventObject</code></td><td>"Object to listen for"</td></tr>
+ * <tr><td><code>VisualisationUpdate</code></td><td>"Update visualisation"</td></tr>
+ * <tr><td><code>UpdateObject</code></td><td>"Object to visualise"</td></tr>
+ * <tr><td><code>VisTool</code></td><td>"Visualisationtool"</td></tr>
+ * <tr><td><code>FileExport</code></td><td>"Export to file"</td></tr>
+ * <tr><td><code>ExportSource</code></td><td>"Export object"</td></tr>
+ * <tr><td><code>ExportFactory</code></td><td>"Export method"</td></tr>
+ * <tr><td><code>ExportDest</code></td><td>"Export destination"</td></tr>
+ * <tr><td><code>new</code></td><td>"new"</td></tr>
+ * <tr><td><code>StartMess</code></td><td>"Starting Xulu"</td></tr>
+ * </table>
+ * Diese Ressourcen werden in der Xulu-Standard-GUI verwendet. Fuer die einzelnen
+ * PlugIns sollten eigene ResourceBundles erstellt werden.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class XuluGUIResource_en extends XuluGUIResource {
+  /**
+   * Liefert die (Key/Wert)-Paerchen. Die Keys (erste Dimension) muessen aus Strings
+   * bestehen.
+   */
+  public Object[][] getContents() {
+    return new Object[][] {
+        {"XuluTitle","XULU - eXtendable Unified Land Use Modelling Platform"},
+        {"Menu_File","File"},
+        {"Menu_File_Exit","Exit"},
+        {"Menu_Model","Model"},
+        {"Menu_Model_New","New"},
+        {"Menu_Model_Reload","Reload model class"},
+        {"Menu_View","View"},
+        {"Menu_View_Arrange","Arrange Windows"},
+        {"Menu_View_AutoArrange","Auto-Arrange"},
+        {"Menu_Scripts","Scripts"},
+        {"Menu_RecentScripts","Recent scripts"},
+        {"Menu_Help","Help"},
+        {"Menu_Help_Info","About..."},
+        {"Menu_Advanced_Preferences","Xulu Preferences"},
+        {"Menu_Advanced","Advanced"},
+        {"Menu_DataPool","Datapool"},
+        {"Menu_DataPool_Del","Delete"},
+        {"Menu_DataPool_New","New"},
+        {"Menu_DataPool_New_CopyStr","Copy structure"},
+        {"Menu_DataPool_Import","Import"},
+        {"Menu_DataPool_RecentImport","Recent imports"},
+        {"Menu_DataPool_Export","Export"},
+        {"Menu_DataPool_RecentExport","Recent exports"},
+        {"Menu_DataPool_Display","Display"},
+        {"Menu_DataPool_Display_Actualise","Actualise"},
+        {"Menu_DataPool_Display_New","New"},
+        {"Comp_DataPool","Xulu Datapool"},
+        {"Comp_Registry","Xulu Registry"},
+        {"Comp_Models","Loaded Models"},
+        {"Comp_EventManager","Event Manager"},
+        {"Comp_PluginManager","Plugins"},
+        {"Comp_Log","Status Messages"},
+        {"Comp_Visualisation","Visualisation Tools"},
+        {"Model","Model"},
+        {"DynModel","Dynamic model"},
+        {"Access","access"},
+        {"ReadAccess","read access"},
+        {"WriteAccess","write access"},
+        {"ScriptProgressMess","Script is working..."},
+        {"ImportProgressMess","Import in progress..."},
+        {"ExportProgressMess","Export in progress..."},
+        {"ModelChoiceMess","Please choose a model..."},
+        {"DefaultModelName","New model"},
+        {"ModelClassChoiceMess","Please choose a model class..."},
+        {"DynModelChoiceMess","Please choose a dynamic model from datapool..."},
+        {"ModelReloadSuccessMess","Model class reloaded successfully..."},
+        {"Name","Name"},
+        {"Type","Type"},
+        {"Object","Object"},
+        {"Event","Event"},
+        {"Handler","Handler"},
+        {"EventObject","Object to listen for"},
+        {"VisualisationUpdate","Update visualisation"},
+        {"UpdateObject","Object to visualise"},
+        {"VisTool","Visualisationtool"},
+        {"FileExport","Export to file"},
+        {"ExportSource","Export object"},
+        {"ExportFactory","Export method"},
+        {"ExportDest","Export destination"},
+        {"new","neu"},
+        {"StartMess","Starting Xulu"}
+    };
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/gui/XuluGUIUtil.java
===================================================================
--- trunk/src/edu/bonn/xulu/gui/XuluGUIUtil.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/gui/XuluGUIUtil.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,956 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.gui;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.ResourceBundle;
+
+import java.awt.Component;
+import java.awt.BorderLayout;
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JDialog;
+
+import appl.parallel.gui.ModelControlFrame_parallel;
+
+import schmitzm.lang.LangUtil;
+import schmitzm.lang.AlreadyHandledException;
+import schmitzm.lang.OperationCanceledException;
+import schmitzm.data.property.Property;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyReadAccess;
+import schmitzm.data.property.ScalarProperty;
+
+import schmitzm.data.property.Properties;
+import schmitzm.io.IOUtil;
+import schmitzm.lang.DuplicateException;
+import schmitzm.swing.SwingWorker;
+import schmitzm.swing.MultipleOptionPane;
+import schmitzm.swing.InputOption;
+import schmitzm.swing.SelectionInputOption;
+import schmitzm.swing.ManualInputOption;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.io.IODefinition;
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.io.FactoryCanceledException;
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.data.XuluDataException;
+import edu.bonn.xulu.data.DuplicateXuluObjectNameException;
+import edu.bonn.xulu.appl.XuluConstants;
+import edu.bonn.xulu.appl.DataPool;
+import edu.bonn.xulu.appl.ScriptInterpreter;
+import edu.bonn.xulu.model.XuluModel;
+import edu.bonn.xulu.gui.XuluGUIMessages;
+import edu.bonn.xulu.model.ModelResource;
+import edu.bonn.xulu.plugin.gui.ModelControlFrame_Basic;
+
+// nur fuer Doku
+import schmitzm.swing.StatusDialog;
+
+/**
+ * Diese Klasse stellt Funktionen fuer die Xulu-GUI zur Verfuegung.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class XuluGUIUtil implements XuluConstants {
+  //######################################################################
+  //######################   A L L G E M E I N   #########################
+  //######################################################################
+  private static Object askObject(Object[] objects, boolean askIfClear) {
+    return null;
+  }
+
+  /**
+   * Fragt eines der in Xulu geladenen Modelle ab.
+   * @param appl Xulu-Instanz
+   * @param askIfClear Flag, ob der Dialog auch angezeigt werden soll,
+   *                   wenn nur ein einziges Modell geladen ist (die Auswahl
+   *                   also eindeutig ist)
+   * @exception UnsupportedOperationException, falls aktuell <b>kein</b> Modell
+   *            in Xulu geladen ist
+   */
+  public static ModelControlFrame askModelFrame(XuluModellingPlatform appl, boolean askIfClear) {
+    // Auswahl der geladenen Modellen aus dem Modell-Manager ermitteln
+    ModelControlFrame[] modelFrame         = appl.getModelControlManager().getAll();
+    ModelControlFrame   selectedModelFrame = null;
+    if ( modelFrame == null || modelFrame.length == 0 )
+      throw new UnsupportedOperationException("No models loaded!");
+    // wenn nur ein einziges Modell geladen ist, wird kein Auswahl-Dialog
+    // angezeigt
+    if ( modelFrame.length == 1 && !askIfClear )
+      selectedModelFrame = modelFrame[0];
+    else {
+      String[] modelName = new String[modelFrame.length];
+      for (int i = 0; i < modelName.length; i++)
+        modelName[i] = modelFrame[i].getTitle();
+      // Dialog zum Auswaehlen eines Modells
+      Object[] inputOption = MultipleOptionPane.showMultipleInputDialog(
+          null,
+          XULUGUI_RES.getString("ModelChoiceMess"),
+          new SelectionInputOption.Combo(XULUGUI_RES.getString("Model"), true,
+                                         modelFrame, 0, modelName)
+          );
+      // Dialog abgebrochen
+      if (inputOption == null)
+        return null;
+      selectedModelFrame = (ModelControlFrame) inputOption[0];
+    }
+    return selectedModelFrame;
+  }
+
+  /**
+   * Fragt eine der in der Xulu-Registry geladenen Modell-Klassen ab.
+   * @param appl Xulu-Instanz
+   * @param askIfClear Flag, ob der Dialog auch angezeigt werden soll,
+   *                   wenn nur eine einzige Modell-Klasse geladen ist (die Auswahl
+   *                   also eindeutig ist)
+   * @exception UnsupportedOperationException, falls aktuell <b>keine</b> Modell-Klassen
+   *            in Xulu registriert sind
+   */
+  public static Class<XuluModel> askModelClass(XuluModellingPlatform appl, boolean askIfClear) {
+    // Auswahl der geladenen Modellen aus dem Modell-Manager ermitteln
+    Class[] modelClass = appl.getRegistry().getModelClasses();
+    Class   selectedModelClass = null;
+    if ( modelClass == null || modelClass.length == 0 )
+      throw new UnsupportedOperationException("No models classes registrated in registry!");
+    // wenn nur ein einziges Modell geladen ist, wird kein Auswahl-Dialog
+    // angezeigt
+    if ( modelClass.length == 1 && !askIfClear )
+      selectedModelClass = modelClass[0];
+    else {
+      String[] modelClassName = new String[modelClass.length];
+      for (int i = 0; i < modelClassName.length; i++)
+        modelClassName[i] = modelClass[i].getName();
+      // Dialog zum Auswaehlen eines Modells
+      Object[] inputOption = MultipleOptionPane.showMultipleInputDialog(
+          null,
+          XULUGUI_RES.getString("ModelClassChoiceMess"),
+          new SelectionInputOption.Combo(XULUGUI_RES.getString("Model"), true,
+                                         modelClass, 0, modelClassName)
+          );
+      // Dialog abgebrochen
+      if (inputOption == null)
+        return null;
+      selectedModelClass = (Class)inputOption[0];
+    }
+    return selectedModelClass;
+  }
+
+  //######################################################################
+  //#########################   I M P O R T   ############################
+  //######################################################################
+  /**
+   * Importiert Objekte ueber eine {@link ImportFactory}. Je nachdem welche
+   * Eingabequelle die Factory benoetigt, wird diese ueber einen passenden
+   * Anwender Dialog ermittelt. Zur Zeit werden folgende Verfahren unterstuetzt:<br>
+   * <br>
+   * <table width="80%" align=center border=2 cellpadding=5><code>
+   * <tr><th>Art</th><th>benoetigte Quelle</th><th>Ablauf</th></tr>
+   * <tr><td>Import aus Datei(en)</td>
+   *     <td><code>File<br>File[]<br>InputStream<br>InputStream[]<br>FileInputStream<br>FileInputStream[]</code></td>
+   *     <td>Es wird ein Dateiauswahl-Dialog angezeigt, ueber den der Anwender
+   *         eine Datei (bzw. mehrere, falls von der Factory gefordert)
+   *         fuer den Datenimport bestimmt. Ggf. werden die ausgewaehlten
+   *         Files noch in {@link FileInputStream}-Instanzen umgewandelt.
+   *         (siehe {@link #importObjectsFromFiles(Component,ImportFactory,XuluModellingPlatform)})</td></tr>
+   * </table>
+   * @param parent aufrufende Komponente (kann <code>null</code> sein)
+   * @param fac    fuer den Import zu verwendende Factory
+   * @param appl   Instanz der Xulu-Anwendung
+   * @return alle von der Factory erzeugten Objekte
+   * @throws UnsupportedOperationException falls fuer die von der Factory benoetigte Quelle (noch) kein
+   *         Ablauf implementiert ist
+   * @throws Exception falls ein unerwarteter Fehler beim Import auftritt
+   */
+  public static Object[] importObjects(Component parent, ImportFactory fac, XuluModellingPlatform appl) throws Exception{
+    Class neededSource = fac.getImportSourceType();
+    // Passendes Import-Verfahren fuer die Factory auswaehlen
+    if ( neededSource.isAssignableFrom( File.class ) ||
+         neededSource.isAssignableFrom( File[].class ) ||
+         neededSource.isAssignableFrom( FileInputStream.class ) ||
+         neededSource.isAssignableFrom( FileInputStream[].class ) )
+      return importObjectsFromFiles(parent,fac,appl);
+
+    // keine passendes Verfahren verfuegbar
+    throw new UnsupportedOperationException("Die von der ImportFactory benoetigte Eingabequelle ".concat(neededSource.getSimpleName()).concat(" kann von der Xulu-Plattform zur Zeit (noch) nicht bereitgestellt werden!!"));
+
+  }
+
+  /**
+   * Importiert Objekte ueber eine {@link ImportFactory}. Hierzu werden vom
+   * Anwender ueber einen {@linkplain JFileChooser Auswahl-Dialog} Dateien als
+   * Import-Quelle ausgewahlt. Je nach von der Factory benoetigter
+   * Eingabequelle, werden diese in {@link FileInputStream}s umgewandelt.<br>
+   * Benoetigt die Factory nur eine Datei (bzw. einen InputStream) als Quelle,
+   * wird sie fuer jede vom Anwender ausgewaehlte Datei ausgefuehrt und
+   * entsprechend mehrere Objekte erzeugt.
+   * @param parent aufrufende Komponente (kann <code>null</code> sein)
+   * @param fac    fuer den Import zu verwendende Factory
+   * @param appl   Instanz der Xulu-Anwendung
+   * @return alle von der Factory erzeugten Objekte
+   * @throws UnsupportedOperationException falls fuer die von der Factory
+   *         benoetigte Quelle kein <code>File</code>, <code>File[]</code>,
+   *         <code>InputStream</code> oder <code>InputStream[]</code> ist.
+   * @throws Exception falls ein unerwarteter Fehler beim Import auftritt
+   */
+  public static Object[] importObjectsFromFiles(final Component parent, final ImportFactory fac, final XuluModellingPlatform appl) throws Exception {
+    final Class neededSource = fac.getImportSourceType();
+
+    if ( !neededSource.isAssignableFrom( File.class ) &&
+         !neededSource.isAssignableFrom( File[].class ) &&
+         !neededSource.isAssignableFrom( FileInputStream.class ) &&
+         !neededSource.isAssignableFrom( FileInputStream[].class ) )
+      throw new UnsupportedOperationException("Die von der ImportFactory benoetigte Eingabequelle ".concat(neededSource.getSimpleName()).concat(" kann nicht ueber einen Datei-Dialog bereitgestellt werden!!"));
+
+    // Datei(en) auswaehlen
+    final JFileChooser fileChooser = appl.getMainFrame().FILE_CHOOSER;
+    fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
+//    fileChooser.setDialogTitle("Import > "+fac.getName());
+    fileChooser.setMultiSelectionEnabled( true );
+    if (fileChooser.showOpenDialog(parent) != JFileChooser.APPROVE_OPTION)
+      return new Object[0];
+
+    // Arbeit definieren fuer SwingWorker
+    SwingWorker.Work importWork =  new SwingWorker.Work() {
+      public Object execute() throws Exception {
+        // Quell-Objekt(e) erzeugen
+        File[] sourceFile = fileChooser.getSelectedFiles();
+
+        // Factory benoetigt mehrere Objekte als Quelle
+        if ( Object[].class.isAssignableFrom( neededSource ) ) {
+          Object sourceObject = convertImportSourceAsNeeded(fac,sourceFile);
+          // Import in die Liste der Recent-Imports aufnehmen (am Anfang)
+          appl.getRegistry().getRecentImports().add( new IODefinition.ImportDefinition(sourceFile,fac,appl.getRegistry()) );
+          // Objekte importieren
+          Object newObject = fac.importObject(sourceObject,appl.getRegistry());
+          // Streams schliessen (falls dies von Factory noch nicht getan wurde!)
+          if ( sourceObject instanceof InputStream[] )
+            IOUtil.closeInputStream((InputStream[])sourceObject);
+
+          // Rueckgabe-Array erzeugen
+          if ( newObject instanceof Object[] )
+            return (Object[])newObject;
+          return new Object[] { newObject };
+        }
+
+        // Factory benoetigt nur ein Objekt als Quelle
+        // >> Fuer jeden selektieren File die Factory einmal aufrufen
+        //    und erzeugte Objekte in einem Vector sammeln
+        Vector newObjects = new Vector();
+        for (int i=0; i<sourceFile.length; i++) {
+          Object sourceObject = convertImportSourceAsNeeded(fac,sourceFile[i]);
+          // Import in die Liste der Recent-Imports aufnehmen
+          appl.getRegistry().getRecentImports().add( new IODefinition.ImportDefinition(sourceFile[i],fac,appl.getRegistry()) );
+          // Objekte importieren
+          try {
+            Object newObject = fac.importObject(sourceObject,appl.getRegistry());
+            // Objekte im Vector sammeln
+            if (newObject instanceof Object[])
+              LangUtil.addObjectsToVector( (Object[]) newObject, newObjects);
+            else
+              newObjects.add(newObject);
+          } catch (FactoryCanceledException err) {
+            // manueller/gewollter Abbruch der Factory
+          } catch (XuluDataException err) {
+            XuluGUIMessages.showError(parent, err, "Objekt kann nicht erzeugt werden!");
+          } catch (AlreadyHandledException err) {
+            // Exception wurde bereits verarbeitet
+          } catch (Exception err) {
+            XuluGUIMessages.showError(parent, err);
+          }
+          // Stream schliessen (falls dies von Factory noch nicht getan wurde!)
+          if ( sourceObject instanceof InputStream )
+            IOUtil.closeInputStream( (InputStream)sourceObject );
+        }
+        return newObjects.toArray(new Object[0]);
+      }
+    };
+
+    // Skript im Thread ausfuehren
+    SwingWorker worker = new SwingWorker(importWork,appl.getMainFrame(),XULUGUI_RES.getString("ImportProgressMess"),0.2,0.2);
+    worker.start();
+    Object[] newObjects = (Object[])worker.getWorkResult();
+    return newObjects == null ? new Object[0] : newObjects;
+  }
+
+
+  /**
+   * Konvertiert ein durch die Plattform zur Verfuegung gestelltes Objekt
+   * in ein Objekt, das von der Factory angefordert wird.
+   * @param fac Import-Factory
+   * @param givenSource gegebenes Objekt
+   * @throws Exception falls eine Konvertierung nicht moeglich ist
+   */
+  public static Object convertImportSourceAsNeeded(ImportFactory fac, Object givenSource) throws Exception {
+    Class neededSource = fac.getImportSourceType();
+
+    // Nichts machen, wenn inputSource bereits im benoetigten Format
+    if ( neededSource.isAssignableFrom( givenSource.getClass() ) )
+      return givenSource;
+
+    // Stream aus Datei erzeugen
+    if ( givenSource instanceof File &&
+         neededSource.isAssignableFrom( FileInputStream.class ) )
+      return new FileInputStream( (File)givenSource );
+
+    // Stream-Array aus Datei-Array erzeugen
+    if ( givenSource instanceof File[] &&
+         neededSource.isAssignableFrom( FileInputStream[].class ) ) {
+      FileInputStream[] stream = new FileInputStream[ ((File[])givenSource).length ];
+      for (int i=0; i<stream.length; i++)
+        stream[i] = new FileInputStream( ((File[])givenSource)[i] );
+      return stream;
+    }
+
+    throw new UnsupportedOperationException("Given import source "+givenSource.getClass().getSimpleName()+" can not be converted to needed input "+neededSource.getSimpleName());
+  }
+
+  /**
+   * Fuegt eine Anzahl an Objekten in den Xulu-Datenpool ein.
+   * @param parent aufrufende Komponente (kann <code>null</code> sein)
+   * @param object einzufuegende Objekte
+   * @param pool   Datenpool in den die Objekte eingefuegt werden sollen
+   * @see #insertObjectToDataPool(Component,Object,DataPool,boolean,boolean)
+   */
+  public static void insertObjectsToDataPool(Component parent, Object[] object, DataPool pool) {
+    // Waehrend der Einfuegung von mehreren Objekten kann der Anwender im
+    // Konfliktfall auswaehlen, wie automatisch mit folgenden Konflikten
+    // umgegangen werden soll
+    // --> Entsprechend werden Einstellungen am Datenpool vorgenommen
+    // --> Nach der kollektiven Einfuegung sollen die alten Einstellungen
+    //     wieder hergestellt werden
+    boolean oldOverwriteOption = pool.getAutoOverwrideDuplicateNames();
+    boolean oldDuplicateOption = pool.getDuplicateNamesAllowed();
+
+    boolean autoSkipConflicts = false;
+    for (int i = 0; i < object.length; i++)
+      try {
+        insertObjectToDataPool(parent, object[i], pool, object.length > 1, autoSkipConflicts);
+      } catch (OperationCanceledException err) {
+        // Einfuegung wurde (ueber Anwender-Dialog) komplett abgebrochen
+        // --> Schleife abbrechen
+        break;
+      } catch ( AlreadyHandledException err ) {
+        // Einfuegung wurde (ueber Anwender-Dialog) fuer das Objekt uebergangen
+        // und soll auch fuer alle alle Folge-Konflikte uebergangen werden
+        // --> Schleife fortsetzen, aber mit autoSkip
+        autoSkipConflicts = true;
+      }
+
+    // alte Datenpool-Einstellungen wieder herstellen
+    pool.setAutoOverwriteDuplicateNames(oldOverwriteOption);
+    pool.setDuplicateNamesAllowed(oldDuplicateOption);
+  }
+
+  /**
+   * Fuegt ein Objekt in den Xulu-Datenpool ein. Fehler werden nicht durch
+   * eine Exception verarbeitet, sondern werden ueber eine Meldung dem Anwender
+   * mitgeteilt. Das Objekt wird in diesem Fall ignoriert und nicht in den
+   * Datenpool eingefuegt.
+   * @param parent aufrufende Komponente (kann <code>null</code> sein)
+   * @param object einzufuegendes Objekt
+   * @param pool   Datenpool in den das Objekt eingefuegt werden sollen
+   * @param partOfMultipleInsert gibt an, dass die Einfuege-Operation Teil von
+   *                             mehreren Einfuegungen ist; in einem etwaigen
+   *                             Dialog kann der Anwender dann angeben, dass seine
+   *                             Auswahl auch fuer die Folge-Operationen verwendet
+   *                             werden soll
+   * @param autoSkipDupl gibt an, ob Duplikat-Fehler automatisch uebergangen werden
+   *                     sollen (ohne dass eine Fehlermeldung erscheint)
+   * @return {@code false}, falls die Einfuegung nicht vorgenommen werden konnte
+   * @exception OperationCanceledException, falls der Anwender in einem
+   *            Konflikt-Dialog die "Abbrechen"-Auswahl getroffen hat (Folge-Einfuegungen
+   *            sollten in diesem Fall nicht mehr durchgefuehrt werden!)
+   * @exception AlreadyHandledException, falls der Anwender in einem
+   *            Konflikt-Dialog die "Uebergehen"-Auswahl getroffen hat und
+   *            diese Auswahl fuer alle Folge-Einfuegungen gemerkt werden soll
+   */
+  public static boolean insertObjectToDataPool(Component parent, Object object, DataPool pool, boolean partOfMultipleInsert, boolean autoSkipDupl) {
+    try {
+      pool.addObject( (XuluObject)object );
+      return true;
+    } catch (ClassCastException err) {
+      XuluGUIMessages.showError(parent,"In den Xulu-Datenpool können nur Instanzen von XuluObject eingefuegt werden!! Keine Instanzen von ".concat(object.getClass().getName()));
+    } catch (DuplicateXuluObjectNameException err) {
+      // keine Duplikate im Datenpool erlaubt
+
+      // kein Dialog wenn Duplikate automatisch uebergangen werden sollen
+      if ( autoSkipDupl )
+        return false;
+
+      // Fehler-Dialog
+      // --> Abfrage Abbrechen / Uebergehen / Ueberschreiben / Duplikat anlegen
+      //     + Auswahl merken (falls Einfuegung Teil von mehreren Einfuegungen ist)
+      String    cancelOption    = SWING_RES.getString("Cancel");
+      String    skipOption      = SWING_RES.getString("Skip");
+      String    overwriteOption = SWING_RES.getString("Overwrite");
+      String    duplicateOption = SWING_RES.getString("CreateDuplicate");
+      JCheckBox rememberOption  = new JCheckBox(SWING_RES.getString("RememberChoice"), false);
+      String    mess = XULUERR_RES.getString("DuplXuluObjectNameMessIntro") + " '" + ((XuluObject)object).getDescription() + "' ...";
+      Object selection = MultipleOptionPane.showMultipleOptionDialog(
+          parent,
+          JOptionPane.ERROR_MESSAGE,
+          XULUERR_RES.getString("DataError"),
+          partOfMultipleInsert ? new Object[] {  mess, rememberOption } : mess,
+          new String[] { cancelOption, skipOption, overwriteOption, duplicateOption },
+          skipOption
+      );
+
+      // Abbrechen
+      if ( selection.equals(cancelOption) )
+        throw new OperationCanceledException();
+      // Immer Uebergehen
+      if ( (selection == null || selection.equals(skipOption)) && rememberOption.isSelected() )
+        throw new AlreadyHandledException();
+      // Ueberschreiben
+      if ( selection.equals(overwriteOption) ) {
+        boolean oldOverwriteOption = pool.getAutoOverwrideDuplicateNames();
+        pool.setAutoOverwriteDuplicateNames( true );
+        pool.addObject( (XuluObject)object );
+        if ( !rememberOption.isSelected() )
+          pool.setAutoOverwriteDuplicateNames( oldOverwriteOption );
+        return true;
+      }
+      // Duplikat erzeugen
+      if ( selection.equals(duplicateOption) ) {
+        boolean oldDuplicateOption = pool.getDuplicateNamesAllowed();
+        pool.setDuplicateNamesAllowed( true );
+        pool.addObject( (XuluObject)object );
+        if ( !rememberOption.isSelected() )
+          pool.setDuplicateNamesAllowed( oldDuplicateOption );
+        return true;
+      }
+
+    } catch (Exception err) {
+      XuluGUIMessages.showError(parent,err);
+    }
+
+    return false;
+  }
+
+  /**
+   * Importiert ein oder mehrere Objekte ueber eine {@link ImportFactory}
+   * und fuegt sie in den Xulu-Datenpool ein. Wie die Import-Quelle vom Anwender
+   * abgefragt wird, haengt von der Quellenanforderung der Factory ab.
+   * Entsprechend wird ein passender Ablauf gewahlt (siehe
+   * {@link #importObjects(Component,ImportFactory,XuluModellingPlatform)}).<br>
+   * Fehler beim Import werden nicht durch eine Exception verarbeitet, sondern werden
+   * ueber eine Meldung dem Anwender mitgeteilt. Das betroffene Objekt wird
+   * in diesem Fall ignoriert und nicht in den Datenpool eingefuegt.
+   * @param parent aufrufende Komponente (kann <code>null</code> sein)
+   * @param fac    fuer den Import zu verwendende Factory
+   * @param appl   Instanz der Xulu-Anwendung
+   * @see #importObjectsFromFiles(Component,ImportFactory,XuluModellingPlatform)
+   * @see #insertObjectsToDataPool(Component,Object[],DataPool)
+   * @exception java.lang.XuluDataException falls die Factory keine Objekte
+   *            erzeugt, die im Datenpool verwaltet werden koennen
+   */
+  public static void importObjectsToDataPool(Component parent, ImportFactory fac, XuluModellingPlatform appl) throws Exception {
+    if (!XuluObject.class.isAssignableFrom(fac.getImportType()) &&
+        !XuluObject[].class.isAssignableFrom(fac.getImportType()))
+      throw new XuluDataException("Factory does not create instances of ".concat(XuluObject.class.getName()));
+
+    Object[] newObject = importObjects(parent,fac,appl);
+    insertObjectsToDataPool(parent,newObject,appl.getDataPool());
+  }
+
+  /**
+   * Importiert ein oder mehrere Objekte ueber eine {@link ImportFactory}
+   * und fuegt sie in den Xulu-Datenpool ein. Quelle fuer den Import
+   * bilden Dateien, die ueber einen Anwender-Dialog abgefragt werden.
+   * Fehler beim Import werden nicht durch eine Exception verarbeitet, sondern werden
+   * ueber eine Meldung dem Anwender mitgeteilt. Das betroffene Objekt wird
+   * in diesem Fall ignoriert und nicht in den Datenpool eingefuegt.
+   * @param parent aufrufende Komponente (kann <code>null</code> sein)
+   * @param fac    fuer den Import zu verwendende Factory
+   * @param appl   Instanz der Xulu-Anwendung
+   * @see #importObjectsFromFiles(Component,ImportFactory,XuluModellingPlatform)
+   * @see #insertObjectsToDataPool(Component,Object[],DataPool)
+   * @exception java.lang.XuluDataException falls die Factory keine Objekte
+   *            erzeugt, die im Datenpool verwaltet werden koennen
+   */
+  public static void importObjectsFromFileToDataPool(Component parent, ImportFactory fac, XuluModellingPlatform appl) throws Exception {
+    if (!XuluObject.class.isAssignableFrom(fac.getImportType()) &&
+        !XuluObject[].class.isAssignableFrom(fac.getImportType()))
+      throw new XuluDataException("Factory does not create instances of ".concat(XuluObject.class.getName()));
+
+    Object[] newObject = importObjectsFromFiles(parent,fac,appl);
+    insertObjectsToDataPool(parent,newObject,appl.getDataPool());
+  }
+
+
+  //######################################################################
+  //#########################   E X P O R T   ############################
+  //######################################################################
+  /**
+   * Exportiert ein Objekt ueber eine {@link ExportFactory}. Je nachdem welches
+   * Ausgabe-Ziel die Factory benoetigt, wird dieses ueber einen passenden
+   * Anwender Dialog ermittelt. Zur Zeit werden folgende Verfahren unterstuetzt:<br>
+   * <br>
+   * <table width="80%" align=center border=2 cellpadding=5><code>
+   * <tr><th>Art</th><th>benoetigtes Ziel</th><th>Ablauf</th></tr>
+   * <tr><td>Export in Datei(en)</td>
+   *     <td><code>File<br>File[]<br>OutputStream<br>OutputStream[]<br>FileOutputStream<br>FileOutputStream[]</code></td>
+   *     <td>Es wird ein Dateiauswahl-Dialog angezeigt, ueber den der Anwender
+   *         eine Datei (bzw. mehrere, falls von der Factory gefordert)
+   *         fuer den Datenexport bestimmt. Ggf. werden die ausgewaehlten
+   *         Files noch in {@link FileOutputStream}-Instanzen umgewandelt.
+   *         (siehe {@link #exportObjectsToFiles(Component,Object,ExportFactory,XuluModellingPlatform)})</td></tr>
+   * </table>
+   * @param parent aufrufende Komponente (kann <code>null</code> sein)
+   * @param object zu exportierendes Objekt
+   * @param fac    fuer den Export zu verwendende Factory
+   * @param appl   Instanz der Xulu-Anwendung
+   * @throws UnsupportedOperationException falls fuer die von der Factory benoetigte Quelle (noch) kein
+   *         Ablauf implementiert ist
+   * @throws IllegalArgumentException falls die Factory das angegebene Objekt nicht exportieren kann
+   * @throws Exception falls ein unerwarteter Fehler beim Export auftritt
+   */
+  public static void exportObjects(Component parent, Object object, ExportFactory fac, XuluModellingPlatform appl) throws Exception{
+    if ( !fac.isExportable(object) )
+      throw new IllegalArgumentException(fac.getClass().getName().concat(" can not export instances of ").concat(object.getClass().getName()));
+
+    Class neededDest = fac.getExportDestinationType();
+    // Passendes Export-Verfahren fuer die Factory auswaehlen
+    if ( neededDest.isAssignableFrom( File.class ) ||
+         neededDest.isAssignableFrom( File[].class ) ||
+         neededDest.isAssignableFrom( FileOutputStream.class ) ||
+         neededDest.isAssignableFrom( FileOutputStream[].class ) ) {
+      exportObjectsToFiles(parent, object, fac, appl);
+      return;
+    }
+    // keine passendes Verfahren verfuegbar
+    throw new UnsupportedOperationException("Das von der ExportFactory benoetigte Ausgabeziel ".concat(neededDest.getSimpleName()).concat(" kann von der Xulu-Plattform zur Zeit (noch) nicht bereitgestellt werden!!"));
+
+  }
+
+  /**
+   * Exportiert ein Objekt ueber eine {@link ExportFactory}. Hierzu werden vom
+   * Anwender ueber einen {@linkplain JFileChooser Auswahl-Dialog} Dateien als
+   * Export-Ziel ausgewahlt. Je nach von der Factory benoetigtem
+   * Ausgabe-Ziel, werden diese in {@link FileOutputStream}s umgewandelt.<br>
+   * @param parent aufrufende Komponente (kann <code>null</code> sein)
+   * @param fac    fuer den Export zu verwendende Factory
+   * @param appl   Instanz der Xulu-Anwendung
+   * @throws UnsupportedOperationException falls fuer das von der Factory
+   *         benoetigte Ziel kein <code>File</code>, <code>File[]</code>,
+   *         <code>OutputStream</code> oder <code>OutputStream[]</code> ist.
+   * @throws Exception falls ein unerwarteter Fehler beim Export auftritt
+   */
+  public static void exportObjectsToFiles(final Component parent, final Object object, final ExportFactory fac, final XuluModellingPlatform appl) throws Exception {
+    if ( !fac.isExportable(object) )
+      throw new IllegalArgumentException(fac.getClass().getName().concat(" can not export instances of ").concat(object.getClass().getName()));
+
+    final Class neededDest = fac.getExportDestinationType();
+
+    if ( !neededDest.isAssignableFrom( File.class ) &&
+         !neededDest.isAssignableFrom( File[].class ) &&
+         !neededDest.isAssignableFrom( FileOutputStream.class ) &&
+         !neededDest.isAssignableFrom( FileOutputStream[].class ) )
+      throw new UnsupportedOperationException("Das von der ExportFactory benoetigte Ausgabeziel ".concat(neededDest.getSimpleName()).concat(" kann nicht ueber einen Datei-Dialog bereitgestellt werden!!"));
+
+    // Datei(en) auswaehlen
+    final JFileChooser fileChooser = appl.getMainFrame().FILE_CHOOSER;
+    fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
+    fileChooser.setMultiSelectionEnabled( Object[].class.isAssignableFrom(neededDest) );
+    if (fileChooser.showSaveDialog(parent) != JFileChooser.APPROVE_OPTION)
+      return;
+
+    // Arbeit definieren fuer SwingWorker
+    SwingWorker.Work exportWork =  new SwingWorker.Work() {
+      Object destObject = null;
+
+      public Object execute() throws Exception {
+        // Ziel-Objekt(e) erzeugen
+        // Factory benoetigt mehrere Objekte als Ziel
+        if ( Object[].class.isAssignableFrom( neededDest ) ) {
+          File[] destFile = fileChooser.getSelectedFiles();
+          // Pruefen, ob Dateien bereits existieren
+          for (File file : destFile) {
+            XuluGUIMessages.FileOverrideOption opt = XuluGUIMessages.checkFileOverwrite(parent, file, destFile.length > 1);
+            if ( opt == XuluGUIMessages.FileOverrideOption.CANCEL )
+              return null;
+            if ( opt == XuluGUIMessages.FileOverrideOption.OVERWRITE_ALL )
+              break;
+          }
+          destObject = destFile; // Default: Dateien
+          // Factory benoetigt mehrere OutputStreams
+          if ( neededDest.isAssignableFrom( FileOutputStream[].class ) ) {
+            destObject = new OutputStream[destFile.length];
+            for (int i=0; i<destFile.length; i++)
+              ((OutputStream[])destObject)[i] = new FileOutputStream(destFile[i]);
+          }
+        } else {
+          // Factory benoetigt ein Objekt als Ziel
+          File destFile = fileChooser.getSelectedFile();
+          // Pruefen, ob Dateien bereits existieren
+          if ( XuluGUIMessages.checkFileOverwrite(parent, destFile, false) == XuluGUIMessages.FileOverrideOption.CANCEL )
+            return null;
+          destObject = destFile; // Default: Datei
+          // Factory benoetigt OutputStream
+          if ( neededDest.isAssignableFrom( FileOutputStream.class ) )
+            destObject = new FileOutputStream(destFile);
+        }
+
+        // Objekte exportieren
+        fac.exportObject(object,destObject);
+        closeDestObject();
+
+        return null;
+      }
+
+      public void performError(Throwable err) {
+        closeDestObject();
+        super.performError(err);
+      }
+
+      private void closeDestObject() {
+        if ( destObject == null )
+          return;
+
+        // Streams schliessen (falls dies von Factory noch nicht getan wurde!)
+        if ( destObject instanceof OutputStream[] ) {
+          OutputStream[] out = (OutputStream[])destObject;
+          for (int i=0; i<out.length; i++)
+            IOUtil.closeOutputStream(out[i]);
+        }
+        if ( destObject instanceof OutputStream )
+          IOUtil.closeOutputStream( (OutputStream)destObject );
+      }
+    };
+
+    // Skript im Thread ausfuehren
+    new SwingWorker(exportWork,appl.getMainFrame(),XULUGUI_RES.getString("ExportProgressMess"),0.2,0.2).start();
+  }
+
+  //######################################################################
+  //###################   N E U E S   M O D E L L   ######################
+  //######################################################################
+  /**
+   * Ermittelt alle registrierten Modelle aus der Xulu-Registry und gibt
+   * sie dem Anwender zur Auswahl. Von dem ausgewaehlten Modell-Typ wird
+   * eine neue Instanz erzeugt und ein entsprechender {@link ModelControlFrame_Basic}
+   * dem ModelControlManager hinzugefuegt.
+   * @param parent aufrufende Komponente (kann <code>null</code> sein)
+   * @param appl   Instanz der Xulu-Anwendung
+   */
+  public static void createNewModel(Component parent, XuluModellingPlatform appl) {
+    // Auswahl an Modellen aus der Registry ermitteln
+    Class[] modelClass = appl.getRegistry().getModelClasses();
+    Object[] input     = MultipleOptionPane.showClassAndDescInputDialog(parent,XULUGUI_RES.getString("ModelChoiceMess"),modelClass,XULUGUI_RES.getString("DefaultModelName"));
+    if ( input != null )
+      createNewModel(parent,(Class)input[0],(String)input[1],appl);
+  }
+  /**
+   * Erzeugt ein neues Model aus einem übergebenen Modellklassennamen
+   * und einer Modelbezeichnung
+   *
+   * @param modelClass Modellklasse
+   * @param modelName Modellbezeichnung
+   */
+  public static void createNewModel(Component parent, Class modelClass, String modelName, XuluModellingPlatform appl) {
+      if ( modelClass ==null || modelName==null)
+        return;
+
+      ModelControlFrame controlFrame = null;
+      try {
+        // Modell instanziieren
+        XuluModel model = (XuluModel)modelClass.newInstance();
+        // Modellfenster erzeugen
+        controlFrame = new ModelControlFrame_parallel(appl, model);
+        controlFrame.setTitle( modelName );
+        appl.getModelControlManager().add(controlFrame);
+      } catch (InstantiationException err) {
+//        System.err.println("ERROR: Could not create instance of " + modelClass);
+        XuluGUIMessages.showInstantiationError(parent,err);
+      } catch (IllegalAccessException err) {
+//        System.out.println("Access violation while creating Model: " + err.getMessage());
+        XuluGUIMessages.showError(parent,err);
+      } catch (DuplicateException err) {
+        // Modell-Manager enthaelt bereits ein Modell mit dem angegebenen Namen
+        // -> Ersetzen-Abfrage
+        String cancelOption  = SWING_RES.getString("Cancel");
+        String replaceOption = SWING_RES.getString("Replace");
+        String mess          = XULUERR_RES.getString("DuplModelNameMessIntro") + " '" + modelName + "' ...";
+        Object selection = MultipleOptionPane.showMultipleOptionDialog(
+            parent,
+            JOptionPane.ERROR_MESSAGE,
+            SWING_RES.getString("Error"),
+            mess,
+            new String[] { cancelOption, replaceOption },
+            cancelOption
+        );
+        if ( selection == replaceOption ) {
+          // Alle Modelle mit dem gleichen Namen loeschen
+          ModelControlFrame[] frames = appl.getModelControlManager().getAll();
+          for ( ModelControlFrame f : frames )
+            if ( controlFrame.equals(f) )
+              appl.getModelControlManager().remove(f);
+          // Modell nochmal einzufuegen
+          appl.getModelControlManager().add(controlFrame);
+        }
+
+      } catch (AlreadyHandledException err) {
+        // nichts machen
+      }
+    }
+
+  /**
+   * Ermittelt alle geladenen Modelle aus dem Xulu-Datenpool und gibt
+   * sie dem Anwender zur Auswahl. Von dem ausgewaehlten Modell wird
+   * ein entsprechender {@link ModelControlFrame_Basic} dem ModelControlManager
+   * hinzugefuegt.
+   * @param parent aufrufende Komponente (kann <code>null</code> sein)
+   * @param appl   Instanz der Xulu-Anwendung
+   */
+  public static void createNewDynamicModel(Component parent, XuluModellingPlatform appl) {
+    // Auswahl an Modellen aus dem Datenpool ermitteln Registry ermitteln
+    XuluObject[] modelObj = appl.getDataPool().getObjects( XuluModel.class );
+    // Eingabe-Optionen fuer den Dialog erstellen
+    Object[] input = MultipleOptionPane.showMultipleInputDialog(
+      parent,
+      XULUGUI_RES.getString("ModelChoiceMess"),
+      new InputOption[] { new SelectionInputOption.Combo(XULUGUI_RES.getString("DynModelChoiceMess"),true,modelObj,null),
+      new ManualInputOption.Text(SWING_RES.getString("Description"),true) }
+    );
+
+    if ( input != null ) {
+      // Modellfenster erzeugen
+      ModelControlFrame controlFrame = new ModelControlFrame_Basic(appl,(XuluModel)input[0]);
+      controlFrame.setTitle( (String) input[1]);
+      appl.getModelControlManager().add(controlFrame);
+    }
+  }
+
+  //######################################################################
+  //###############   M O D E L L   N E U   L A D E N  ###################
+  //######################################################################
+  /**
+   * Ermittelt alle Modell-Klassen aus der Xulu-Registry und stellt sie
+   * dem Anwender zur Auswahl. Die ausgewaehlte Klasse wird neu geladen,
+   * so dass fuer alle folgenden Instanzen dieser Klasse die aktualisierte
+   * Version verwendet wird.
+   * @param appl Xulu-Instanz
+   */
+  public static void reloadModelClass(XuluModellingPlatform appl) {
+    // Modell-Klasse abfragen
+    Class<XuluModel> oldModelClass = askModelClass(appl,true);
+    // Dialog abgebrochen
+    if ( oldModelClass == null )
+      return;
+
+//    // GarbageCollection aufrufen
+//    Runtime.getRuntime().runFinalization();
+//    LangUtil.gcTotal();
+    try {
+      // Klasse neu laden
+//      Class newModelClass = LangUtil.loadClass( oldModelClass.getName(), appl.getDynamicClassRootDirectory().toURL() );
+      Class newModelClass = LangUtil.loadPreferredClass( oldModelClass.getName(), appl.getDynamicClassRootDirectory().toURL() );
+      // Alte Klasse in Registry durch neue ersetzen
+      appl.getRegistry().replaceModelClass(oldModelClass,newModelClass);
+      // Meldung geben
+      XuluGUIMessages.showInfoMessage(appl.getMainFrame(),XULUGUI_RES.getString("ModelReloadSuccessMess"));
+    } catch (ClassNotFoundException err) {
+      XuluGUIMessages.showClassNotFoundError(appl.getMainFrame(),err,oldModelClass.getName());
+    } catch (Exception err) {
+      XuluGUIMessages.showError(appl.getMainFrame(),err);
+    }
+  }
+
+  //######################################################################
+  //#########################   S C R I P T   ############################
+  //######################################################################
+  /**
+   * Fuehrt ein Skript innerhalb der Xulu-Modelling-Platform aus. Hierzu
+   * wird das Skript ueber einen Datei-Eingabe-Dialog abgefragt und
+   * in einem eigenen {@linkplain SwingWorker Thread} ausgefuehrt.<br>
+   * Waehrend der Ausfuehrung wird ein Status-Dialog angezeigt. Wird dieser
+   * durch den Anwender abgebrochen, wird die Skript-Ausfuehrung unmittelbar
+   * gestoppt.
+   * @param appl        Applikation innerhalb der das Skript ausgefuehrt wird
+   * @param interpreter Interpreter, der das Skript ausfuehrt
+   * @see SwingWorker
+   * @see StatusDialog
+   */
+  public static void performScriptInThread(final XuluModellingPlatform appl, final ScriptInterpreter interpreter) {
+    // Datei auswaehlen
+    final JFileChooser fileChooser = appl.getMainFrame().FILE_CHOOSER;
+    fileChooser.setMultiSelectionEnabled(false);
+    if ( fileChooser.showOpenDialog(appl.getMainFrame()) != JFileChooser.APPROVE_OPTION )
+      return;
+
+    // Arbeits-Verzeichnis neu setzen
+    appl.setWorkingDirectory( fileChooser.getCurrentDirectory()  );
+
+    // Skript-Definition erzeugen
+    ScriptInterpreter.ScriptExecutionDefinition scriptDef =
+        new ScriptInterpreter.ScriptFileExecutionDefinition(fileChooser.getSelectedFile(),interpreter);
+    // Skript ausfuehren
+    performScriptInThread(appl,scriptDef);
+  }
+
+  /**
+   * Fuehrt ein Skript innerhalb der Xulu-Modelling-Platform aus. Hierbei
+   * wird das Skript in einem eigenen {@linkplain SwingWorker Thread}
+   * ausgefuehrt.<br>
+   * Waehrend der Ausfuehrung wird ein Status-Dialog angezeigt. Wird dieser
+   * durch den Anwender abgebrochen, wird die Skript-Ausfuehrung unmittelbar
+   * gestoppt.
+   * @param appl      Applikation innerhalb der das Skript ausgefuehrt wird
+   * @param scriptDef Script-Definition
+   * @see SwingWorker
+   * @see StatusDialog
+   */
+  public static void performScriptInThread(final XuluModellingPlatform appl, final ScriptInterpreter.ScriptExecutionDefinition scriptDef) {
+    // Skript-Definition an den Anfang der Recent Scripts setzen
+//    appl.getRegistry().getRecentScripts().remove( scriptDef );
+    appl.getRegistry().getRecentScripts().add( scriptDef );
+
+    // "Arbeit" fuer Thread erzeugen
+    SwingWorker.Work scriptWork =  new SwingWorker.Work() {
+      public Object execute() throws Exception {
+        scriptDef.execute(appl);
+        return null;
+      }
+    };
+
+    // Skript im Thread ausfuehren
+    new SwingWorker(scriptWork,appl.getMainFrame(),XULUGUI_RES.getString("ScriptProgressMess"),0.2,0.2).start();
+  }
+
+  //######################################################################
+  //############   Objekte/Objektbezeichnungen ermitteln   ###############
+  //######################################################################
+  /**
+   * Ermittelt (rekursiv) alle Xulu-Objekte und Eigenschaften aus dem Xulu-Datenpool,
+   * die zu einer Klasse (oder Ressource) passen.
+   * @param type      Objekt-Type (spezifiert durch ein {@link Class}-Objekt oder
+   *                  ein {@link ModelResource}-Objekt)
+   * @param dataPool  Datenpool, in dem gesucht wird
+   * @return 2-dimensionan Array {@code obj[][]}, wobei {@code obj[0]} die ermittelten
+   *         Objekte enthaelt und {@code obj[1]} deren Objektnamen.
+   * @exception IllegalArgumentException falls {@code type} keine {@link Class}-
+   *            oder {@link ModelResource}-Instanz ist
+   */
+  public static Object[][] determineObjectsFromDataPool(Object type, DataPool dataPool) {
+    Vector         objects = new Vector();
+    Vector<String> names   = new Vector<String>();
+    determineObjectsFromList(type,dataPool.asEnumeration(),objects,names,"");
+    return new Object[][] { objects.toArray(), (String[])names.toArray(new String[0]) };
+  }
+
+  /**
+   * Ermittelt (rekursiv) alle Xulu-Objekte und Eigenschaften aus dem Xulu-Datenpool,
+   * die zu einer Klasse (oder Ressource) passen.
+   * @param type      Objekt-Type (spezifiert durch ein {@link Class}-Objekt oder
+   *                  ein {@link ModelResource}-Objekt)
+   * @param dataPool   Liste von Objekten, in denen gesucht wird
+   * @param objects   wird mit den gefundenen (passenden) Objekten gefuellt
+   * @param names     wird mit den Bezeichnungen zu den <code>objects</code>-Elementen
+   *                  befuellt
+   * @exception IllegalArgumentException falls {@code type} keine {@link Class}-
+   *            oder {@link ModelResource}-Instanz ist
+   */
+  public static void determineObjectsFromDataPool(Object type, DataPool dataPool, Vector objects, Vector<String> names) {
+    determineObjectsFromList(type,dataPool.asEnumeration(),objects,names,"");
+  }
+
+  /**
+   * Ermittelt (rekursiv) alle Xulu-Objekte und Eigenschaften aus einer
+   * Liste, die zu einer Klasse (oder Ressource) passen.
+   * @param type      Objekt-Type (spezifiert durch ein {@link Class}-Objekt oder
+   *                  ein {@link ModelResource}-Objekt)
+   * @param objList   Liste von Objekten, in denen gesucht wird
+   * @param objects   wird mit den gefundenen (passenden) Objekten gefuellt
+   * @param names     wird mit den Bezeichnungen zu den <code>objects</code>-Elementen
+   *                  befuellt
+   * @param namePrefix Praefix, die den Bezeichnungen vorangestellt wird, bevor
+   *                   sie in <code>names</code> eingefuegt werden (wird fuer Rekursion
+   *                   benoetigt, sollte beim Aufruf "" oder {@code null} sein)
+   * @exception IllegalArgumentException falls {@code type} keine {@link Class}-
+   *            oder {@link ModelResource}-Instanz ist
+   */
+  public static void determineObjectsFromList(Object type, Enumeration objList, Vector objects, Vector<String> names, String namePrefix) {
+    if ( !(type instanceof Class) && !(type instanceof ModelResource) )
+      throw new IllegalArgumentException("Instance of Class or ModelResource expected as type specification!");
+    if ( namePrefix == null )
+      namePrefix = "";
+
+    for (;objList.hasMoreElements();) {
+      Object obj = objList.nextElement();
+      String name = "";
+      if ( obj instanceof XuluObject )
+        name = ((XuluObject)obj).getDescription();
+      else if ( obj instanceof Property )
+        name = ((Property)obj).getName();
+
+      // passt das Objekt zur Ressource, wird es in die Liste aufgenommen
+      if ( type instanceof Class && ((Class)type).isInstance(obj) ||
+           type instanceof ModelResource && ((ModelResource)type).checkType(obj) ) {
+        objects.add(obj);
+        names.add( namePrefix.concat(name) );
+      } else if ( obj instanceof ScalarProperty ) {
+        Object propObj = ((ScalarProperty)obj).getOneTimeReadAccess().getValue();
+        if ( type instanceof Class && ((Class)type).isInstance(propObj) ||
+             type instanceof ModelResource && ((ModelResource)type).checkType(propObj) ) {
+          objects.add(propObj);
+          names.add( namePrefix.concat(name) );
+        }
+      } else if ( obj instanceof ListProperty ) {
+        ListPropertyReadAccess listPropAccess = ((ListProperty)obj).getReadAccess(XuluGUIUtil.class);
+        for (int i=0; i<listPropAccess.getCount(); i++) {
+          Object propObj = listPropAccess.getValue(i);
+          if ( type instanceof Class && ((Class)type).isInstance(propObj) ||
+               type instanceof ModelResource && ((ModelResource)type).checkType(propObj) ) {
+            objects.add(propObj);
+            names.add( namePrefix.concat(name+"["+i+"]") );
+          }
+        }
+        listPropAccess.release();
+      }
+
+      // wenn das Objekt aus Eigenschaften besteht wird rekursiv
+      // weitergesucht
+      if (obj instanceof Properties) {
+        //=== Property-Array in Liste umwandeln ===
+        Property[] prop = ( (Properties) obj).getProperties();
+        Vector propVec = new Vector(prop.length);
+        for (int i = 0; i < prop.length; i++)
+          if ( prop[i] != obj )
+            propVec.add(prop[i]); // Property nur in Liste aufnehmen,
+                                  // wenn es sich nicht um das Vater-Objekt
+                                  // selbst handelt
+        //=========================================
+
+        // Rekursion starten
+        determineObjectsFromList(type,
+                                 propVec.elements(),
+                                 objects,
+                                 names,
+                                 namePrefix.concat(name).concat(".")
+        );
+      }
+    }
+  }
+
+
+}

Added: trunk/src/edu/bonn/xulu/gui/XuluInternalFrame.java
===================================================================
--- trunk/src/edu/bonn/xulu/gui/XuluInternalFrame.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/gui/XuluInternalFrame.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,49 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.gui;
+
+import java.awt.Component;
+import javax.swing.JInternalFrame;
+
+import edu.bonn.xulu.appl.XuluConstants;
+
+/**
+ * Diese Klasse bildet die abstrakte Oberklasse fuer ein Fenster, das im
+ * {@link edu.bonn.xulu.gui.XuluMainFrame} dargestellt werden soll.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class XuluInternalFrame extends JInternalFrame implements XuluConstants {
+  /** Wird benoetigt, um in internen Subklassen Zugriff auf den Frame (als Parent) zu haben */
+  protected Component GUI_COMPONENT = this;
+
+  /**
+   * Erzeugt einen neue Instanz des internen Fensters. Dieses ist
+   * vergroesserbar, maxi- und minimierbar, nicht aber schliessbar.
+   * Implementiert das Hauptfenster Methoden, um das Fenster wieder sichtbar
+   * zu machen, kann diese Option mittels {@link JInternalFrame#setClosable(boolean)}
+   * geaendert werden. Gleichzeitig muss aber auch die
+   * {@link JInternalFrame#setDefaultCloseOperation(int) DefaultCloseOperation}
+   * auf <code>HIDE_ON_CLOSE</code> gesetzt werden, da sonst das Fenster beim
+   * Schliessen zerstoert wird!
+   * @param name Bezeichnung fuer das Fenster
+   */
+  public XuluInternalFrame(String name) {
+    super(name, true, false, true, true);
+    this.setFrameIcon( this.XULU_ICON );
+  }
+
+  /**
+   * Aktualisiert die grafische Darstellung des internen Fensters.
+   */
+  public abstract void refresh();
+}

Added: trunk/src/edu/bonn/xulu/gui/XuluLanguageManagerFrame.java
===================================================================
--- trunk/src/edu/bonn/xulu/gui/XuluLanguageManagerFrame.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/gui/XuluLanguageManagerFrame.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,319 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.gui;
+
+import java.awt.Frame;
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.AWTEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.awt.event.WindowEvent;
+import javax.swing.JDialog;
+import javax.swing.JButton;
+import javax.swing.JTable;
+import javax.swing.JScrollPane;
+import javax.swing.JTextPane;
+import javax.swing.table.AbstractTableModel;
+import java.io.File;
+import java.util.Locale;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.ResourceBundle;
+
+import schmitzm.swing.ExceptionDialog;
+import schmitzm.swing.JPanel;
+import schmitzm.swing.MultipleOptionPane;
+import schmitzm.swing.InputOption;
+import schmitzm.swing.SelectionInputOption;
+import schmitzm.swing.ManualInputOption;
+import schmitzm.swing.event.InputOptionAdapter;
+import schmitzm.lang.ResourceProvider;
+import schmitzm.lang.LocaleComparator;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.XuluComponent;
+
+
+/**
+ * Diese Klasse stellt einen Dialog zum Verwalten der Xulu-Spachpakete dar.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class XuluLanguageManagerFrame extends JDialog implements ActionListener, XuluComponent {
+  private boolean disposed     = false;
+
+  private JTextPane infoText      = null;
+  private JButton   cancelButton  = null;
+  private JButton   newLangButton = null;
+  private JTable    bundleTable   = null;
+  private JPanel    controlPanel  = null;
+
+  private SelectionInputOption newLangDialog_LangDesc = null;
+  private ManualInputOption    newLangDialog_LangCode = null;
+
+  /**
+   * Erzeugt einen neuen Dialog.
+   * @param parent aufrufendes Fenster
+   * @param modal  Flag, ob des Fenster model ist
+   */
+  public XuluLanguageManagerFrame(Frame parent, boolean modal) {
+    super(parent,modal);
+    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
+    try {
+      initGUI();
+      initNewLanguageDialog();
+    }
+    catch(Exception e) {
+      ExceptionDialog.show(e);
+    }
+  }
+
+  /**
+   * Initialisiert die GUI.
+   */
+  private void initGUI() throws Exception  {
+    //imageLabel.setIcon(new ImageIcon(XuluMainFrame_Infodialog.class.getResource("[Ihre Grafik]")));
+    this.setTitle(XULUGUI_RES.getString("LangFrame.Title"));
+    this.setSize(500,400);
+    this.getContentPane().setLayout(new BorderLayout());
+    
+    infoText = new JTextPane();
+    infoText.setText( XULUGUI_RES.getString("LangFrame.InfoText") );
+    infoText.setBackground( this.getContentPane().getBackground() );
+    
+    bundleTable = new JTable( new BundleTableModel() );
+
+    cancelButton = new JButton(SWING_RES.getString("Cancel"));
+    cancelButton.addActionListener(this);
+    newLangButton = new JButton(XULUGUI_RES.getString("LangFrame.NewLang"));
+    newLangButton.addActionListener(this);
+
+    controlPanel = new JPanel();
+    controlPanel.setLayout( new FlowLayout(FlowLayout.CENTER) );
+    controlPanel.add( cancelButton );
+    controlPanel.add( newLangButton );
+
+    this.getContentPane().add(infoText, BorderLayout.NORTH);
+    this.getContentPane().add(controlPanel, BorderLayout.SOUTH);
+    this.getContentPane().add(new JScrollPane(bundleTable), BorderLayout.CENTER);
+
+//    this.pack();
+  }
+
+  /**
+   * Initalisiert die Eingabe-Optionen fuer den Dialog zum Ergeugen
+   * eines neuen Sprach-Bundles.
+   */
+  private void initNewLanguageDialog() {
+    // Verfuegbare Sprachen nach der Bezeichnung sortieren
+    TreeSet<Locale> sortedLocales = new TreeSet<Locale>(new LocaleComparator(true));
+    for (Locale l : Locale.getAvailableLocales())
+      sortedLocales.add(l);
+
+    // Bezeichnungen und Sprachcodes in Array einfuegen
+    String[] avLocaleDesc = new String[sortedLocales.size()+1];
+    String[] avLocaleCode = new String[sortedLocales.size()+1];
+    int i = 0;
+    for (Locale l : sortedLocales) {
+      avLocaleDesc[i] = l.getDisplayName();
+      avLocaleCode[i] = l.toString();
+      i++;
+    }
+    // Zusaetzliche Auswahl "andere Sprache" hinzufuegen
+    avLocaleDesc[i] = XULUGUI_RES.getString("LangFrame.OtherLang");
+    avLocaleCode[i] = "";
+
+    // Eingabe-Option fuer den Sprach-Code erstellen
+    newLangDialog_LangCode = new ManualInputOption.Text(
+      XULUGUI_RES.getString("LangFrame.LanguageCode"),
+      true
+    );
+    // Auswahl-Option mit den vordefinierten Sprachen erstellen
+    newLangDialog_LangDesc = new SelectionInputOption.Combo(
+      XULUGUI_RES.getString("LangFrame.Language"),
+      true,
+      avLocaleCode,
+      "",
+      avLocaleDesc
+    );
+    // Wenn sich die Auswahl aendert, soll der Code im Text-Feld
+    // angezeigt werden
+    newLangDialog_LangDesc.addInputOptionListener(new InputOptionAdapter() {
+      public void optionChanged(InputOption option, Object oldValue, Object newValue) {
+        newLangDialog_LangCode.setValue(newValue);
+        newLangDialog_LangCode.transferFocus();
+        newLangDialog_LangCode.setEnabled( "".equals(newValue));
+      }
+    });
+  }
+
+  /**
+   * Schliesst das Fenster, wenn es sich um ein <code>WindowEvent.WINDOW_CLOSING<code>-Event
+   * handelt.
+   */
+  protected void processWindowEvent(WindowEvent e) {
+    if (e.getID() == WindowEvent.WINDOW_CLOSING) {
+      cancel();
+    }
+    super.processWindowEvent(e);
+  }
+
+  /**
+   * Zerstoert das Fenster. Ruft <code>super.dispose()</code> auf.
+   */
+  public void dispose() {
+    disposed = true;
+    super.dispose();
+  }
+
+  /**
+   * Prueft, ob das Fenster zerstoert ist.
+   */
+  public boolean isDisposed() {
+    return disposed;
+  }
+
+  /**
+   * Schliesst das Fenster.
+   */
+  private void cancel() {
+    dispose();
+  }
+
+  /**
+   * Fragt eine neue Sprache vom Anwender ab und legt die entsprechenden
+   * Resource-Bundles an.
+   */
+  private void createNewLanguage() {
+    // Auswahl auf die erste Sprache setzen
+    newLangDialog_LangDesc.setSelectedIndex(0);
+    // Dialog anzeigen
+    Object[] input = MultipleOptionPane.showMultipleInputDialog(
+        this,
+        XULUGUI_RES.getString("LangFrame.NewLang"),
+        newLangDialog_LangDesc,
+        newLangDialog_LangCode
+    );
+    if ( input == null )
+      return;
+
+    // Property-Daten fuer alle Sprach-Bundles erstellen
+    Locale newLocale = new Locale((String)input[1]);
+    try {
+      // Pruefen, ob irgendeine Datei bereits existiert
+      for ( ResourceProvider rp : XuluModellingPlatform.RESOURCE_BUNDLES ) {
+        File file = ResourceProvider.getPropertyFile(rp,newLocale);
+        if ( file.exists() ) {
+          XuluGUIMessages.FileOverrideOption answer = XuluGUIMessages.approveFileOverwrite(this,file.getName(),true);
+          if ( answer.equals( XuluGUIMessages.FileOverrideOption.CANCEL ) )
+            return;
+          if ( answer.equals( XuluGUIMessages.FileOverrideOption.OVERWRITE_ALL ) )
+            break;
+          }
+      }
+      // Wenn alle Dateien zum Ueberschreiben bestaetigt wurden, dann die
+      // Dateien loeschen
+      for ( ResourceProvider rp : XuluModellingPlatform.RESOURCE_BUNDLES ) {
+        File file = ResourceProvider.getPropertyFile(rp,newLocale);
+        if ( file.exists() )
+          file.delete();
+      }
+      // Dateien neu erstellen (mit APPEND-Funktion, damit erweiterte
+      // Bundles nicht direkt wieder ueberschrieben werden)
+      for ( ResourceProvider rp : XuluModellingPlatform.RESOURCE_BUNDLES )
+        ResourceProvider.createPropertyFile(rp, newLocale, true);
+
+      // Tabelle aktuelisieren
+      ResourceBundle.clearCache();
+      ((AbstractTableModel)bundleTable.getModel()).fireTableDataChanged();
+      // Meldung anzeigen
+      XuluGUIMessages.showInfoMessage(this,XULUGUI_RES.getString("LangFrame.FinishMess"));
+    } catch (Exception err) {
+      XuluGUIMessages.showError(this,err);
+    }
+  }
+
+
+  /**
+   * Initiiert die Aktion der Buttons.
+   */
+  public void actionPerformed(ActionEvent e) {
+    if (e.getSource() == cancelButton)
+      cancel();
+    if (e.getSource() == newLangButton)
+      createNewLanguage();
+  }
+
+  /**
+   * Stellt ein Tabellen-Modell fuer die Sprachpakete dar.
+   * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  private class BundleTableModel extends AbstractTableModel {
+    public BundleTableModel() {
+      super();
+      fireTableDataChanged();
+    }
+
+
+    public int getColumnCount() {
+      return 4;
+    }
+
+    public String getColumnName(int col) {
+      switch ( col ) {
+        case 0: return XULUGUI_RES.getString("LangFrame.Bundle");
+        case 1: return XULUGUI_RES.getString("LangFrame.ExtentionOf");
+        case 2: return XULUGUI_RES.getString("LangFrame.RootLang");
+        case 3: return XULUGUI_RES.getString("LangFrame.AdditionalLang");
+      }
+      return null;
+    }
+
+    public int getRowCount() {
+      return XuluModellingPlatform.RESOURCE_BUNDLES.size();
+    }
+
+    public Object getValueAt(int row, int col) {
+      ResourceProvider rp = XuluModellingPlatform.RESOURCE_BUNDLES.elementAt(row);
+      switch ( col ) {
+        // Name des Bundles
+        case 0: return rp.getBundleName();
+        // Name des Original-Bundles (falls es existiert)
+        case 1: String defName    = rp.getDefaultBundleName();
+                String bundleName = rp.getBundleName();
+                return !defName.equals(bundleName) ? defName : "";
+        // Root-Sprache (Fall-Back-Locale)
+        case 2: return rp.getRootLocale().getDisplayLanguage()+ " (" + rp.getRootLocale().toString() + ")";
+        // weitere zur Verfuegung stehende Sprachen (durch Komma getrennt)
+        case 3: return getLanguageString( rp.getAvailableLocales(false) );
+      }
+      return null;
+    }
+
+    private String getLanguageString(Set<Locale> locales) {
+      String langStr = "";
+      for (Locale l : locales) {
+        if ( !langStr.equals("") )
+          langStr += ", ";
+        langStr += l.getDisplayLanguage() + " (" + l.toString() + ")";
+      }
+      return langStr;
+    }
+
+    public void fireTableDataChanged() {
+      XuluModellingPlatform.RESOURCE_BUNDLES.sort();
+      super.fireTableDataChanged();
+    }
+  }
+}

Added: trunk/src/edu/bonn/xulu/gui/XuluMainFrame.java
===================================================================
--- trunk/src/edu/bonn/xulu/gui/XuluMainFrame.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/gui/XuluMainFrame.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,750 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+
+import appl.ext.XuluConfig;
+
+import java.util.Vector;
+
+import schmitzm.lang.AlreadyHandledException;
+import schmitzm.swing.MultipleOptionPane;
+import schmitzm.swing.SelectionInputOption;
+import schmitzm.swing.InputOption;
+import schmitzm.swing.ExceptionDialog;
+import schmitzm.swing.SwingUtil;
+import schmitzm.swing.menu.ObjectMenuItem;
+import schmitzm.data.event.ObjectListener;
+import schmitzm.data.event.ObjectEvent;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.ScriptInterpreter;
+import edu.bonn.xulu.appl.XuluComponent;
+import edu.bonn.xulu.appl.XuluComponentUtil;
+import edu.bonn.xulu.appl.DataPool;
+import edu.bonn.xulu.appl.EventManager;
+import edu.bonn.xulu.appl.XuluRegistry;
+import edu.bonn.xulu.appl.VisualisationManager;
+import edu.bonn.xulu.appl.ModelControlManager;
+
+import edu.bonn.xulu.gui.XuluGUIMessages;
+import edu.bonn.xulu.gui.DataPoolFrame;
+import edu.bonn.xulu.plugin.gui.DataPoolFrame_Tree;
+import edu.bonn.xulu.plugin.gui.DataPoolFrame_BasicTable;
+import edu.bonn.xulu.gui.StatusFrame;
+import edu.bonn.xulu.plugin.gui.StatusFrame_BasicTextArea;
+import edu.bonn.xulu.gui.RegistryFrame;
+import edu.bonn.xulu.plugin.gui.RegistryFrame_Tree;
+import edu.bonn.xulu.gui.AbstractManagerFrame;
+import edu.bonn.xulu.plugin.gui.AbstractManagerFrame_BasicTable;
+import edu.bonn.xulu.plugin.gui.EventManagerFrame_BasicTable;
+import edu.bonn.xulu.plugin.gui.PluginManagerFrame_BasicTable;
+import edu.bonn.xulu.gui.ModelControlFrame;
+
+/**
+ * Diese Klasse stellt das Hauptfenster der Xulu-Modelling-Platform dar.
+ * Die einzelenen Komponenten werden in Unterfenstern dargestellt, welche
+ * wahlweise angezeigt oder verborgen werden koennen:
+ * <ul>
+ * <li>Ein Fenster fuer den {@link DataPoolFrame Datenpool}</li>
+ * <li>Ein Fenster fuer die {@link AbstractManagerFrame Visualisierungsfenster}</li>
+ * <li>Ein Fenster fuer die {@link AbstractManagerFrame aktiven Modelle/Modellfenster}</li>
+ * <li>Ein Fenster fuer den {@link AbstractManagerFrame Event-Manager}</li>
+ * <li>Ein Fenster fuer die {@link RegistryFrame Registry}</li>
+ * <li>Ein Fenster fuer die {@link StatusFrame Statusausgaben}</li>
+ * </ul>
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class XuluMainFrame extends JFrame implements XuluComponent {
+  //########## Konstanten fuer Labels ##########
+  private final String VISTOOLS_DESC     = XULUGUI_RES.getString("Comp_Visualisation");
+  private final String MODELS_DESC       = XULUGUI_RES.getString("Comp_Models");
+  private final String EVENTMANAGER_DESC = XULUGUI_RES.getString("Comp_EventManager");
+  private final String DATAPOOL_DESC     = XULUGUI_RES.getString("Comp_DataPool");
+  private final String REGISTRY_DESC     = XULUGUI_RES.getString("Comp_Registry");
+  private final String STATUS_DESC       = XULUGUI_RES.getString("Comp_Log");
+  private final String PLUGINS_DESC      = XULUGUI_RES.getString("Comp_PluginManager");
+
+  //########## Komponenten ##########
+  private XuluModellingPlatform appl = null;
+  private DataPool              dataPool = null;
+  private XuluRegistry          registry = null;
+  private VisualisationManager  visManager = null;
+  private ModelControlManager   modelManager = null;
+  private EventManager          eventManager = null;
+  private XuluMainFrame         mainFrame = this;
+
+  //########## GUI ##########
+  private JDesktopPane               desktopPane = new JDesktopPane();
+  private LayoutManager              layout      = new GridBagLayout();
+  private DataPoolFrame              dataPoolFrame;
+  private AbstractManagerFrame       visManagerFrame;
+  private AbstractManagerFrame       modelManagerFrame;
+  private AbstractManagerFrame       eventManagerFrame;
+  private RegistryFrame              registryFrame;
+  private XuluInternalFrame          pluginManagerFrame;
+  private StatusFrame                statusFrame;
+  private XuluLanguageManagerFrame   languageDlg = new XuluLanguageManagerFrame(this,true);
+  private XuluMainFrameInfo          infoDlg     = new XuluMainFrameInfo(this,true);
+
+  private Cursor                     waitCursor = new Cursor(Cursor.WAIT_CURSOR);
+  private Cursor                     activeCursor = new Cursor(Cursor.DEFAULT_CURSOR);
+
+  /**
+   * Einheitlicher <@linkplain JFileChooser FileChooser> fuer die Xulu-Applikation.
+   * Dieser kann in allen Untermodulen verwendet werden. Somit kann auf ein
+   * einheitliches Ausgangsverzeichnis zurueckgegriffen werden.<br>
+   * <b>Bemerke:</b><br>
+   * Der File-Chooser ueberschreibt die Methoden <code>showOpenDialog(..)</code>
+   * und <code>showSaveDialog(..)</code>, so dass die Datei-Auswahl bei
+   * jedem Anzeigen initialisiert wird!
+   */
+  public final JFileChooser FILE_CHOOSER = new JFileChooser() {
+    public int showOpenDialog(Component parent) {
+      this.setSelectedFile( new java.io.File("") );
+      this.setSelectedFiles( new java.io.File[0] );
+      return super.showOpenDialog(parent);
+    }
+    public int showSaveDialog(Component parent) {
+      this.setSelectedFile( new java.io.File("") );
+      this.setSelectedFiles( new java.io.File[0] );
+      return super.showSaveDialog(parent);
+    }
+  };
+
+  //########## Menue-Struktur ##########
+  private JMenuBar  menuBar = new JMenuBar();
+  private JMenu     menuFile = new JMenu();
+  private JMenuItem menuFile_Exit = new JMenuItem();
+  private JMenu     menuView = new JMenu();
+  private JMenuItem menuView_DataPool      = new JCheckBoxMenuItem();
+  private JMenuItem menuView_Registry      = new JCheckBoxMenuItem();
+  private JMenuItem menuView_Status        = new JCheckBoxMenuItem();
+  private JMenuItem menuView_VisManager    = new JCheckBoxMenuItem();
+  private JMenuItem menuView_ModelManager  = new JCheckBoxMenuItem();
+  private JMenuItem menuView_EventManager  = new JCheckBoxMenuItem();
+  private JMenuItem menuView_PluginManager = new JCheckBoxMenuItem();
+  private JMenuItem menuView_Arange        = new JMenuItem();
+  private JMenuItem menuView_ArangeAuto    = new JCheckBoxMenuItem();
+  private JMenu     menuAdvanced           = new JMenu();
+  private JMenuItem menuAdvanced_Languages = new JMenuItem();
+  private JMenu     menuHelp               = new JMenu();
+  private JMenuItem menuHelp_About         = new JMenuItem();
+  private JMenu     menuScript             = new JMenu();
+  private JMenu     menuScript_Recent      = new JMenu();
+  private JMenu     menuModel = new JMenu();
+  private JMenu     menuModel_New = new JMenu();
+  private JMenuItem menuModel_New_Model = new JMenuItem();
+  private JMenuItem menuModel_New_DynModel = new JMenuItem();
+  private JMenuItem menuModel_Reload = new JMenuItem();
+
+  /**
+   * Erzeugt ein neues Haupt-Fenster des Xulu-Applikation.
+   * @param appl Xulu-Applikation fuer die dieses Fenster die GUI bildet
+   */
+  public XuluMainFrame(XuluModellingPlatform appl) {
+    this.appl         = appl;
+    this.dataPool     = appl.getDataPool();
+    this.registry     = appl.getRegistry();
+    this.modelManager = appl.getModelControlManager();
+    this.FILE_CHOOSER.setCurrentDirectory( appl.getWorkingDirectory() );
+
+    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
+    try {
+      guiInit();    // GUI initialisieren
+      menuInit();   // Menue initialisieren
+      menuUpdate(); // dynamische Menue-Eintraege erzeugen
+      popupMenuInit(); // Popup-Menues initialisieren
+    }
+    catch(Exception e) {
+      ExceptionDialog.show(e);
+    }
+  }
+
+  /**
+   * Zerstoert das Fenster. Ruft <code>super.dispose()</code> auf.
+   */
+  public void dispose() {
+    super.dispose();
+    appl = null;
+  }
+
+  /**
+   * Prueft, ob das Fenster zerstoert ist.
+   */
+  public boolean isDisposed() {
+    return appl == null;
+  }
+
+  /**
+   * Liefert das {@linkplain DataPool Datenpool}-Fenster der Xulu-Anwendung.
+   */
+  public DataPoolFrame getDataPoolFrame() {
+    return this.dataPoolFrame;
+  }
+
+  /**
+   * Liefert das Fenster der Xulu-Anwendung, in dem die
+   * {@linkplain VisualisationManager Visualisierungstools} verwaltet werden.
+   */
+  public AbstractManagerFrame getVisualisationManagerFrame() {
+    return this.visManagerFrame;
+  }
+
+  /**
+   * Liefert das Fenster der Xulu-Anwendung, in dem die Modelle / Modellfenster
+   * verwaltet werden.
+   * @see ModelControlManager
+   */
+  public AbstractManagerFrame getModelManagerFrame() {
+    return this.modelManagerFrame;
+  }
+
+  /**
+   * Liefert das {@linkplain EventManager EventManager}-Fenster der Xulu-Anwendung.
+   */
+  public AbstractManagerFrame getEventManagerFrame() {
+    return this.eventManagerFrame;
+  }
+
+  /**
+   * Liefert das Fenster der Xulu-Anwendung, in dem die {@linkplain XuluRegistry Xulu-Registry}
+   * verwaltet wird.
+   */
+  public RegistryFrame getRegistryFrame() {
+    return this.registryFrame;
+  }
+
+  /**
+   * Liefert das Fenster der Xulu-Anwendung, in dem die Xulu-Plugins
+   * verwaltet wird.
+   */
+  public XuluInternalFrame getPluginManagerFrame() {
+    return this.pluginManagerFrame;
+  }
+
+  /**
+   * Liefert das Status-Fenster der Xulu-Anwendung.
+   */
+  public StatusFrame getStatusFrame() {
+    return this.statusFrame;
+  }
+
+  /**
+   * Initialisierung der GUI.
+   */
+  private void guiInit() throws Exception  {
+    //setIconImage(Toolkit.getDefaultToolkit().createImage(XuluMainFrame.class.getResource("[Ihr Symbol]")));
+    this.setIconImage(XuluComponent.XULU_ICON.getImage());
+    this.setSize(new Dimension(800, 600));
+    this.setTitle(XULUGUI_RES.getString("XuluTitle"));
+//    this.setContentPane( new JScrollPane(desktopPane) );
+    this.layout = new GridBagLayout();
+    this.setContentPane( desktopPane );
+    this.setJMenuBar(menuBar);
+    desktopPane.setLayout( null );
+
+    // Listener auf Registry, um Menues anzupassen
+    registry.addObjectListener( new ObjectListener() {
+      public void performObjectEvent(ObjectEvent e) {
+        if ( !e.getSource().contains( registry ) )
+          return;
+        // dynamische Menues neu organisieren
+        menuUpdate();
+      }
+    });
+
+    // Frame hinzufuegen
+//    dataPoolFrame     = (DataPoolFrame)initInternalFrame( new DataPoolFrame_BasicTable(appl), true, getWidth()/3, 2*(getHeight()-50)/3, menuView_DataPool );
+    dataPoolFrame      = (DataPoolFrame)initInternalFrame( new DataPoolFrame_Tree(appl), true, getWidth()/3, 2*(getHeight()-50)/3, menuView_DataPool );
+    visManagerFrame    = (AbstractManagerFrame)initInternalFrame( new AbstractManagerFrame_BasicTable(VISTOOLS_DESC,appl.getVisualisationManager()), true, getWidth()/3, 2*(getHeight()-50)/3, menuView_VisManager );
+    modelManagerFrame  = (AbstractManagerFrame)initInternalFrame( new AbstractManagerFrame_BasicTable(MODELS_DESC, new AbstractManagerFrame_BasicTable.AbstractManagerTableModel(appl.getModelControlManager()) {
+                                                                         // TableModel fuer Modell-Fenster soll als Typ nicht
+                                                                         // die Klasse des Modell-Fensters, sondern den Typ
+                                                                         // des Modells anzeigen
+                                                                         public Object getValueAt(int row, int col) {
+                                                                           if ( col == 1 )
+                                                                             return ((ModelControlFrame)manager.get(row)).getModel().getClass().getName();
+                                                                           return super.getValueAt(row,col);
+                                                                         }
+                                                                  }), true, getWidth()/3, 2*(getHeight()-50)/3, menuView_ModelManager );
+    eventManagerFrame  = (AbstractManagerFrame)initInternalFrame( new EventManagerFrame_BasicTable(appl,EVENTMANAGER_DESC), true, getWidth()/3, 2*(getHeight()-50)/3, menuView_EventManager );
+    registryFrame      = (RegistryFrame)initInternalFrame( new RegistryFrame_Tree(registry), false, getWidth()/3, 2*(getHeight()-50)/3, menuView_Registry );
+    statusFrame        = (StatusFrame)initInternalFrame( new StatusFrame_BasicTextArea(appl), true, getWidth(), getHeight()/3,menuView_Status);
+    pluginManagerFrame = (XuluInternalFrame)initInternalFrame( new PluginManagerFrame_BasicTable(PLUGINS_DESC,appl), false, getWidth()/3, 2*(getHeight()-50)/3, menuView_PluginManager );
+
+    // (SK) Die Standard-Ausgaben wird immer mit dem Statusfenster verbunden,
+    // ausser wenn ein Eintrag "Console.Logging" in der XuluProperties Datei existiert,
+    // welcher nicht "false" lautet.
+    XuluConfig config = XuluConfig.getXuluConfig();
+    String consoleLogging = config.getProperty("Console.Logging");
+    if (consoleLogging == null) {
+    	consoleLogging = "false";
+    	config.setProperty("Console.Logging",consoleLogging);
+    }
+    if 	((!consoleLogging.toLowerCase().equals("true"))
+    	   && (!consoleLogging.equals("1"))
+    	) {
+    	System.setOut( statusFrame.out );
+    	System.setErr( statusFrame.out );
+    }
+  }
+
+  /**
+   * Initialisiert einen internen Frame und fuegt ihn dem DesktopPane hinzu.
+   * @param frame  neue Frame
+   * @param width  Breite des Frames
+   * @param height Hoehe des Frames
+   * @param connectedMenu MenuItem, mit dem der Frame un/sichtbar gemacht wird
+   * @return der uebergebene Frame, damit Zuweiseung "schoener" moeglich
+   */
+  private JInternalFrame initInternalFrame(JInternalFrame frame, boolean visible, int width, int height, final JMenuItem connectedMenu) {
+    frame.setSize(new Dimension(width,height));
+    frame.setClosable(true);
+    frame.setVisible(visible);
+    frame.setDefaultCloseOperation( JInternalFrame.HIDE_ON_CLOSE );
+    frame.addComponentListener( new ComponentAdapter() {
+      public void componentHidden(ComponentEvent e) {
+        if ( connectedMenu != null )
+          connectedMenu.setSelected(false);
+      }
+    });
+    desktopPane.add( frame );
+    return frame;
+  }
+
+  /**
+   * Ordnet die Fenster (in einer festen Anordnung) an.
+   */
+  public void arrangeInnerFrames() {
+    final int COL_COUNT = 3;
+    final int ROW_COUNT = 4;
+
+    // Alle Fenster entfernen und dabei alle "nicht-standard" Fenster merken (die
+    // u.U. von Plugins erzeugt wurden). Diese duerfen nicht verloren gehen!
+//    Vector<JInternalFrame> others = new Vector<JInternalFrame>(); // Probleme mit Stefans PLAF; da ist eine Komponente dabei, die nicht JInternalFrame ist!
+    Vector<Component> others = new Vector<Component>();
+    for ( ; desktopPane.getComponentCount() > 0; ) {
+      Component frame = (Component)desktopPane.getComponent(0);
+      if ( frame != dataPoolFrame &&
+           frame != visManagerFrame &&
+           frame != modelManagerFrame &&
+           frame != eventManagerFrame &&
+           frame != registryFrame &&
+           frame != statusFrame &&
+           frame != pluginManagerFrame )
+        others.add( frame );
+      desktopPane.remove(frame);
+    }
+
+    desktopPane.setLayout( layout );
+    desktopPane.add( dataPoolFrame, new GridBagConstraints(0, 0, 1, 3, 0.3, 0.6,
+        GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0,0,0,0),0,0) );
+    desktopPane.add( visManagerFrame, new GridBagConstraints(1, 0, 1, 1, 0.3, 0.2,
+        GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0,0,0,0),0,0) );
+    desktopPane.add( modelManagerFrame, new GridBagConstraints(1, 1, 1, 1, 0.3, 0.2,
+        GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0,0,0,0),0,0) );
+    desktopPane.add( eventManagerFrame, new GridBagConstraints(1, 2, 1, 1, 0.3, 0.2,
+        GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0,0,0,0),0,0) );
+    desktopPane.add( registryFrame, new GridBagConstraints(2, 1, 1, 2, 0.4, 0.3,
+        GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0,0,0,0),0,0) );
+    desktopPane.add( statusFrame, new GridBagConstraints(0, ROW_COUNT-1, COL_COUNT, 1, 1.0, 0.4,
+        GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0,0,0,0),0,0) );
+    desktopPane.add( pluginManagerFrame, new GridBagConstraints(2, 0, 1, 1, 0.4, 0.3,
+        GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0,0,0,0),0,0) );
+    desktopPane.doLayout();
+    if ( !menuView_ArangeAuto.isSelected() )
+      desktopPane.setLayout( null );
+
+    // "nicht-standard" Fenster wieder einfuegen
+    for ( int i=0; i<others.size(); i++ ) {
+      desktopPane.add(others.elementAt(i), new GridBagConstraints());
+      if ( others.elementAt(i) instanceof JInternalFrame )
+        ((JInternalFrame)others.elementAt(i)).toFront();
+    }
+  }
+
+  /**
+   * Initialisierung der Menues.
+   */
+  private void menuInit() {
+    // Menue "Datei"
+    menuBar.add(menuFile);
+    menuFile.setText( XULUGUI_RES.getString("Menu_File") );
+    menuFile.setMnemonic('d');
+//    menuFile.addSeparator();
+    menuFile.add(menuFile_Exit);
+    menuFile_Exit.setText( XULUGUI_RES.getString("Menu_File_Exit") );
+    menuFile_Exit.addActionListener(new ActionListener()  {
+      public void actionPerformed(ActionEvent e) {
+        menuFile_Exit_actionPerformed(e);
+      }
+    });
+
+    // Menue "Modell"
+    menuBar.add(menuModel);
+    menuModel.setText( XULUGUI_RES.getString("Menu_Model") );
+    menuModel.setMnemonic('m');
+    menuModel.add(menuModel_New);
+    menuModel.addSeparator();
+    menuModel.add(menuModel_Reload);
+    menuModel_Reload.setText( XULUGUI_RES.getString("Menu_Model_Reload") );
+    menuModel_Reload.addActionListener(new ActionListener()  {
+      public void actionPerformed(ActionEvent e) {
+        menuModel_Reload_actionPerformed(e);
+      }
+    });
+
+    // Menue "Modell -> Neu"
+    menuModel_New.setText( XULUGUI_RES.getString("Menu_Model_New") );
+    menuModel_New.add(menuModel_New_Model);
+    menuModel_New_Model.setText( XULUGUI_RES.getString("Model") );
+    menuModel_New_Model.addActionListener(new ActionListener()  {
+      public void actionPerformed(ActionEvent e) {
+        menuModel_New_Model_actionPerformed(e);
+      }
+    });
+//    menuModel_New.add(menuModel_New_DynModel);
+    menuModel_New_DynModel.setText( XULUGUI_RES.getString("DynModel") );
+    menuModel_New_DynModel.addActionListener(new ActionListener()  {
+      public void actionPerformed(ActionEvent e) {
+        menuModel_New_DynamicModel_actionPerformed(e);
+      }
+    });
+
+    // Menue "Ansicht"
+    menuBar.add(menuView);
+    menuView.setText( XULUGUI_RES.getString("Menu_View") );
+    menuView.setMnemonic('a');
+    menuView.add(menuView_DataPool);
+    menuView_DataPool.setText( DATAPOOL_DESC );
+    menuView_DataPool.setSelected( dataPoolFrame.isVisible() );
+    menuView_DataPool.addActionListener(new ActionListener()  {
+      public void actionPerformed(ActionEvent e) {
+        menuView_DataPool_actionPerformed(e);
+      }
+    });
+    menuView.add(menuView_VisManager);
+    menuView_VisManager.setText( VISTOOLS_DESC );
+    menuView_VisManager.setSelected( visManagerFrame.isVisible() );
+    menuView_VisManager.addActionListener(new ActionListener()  {
+      public void actionPerformed(ActionEvent e) {
+        menuView_VisManager_actionPerformed(e);
+      }
+    });
+    menuView.add(menuView_ModelManager);
+    menuView_ModelManager.setText( MODELS_DESC );
+    menuView_ModelManager.setSelected( modelManagerFrame.isVisible() );
+    menuView_ModelManager.addActionListener(new ActionListener()  {
+      public void actionPerformed(ActionEvent e) {
+        menuView_ModelManager_actionPerformed(e);
+      }
+    });
+    menuView.add(menuView_EventManager);
+    menuView_EventManager.setText( EVENTMANAGER_DESC );
+    menuView_EventManager.setSelected( eventManagerFrame.isVisible() );
+    menuView_EventManager.addActionListener(new ActionListener()  {
+      public void actionPerformed(ActionEvent e) {
+        menuView_EventManager_actionPerformed(e);
+      }
+    });
+    menuView.add(menuView_Registry);
+    menuView_Registry.setText( REGISTRY_DESC );
+    menuView_Registry.setSelected( registryFrame.isVisible() );
+    menuView_Registry.addActionListener(new ActionListener()  {
+      public void actionPerformed(ActionEvent e) {
+        menuView_Registry_actionPerformed(e);
+      }
+    });
+    menuView.add(menuView_PluginManager);
+    menuView_PluginManager.setText( PLUGINS_DESC );
+    menuView_PluginManager.setSelected( pluginManagerFrame.isVisible() );
+    menuView_PluginManager.addActionListener(new ActionListener()  {
+      public void actionPerformed(ActionEvent e) {
+        menuView_PluginManager_actionPerformed(e);
+      }
+    });
+    menuView.add(menuView_Status);
+    menuView_Status.setText( STATUS_DESC );
+    menuView_Status.setSelected( statusFrame.isVisible() );
+    menuView_Status.addActionListener(new ActionListener()  {
+      public void actionPerformed(ActionEvent e) {
+        menuView_Status_actionPerformed(e);
+      }
+    });
+    menuView.addSeparator();
+    menuView.add(menuView_Arange);
+    menuView_Arange.setText( XULUGUI_RES.getString("Menu_View_Arrange") );
+    menuView_Arange.addActionListener(new ActionListener()  {
+      public void actionPerformed(ActionEvent e) {
+        menuView_Arange_actionPerformed(e);
+      }
+    });
+    menuView.add(menuView_ArangeAuto);
+    menuView_ArangeAuto.setText( XULUGUI_RES.getString("Menu_View_AutoArrange") );
+    menuView_ArangeAuto.addActionListener(new ActionListener()  {
+      public void actionPerformed(ActionEvent e) {
+        menuView_ArangeAuto_actionPerformed(e);
+      }
+    });
+
+    // Menue "Skript"
+    menuBar.add(menuScript);
+    menuScript.setText( XULUGUI_RES.getString("Menu_Scripts") );
+    menuScript.setMnemonic('s');
+
+    // Menue "Skript -> Skript erneut ausfuehren"
+    menuScript_Recent.setText( XULUGUI_RES.getString("Menu_RecentScripts") );
+
+    // menu advanced
+    menuAdvanced.setText( XULUGUI_RES.getString("Menu_Advanced") );
+    menuAdvanced.setMnemonic('a');
+    menuBar.add(menuAdvanced);
+    menuAdvanced.add(menuAdvanced_Languages);
+    menuAdvanced_Languages.setText( XULUGUI_RES.getString("Menu_Advanced_Languages") );
+    menuAdvanced_Languages.addActionListener(new ActionListener()  {
+        public void actionPerformed(ActionEvent e) {
+        menuAdvanced_Languages_actionPerformed(e);
+      }
+    });
+
+    // Menue "Hilfe"
+    menuHelp.setText( XULUGUI_RES.getString("Menu_Help") );
+    menuHelp.setMnemonic('h');
+    menuBar.add(menuHelp);
+    menuHelp.add(menuHelp_About);
+    menuHelp_About.setText( XULUGUI_RES.getString("Menu_Help_Info") );
+    menuHelp_About.addActionListener(new ActionListener()  {
+       	public void actionPerformed(ActionEvent e) {
+        menuHelp_About_actionPerformed(e);
+      }
+    });
+
+  }
+
+  /**
+   * Nachtraegliches Update der Menues.
+   */
+  private void menuUpdate() {
+    // Menue "Datei"
+    // ...
+
+    // Menue "Datei -> Neu"
+    // ...
+
+    // Menue "Ansicht"
+    // ...
+
+    // Menue "Skript"
+    menuScript.removeAll();
+    menuScript.add(menuScript_Recent);
+    menuScript.addSeparator();
+    ScriptInterpreter[] si = registry.getScriptInterpreter();
+    for (int i=0; i<si.length; i++) {
+      String name = si[i].getClass().getSimpleName();
+      if ( si[i].getName() != null && !si[i].getName().trim().equals("") )
+        name = si[i].getName();
+      JMenuItem item = new ObjectMenuItem(name,si[i],null);
+      item.addActionListener(new ActionListener()  {
+        public void actionPerformed(ActionEvent e) {
+          menuScript_actionPerformed(e);
+        }
+      });
+      menuScript.add(item);
+    }
+
+    // Menue "Skript -> Erneut ausfuehren"
+    menuScript_Recent.removeAll();
+    for (ScriptInterpreter.ScriptExecutionDefinition sed : registry.getRecentScripts()) {
+      JMenuItem item = new ObjectMenuItem(sed.getName(),sed,null);
+      item.addActionListener(new ActionListener()  {
+        public void actionPerformed(ActionEvent e) {
+          menuRecentScript_actionPerformed(e);
+        }
+      });
+      menuScript_Recent.add(item,0);
+    }
+
+
+    // Menue "Hilfe"
+    // ...
+  }
+
+  /**
+   * Initialisierung der Popup-Menues.
+   */
+  private void popupMenuInit() {
+    // Menue fuer Datenpool
+  }
+
+  /**
+   * �berschrieben, so dass eine Beendigung beim Schlie�en des Fensters moeglich ist.
+   */
+  protected void processWindowEvent(WindowEvent e) {
+    super.processWindowEvent(e);
+    if (e.getID() == WindowEvent.WINDOW_CLOSING) {
+      menuFile_Exit_actionPerformed(null);
+    }
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Menue-Aktionen
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Aktion Datei | Beenden durchfuehren.
+   */
+  public void menuFile_Exit_actionPerformed(ActionEvent e) {
+    appl.dispose();
+  }
+
+  /**
+   * Aktion Modell | Neu | Modell durchfuehren.
+   */
+  public void menuModel_New_Model_actionPerformed(ActionEvent e) {
+    XuluGUIUtil.createNewModel(this,appl);
+  }
+
+  /**
+   * Aktion Modell | Neu | Dynamisches Modell durchfuehren.
+   */
+  public void menuModel_New_DynamicModel_actionPerformed(ActionEvent e) {
+    XuluGUIUtil.createNewDynamicModel(this,appl);
+  }
+
+  /**
+   * Aktion Modell | Neu laden durchfuehren.
+   */
+  public void menuModel_Reload_actionPerformed(ActionEvent e) {
+    XuluGUIUtil.reloadModelClass(appl);
+  }
+
+  /**
+   * Aktion Ansicht | Daten-Pool durchfuehren.
+   */
+  public void menuView_DataPool_actionPerformed(ActionEvent e) {
+    dataPoolFrame.setVisible( menuView_DataPool.isSelected() );
+  }
+
+  /**
+   * Aktion Ansicht | Visualisierungstools durchfuehren.
+   */
+  public void menuView_VisManager_actionPerformed(ActionEvent e) {
+    visManagerFrame.setVisible( menuView_VisManager.isSelected() );
+  }
+
+  /**
+   * Aktion Ansicht | Aktive Modelle durchfuehren.
+   */
+  public void menuView_ModelManager_actionPerformed(ActionEvent e) {
+    modelManagerFrame.setVisible( menuView_ModelManager.isSelected() );
+  }
+
+  /**
+   * Aktion Ansicht | Event-Manager durchfuehren.
+   */
+  public void menuView_EventManager_actionPerformed(ActionEvent e) {
+    eventManagerFrame.setVisible( menuView_EventManager.isSelected() );
+  }
+
+  /**
+   * Aktion Ansicht | Registrierung durchfuehren.
+   */
+  public void menuView_Registry_actionPerformed(ActionEvent e) {
+    registryFrame.setVisible( menuView_Registry.isSelected() );
+  }
+
+  /**
+   * Aktion Ansicht | Plugin-Manager durchfuehren.
+   */
+  public void menuView_PluginManager_actionPerformed(ActionEvent e) {
+    pluginManagerFrame.setVisible( menuView_PluginManager.isSelected() );
+  }
+
+  /**
+   * Aktion Ansicht | Status-Ausgaben durchfuehren.
+   */
+  public void menuView_Status_actionPerformed(ActionEvent e) {
+    statusFrame.setVisible( menuView_Status.isSelected() );
+  }
+
+  /**
+   * Aktion Ansicht | Fenster anordnen durchfuehren.
+   */
+  public void menuView_Arange_actionPerformed(ActionEvent e) {
+    arrangeInnerFrames();
+  }
+
+  /**
+   * Aktion Ansicht | Automatische Fensteranordnung durchfuehren.
+   */
+  public void menuView_ArangeAuto_actionPerformed(ActionEvent e) {
+//    menuView_Arange.setEnabled( !menuView_ArangeAuto.isSelected() );
+    if ( menuView_ArangeAuto.isSelected() )
+      menuView_Arange_actionPerformed(null);
+    else {
+      desktopPane.setLayout(null);
+      desktopPane.doLayout();
+    }
+  }
+
+  /**
+   * Aktion Skript | ... durchfuehren.
+   */
+  public void menuScript_actionPerformed(ActionEvent e) {
+    if ( !(e.getSource() instanceof ObjectMenuItem) )
+      return;
+    XuluGUIUtil.performScriptInThread(
+      appl,
+      (ScriptInterpreter) ((ObjectMenuItem)e.getSource()).getObject()
+    );
+  }
+
+  /**
+   * Aktion Skript | Erneut ausfuehren | ... durchfuehren.
+   */
+  public void menuRecentScript_actionPerformed(ActionEvent e) {
+    if ( !(e.getSource() instanceof ObjectMenuItem) )
+      return;
+    XuluGUIUtil.performScriptInThread(
+      appl,
+      (ScriptInterpreter.ScriptExecutionDefinition) ((ObjectMenuItem)e.getSource()).getObject()
+    );
+  }
+
+  /**
+   * Aktion Erweitert | Xulu Sprach-Pakete
+   */
+  public void menuAdvanced_Languages_actionPerformed(ActionEvent e) {
+    SwingUtil.centerFrameOnScreen(languageDlg);
+    languageDlg.setVisible(true);
+  }
+
+  /**
+   * Aktion Hilfe | Info durchfuehren.
+   */
+  public void menuHelp_About_actionPerformed(ActionEvent e) {
+    SwingUtil.centerFrameOnScreen(infoDlg);
+    infoDlg.setVisible(true);
+//    Dimension dlgSize = dlg.getPreferredSize();
+//    Dimension frmSize = getSize();
+//    Point loc = getLocation();
+//    dlg.setLocation((frmSize.width - dlgSize.width) / 2 + loc.x, (frmSize.height - dlgSize.height) / 2 + loc.y);
+//    dlg.setModal(true);
+//    dlg.pack();
+//    dlg.setVisible(true);
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/gui/XuluMainFrameInfo.java
===================================================================
--- trunk/src/edu/bonn/xulu/gui/XuluMainFrameInfo.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/gui/XuluMainFrameInfo.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,184 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.text.*;
+import javax.swing.border.*;
+import schmitzm.swing.ExceptionDialog;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.XuluComponent;
+
+/**
+ * Diese Klasse stellt einen Info-Dialog zur Xulu-Modelling-Platform dar,
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class XuluMainFrameInfo extends JDialog implements ActionListener, XuluComponent {
+  private boolean disposed     = false;
+
+  private JPanel  infoPane     = new JPanel();
+  private JPanel  controlPanel = new JPanel();
+  private JPanel  iconPanel    = new JPanel();
+  private JPanel  textPanel    = new JPanel();
+  private JButton okButton     = new JButton();
+  private JLabel  iconLabel    = new JLabel();
+
+  // Inhalt des Text-Bereichs
+  private String  product      = "Xulu Modelling Platform";
+  private String  version      = "Version "+VERSION+", "+VERSION_DATE;
+  private String  author       = "Developed by Martin Schmitz";
+  private String  organisation = "University of Bonn/Germany";
+  private String  contact      = "martin.schmitz at koeln.de";
+  private String  copyright    = "Copyright (c) 2007";
+
+  // Definiert die Reihenfolge der Textzeilen
+  private String[] textLines = new String[] {
+      product,
+      version,
+      author,
+      organisation,
+      contact,
+      copyright
+  };
+
+  /**
+   * Erzeugt einen neuen Info-Dialog.
+   * @param parent aufrufendes Fenster
+   */
+  public XuluMainFrameInfo(Frame parent, boolean modal) {
+    super(parent,modal);
+    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
+    try {
+      jbInit();
+    }
+    catch(Exception e) {
+      ExceptionDialog.show(e);
+    }
+  }
+
+  /**
+   * Initialisiert die GUI.
+   */
+  private void jbInit() throws Exception  {
+    //imageLabel.setIcon(new ImageIcon(XuluMainFrame_Infodialog.class.getResource("[Ihre Grafik]")));
+    this.setTitle(XULUGUI_RES.getString("Menu_Help_Info"));
+    this.getContentPane().setLayout(new BorderLayout());
+    this.getContentPane().add(controlPanel, BorderLayout.SOUTH);
+    this.getContentPane().add(infoPane, BorderLayout.NORTH);
+    this.setResizable(false);
+
+    // oberes Pane, in dem Icon und Text angezeigt werden
+    infoPane.setLayout(new BorderLayout());
+    infoPane.add(iconPanel, BorderLayout.WEST);
+    infoPane.add(textPanel, BorderLayout.CENTER);
+
+    iconPanel.setLayout(new GridBagLayout());
+    iconPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+    iconLabel.setIcon( this.XULU_INFOICON );
+    iconPanel.add(iconLabel, new GridBagConstraints(0,0,1,1,1,1,GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets(0,0,0,0),0,0));
+//    iconPanel.add(createStyledLabel(), new GridBagConstraints(0,1,1,1,0,0,GridBagConstraints.NORTH,GridBagConstraints.HORIZONTAL,new Insets(0,5,0,0),0,0));
+
+    textPanel.setLayout(new GridLayout(textLines.length,1));
+    textPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+    for (int i=0; i<textLines.length; i++) {
+      JLabel label = new JLabel(textLines[i]);
+      // die ersten beiden Zeile erscheint FETT
+      if ( i<2 )
+        label.setFont( label.getFont().deriveFont(Font.BOLD) );
+      textPanel.add(label, null);
+    }
+
+    // unteres Pane, in dem sich der Kontroll-Button befindet
+    controlPanel.setLayout(new FlowLayout());
+    okButton.setText(SWING_RES.getString("Close"));
+    okButton.addActionListener(this);
+    controlPanel.add(okButton, null);
+
+    this.pack();
+  }
+
+  private Component createStyledLabel() {
+    JTextPane textPane = new JTextPane();
+    StyledDocument doc = textPane.getStyledDocument();
+    textPane.setEditable(false);
+    textPane.setBackground( iconPanel.getBackground() );
+
+    // Default-Style erstellen
+    Style def     = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
+    Style regular = doc.addStyle("regular", def);
+    StyleConstants.setFontFamily(def, "SansSerif");
+    // kursiven Style ableiten
+    Style s = doc.addStyle("italic", regular);
+    StyleConstants.setItalic(s, true);
+    // fett-kursiven Style ableiten
+    s = doc.addStyle("bolditalic", regular);
+    StyleConstants.setItalic(s, true);
+    StyleConstants.setBold(s, true);
+
+    // formatierten Text zusammensetzen
+    try {
+      doc.insertString(doc.getLength(), "M", doc.getStyle("bolditalic"));
+      doc.insertString(doc.getLength(), "odellers, ", doc.getStyle("italic"));
+      doc.insertString(doc.getLength(), "A", doc.getStyle("bolditalic"));
+      doc.insertString(doc.getLength(), "vail ", doc.getStyle("italic"));
+      doc.insertString(doc.getLength(), "X", doc.getStyle("bolditalic"));
+      doc.insertString(doc.getLength(), "ulu !!", doc.getStyle("italic"));
+    } catch (Exception err) {
+    }
+    return textPane;
+  }
+
+  /**
+   * Schliesst das Fenster, wenn es sich um ein <code>WindowEvent.WINDOW_CLOSING<code>-Event
+   * handelt.
+   */
+  protected void processWindowEvent(WindowEvent e) {
+    if (e.getID() == WindowEvent.WINDOW_CLOSING) {
+      cancel();
+    }
+    super.processWindowEvent(e);
+  }
+
+  /**
+   * Zerstoert das Fenster. Ruft <code>super.dispose()</code> auf.
+   */
+  public void dispose() {
+    disposed = true;
+    super.dispose();
+  }
+
+  /**
+   * Prueft, ob das Fenster zerstoert ist.
+   */
+  public boolean isDisposed() {
+    return disposed;
+  }
+
+  /**
+   * Schliesst das Fenster.
+   */
+  private void cancel() {
+    dispose();
+  }
+
+  /**
+   * Aktion des OK-Buttons. Schlisst das Fenster.
+   */
+  public void actionPerformed(ActionEvent e) {
+    if (e.getSource() == okButton) {
+      cancel();
+    }
+  }
+}

Added: trunk/src/edu/bonn/xulu/gui/XuluStartingFrame.java
===================================================================
--- trunk/src/edu/bonn/xulu/gui/XuluStartingFrame.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/gui/XuluStartingFrame.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,82 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.gui;
+
+import java.awt.Component;
+import javax.swing.JLabel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.ImageIcon;
+import java.util.ResourceBundle;
+import java.util.Vector;
+import java.io.PrintStream;
+
+import schmitzm.lang.ResourceProvider;
+import schmitzm.swing.SwingUtil;
+import schmitzm.swing.StatusDialog;
+import schmitzm.swing.TextAreaPrintStream;
+import edu.bonn.xulu.appl.XuluConstants;
+
+// nur fuer Doku
+import edu.bonn.xulu.XuluModellingPlatform;
+
+/**
+ * Diese Klasse stellt einen Dialog dar, der angezeigt wird, waehrend die
+ * Xulu-Applikation gestartet wird. Neben einem Status-Balken wird ein
+ * Text-Feld angezeigt, in dem (durch den {@link XuluModellingPlatform}-Konstruktor)
+ * die einzelnen Phasen der Initialisierung aufgelistet werden. Hierzu stellt
+ * diese Klasse einen {@link #getPrintStream() PrintStream} zur Verfuegung, in
+ * den nach und nach die Meldungen hineingeschrieben werden koennen.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class XuluStartingFrame extends StatusDialog {
+  private JTextArea           textArea;
+  private TextAreaPrintStream stream;
+//  // Bemerkung: Es koennen nicht die ResourceBundles aus XuluConstants verwendet
+//  //            werden, da zum Zeitpunkt des StartingFrame die CommandLine-Parameters
+//  //            noch nicht eingelesen wurden und somit die DefaultLocale noch
+//  //            nicht gesetzt wurde. Wird zu diesem Zeitpunkt auf diese ResourceBundles
+//  //            zugegriffen, werden diese nicht entsprechend dem CommandLine-Parameter
+//  //            initialisiert!
+//  private static ResourceBundle SWING_RES   = ResourceBundle.getBundle(SwingResource.class.getName());
+//  private static ResourceBundle XULUGUI_RES = ResourceBundle.getBundle(XuluGUIResource.class.getName());
+    /**
+     * Erzeugt einen neues Start-Fenster.
+     */
+    public XuluStartingFrame() {
+      super(null,XuluConstants.XULUGUI_RES.getString("StartMess")+" v"+XuluConstants.VERSION+" ["+XuluConstants.VERSION_DATE+"]",XuluConstants.SWING_RES.getString("WaitMess"),XuluConstants.XULU_STARTICON,0.5,0.5);
+      setResizable(false);
+      stream = new TextAreaPrintStream(textArea);
+    }
+
+    /**
+     * Fuegt zu den GUI-Komponenten von {@link StatusDialog} ein
+     * Text-Fenster in die Komponenten-Liste ein.
+     * @param list Liste der GUI-Komponenten des Dialogs
+     */
+    protected void insertInformationComponents(Vector<Component> list) {
+      super.insertInformationComponents(list);
+      textArea = new JTextArea(10,30);
+      textArea.setEditable(false);
+      textArea.setFont( new JLabel().getFont() );
+      textArea.setBackground( new JLabel().getBackground() );
+      list.add( new JScrollPane(textArea) );
+    }
+
+    /**
+     * Liefert einen Stream, der auf das Text-Fenster umgeleitet wird.
+     */
+    public PrintStream getPrintStream() {
+      return stream;
+    }
+}

Added: trunk/src/edu/bonn/xulu/gui/package.html
===================================================================
--- trunk/src/edu/bonn/xulu/gui/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/gui/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,10 @@
+<html>
+<body>
+	Dieses Paket enthält die GUI-Implementierungen der Xulu-Verwaltungsklassen (siehe
+	{@link edu.bonn.xulu.appl}).
+	Hierzu zählt insbesondere das {@linkplain edu.bonn.xulu.gui.XuluMainFrame Haupt-Fenster}
+	der Xulu-Modelling-Platform. Für Datenpool, Registrierung, Statusfenster, ... befinden sich
+	in diesem Paket jedoch nur abstrakte Oberklassen. Basis-Implementierungen hierzu sind im Paket
+	{@link edu.bonn.xulu.plugin.gui} zu finden.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/edu/bonn/xulu/io/AbstractFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/io/AbstractFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/io/AbstractFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,146 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.io;
+
+import edu.bonn.xulu.appl.XuluRegistry;
+import edu.bonn.xulu.io.Factory;
+
+/**
+ * Diese Klasse bildet eine Basisklasse fuer alle Factorys und implementiert
+ * die <code>equals</code>-Methode des {@link Factory#equals(Factory) Factory}-Interfaces.
+ * Da Factorys nur quasi-statische Methoden besitzen, gelten zwei Factorys
+ * als gleich, wenn sie Instanz derselben Klasse sind.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class AbstractFactory implements Factory {
+  /** Speichert den Namen, mit der die Factory gegenueber dem Anwender
+   *  identifiziert wird. */
+  protected String name = "";
+
+  /**
+   * Erzeugt eine neue Factory.
+   * @param name Bezeichnung/Beschreibung der Factory
+   */
+  public AbstractFactory(String name) {
+    setName(name);
+  }
+
+  /**
+   * Erzeugt eine neue Factory ohne Namen.
+   */
+  public AbstractFactory() {
+    setName("");
+  }
+
+  /**
+   * Liefert den Namen der Factory.
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Setzt den Namen der Factory.
+   * @param name neuer Name
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * Prueft, ob die Factory mit einer anderen uebereinstimmt. Dies ist der Fall
+   * wenn sie Instanzen derselben Klasse sind.
+   */
+  public boolean equals(Factory fac) {
+    return fac.getClass().equals( this.getClass() );
+  }
+
+  /**
+   * Prueft, ob die Factory mit einer anderen uebereinstimmt. Dies ist der Fall
+   * wenn sie Instanzen derselben Klasse sind.
+   * @return <code>false</code>, wenn das uebergebene Objekt keine Implementierung
+   *         von {@link Factory} ist
+   * @see #equals(Factory)
+   */
+  public boolean equals(Object o) {
+    if ( !(o instanceof Factory) )
+      return false;
+    return equals((Factory)o);
+  }
+
+  /**
+   * Wirft eine Exception oder gibt <code>false</code> zurueck, je nachdem
+   * ob das <code>throwException</code>-Flag gesetzt ist oder nicht.
+   */
+  private static boolean performNoGood(boolean throwException, RuntimeException err) {
+    if ( !throwException )
+      return false;
+    throw err;
+  }
+
+  /**
+   * Liefert eine InstantiationFactory aus der Xulu-Registry, die einen
+   * bestimmten Datentyp erzeugt.
+   * @param reg  Xulu-Registry
+   * @param need Datentyp zu dem eine Factory gesucht wird
+   * @param throwException bestimmt, ob eine Exception geworfen wird, wenn keine
+   *        Factory gefunden wird
+   * @exception java.lang.UnsupportedOperationException wenn die Suche in der Registry
+   *            fehl schlaegt und das <code>throwException</code>-Flag gesetzt ist
+   */
+  public static InstantiationFactory getInstantiationFactoryFromRegistry(XuluRegistry reg, Class need, boolean throwException) {
+    if ( reg == null && throwException )
+      throw new UnsupportedOperationException("Can search for a factory in null-registry");
+
+    InstantiationFactory fac = reg.getDefaultFactory(need);
+    if ( fac == null && throwException )
+      throw new UnsupportedOperationException("No factory found in registry, that creates an instances of ".concat(need.getName()).concat("!"));
+    return fac;
+  }
+
+  /**
+   * Prueft, ob ein Eingabequelle-Objekt fuer eine ImportFactory geeignet ist.
+   * @param fac   Factory, fuer die dieser Check aufgerufen wird
+   * @param input Eingabequelle, die geprueft wird
+   * @param need  Klasse, die fuer die Factory als Eingabequelle benoetigt wird
+   * @param throwException bestimmt, ob eine Exception geworfen wird, oder
+   *        nicht
+   * @exception java.lang.UnsupportedOperationException wenn der Check fehl
+   *            schlaegt und das <code>throwException</code>-Flag gesetzt ist
+   */
+  public static boolean checkImportSourceObject(ImportFactory fac, Object input, Class need, boolean throwException) {
+    if ( input == null )
+      return performNoGood( throwException, new UnsupportedOperationException(fac.getClass().getName().concat(".importObject(.) can not import from null-input")) );
+    if ( !need.isInstance(input) )
+      return performNoGood( throwException, new UnsupportedOperationException(fac.getClass().getName().concat(".importObject(.) needs ").concat(need.getName()).concat(" for input-Parameter!")) );
+    return true;
+  }
+
+  /**
+   * Prueft, ob ein Ausgabeziel-Objekt fuer eine ExportFactory geeignet ist.
+   * @param fac    Factory, fuer die dieser Check aufgerufen wird
+   * @param output Ausgabequelle, die geprueft wird
+   * @param need   Klasse, die fuer die Factory als Ausgabeziel benoetigt wird
+   * @param throwException bestimmt, ob eine Exception geworfen wird, oder
+   *        nicht
+   * @exception java.lang.UnsupportedOperationException wenn der Check fehl
+   *            schlaegt und das <code>throwException</code>-Flag gesetzt ist
+   */
+  public static boolean checkExportDestinationObject(ExportFactory fac, Object output, Class need, boolean throwException) {
+    if ( output == null )
+      return performNoGood( throwException, new UnsupportedOperationException(fac.getClass().getName().concat(".exportObject(.) can not export to null-output")) );
+    if ( !need.isInstance(output) )
+      return performNoGood( throwException, new UnsupportedOperationException(fac.getClass().getName().concat(".exportObject(.) needs ").concat(need.getName()).concat(" for output-Parameter!")) );
+    return true;
+  }
+}

Added: trunk/src/edu/bonn/xulu/io/ExportFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/io/ExportFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/io/ExportFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,61 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.io;
+
+// nur fuer Doku
+import java.io.OutputStream;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+/**
+ * Dieses Interface bildet den Obertyp fuer alle Export-Factorys. Diese haben
+ * die Aufgabe, ein Objekt in einen Ausgabe-Stream (z.B. eine Datei) zu
+ * schreiben. Das Format haengt von der jeweiligen Factory-Implementierung
+ * ab.<br>
+ * <b>Bemerke:</b><br>
+ * Die (entscheidende) Methode {@link #exportObject(Object,Object)} erhaelt
+ * als Parameter fuer den Ausgabe-Ziel ein <code>Object</code> (und nicht
+ * z.B. einen <code>File</code> oder <code>OutputStream</code>), um die
+ * Moeglichkeiten fuer die Implementierungen flexibler zu gestalten.
+ * Was fuer ein Ausgabe-Object uebergeben wird, haengt von der aufrufenden
+ * Anwendung ab.
+ * Die Methode {@link AbstractFactory#checkExportDestinationObject(ExportFactory,Object,Class,boolean)}
+ * bietet eine Hilfsmethode, um zu pruefen, ob die richtige Ausgabe-Klasse
+ * uebergeben wurde.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public interface ExportFactory extends Factory {
+  /**
+   * Prueft, ob ein Objekt von der Factory exportiert werden kann.
+   */
+  public boolean isExportable(Object obj);
+
+  /**
+   * Prueft, ob ein Objekt-Klasse von der Factory exportiert werden kann.
+   */
+  public boolean isExportable(Class c);
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt (z.B. {@link java.io.File} oder {@link java.io.InputStream}).<br>
+   */
+  public Class getExportDestinationType();
+
+  /**
+   * Exportiert ein Objekt in einen Ausgabe-Stream.
+   * @param obj zu exportierendes Objekt
+   * @param out Stream/Datei, in den das Objekt geschrieben wird
+   * @exception java.lang.Exception wenn ein Fehler beim Export auftritt
+   */
+  public void exportObject(Object obj, Object out) throws Exception;
+}

Added: trunk/src/edu/bonn/xulu/io/Factory.java
===================================================================
--- trunk/src/edu/bonn/xulu/io/Factory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/io/Factory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,32 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.io;
+
+import schmitzm.lang.NamedObject;
+
+/**
+ * Dieses Interface bildet den Obertyp fuer jegliche Art von Factory.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public interface Factory extends NamedObject {
+  /**
+   * Vergleicht, ob die Factory mit einer anderen uebereinstimmt. Da Factorys
+   * nur quasi-statische Methoden besitzen, sollte dies der Fall sein, wenn die
+   * Factorys derselben Klasse angehoeren. Die Methode sollte also einfach
+   * folgendes zurueckgeben:<br>
+   * <code>return fac.getClass().equals( this.getClass() );</code>
+   * @param fac andere Factory
+   */
+  public boolean equals(Factory fac);
+
+}

Added: trunk/src/edu/bonn/xulu/io/FactoryCanceledException.java
===================================================================
--- trunk/src/edu/bonn/xulu/io/FactoryCanceledException.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/io/FactoryCanceledException.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,42 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.io;
+
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.ExportFactory;
+
+/**
+ * Diese Exception wird geworfen, wenn der Anwender die "Arbeit" einer
+ * {@linkplain InstantiationFactory Default}-, {@linkplain ImportFactory Import}-
+ * oder {@linkplain ExportFactory Export}-Factory kontrolliert abbricht
+ * (z.B. durch einen Dialog).
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class FactoryCanceledException extends RuntimeException {
+  /**
+   * Erzeugt einen neue Exception.
+   * @param mess Meldung
+   */
+  public FactoryCanceledException(String mess) {
+    super(mess);
+  }
+
+  /**
+   * Erzeugt einen neue Exception.
+   * @param fac Factory, die abgebrochen wurde
+   */
+  public FactoryCanceledException(Factory fac) {
+    this(fac.getClass().getSimpleName().concat(" canceled by user!"));
+  }
+}

Added: trunk/src/edu/bonn/xulu/io/IODefinition.java
===================================================================
--- trunk/src/edu/bonn/xulu/io/IODefinition.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/io/IODefinition.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,144 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.io;
+
+import java.io.File;
+import schmitzm.lang.AbstractNamedObject;
+import edu.bonn.xulu.gui.DataPoolMenu;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+/**
+ * Diese Klasse stellt eine Oberklasse fuer die Informationen dar, die zum
+ * Import oder Export von Xulu-Objekten notwendig sind.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class IODefinition /*extends AbstractNamedObject*/ {
+  /** Speichert das Object aus dem importiert (in das exportiert) wird. */
+  protected Object       object   = null;
+  /** Speichert die Factory, die den Import (Export) vornimmt. */
+  protected Factory      factory  = null;
+  /** Speichert die Xulu-Registry, in der die Factories registriert sind. */
+  protected XuluRegistry registry = null;
+
+  /**
+   * Erzeugt eine neue Import/Export-Definition.
+   * @param object   Objekt aus dem importiert (bzw. in das exportiert) wird; z.B. eine Datei
+   * @param factory  Factory, die den Import/Export vornimmt
+   * @param registry Xulu-Registry in der die Factories registriert sind
+   */
+  public IODefinition(Object object, Factory factory, XuluRegistry registry) {
+    if ( object == null )
+      throw new IllegalArgumentException("null-object not allowed!");
+    if ( factory == null )
+      throw new IllegalArgumentException("null-factory not allowed!");
+    this.object     = object;
+    this.factory    = factory;
+    this.registry   = registry;
+  }
+
+  /**
+   * Liefert die Xulu-Registry, in der die Factories registriert sind.
+   */
+  public XuluRegistry getRegistry() {
+    return this.registry;
+  }
+
+  /**
+   * Liefert die Factory, die den Import (Export) vornimmt.
+   */
+  public Factory getFactory() {
+    return factory;
+  }
+
+  /**
+   * Liefert das Objekt aus dem importiert wird (in das exportiert
+   * wird).
+   */
+  public Object getIOObject() {
+    return object;
+  }
+
+  /**
+   * Vergleicht die {@code IODefinition} mit einer anderen. Beide sind
+   * gleich, gdw. beide die gleiche Factory und das gleiche I/O-Objekt
+   * enthalten.
+   * @param o andere {@code IODefinition}
+   * @see Factory#equals(Factory)
+   * @see Object#equals(Object)
+   */
+  public boolean equals(Object o) {
+    return o != null &&
+           o instanceof IODefinition &&
+           ((IODefinition)o).getFactory().equals( getFactory() ) &&
+           ((IODefinition)o).getIOObject().equals( getIOObject() );
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  //////////////////////   Import-Definition   //////////////////////
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse stellt eine Import-Definition dar. Sie besteht aus
+   * einer {@link ImportFactory} und einem Quell-Objekt aus dem
+   * die Factory ein Objekt generiert.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class ImportDefinition extends IODefinition {
+    /**
+     * Erzeugt eine neue Import-Definition.
+     * @param source   Objekt aus dem importiert wird; z.B. eine Datei
+     * @param fac      Factory, die den Import vornimmt
+     * @param registry Xulu-Registry in der die Factories registriert sind
+     */
+    public ImportDefinition(Object source, ImportFactory fac, XuluRegistry registry) {
+      super(source,fac,registry);
+    }
+
+    /**
+     * Liefert die Factory, die den Import vornimmt.
+     */
+    public ImportFactory getFactory() {
+      return (ImportFactory)super.getFactory();
+    }
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  //////////////////////   Export-Definition   //////////////////////
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse stellt eine Export-Definition dar. Sie besteht aus
+   * einer {@link ExportFactory} und einem Ziel-Objekt in das
+   * die Factory ein Objekt schreibt.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class ExportDefinition extends IODefinition {
+    /**
+     * Erzeugt eine neue Export-Definition.
+     * @param dest     Objekt in das exportiert wird; z.B. eine Datei
+     * @param fac      Factory, die den Export vornimmt
+     * @param registry Xulu-Registry in der die Factories registriert sind
+     */
+    public ExportDefinition(Object dest, ExportFactory fac, XuluRegistry registry) {
+      super(dest,fac,registry);
+    }
+
+    /**
+     * Liefert die Factory, die den Export vornimmt.
+     */
+    public ExportFactory getFactory() {
+      return (ExportFactory)super.getFactory();
+    }
+  }
+}
+

Added: trunk/src/edu/bonn/xulu/io/ImportFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/io/ImportFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/io/ImportFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,58 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.io;
+
+import edu.bonn.xulu.appl.XuluRegistry;
+// nur fuer Doku
+import edu.bonn.xulu.io.AbstractFactory;
+/**
+ * Dieses Interface bildet den Obertyp fuer alle Import-Factorys. Diese haben
+ * die Aufgabe, ein Objekt aus einer Import-Quelle (z.B. einer Datei) zu
+ * erzeugen. Das Format, das dieser Stream haben muss, haengt von der jeweiligen
+ * Factory-Implementierung ab.
+ * <b>Bemerke:</b><br>
+ * Die (entscheidende) Methode {@link #importObject(Object,XuluRegistry)} erhaelt
+ * als Parameter fuer die Eingabe-Quelle ein <code>Object</code> (und nicht
+ * z.B. einen <code>File</code> oder <code>OutputStream</code>), um die
+ * Moeglichkeiten fuer die Implementierungen flexibler zu gestalten.
+ * Was fuer ein Eingabe-Objekt uebergeben wird, haengt von der aufrufenden
+ * Anwendung ab. Die Methode
+ * {@link AbstractFactory#checkImportSourceObject(ImportFactory,Object,Class,boolean)}
+ * bietet eine Hilfsmethode, um zu pruefen, ob die richtige Eingabe-Klasse
+ * uebergeben wurde.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public interface ImportFactory extends Factory {
+  /**
+   * Liefert den Objekt-Typ, der von der Factory erzeugt wird.
+   */
+  public Class getImportType();
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Quelle zum Importieren
+   * benoetigt (z.B. {@link java.io.File} oder {@link java.io.InputStream}).<br>
+   * <b>Bemerke:</b><br>
+   * An dieser Stelle koennen auch Arrays angegeben werden,
+   * wenn die Factory ein Objekt z.B. aus mehreren Dateien erzeugt!
+   */
+  public Class getImportSourceType();
+
+  /**
+   * Importiert ein Objekt aus einen Eingabe-Stream.
+   * @param in  Import-Quelle (z.B. Stream oder Datei), aus dem das Objekt gelesen wird
+   * @param reg bietet Zugriff auf andere registrierte Factories (um z.B. eine
+   *            Standard-Instanz zu erzeugen, in die das Objekt importiert wird)
+   * @exception java.lang.Exception wenn beim Importieren ein Fehler auftritt
+   */
+  public Object importObject(Object in, XuluRegistry reg) throws Exception;
+}

Added: trunk/src/edu/bonn/xulu/io/InstantiationFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/io/InstantiationFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/io/InstantiationFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,46 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.io;
+
+/**
+ * Dieses Interface bildet den Obertyp fuer alle Factorys, die Standard-Instanzen
+ * eines Objekt-Typ erzeugen.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public interface InstantiationFactory extends Factory {
+  /**
+   * Liefert den Datentyp, den diese Factory instanziiert.
+   * @see #newInstance(boolean)
+   */
+  public Class getInstanceType();
+
+  /**
+   * Erzeugt eine neue Instanz des Datentyps. Da diese Methode parameterlos
+   * ist, muss es sich um eine (leere) Standard-Instanz handeln oder die
+   * Factory-Implementierung muss selbst die notwendigen Angaben (durch einen
+   * Anwender-Dialog) ermitteln.
+   * @param dialog gibt an, ob die Factory einen Dialog mit dem Anwender
+   *               fuehren darf, um die Instanz zu initialisieren (bei
+   *               <code>false</code> muss eine Standard-Instanz erzeugt werden)
+   */
+  public Object newInstance(boolean dialog) throws Exception;
+
+  /**
+   * Erzeugt eine neue Instanz des Datentyps aus der Vorlage eines anderen
+   * Objekts.
+   * @param sample Vorlage, aus der die Objekt-Struktur kopiert wird
+   * @param dialog gibt an, ob die Factory einen Dialog mit dem Anwender
+   *               fuehren darf, um die Vorlagen-Daten abzuaendern
+   */
+  public Object newInstance(boolean dialog, Object sample) throws Exception;
+}

Added: trunk/src/edu/bonn/xulu/io/TypeMapping.java
===================================================================
--- trunk/src/edu/bonn/xulu/io/TypeMapping.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/io/TypeMapping.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,222 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.io;
+
+import java.util.Vector;
+
+/**
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class TypeMapping {
+  private Class                type       = null;
+  private InstantiationFactory defaultFac = null;
+  private Vector               importFac  = new Vector<ImportFactory>();
+  private Vector               exportFac  = new Vector<ExportFactory>();
+
+  /**
+   * Erzeugt ein neues TypeMapping.
+   * @param type Datentyp
+   * @param fac  Factory, die eine Standard-Instanz des Datentyps erzeugt
+   * @exception schmitzm.data.io.TypeMappingException falls die
+   *            Default-Factory den Datentyp nicht erzeugt oder die Factory
+   *            <code>null</code> ist
+   */
+  public TypeMapping(Class type, InstantiationFactory fac) {
+    this.type = type;
+    setDefaultFactory(fac);
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Allgemeine Methoden
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Ersetzt ein Object in einem Vector durch ein anderes.
+   * Ist das <code>o1</code> nicht im Vector vorhanden wird nichts gemacht und
+   * <code>false</code> zurueckgegeben.
+   */
+  private boolean replace(Object o1, Object o2, Vector vector) {
+    int idx = vector.indexOf(o1);
+    if ( idx < 0 )
+      return false;
+    vector.set(idx,o2);
+    return true;
+  }
+
+  /**
+   * Prueft, ob diese angegebene allgemeine Factory zulaessig ist.
+   */
+  private void checkFactory(Factory fac) {
+    if ( fac == null )
+      throw new TypeMappingException("null-Factories are not allowed!");
+  }
+
+  /**
+   * Liefert den Datentyp des Mappings.
+   */
+  public Class getType() {
+    return this.type;
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Default-Factory
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Liefert die Factory, die den Datentyp standardmaessig instanziiert.
+   */
+  public InstantiationFactory getDefaultFactory() {
+    return this.defaultFac;
+  }
+
+  /**
+   * Prueft, ob diese angegebene allgemeine Factory als DefaultFactory zulaessig ist.
+   */
+  private void checkDefaultFactory(Factory fac) {
+    checkFactory(fac);
+    if ( !(fac instanceof InstantiationFactory) )
+      throw new TypeMappingException("DefaultFactory must be an instance of schmitzm.data.io.InstantiationFactory!");
+    if ( !getType().isAssignableFrom(((InstantiationFactory)fac).getInstanceType()) )
+      throw new TypeMappingException(getType(),fac,"Factory does not instantiate this type!");
+
+  }
+
+  /**
+   * Setzt die Factory, die den Datentyp standardmaessig instanziiert.
+   * @exception schmitzm.data.io.TypeMappingException falls die
+   *            Default-Factory den Datentyp nicht erzeugt oder die Factory
+   *            <code>null</code> ist
+   */
+  public void setDefaultFactory(InstantiationFactory fac) {
+    checkDefaultFactory(fac);
+    this.defaultFac = fac;
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Import-Factory
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Liefert alle Factorys, die den Datentyp importieren.
+   */
+  public ImportFactory[] getImportFactories() {
+    return (ImportFactory[])importFac.toArray(new ImportFactory[0]);
+  }
+
+  /**
+   * Prueft, ob diese angegebene allgemeine Factory als ImportFactory zulaessig ist.
+   */
+  private void checkImportFactory(Factory fac) {
+    checkFactory(fac);
+    if ( !(fac instanceof ImportFactory) )
+      throw new TypeMappingException("ImportFactory must be an instance of schmitzm.data.io.ImportFactory!");
+    if ( !getType().isAssignableFrom(((ImportFactory)fac).getImportType()) )
+      throw new TypeMappingException(getType(),fac,"Factory does not instantiate this type!");
+  }
+
+  /**
+   * Fuegt eine Import-Factory fuer den Datentyp hinzu.
+   * @return <code>false</code> falls diese Factory bereits fuer den Datentyp
+   *         registriert ist
+   * @exception schmitzm.data.io.TypeMappingException falls die
+   *            Import-Factory den Datentyp des TypeMappings nicht erzeugt
+   *            oder die Factory <code>null</code> ist
+   */
+  public boolean addImportFactory(ImportFactory fac) {
+    checkImportFactory(fac);
+    if ( importFac.contains(fac) )
+      return false;
+    return importFac.add(fac);
+  }
+
+  /**
+   * Entfernt eine Import-Factory aus dem TypeMapping.
+   * @return <code>false</code> falls diese Factory nicht fuer den Datentyp
+   *         registriert ist
+   */
+  public boolean removeImportFactory(ImportFactory fac) {
+    return importFac.remove(fac);
+  }
+
+  /**
+   * Ersetzt eine Import-Factory des TypeMappings durch eine andere.
+   * @param facOld zu ersetzende Factory
+   * @param facNew neue Factory
+   * @return <code>false</code> falls <code>facOld</code> nicht fuer den Datentyp
+   *         registriert war und deshalb keine Ersetzung moeglich ist
+   * @exception schmitzm.data.io.TypeMappingException falls die
+   *            neue Import-Factory den Datentyp des TypeMappings nicht erzeugt
+   *            oder die Factory <code>null</code> ist
+   */
+  public boolean replaceImportFactory(ImportFactory facOld, ImportFactory facNew) {
+    checkImportFactory(facNew);
+    return replace(facOld,facNew,importFac);
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Export-Factory
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Liefert alle Factorys, die den Datentyp exportieren.
+   */
+  public ExportFactory[] getExportFactories() {
+    return (ExportFactory[])exportFac.toArray(new ExportFactory[0]);
+  }
+
+  /**
+   * Prueft, ob diese angegebene allgemeine Factory als ExportFactory zulaessig ist.
+   */
+  private void checkExportFactory(Factory fac) {
+    checkFactory(fac);
+    if ( !(fac instanceof ExportFactory) )
+      throw new TypeMappingException("ExportFactory must be an instance of schmitzm.data.io.ExportFactory!");
+    if ( !((ExportFactory)fac).isExportable(getType()) )
+      throw new TypeMappingException(getType(),fac,"Factory can not export this type!");
+  }
+
+  /**
+   * Fuegt eine Export-Factory fuer den Datentyp hinzu.
+   * @return <code>false</code> falls diese Factory bereits fuer den Datentyp
+   *         registriert ist
+   * @exception schmitzm.data.io.TypeMappingException falls die
+   *            Export-Factory den Datentyp des TypeMappings nicht exportieren
+   *            kann oder die Factory <code>null</code> ist
+   */
+  public boolean addExportFactory(ExportFactory fac) {
+    checkExportFactory(fac);
+    if ( exportFac.contains(fac) )
+      return false;
+    return exportFac.add(fac);
+  }
+
+  /**
+   * Entfernt eine Export-Factory aus dem TypeMapping.
+   * @return <code>false</code> falls diese Factory nicht fuer den Datentyp
+   *         registriert ist
+   */
+  public boolean removeExportFactory(ImportFactory fac) {
+    return exportFac.remove(fac);
+  }
+
+  /**
+   * Ersetzt eine Export-Factory des TypeMappings durch eine andere.
+   * @param facOld zu ersetzende Factory
+   * @param facNew neue Factory
+   * @return <code>false</code> falls <code>facOld</code> nicht fuer den Datentyp
+   *         registriert war und deshalb keine Ersetzung moeglich ist
+   * @exception schmitzm.data.io.TypeMappingException falls die
+   *            neue Export-Factory den Datentyp des TypeMappings nicht exportieren
+   *            kann oder die Factory <code>null</code> ist
+   */
+  public boolean replaceExportFactory(ExportFactory facOld, ExportFactory facNew) {
+    checkExportFactory(facNew);
+    return replace(facOld,facNew,exportFac);
+  }
+}

Added: trunk/src/edu/bonn/xulu/io/TypeMappingException.java
===================================================================
--- trunk/src/edu/bonn/xulu/io/TypeMappingException.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/io/TypeMappingException.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,48 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.io;
+
+/**
+ * Dieser Fehler wird erzeugt, wenn ein Fehler mit bei der Datentyp/Factory-Zuordnung
+ * auftritt.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of
+ *   Bonn/Germany)
+ * @version 1.0
+ */
+public class TypeMappingException extends RuntimeException {
+  /**
+   * Erzeugt einen neuen Fehler.
+   * @param type Datentyp bei dem der Fehler aufgetreten ist
+   * @param fac  Factory bei der der Fehler auftreten ist
+   * @param mess zusaetzliche Fehlermeldung
+   */
+  public TypeMappingException(Class type, Factory fac, String mess) {
+    super( type.getSimpleName().concat(" can not be mapped to ").concat(fac.getClass().getSimpleName()).concat(". ").concat(mess) );
+  }
+
+  /**
+   * Erzeugt einen neuen Fehler.
+   * @param type Datentyp bei dem der Fehler aufgetreten ist
+   * @param fac  Factory bei der der Fehler auftreten ist
+   */
+  public TypeMappingException(Class type, Factory fac) {
+    this(type,fac,"");
+  }
+
+  /**
+   * Erzeugt einen neuen Fehler.
+   * @param mess Fehlermeldung
+   */
+  public TypeMappingException(String mess) {
+    super(mess);
+  }
+}

Added: trunk/src/edu/bonn/xulu/io/package.html
===================================================================
--- trunk/src/edu/bonn/xulu/io/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/io/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,7 @@
+<html>
+<body>
+	Dieses Paket enthält Klassen (insbesondere Interfaces) für die Factory-gesteuerte Objekt-Erzeugung,
+	sowie den Import und Export. Darüberhinaus bietet die Klasse {@link edu.bonn.xulu.io.TypeMapping} die
+	Möglichkeit, einer Objekt-Klasse feste Instanziierungs-, Import- und Export-Factorys zuzuordnen.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/edu/bonn/xulu/model/AbstractModelContentManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/AbstractModelContentManager.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/AbstractModelContentManager.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,135 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model;
+
+import java.util.Map;
+
+import edu.bonn.xulu.model.ModelResource;
+import edu.bonn.xulu.appl.XuluConstants;
+import edu.bonn.xulu.data.XuluDataException;
+
+import schmitzm.lang.LangUtil;
+import schmitzm.lang.ResourceProvider;
+import schmitzm.swing.CaptionsChangeable;
+
+import org.apache.log4j.Logger;
+
+/**
+ * Diese Klasse stellt eine abstrakte Basis-Implementierung fuer den
+ * {@link ModelContentManager} dar. Das einizge, das fuer ein Modell
+ * noch implementieren bleibt, ist die modellspezifische Befuellung
+ * des {@link #resource}-Array (im Konstruktor).<br>
+ * Am besten wird wird die modellspezifische Implementierung als innere
+ * Klasse in die Modell-Klasse integriert.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class AbstractModelContentManager implements ModelContentManager {
+  private ResourceProvider RESOURCE = XuluConstants.XULUGUI_RES;
+
+  /** {@link Logger} fuer Debug- oder Warn-Meldungen. */
+  protected Logger LOGGER = LangUtil.createLogger(this);
+
+  /** Speichert die Ressourcen, die ein Modell benoetigt. */
+  protected ModelResource[] resource = null;
+
+  /**
+   * Erzeugt einen neuen ContentManager. Der {@link #resource}-Array wird auf
+   * die benoetigte Ressourcen-Anzahl initialisiert.
+   * @param count Anzahl an Ressourcen, die das Model benoetigt.
+   */
+  public AbstractModelContentManager(int count) {
+    this.resource = new ModelResource[count];
+  }
+
+  /**
+   * Erzeugt einen neuen ContentManager. Der {@link #resource}-Array wird auf
+   * eine groesse von 0 initialisiert.
+   */
+  public AbstractModelContentManager() {
+    this(0);
+  }
+
+  /**
+   * Liefert eine Ressource, die ein Modell benoetigt.
+   * @param idx Nummer der Ressource
+   */
+  public ModelResource getResource(int idx) {
+    return resource[idx];
+  }
+
+  /**
+   * Liefert das Datenobjekt einer Ressourcen.
+   * @param idx Nummer der Ressource
+   */
+  public Object getResourceData(int idx) {
+    return getResource(idx).getData();
+  }
+
+  /**
+   * Liefert die Anzahl der Ressourcen, die das Modell benoetigt.
+   */
+  public int getResourceCount() {
+    return resource.length;
+  }
+
+  /**
+   * Ueberprueft alle Ressourcen auf Korrektheit.
+   * @see ModelResource#check()
+   * @return <code>false</code> falls eine Ressource nicht korret gefuellt ist
+   */
+  public boolean check() {
+    try {
+      checkAndError();
+    } catch (Exception err) {
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * Ueberprueft alle Ressourcen auf Korrektheit. Unterklassen muessen diese
+   * Methode ueberschreiben, falls eine Uberpruefung der Konsistenz
+   * <b>zwischen</b> den einzelnen Ressourcen notwendig ist.
+   * @exception XuluDataException falls eine Ressource nicht korret gefuellt ist
+   * @see ModelResource#checkAndError()
+   */
+  public void checkAndError() throws XuluDataException {
+    for (int i=0; resource != null & i<resource.length; i++)
+      resource[i].checkAndError();
+  }
+
+  /**
+   * Belegt die sprachspezifischen Elemente des Modells (Ressourcen-Beschreibungen)
+   * neu mit Elementen aus der Map. Diese Standard-Implementierung macht nichts.
+   * @param captionMap Label-Beschreibungen
+   */
+  public void resetCaptions(Map<String, Object> captionMap) { 
+  }
+
+  /**
+   * Belegt die Beschreibung einer Ressource neu. Zunaechst wird die {@code captionMap}
+   * herangezogen. Wenn dort zu dem {@code captionKey} kein Wert hinterlegt ist,
+   * wird auf dan angegebenen ResourceProvider zurueckgegriffen.
+   * @param resourceNo    Index einer Modell-Ressource
+   * @param captionMap    Map mit neuen Bezeichnungen
+   * @param rp            ResourceProvider
+   * @param captionKey    Key unter dem in der Map und im ResourceProvider gesucht wird 
+   * @param captionParams Parameter, die durch den ResourceProvider in die Caption "eingebaut" werden
+   * @see ResourceProvider#getString(String, Object...)
+   */
+  public void resetResourceDescription(int resourceNo, Map<String,Object> captionMap, ResourceProvider rp, String captionKey, Object... captionParams) {
+    String newCaption = AbstractXuluModel.determineCaption(captionMap, rp, captionKey, captionParams);
+    if ( newCaption != null )
+      resource[resourceNo].setDesc( newCaption );
+  }
+}

Added: trunk/src/edu/bonn/xulu/model/AbstractModelResource.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/AbstractModelResource.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/AbstractModelResource.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,317 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model;
+
+import schmitzm.lang.ResourceProvider;
+
+import edu.bonn.xulu.model.ModelResource;
+import edu.bonn.xulu.data.XuluDataException;
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.appl.XuluConstants;
+
+/**
+ * Diese Klasse bildet eine abstrakte Basis-Implementierung fuer eine Modell-Ressource.
+ * Die einzigen Methoden, die eine Unterklasse noch implementieren muss, sind
+ * {@link #checkAndError(Object)} und {@link #checkTypeAndError(Object)},
+ * ueber die geprueft wird, ob ein Objekt fuer die Ressource zulaessig ist.<br>
+ * Details zur Funktionalitaet und Bestimmung dieser Klasse sind in
+ * {@link ModelResource} zu finden.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class AbstractModelResource implements ModelResource {
+  private ResourceProvider RESOURCE = XuluConstants.XULUGUI_RES;
+
+    /** Speichert den Datentyp der Ressource. */
+    protected Class type   = null;
+    /** Speichert das Daten-Objekt der Ressource. */
+    protected Object data = null;
+    /** Speichert die Beschreibung der Ressource. */
+    protected String desc   = "";
+    /** Speichert, ob die Ressource unbelegt bleiben darf */
+    protected boolean nullable = false;
+    /** Speichert die Kategorie der Ressource (Default: {@link #CATEGORY_OTHER}) */
+    protected int category = CATEGORY_OTHER;
+
+    /**
+     * Erzeugt eine leere Ressource.
+     * @param category Ordnet die Ressource in eine Kategorie ein (siehe
+     *                 {@link #setCategory(int)})
+     * @param desc Beschreibung der Ressource
+     * @param type Datentyp der Ressource
+     * @param nullable gibt an, ob die Ressource unbelegt bleiben darf
+     * @exception XuluDataException falls der Datentyp <code>null</code> ist.
+     */
+    public AbstractModelResource(int category, String desc, Class type, boolean nullable) {
+      if ( type == null )
+        throw new XuluDataException( RESOURCE.getString("ModelResource.Type.Null") );
+      checkCategory(category);
+      this.category = category;
+      this.type     = type;
+      this.desc     = desc;
+      this.nullable = nullable;
+    }
+
+    /**
+     * Erzeugt Ressource und ordnet ihr ein konretes Datenobjekt zu. Der Datentyp
+     * wird implizit aus dem uebergebenen Objekt ermittelt.
+     * @param category Ordnet die Ressource in eine Kategorie ein (siehe
+     *                 {@link #setCategory(int)})
+     * @param desc Beschreibung der Ressource
+     * @param data Daten-Objekt fuer die Ressource
+     * @param nullable gibt an, ob die Ressource unbelegt bleiben darf
+     * @exception XuluDataException falls das Datenobjekt <code>null</code> ist,
+     *           denn aus <code>null</code> kann kein Datentyp ermittelt werden
+     */
+    public AbstractModelResource(int category, String desc, Object data, boolean nullable) {
+      if ( data == null )
+        throw new XuluDataException( RESOURCE.getString("ModelResource.Data.Null") );
+      checkCategory(category);
+      this.category = category;
+      this.type = data.getClass();
+      this.desc = desc;
+      this.nullable = nullable;
+      setData(data);
+    }
+
+    /**
+     * Erzeugt eine leere Ressource.
+     * @param desc Beschreibung der Ressource
+     * @param type Datentyp der Ressource
+     * @param nullable gibt an, ob die Ressource unbelegt bleiben darf
+     * @exception XuluDataException falls der Datentyp <code>null</code> ist.
+     * @exception IllegalArgumentException falls eine unbekannte Kategorie
+     *            angegeben wird
+     */
+    public AbstractModelResource(String desc, Class type, boolean nullable) {
+      this(CATEGORY_OTHER,desc,type,nullable);
+    }
+
+    /**
+     * Erzeugt Ressource und ordnet ihr ein konretes Datenobjekt zu. Der Datentyp
+     * wird implizit aus dem uebergebenen Objekt ermittelt.
+     * @param desc Beschreibung der Ressource
+     * @param data Daten-Objekt fuer die Ressource
+     * @param nullable gibt an, ob die Ressource unbelegt bleiben darf
+     * @exception XuluDataException falls das Datenobjekt <code>null</code> ist,
+     *           denn aus <code>null</code> kann kein Datentyp ermittelt werden
+     * @exception IllegalArgumentException falls eine unbekannte Kategorie
+     *            angegeben wird
+     */
+    public AbstractModelResource(String desc, Object data, boolean nullable) {
+      this(CATEGORY_OTHER,desc,data,nullable);
+    }
+
+    /**
+     * Prueft, ob die angegebene Kategorie korrekt ist. Unterklassen, die neue
+     * Kategorien definieren, muessen diese Methode ueberschreiben.
+     * @exception IllegalArgumentException falls eine unbekannte Kategorie
+     *            angegeben wird
+     */
+    protected void checkCategory(int category) {
+      if ( category < 0 ||
+           category > (CATEGORY_INPUT | CATEGORY_OUTPUT | CATEGORY_TEMP) )
+        throw new XuluDataException( RESOURCE.getString("ModelResource.Cat.Unknown", category) );
+    }
+
+    /**
+     * Gibt an, ob die Ressource opional ist (also unbelegt bleiben darf).
+     */
+    public boolean isNullable() {
+      return nullable;
+    }
+
+    /**
+     * Bestimmt, ob die Ressource opional ist (also unbelegt bleiben darf).
+     */
+    public void setNullable(boolean nullable) {
+      this.nullable = nullable;
+    }
+
+    /**
+     * Liefert die Kategorie der Ressource. Dies kann die Konstante
+     * {@link #CATEGORY_OTHER} sein, oder eine logische
+     * Oder-Verknuepfung der Konstanten {@link #CATEGORY_INPUT},
+     * {@link #CATEGORY_OUTPUT} und {@link #CATEGORY_TEMP}.
+     */
+    public int getCategory() {
+      return this.category;
+    }
+
+    /**
+     * Setzt die Kategorie der Ressource. Dies kann die Konstante
+     * {@link #CATEGORY_OTHER} sein, oder eine logische
+     * Oder-Verknuepfung der Konstanten {@link #CATEGORY_INPUT},
+     * {@link #CATEGORY_OUTPUT} und {@link #CATEGORY_TEMP}.
+     * @exception IllegalArgumentException falls eine unbekannte Kategorie
+     *            angegeben wird
+     */
+    public void setCategory(int category) {
+      checkCategory(category);
+      this.category = category;
+    }
+
+    /**
+     * Prueft, ob die Ressource einer bestimmten Kategorie
+     * zugeordnet ist. Liefert <code>true</code> wenn die Ressource <b>einer</b>
+     * der angegebenen Kategorien zugeordnet ist (ODER).
+     * @param category Oder-Verknuepfung von Kategorien
+     * @return <code>this.getCategory() == CATEGORY_OTHER && category == CATEGORY_OTHER ||
+     *         (this.getCategory() & category) > 0</code>
+     */
+    public boolean isCategory(int category) {
+      return getCategory() == CATEGORY_OTHER && category == CATEGORY_OTHER ||
+            (getCategory() & category) > 0;
+    }
+
+    /**
+     * Prueft, ob die Ressource einer bestimmten Kategorie-Kombination
+     * zugeordnet ist. Liefert <code>true</code> wenn die Ressource <b>allen</b>
+     * angegebenen Kategorien zugeordnet ist (UND).
+     * @return <code>this.getCategory() == CATEGORY_OTHER && category == CATEGORY_OTHER ||
+     *         (this.getCategory() & category) == category</code>
+     */
+    public boolean isCategoryAll(int category) {
+      return getCategory() == CATEGORY_OTHER && category == CATEGORY_OTHER ||
+            (getCategory() & category) == category;
+    }
+
+    /**
+     * Prueft ein beliebiges Objekt nur auf Typ-Vertraeglichkeit mit der
+     * Ressource.
+     */
+    public boolean checkType(Object data) {
+      try {
+        checkTypeAndError(data);
+      } catch (Exception err) {
+        return false;
+      }
+      return true;
+    }
+
+    /**
+     * Prueft ein beliebiges Objekt nur auf Typ-Vertraeglichkeit mit der
+     * Ressource.
+     * @exception XuluDataException falls der Objekt-Typ nicht mit der Ressourcen
+     *            vertraeglich ist
+     */
+    public abstract void checkTypeAndError(Object data) throws XuluDataException;
+
+    /**
+     * Prueft ein beliebiges Objekt auf Typ- und Wert-Konsistenz mit der
+     * Ressource.
+     * @see #checkAndError(Object)
+     */
+    public boolean check(Object data) {
+      try {
+        checkAndError(data);
+      } catch (Exception err) {
+        return false;
+      }
+      return true;
+    }
+
+    /**
+     * Prueft ein beliebiges Objekt auf Typ- und Wert-Konsistenz mit der
+     * Ressource. Kann manuell aufgerufen werden und wird automatisch von
+     * {@link #setData(Object)} aufgerufen.
+     * @exception XuluDataException falls der Typ oder der Wert des zugeordneten
+     *            Objekts nicht mit der Ressource vertraeglich ist
+     */
+    public abstract void checkAndError(Object data) throws XuluDataException;
+
+    /**
+     * Prueft das der Ressource zugeordnete Objekt auf Typ- und Wert-Konsistenz
+     * mit der Ressource.
+     * @see #checkAndError()
+     */
+    public boolean check() {
+      return check( getData() );
+    }
+
+    /**
+     * Prueft das der Ressource zugeordnete Objekt auf Typ- und Wert-Konsistenz
+     * mit der Ressource.
+     * @exception XuluDataException falls der Typ oder der Wert des zugeordneten
+     *            Objekts nicht mit der Ressource vertraeglich ist
+     * @see #checkAndError(Object)
+     */
+    public void checkAndError() throws XuluDataException {
+      checkAndError( getData() );
+    }
+
+    /**
+     * Liefert den Datentyp der Ressource.
+     */
+    public Class getType() {
+      return this.type;
+    }
+
+    /**
+     * Liefert das Daten-Objekt der Ressource.
+     */
+    public Object getData() {
+      return this.data;
+    }
+
+    /**
+     * Liefert eine Beschreibung, worum es sich bei der Ressource handelt.
+     */
+    public String getDesc() {
+      return this.desc;
+    }
+
+    /**
+     * Setzt eine Beschreibung, worum es sich bei der Ressource handelt.
+     */
+    public void setDesc(String desc) {
+      this.desc = desc;
+    }
+
+    /**
+     * Ordnet der Ressource ein bestimmtes Datenobjekt zu.
+     * @param data Daten-Objekt
+     * @param check bestimmt, ob das Datenobjekt sofort auf Typ-Vertraeglichkeit
+     *   ueberprueft werden soll
+     * @see #checkAndError(Object)
+     */
+    public void setData(Object data, boolean check) {
+      if ( check )
+        checkAndError( data );
+      this.data = data;
+    }
+
+    /**
+     * Ordnet der Ressource ein bestimmtes Datenobjekt zu.
+     * @param data Daten-Objekt
+     * @throws XuluDataException falls das nicht mit dem Ressourcen-Typ
+     *         vertraeglich ist
+     * @see #checkAndError(Object)
+     */
+    public void setData(Object data) throws XuluDataException {
+      setData(data,true);
+    }
+
+    /**
+     * Erzeugt und wirft eine {@link XuluDataException} mit der Beschreibung
+     * <center>
+     * "Resource '<i>resource_name</i>': <i>expected</i> expected"
+     * </center>
+     * Der Ressourcenname wird automatisch ueber {@link #getDesc() this.getDesc()}
+     * ermittelt. Der erwartete Wert/Typ wird als Parameter uebergeben.
+     * @param expected Bezeichnung des erwarteten Typ/Wert
+     */
+    protected void throwDataException(String expected) {
+      throw new XuluDataException( RESOURCE.getString("ModelResource.Data.Error",desc,expected));
+    }
+
+}

Added: trunk/src/edu/bonn/xulu/model/AbstractStepModel.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/AbstractStepModel.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/AbstractStepModel.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,98 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model;
+
+import schmitzm.lang.ResourceProvider;
+import edu.bonn.xulu.appl.XuluConstants;
+import edu.bonn.xulu.model.AbstractXuluModel;
+import edu.bonn.xulu.model.StepModel;
+import edu.bonn.xulu.model.event.ModelListener;
+import edu.bonn.xulu.model.event.ModelStepStartedEvent;
+import edu.bonn.xulu.model.event.ModelStepFinishedEvent;
+
+/**
+ * Diese Klasse implementiert ein Modell, welches schrittweise ausgefuehrt
+ * wird. Das Modell arbeitet eine feste Anzahl von Arbeitsschritten ab, bevor
+ * es automatisch auslaeuft. Die Anzahl wird in der Variablen {@link #stepCount}
+ * hinterlegt und <b>muss</b> von einer Implementierung befuellt werden!
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class AbstractStepModel extends AbstractXuluModel implements StepModel {
+  /** ResourceProvider fuer allgemeine Uebersetzungen. */
+  private ResourceProvider RESOURCE = XuluConstants.XULUGUI_RES;
+
+  /** Speichert die Anzahl der zu modellierenden Schritte.
+   *  muss vor dem Modellstart von der Implementierung gefuellt werden! */
+  protected int stepCount = 0;
+
+  /**
+   * Erzeugt ein neues Model.
+   * @param contentManager verwaltet die Ressourcen fuer das Model
+   */
+  public AbstractStepModel(ModelContentManager contentManager) {
+    super(contentManager);
+    events.add( ModelStepStartedEvent.class );
+    events.add( ModelStepFinishedEvent.class );
+  }
+
+  /**
+   * Implementiert den Rahmen des Modellablaufs. Ruft sukzessive
+   * {@link #performModelStep(int)} in einer Schleife auf, bis die
+   * vorgegebene Schrittzahl erreicht ist. Wird das Modell zuvor unterbrochen
+   * ({@link #stopModelling()} wird auch die Schleife unterbrochen. Loest
+   * {@link #fireModelStepStarted(int)} und {@link #fireModelStepFinished(int)}
+   * aus.
+   */
+  public void performModelStart() {
+    int stepCount = getStepCount();
+    for (int step=1; !isStopped() && step<=stepCount; step++) {
+      fireModelStepStarted(step);
+      performModelStep(step);
+      fireModelStepFinished(step);
+    }
+  }
+
+  /**
+   * Implementiert einen Modellschritt.
+   * @param stepNo Nummer des Modellschritts (beginnend bei 1)
+   */
+  public abstract void performModelStep(int stepNo);
+
+  /**
+   * Liefert die Anzahl der zu modellierenden Schritte.
+   * @see #stepCount
+   */
+  public int getStepCount() {
+    return stepCount;
+  }
+
+  /**
+   * Informiert alle {@link ModelListener} darueber, dass das Modell einen
+   * neuen Modellierungsschritt beginnt.
+   */
+  protected void fireModelStepStarted(int step) {
+    getStatusOut().println( RESOURCE.getString("Model.Step.Started",step) );
+    for (int i=0; i<listeners.size(); i++)
+      ((ModelListener)listeners.get(i)).performModelEvent(new ModelStepStartedEvent(this,step));
+  }
+
+  /**
+   * Informiert alle {@link ModelListener} darueber, dass das Modell einen
+   * neuen Modellierungsschritt beendet hat.
+   */
+  protected void fireModelStepFinished(int step) {
+    getStatusOut().println( RESOURCE.getString("Model.Step.Finished",step) );
+    for (int i=0; i<listeners.size(); i++)
+      ((ModelListener)listeners.get(i)).performModelEvent(new ModelStepFinishedEvent(this,step));
+  }
+}

Added: trunk/src/edu/bonn/xulu/model/AbstractXuluModel.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/AbstractXuluModel.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/AbstractXuluModel.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,439 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model;
+
+import java.io.PrintStream;
+import java.util.Map;
+import java.util.Vector;
+import java.awt.Component;
+
+import schmitzm.data.property.Access;
+import schmitzm.lang.AbstractNamedObject;
+import schmitzm.lang.LangUtil;
+import schmitzm.lang.ResourceProvider;
+import schmitzm.swing.CaptionsChangeable;
+
+import edu.bonn.xulu.model.XuluModel;
+import edu.bonn.xulu.model.ModelContentManager;
+import edu.bonn.xulu.model.ModelCanceledException;
+import edu.bonn.xulu.model.event.ModelListener;
+import edu.bonn.xulu.model.event.ModelEvent;
+import edu.bonn.xulu.model.event.ModelInitialisedEvent;
+import edu.bonn.xulu.model.event.ModelStartedEvent;
+import edu.bonn.xulu.model.event.ModelStoppedEvent;
+import edu.bonn.xulu.model.event.ModelDisposedEvent;
+
+import org.apache.log4j.Logger;
+import edu.bonn.xulu.appl.XuluConstants;
+
+/**
+ * Diese Klasse stellt eine Basis-Implementierung eines Xulu-Modells dar.
+ * Es werden alle Methoden des {@link XuluModel}-Interface implementiert, in dem
+ * entsprechende Flags sinnvoll gesetzt werden.<br>
+ * Eine konkrete Modell-Implementierung muss nur noch folgende Methoden
+ * implementieren:
+ * <ul>
+ * <li><b>{@link #performModelInit()}</b><br>
+ *     Initialisierung/Ruecksetzen aller internen Modell-Ressourcen und
+ *     Herstellen evt. fuer den Ablauf benoetigter Lese/Schreib-Rechte.</li>
+ * <li><b>{@link #performModelStart()}</b><br>
+ *     Implementierung des kompletten Modellablaufs (in einer Schleife, die
+ *     endet, wenn das {@link #stopped}-Flag gesetzt ist).</li>
+ * <li><b>{@link #performModelDispose()}</b><br>
+ *     Loeschen aller internen Ressourcen aus dem Speicher und Freigabe aller
+ *     externen Ressourcen/Rechte.</li>
+ * </ul>
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class AbstractXuluModel extends AbstractNamedObject implements XuluModel {
+  /** ResourceProvider fuer allgemeine Uebersetzungen. */
+  private ResourceProvider RESOURCE = XuluConstants.XULUGUI_RES;
+  /** ResourceProvider fuer modellspezifische Uebersetzungen. Diese Variable ist inital
+   *  {@code null} und muss von der jeweiligen Modell-Implementierung belegt werden!! */
+  protected ResourceProvider modelResourceProvider = null;
+
+  private Logger LOGGER = LangUtil.createLogger(this);
+
+  /** Ausgabe-Stream fuer Statusausgaben. Standardmaessig auf
+   *  {@link System#out System.out} eingestellt */
+  protected PrintStream statusOut = System.out;
+
+  /** Speichert den ContentManager fuer das Modell. Diese Variable ist
+   *  initial <code>null</code> und muss von der Implementierung befuellt werden! */
+  protected ModelContentManager contManager = null;
+
+  /** Speichert die Listener fuer das Modell. */
+  protected Vector listeners = new Vector<ModelListener>();
+
+  /** Dieses Flag speichert, ob das Modell gestoppt ist. Wird von
+   *  {@link #startModelling()} und {@link #stopModelling()} gesetzt.
+   *  Initial <code>true</code>.<br>
+   *  <b>Dieses Flag sollte an geeigneter Stelle im Modellablauf abgefragt
+   *  werden, um z.B. einen Zwischenschritt abzubrechen. */
+  protected boolean stopped = true;
+
+  /** Dieses Flag speichert, ob die Modellierung gerade laeuft. Wird von
+   *  {@link #startModelling()} und {@link #stopModelling()} gesetzt.
+   *  Initial <code>false</code>. */
+  protected boolean running = false;
+
+  /** Dieses Flag speichert, ob die Modellierung initialisiert ist, also
+   *  sich alle internen Ressourcen in einem Ausgangszustand befinden.
+   *  Wird von {@link #initModel()} und {@link #startModelling()} gesetzt.
+   *  Initial <code>false</code>. */
+  protected boolean initialised = false;
+
+  /** Dieses Flag speichert, ob die internen Modell-Ressourcen "zerstoert"
+   *  sind.
+   *  Wird von {@link #initModel()} und {@link #disposeModel()} gesetzt.
+   *  Initial <code>true</code>. */
+  protected boolean disposed = true;
+
+  /** Speichert die Ereignis-Typen, die waehrend des Modellablaufs geworfen
+   *  werden. Unterklassen koennen diese Liste erweitern.
+   *  @see #getEvents() */
+  protected Vector events = new Vector<ModelEvent>();
+
+  /**
+   * Erzeugt ein neues Modell.
+   * @param contManager verwaltet die Modell-Ressourcen
+   * @param name        Bezeichnung fuer das Modell
+   */
+  public AbstractXuluModel(ModelContentManager contManager, String name) {
+    this.contManager = contManager;
+    // Ereignisse in Liste aufnehmen
+    events.add( ModelInitialisedEvent.class );
+    events.add( ModelStartedEvent.class );
+    events.add( ModelStoppedEvent.class );
+    events.add( ModelDisposedEvent.class );
+  }
+
+  /**
+   * Erzeugt ein neues Modell.
+   * @param contManager verwaltet die Modell-Ressourcen
+   */
+  public AbstractXuluModel(ModelContentManager contManager) {
+    this(contManager,"");
+  }
+
+  /**
+   * Liefert den ContentManager des Modells.
+   */
+  public ModelContentManager getContentManager() {
+    return this.contManager;
+  }
+
+  /**
+   * Setzt den Stream fuer Status-Ausgaben des Modells.
+   */
+  public void setStatusOut(PrintStream out) {
+    this.statusOut = out;
+  }
+
+  /**
+   * Liefert den Stream fuer Status-Ausgaben des Modells.
+   */
+  public PrintStream getStatusOut() {
+    return statusOut;
+  }
+
+  /**
+   * Initialisiert das Model, indem der Modell-Ablauf gestoppt und
+   * {@link #performModelInit()} aufgerufen wird.
+   * Darueberhinaus wird das {@link #running}-Flag auf <code>false</code>, das
+   * {@link #stopped}-Flag auf <code>true</code>, das {@link #initialised}-Flag
+   * auf <code>true</code> und das {@link #disposed}-Flag auf <code>false</code>
+   * gesetzt.
+   */
+  public void initModel() {
+    if ( isRunning() )
+      stopModelling();
+    running = false;
+    stopped = true;
+    performModelInit();
+    initialised = true;
+    disposed = false;
+    fireModelInitialised();
+  }
+
+  /**
+   * Muss die eigentliche Initialisierung des Modells implementieren und
+   * alle <b>internen</b> Modell-Ressourcen auf einen Ausgangszustand
+   * zurueck setzen, so dass das Modell komplett neu gestartet werden
+   * kann.
+   */
+  public abstract void performModelInit();
+
+  /**
+   * Prueft, ob das Modell initialisiert ist - sich also im Ausgangszustand
+   * befindet - und bereit ist gestartet zu werden.
+   * @see #initialised
+   */
+  public boolean isInitialised() {
+    return this.initialised;
+  }
+
+  /**
+   * Startet die Modellierung, indem {@link #performModelStart()} aufgerufen
+   * wird. Desweiteren wird das {@link #running}-Flag auf <code>true</code>,
+   * das {@link #initialised}-Flag auf <code>false</code> und das
+   * {@link #stopped}-Flag auf <code>false</code> gesesetzt.
+   * @return {@code false} wenn das Modell auf irgendeine Art (kontrolliert oder
+   *         Fehler) abgebrochen wurde; {@code true} nur wenn das Modell komplett
+   *         durchgelaufen ist
+   */
+  public boolean startModelling() {
+    running = true;
+    initialised = false;
+    stopped = false;
+    fireModelStarted();
+    try {
+      performModelStart();
+      // Am Ende der Modellierung wird das Modell zerstoert, damit alle
+      // Ressourcen wieder freigegeben werden
+      disposeModel();
+      return true;
+    } catch ( ModelCanceledException err ) {
+      // erwartete Exception
+      // --> wird das Modell gestoppt, wird es zerstoert, damit alle
+      //     Ressourcen wieder freigegeben werden
+      disposeModel();
+    } catch ( Exception err ) {
+      getStatusOut().println("\n"+RESOURCE.getString("Model.ErrorOccured")+"\n   "+err+"\n");
+      performError();
+      err.printStackTrace();
+    }
+    return false;
+  }
+
+  /**
+   * Prueft, ob das Modell gestoppt ist. Ist dies der Fall wird eine
+   * {@link ModelCanceledException} geworfen.<br>
+   * Diese Methode sollte an geeigneten Stellen waehrend des Modellablaufs
+   * aufgerufen werden, um diesen aufgrund eines externen Befehls
+   * abzubrechen. Die Exception wird in der {@link #startModelling()}-Methode
+   * wieder abgefangen.
+   * @exception ModelCanceledException falls das Modell gestoppt ist
+   */
+  protected void checkBreakingCommands() throws ModelCanceledException {
+    if ( isStopped() || Thread.interrupted() )
+      throw new ModelCanceledException();
+  }
+
+  /**
+   * Implementiert den eigentlichen Modellablauf. Dies kann z.B. durch einen
+   * einfachen Befehlsablauf oder eine Schleife geschehen.
+   */
+  public abstract void performModelStart();
+
+  /**
+   * Prueft, ob das Modell gerade laeuft.
+   * @see #running
+   */
+  public boolean isRunning() {
+    return this.running;
+  }
+
+  /**
+   * Stoppt die Modellierung. Diese Implementierung setzt lediglich das
+   * {@link #running}-Flag auf <code>false</code> und das {@link #stopped}-Flag
+   * auf <code>true</code>.<br>
+   * Die Implementierung muss (in {@link #performModelStart()}) selbst auf
+   * {@link #isStopped()} oder das {@link #stopped}-Flag checken, um eine
+   * Schleife oder zeitaufwaendige Zwischenschritte abzubrechen.
+   */
+  public void stopModelling() {
+    running = false;
+    stopped = true;
+    fireModelStopped();
+  }
+
+  /**
+   * Prueft, ob das Modell gestoppt ist.
+   * @see #stopped
+   */
+  public boolean isStopped() {
+    return this.stopped;
+  }
+
+  /**
+   * Diese Methode "zerstoert" das Modell, in dem es zunaechst gestoppt und
+   * dann {@link #performModelDispose()} aufgerufen wird.
+   * Desweiteren wird das {@link #disposed}-Flag auf <code>true</code>
+   * gesetzt.
+   */
+  public void disposeModel() {
+    if ( isRunning() )
+      stopModelling();
+    performModelDispose();
+    disposed = true;
+    fireModelDisposed();
+  }
+
+  /**
+   * Implementiert die eigentliche Freigabe der Modell-Ressourcen, indem alle
+   * <b>internen</b> Modell-Ressourcen aus dem Speicher geloescht und die
+   * externen wieder frei gegeben werden.
+   */
+  public abstract void performModelDispose();
+
+  /**
+   * Prueft, ob das Modell (dessen interen Ressourcen) "zerstoert" ist.
+   * @see #disposed
+   */
+  public boolean isDisposed() {
+    return this.disposed;
+  }
+
+  /**
+   * Diese Methode wird aufgrufen, wenn ein unerwarteter Fehler bei der
+   * Modellierung auftritt, welcher das Beenden der Modellierung zu Folge
+   * hat. Diese Implementierung ruft lediglich {@link #disposeModel()} auf.
+   */
+  public void performError() {
+    disposeModel();
+  }
+
+  /**
+   * Fuegt einen ModelListener hinzu.
+   * @return <code>true</code> wenn dass Hinzufuegen erfolgreich war (siehe
+   *         {@link Vector#add(Object)})
+   */
+  public boolean addModelListener(ModelListener listener) {
+    return listeners.add(listener);
+  }
+
+  /**
+   * Entfernt einen ModelListener von dem Modell.
+   * @return <code>true</code> wenn dass Entfernen erfolgreich war (siehe
+   *         {@link Vector#remove(Object)})
+   */
+  public boolean removeModelListener(ModelListener listener) {
+    return listeners.remove(listener);
+  }
+
+  /**
+   * Informiert alle {@link ModelListener} ueber ein Modell-Ereinis.
+   */
+  protected void fireModelEvent(ModelEvent e) {
+    for (int i=0; i<listeners.size(); i++)
+      ((ModelListener)listeners.get(i)).performModelEvent(e);
+  }
+
+  /**
+   * Informiert alle {@link ModelListener} darueber, dass das Modell initialisiert
+   * wurde.
+   */
+  protected void fireModelInitialised() {
+    getStatusOut().println( RESOURCE.getString("Model.Init") );
+    fireModelEvent(new ModelInitialisedEvent(this));
+  }
+
+  /**
+   * Informiert alle {@link ModelListener} darueber, dass das Modell gestartet
+   * wurde.
+   */
+  protected void fireModelStarted() {
+    getStatusOut().println( RESOURCE.getString("Model.Start") );
+    fireModelEvent(new ModelStartedEvent(this));
+  }
+
+  /**
+   * Informiert alle {@link ModelListener} darueber, dass das Modell
+   * gestoppt wurde.
+   */
+  protected void fireModelStopped() {
+    getStatusOut().println( RESOURCE.getString("Model.Stop") );
+    fireModelEvent(new ModelStoppedEvent(this));
+  }
+
+  /**
+   * Informiert alle {@link ModelListener} darueber, dass das Modell
+   * "zerstoert" wurde.
+   */
+  protected void fireModelDisposed() {
+    getStatusOut().println( RESOURCE.getString("Model.Dispose") );
+    fireModelEvent(new ModelDisposedEvent(this));
+  }
+
+  /**
+   * Liefert immer <code>null</code>. Sub-Klassen koennen diese Methode
+   * ueberschreiben und eine spezielle (zusaetzliche) Modell-GUI
+   * zurueck geben.
+   */
+  public Component getModelSpecificGUI() {
+    return null;
+  }
+
+  /**
+   * Liefert alle Ereignis-Typen, die waehrend des Modellablaufs initiiert werden.
+   * @return leerer Array, falls keine Ereignisse initiiert werden
+   */
+  public Class<ModelEvent>[] getEvents() {
+    return (Class<ModelEvent>[])events.toArray( new Class[0] );
+  }
+
+  /**
+   * Gibt ein Lese- oder Schreibrecht wieder frei. Dabei wird zunaechst
+   * geprueft, ob das uebergebene Objekt nicht <code>null</code> ist.
+   */
+  protected static void releaseAccess(Access a) {
+    if ( a!=null )
+      a.release();
+  }
+
+  /**
+   * Liefert den {@link ResourceProvider}, der die Uebersetzungen
+   * fuer Modell-Ausgaben und modellspezifische GUI verwaltet.
+   * @return {@code null}, wenn das Modell nicht multi-lingual ist
+   */
+  public ResourceProvider getResourceProvider() {
+    return modelResourceProvider;
+  }
+  
+  /**
+   * Belegt die sprachspezifischen Elemente des Modells (Status-Ausgaben, GUI)
+   * neu mit Elementen aus der Map. Diese Standard-Implementierung macht nichts,
+   * ausser die {@code resetCaptions}-Methode des Content-Managers und der
+   * modell-spez. GUI aufzurufen, sofern diese {@link CaptionsChangeable} sind.
+   * @param captionMap Label-Beschreibungen
+   */
+  public void resetCaptions(Map<String, Object> captionMap) { 
+    if ( this.contManager instanceof CaptionsChangeable )
+      ((CaptionsChangeable)contManager).resetCaptions(captionMap);
+    Object gui = this.getModelSpecificGUI(); 
+    if ( gui != null && gui instanceof CaptionsChangeable )
+      ((CaptionsChangeable)gui).resetCaptions(captionMap);
+  }
+
+  /**
+   * Ermittelt einn String-Wert aus der {@code captionMap}. Wenn dort kein Wert
+   * hinterlegt ist, wird auf den ResourceProvider zurueckgegriffen.
+   * @param captionMap    Map mit neuen Bezeichnungen
+   * @param rp            ResourceProvider
+   * @param captionKey    Key unter dem in der Map und im ResourceProvider gesucht wird 
+   * @param captionParams Parameter, die durch den ResourceProvider in die Caption "eingebaut" werden
+   * @see ResourceProvider#getString(String, Object...)
+   */
+  public static String determineCaption(Map<String,Object> captionMap, ResourceProvider rp, String captionKey, Object... captionParams) {
+    // Beschreibung nach Moeglichkeit aus der Map ziehen
+    Object newCaptionObj = (captionMap != null) ? captionMap.get(captionKey) : null;
+    if ( newCaptionObj != null )
+      return newCaptionObj.toString();
+    // Wenn keine Beschreibung in Map hinterlegt, dann die "normale"
+    // Lokalisation verwenden
+    if ( rp != null )
+      return rp.getString(captionKey,captionParams);
+    return ( "" ); 
+  }
+}

Added: trunk/src/edu/bonn/xulu/model/DefaultModelResource.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/DefaultModelResource.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/DefaultModelResource.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,102 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+package edu.bonn.xulu.model;
+
+import edu.bonn.xulu.model.AbstractModelResource;
+import edu.bonn.xulu.data.XuluDataException;
+
+/**
+ * Standard-Implementierung von {@link AbstractModelResource}. Die Check-Methoden
+ * pruefen lediglich auf Typ-Vertraeglichkeit mit dem der Ressource zugeordneten
+ * Datentyp, sowie auf die not-null Eigenschaft.
+ * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a>
+ * @version 1.0
+ */
+public class DefaultModelResource extends AbstractModelResource {
+
+  /**
+   * Erzeugt eine leere Ressource.
+   * @param category Ordnet die Ressource in eine Kategorie ein (siehe
+   *                 {@link #setCategory(int)})
+   * @param desc Beschreibung der Ressource
+   * @param type Datentyp der Ressource
+   * @param nullable gibt an, ob die Ressource unbelegt bleiben darf
+   * @exception XuluDataException falls der Datentyp <code>null</code> ist.
+   */
+  public DefaultModelResource(int category, String desc, Class type, boolean nullable) {
+    super(category, desc, type, nullable);
+  }
+
+  /**
+   * Erzeugt Ressource und ordnet ihr ein konretes Datenobjekt zu. Der Datentyp
+   * wird implizit aus dem uebergebenen Objekt ermittelt.
+   * @param category Ordnet die Ressource in eine Kategorie ein (siehe
+   *                 {@link #setCategory(int)})
+   * @param desc Beschreibung der Ressource
+   * @param data Daten-Objekt fuer die Ressource
+   * @param nullable gibt an, ob die Ressource unbelegt bleiben darf
+   * @exception XuluDataException falls das Datenobjekt <code>null</code> ist,
+   *           denn aus <code>null</code> kann kein Datentyp ermittelt werden
+   */
+  public DefaultModelResource(int category, String desc, Object data, boolean nullable) {
+    super(category, desc, data, nullable);
+  }
+
+  /**
+   * Erzeugt eine leere Ressource.
+   * @param desc Beschreibung der Ressource
+   * @param type Datentyp der Ressource
+   * @param nullable gibt an, ob die Ressource unbelegt bleiben darf
+   * @exception XuluDataException falls der Datentyp <code>null</code> ist.
+   * @exception IllegalArgumentException falls eine unbekannte Kategorie
+   *            angegeben wird
+   */
+  public DefaultModelResource(String desc, Class type, boolean nullable) {
+    super(desc, type, nullable);
+  }
+
+  /**
+   * Erzeugt Ressource und ordnet ihr ein konretes Datenobjekt zu. Der Datentyp
+   * wird implizit aus dem uebergebenen Objekt ermittelt.
+   * @param desc Beschreibung der Ressource
+   * @param data Daten-Objekt fuer die Ressource
+   * @param nullable gibt an, ob die Ressource unbelegt bleiben darf
+   * @exception XuluDataException falls das Datenobjekt <code>null</code> ist,
+   *           denn aus <code>null</code> kann kein Datentyp ermittelt werden
+   * @exception IllegalArgumentException falls eine unbekannte Kategorie
+   *            angegeben wird
+   */
+  public DefaultModelResource(String desc, Object data, boolean nullable) {
+    super(desc, data, nullable);
+  }
+
+  /**
+   * Prueft ein beliebiges Objekt auf Typ- und Wert-Konsistenz mit der
+   * Ressource. Ruft lediglich {@link #checkTypeAndError(Object)} auf.
+   * @throws XuluDataException falls der Typ oder der Wert des zugeordneten
+   *         Objekts nicht mit der Ressource vertraeglich ist
+   */
+  public void checkAndError(Object data) throws XuluDataException {
+    checkTypeAndError(data);
+  }
+
+  /**
+   * Prueft ein beliebiges Objekt nur auf Typ-Vertraeglichkeit mit der
+   * Ressource.
+   * @throws XuluDataException falls der Objekt-Typ nicht mit der Ressourcen
+   *         vertraeglich ist
+   */
+  public void checkTypeAndError(Object data) throws XuluDataException {
+    if ( data!=null && !getType().isInstance(data) ||
+         data==null && !nullable )
+      throwDataException(getType().getSimpleName());
+  }
+}

Added: trunk/src/edu/bonn/xulu/model/ModelCanceledException.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/ModelCanceledException.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/ModelCanceledException.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,28 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model;
+
+/**
+ * Diese Exception wird geworfen, wenn der Modell-Ablauf abgebrochen wird
+ * @see AbstractXuluModel#performModelStart()
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class ModelCanceledException extends RuntimeException {
+  public ModelCanceledException() {
+    super();
+  }
+
+  public ModelCanceledException(String message) {
+    super(message);
+  }
+}

Added: trunk/src/edu/bonn/xulu/model/ModelContentManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/ModelContentManager.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/ModelContentManager.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,57 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model;
+
+import schmitzm.swing.CaptionsChangeable;
+import edu.bonn.xulu.model.ModelResource;
+import edu.bonn.xulu.data.XuluDataException;
+
+/**
+ * Der ModelContentManager spezifiziert die Datenbasis, die ein Modell fuer
+ * seine Ausfuehrung benoetigt. Diese besteht aus einer Reihe von
+ * {@link ModelResource}-Objekten, welche vor allem den Datentyp des jeweils
+ * benoetigten Objekts festlegen.<br>
+ * Die Implementierung ist eng mit dem jeweiligen Modell verbunden und in der
+ * Regel von Modell zu Modell unterschiedlich (aufgrund der unterschiedlichen
+ * Anforderungen). Deshalb wird der ModelContentManager am besten als innere
+ * Klasse des jeweiligen Modells implementiert.
+ * @see edu.bonn.xulu.model.XuluModel
+ * @see edu.bonn.xulu.model.AbstractModelContentManager
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public interface ModelContentManager extends CaptionsChangeable {
+  /**
+   * Liefert eine Ressource, die ein Modell benoetigt.
+   * @param idx Nummer der Ressource
+   */
+  public ModelResource getResource(int idx);
+
+  /**
+   * Liefert die Anzahl benoetigter Ressourcen.
+   */
+  public int getResourceCount();
+
+  /**
+   * Ueberprueft alle Resourcen auf Korrektheit.
+   * @see ModelResource#check()
+   * @return <code>false</code> falls eine Ressource nicht korret gefuellt ist
+   */
+  public boolean check();
+
+  /**
+   * Ueberprueft alle Ressourcen auf Korrektheit.
+   * @exception XuluDataException falls eine Ressource nicht korret gefuellt ist
+   * @see ModelResource#checkAndError()
+   */
+  public void checkAndError() throws XuluDataException;
+}

Added: trunk/src/edu/bonn/xulu/model/ModelResource.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/ModelResource.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/ModelResource.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,178 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model;
+
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.data.XuluDataException;
+
+/**
+ * Eine Ressource beschreibt allgemein ein Datenobjekt, das für die Modellierung
+ * benoetigt wird. Im Unterschied zu einem konkreten Daten-Objekt, existiert die
+ * Ressource auch, wenn noch gar keine Daten vorhanden sind.<br>
+ * Die Ressource beschreibt also vor allem die Struktur des benoetigten
+ * Objekts. Gleichzeitig nimmt sie aber auch die konkreten Daten auf und ist
+ * fuer deren Typenvertraeglichkeit verantwortlich.<br>
+ * Eine Ressource besteht aus 3 Teilen:
+ * <ul>
+ * <li><b>Typ (Klasse)</b><br>
+ *     beschreibt den Datentyp, der für die Ressource benoetigt wird (zulaessig ist)</li>
+ * <li><b>Daten</b><br>
+ *     nimmt ein (zulaessiges) Datenobjekt fuer die Ressource auf</li>
+ * <li><b>Beschreibung</b><br>
+ *     macht gegenueber dem Anwender (im UI) kenntlich, zu welchem Zweck die
+ *     Ressource benoetigt wird</li>
+ * </ul>
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public interface ModelResource {
+  /** Definiert die Ressource als "andere" Ressource */
+  public static final int CATEGORY_OTHER = 0;
+  /** Definiert die Ressource als Eingabe-Ressource */
+  public static final int CATEGORY_INPUT = 1;
+  /** Definiert die Ressource als Ausgabe-Ressource */
+  public static final int CATEGORY_OUTPUT = 2;
+  /** Definiert die Ressource als temporaere Ressource */
+  public static final int CATEGORY_TEMP = 4;
+
+  /**
+   * Liefert den Datentyp der Ressource.
+   */
+  public Class getType();
+
+  /**
+   * Liefert eine Beschreibung, worum es sich bei der Ressource handelt. Diese
+   * macht dem Anwender kenntlich, wofuer die Ressource vom Modell benoetigt wird.
+   */
+  public String getDesc();
+
+  /**
+   * Setzt eine Beschreibung, worum es sich bei der Ressource handelt. Diese
+   * macht dem Anwender kenntlich, wofuer die Ressource vom Modell benoetigt wird.
+   */
+  public void setDesc(String desc);
+
+  /**
+   * Liefert das Daten-Objekt der Ressource. Initial sollte dieses <code>null</code>
+   * sein.
+   */
+  public Object getData();
+
+  /**
+   * Ordnet der Ressource ein bestimmtes Datenobjekt zu. Wird i.d.R. vom
+   * XULU-ModelInputManager aufgerufen, nachdem der Anwender Daten aus dem
+   * DatenPool zugeordnet hat.
+   * @param data  Daten-Objekt
+   * @param check bestimmt, ob das Datenobjekt sofort auf Typ-Vertraeglichkeit
+   *        ueberprueft werden soll
+   */
+  public void setData(Object data, boolean check);
+
+  /**
+   * Gibt an, ob die Ressource opional ist (also unbelegt bleiben darf).
+   */
+  public boolean isNullable();
+
+  /**
+   * Bestimmt, ob die Ressource opional ist (also unbelegt bleiben darf).
+   */
+  public void setNullable(boolean nullable);
+
+  /**
+   * Ordnet der Ressource ein bestimmtes Datenobjekt zu. Zuvor wird das Objekt
+   * auf Korrektheit ueberprueft. Wird i.d.R. vom XULU-ModelInputManager
+   * aufgerufen, nachdem der Anwender Daten aus dem DatenPool zugeordnet hat.
+   * @param data  Daten-Objekt
+   * @exception XuluDataException falls das zugeordnete Objekt <code>null</code>
+   *         ist, oder die Klasse nicht mit dem Ressourcen-Typ vertraeglich ist
+   * @see #checkAndError()
+   */
+  public void setData(Object data) throws XuluDataException;
+
+  /**
+   * Liefert die Kategorie der Ressource. Dies kann die Konstante
+   * {@link #CATEGORY_OTHER} sein, oder eine logische
+   * Oder-Verknuepfung der Konstanten {@link #CATEGORY_INPUT},
+   * {@link #CATEGORY_OUTPUT} und {@link #CATEGORY_TEMP}.
+   */
+  public int getCategory();
+
+  /**
+   * Setzt die Kategorie der Ressource. Dies kann die Konstante
+   * {@link #CATEGORY_OTHER} sein, oder eine logische
+   * Oder-Verknuepfung der Konstanten {@link #CATEGORY_INPUT},
+   * {@link #CATEGORY_OUTPUT} und {@link #CATEGORY_TEMP}.
+   */
+  public void setCategory(int category);
+
+  /**
+   * Prueft, ob die Ressource einer bestimmten Kategorie
+   * zugeordnet ist. Liefert <code>true</code> wenn die Ressource <b>einer</b>
+   * der angegebenen Kategorien zugeordnet ist (ODER).
+   * @param category Oder-Verknuepfung von Kategorien
+   * @return <code>this.getCategory() == CATEGORY_OTHER && category == CATEGORY_OTHER ||
+   *         (this.getCategory() & category) > 0</code>
+   */
+  public boolean isCategory(int category);
+
+  /**
+   * Prueft, ob die Ressource einer bestimmten Kategorie-Kombination
+   * zugeordnet ist. Liefert <code>true</code> wenn die Ressource <b>allen</b>
+   * angegebenen Kategorien zugeordnet ist (UND).
+   * @return <code>this.getCategory() == CATEGORY_OTHER && category == CATEGORY_OTHER ||
+   *         (this.getCategory() & category) == category</code>
+   */
+  public boolean isCategoryAll(int category);
+
+  /**
+   * Prueft ein beliebiges Objekt auf Typ- und Wert-Konsistenz mit der
+   * Ressource.
+   */
+  public boolean check(Object data);
+
+  /**
+   * Prueft ein beliebiges Objekt auf Typ- und Wert-Konsistenz mit der
+   * Ressource. Kann manuell aufgerufen werden und wird automatisch von
+   * {@link #setData(Object)} aufgerufen.
+   * @exception XuluDataException falls der Typ oder der Wert des zugeordneten
+   *            Objekts nicht mit der Ressource vertraeglich ist
+   */
+  public void checkAndError(Object data) throws XuluDataException;
+
+  /**
+   * Prueft ein beliebiges Objekt nur auf Typ-Vertraeglichkeit mit der
+   * Ressource.
+   */
+  public boolean checkType(Object data);
+
+  /**
+   * Prueft ein beliebiges Objekt nur auf Typ-Vertraeglichkeit mit der
+   * Ressource.
+   * @exception XuluDataException falls der Objekt-Typ nicht mit der Ressourcen
+   *            vertraeglich ist
+   */
+  public void checkTypeAndError(Object data) throws XuluDataException;
+
+  /**
+   * Prueft das der Ressource zugeordnete Objekt auf Typ- und Wert-Konsistenz
+   * mit der Ressource.
+   */
+  public boolean check();
+
+  /**
+   * Prueft das der Ressource zugeordnete Objekt auf Typ- und Wert-Konsistenz
+   * mit der Ressource.
+   * @exception XuluDataException falls der Typ oder der Wert des zugeordneten
+   *            Objekts nicht mit der Ressource vertraeglich ist
+   */
+  public void checkAndError() throws XuluDataException;
+}

Added: trunk/src/edu/bonn/xulu/model/PropertiesResource.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/PropertiesResource.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/PropertiesResource.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,127 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model;
+
+import schmitzm.data.property.Properties;
+import edu.bonn.xulu.model.AbstractModelResource;
+import edu.bonn.xulu.data.XuluDataException;
+
+// nur fuer Doku
+import edu.bonn.xulu.model.ModelResource;
+
+/**
+ * Diese Implementierung von <code>ModelResource</code> laesst nur
+ * {@linkplain Properties Properties-Objekte} als Datenobjekt zu.<br>
+ * Details zur Funktionalitaet und Bestimmung dieser Klasse sind in
+ * {@link ModelResource} zu finden.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class PropertiesResource extends AbstractModelResource {
+  /**
+   * Erzeugt eine leere Ressource.
+   * @param category Ordnet die Ressource in eine Kategorie ein (siehe
+   *                 {@link #setCategory(int)})
+   * @param desc   Beschreibung der Ressource
+   * @param type   Datentyp der Ressource; muss eine (Sub)Klasse von
+   *               {@link Properties} sein
+   * @param nullable gibt an, ob die Ressource unbelegt bleiben darf
+   * @exception XuluDataException falls der Datentyp <code>null</code> oder
+   *            keine (Sub)Klasse von {@link Properties} ist.
+   */
+  public PropertiesResource(int category, String desc, Class type, boolean nullable) {
+    super(category, desc, type, nullable);
+    if (!Properties.class.isAssignableFrom(type))
+      throw new XuluDataException("Resource '"+desc+"': Only (sub)classes of ".concat(Properties.class.
+          getName()).concat(" are allowed for ModelResource!"));
+  }
+
+  /**
+   * Erzeugt Ressource und ordnet ihr ein konretes Datenobjekt zu. Der Datentyp
+   * wird implizit aus dem uebergebenen Objekt ermittelt.
+   * @param category Ordnet die Ressource in eine Kategorie ein (siehe
+   *                 {@link #setCategory(int)})
+   * @param data Daten-Objekt fuer die Ressource
+   * @param desc Beschreibung der Ressource
+   * @param nullable gibt an, ob die Ressource unbelegt bleiben darf
+   * @exception XuluDataException falls das Datenobjekt <code>null</code> ist,
+   *           denn aus <code>null</code> kann kein Datentyp ermittelt werden
+   */
+  public PropertiesResource(int category, String desc, Properties data, boolean nullable) {
+    super(category, desc, data, nullable);
+  }
+
+  /**
+   * Erzeugt eine leere Ressource.
+   * @param desc   Beschreibung der Ressource
+   * @param type   Datentyp der Ressource; muss eine (Sub)Klasse von
+   *               {@link Properties} sein
+   * @param nullable gibt an, ob die Ressource unbelegt bleiben darf
+   * @exception XuluDataException falls der Datentyp <code>null</code> oder
+   *            keine (Sub)Klasse von {@link Properties} ist.
+   */
+  public PropertiesResource(String desc, Class type, boolean nullable) {
+    this(CATEGORY_OTHER,desc,type,nullable);
+  }
+
+  /**
+   * Erzeugt Ressource und ordnet ihr ein konretes Datenobjekt zu. Der Datentyp
+   * wird implizit aus dem uebergebenen Objekt ermittelt.
+   * @param data Daten-Objekt fuer die Ressource
+   * @param desc Beschreibung der Ressource
+   * @param nullable gibt an, ob die Ressource unbelegt bleiben darf
+   * @exception XuluDataException falls das Datenobjekt <code>null</code> ist,
+   *           denn aus <code>null</code> kann kein Datentyp ermittelt werden
+   */
+  public PropertiesResource(String desc, Properties data, boolean nullable) {
+    this(CATEGORY_OTHER,desc,data,nullable);
+  }
+
+  /**
+   * Liefert das Daten-Objekt der Ressource.
+   */
+  public Properties getData() {
+    return (Properties)super.getData();
+  }
+
+  /**
+   * Prueft ein beliebiges Objekt auf Typ-Konsistenz mit der Ressource und
+   * ggf. auf <code>not null</code>.
+   * Kann manuell aufgerufen werden und wird automatisch von
+   * {@link #checkAndError(Object)} aufgerufen.
+   * @exception XuluDataException falls das Objekt unerlaubterweise <code>null</code>
+   *         ist, oder dessen Klasse nicht mit dem Ressourcen-Typ vertraeglich ist
+   */
+  public void checkTypeAndError(Object data) throws XuluDataException {
+      // Datenobjekt auf null checken
+      if ( data == null ) {
+        if ( !isNullable() )
+          throw new XuluDataException("Resource '"+desc+": Resource-Data '".concat(this.getDesc()).concat("' is not allowed to be null!"));
+        else
+          return;
+      }
+    if ( !getType().isAssignableFrom( data.getClass() ) )
+      throw new XuluDataException("Resource '"+desc+"': Resource-Data must be an instance of ".concat(getType().getName()).concat("!"));
+  }
+
+  /**
+   * Prueft ein beliebiges Objekt auf Typ-Konsistenz mit der Ressource und auf
+   * die Erfuelltheit der Constraints.<br>
+   * Kann manuell aufgerufen werden und wird automatisch von
+   * {@link #setData(Object)} aufgerufen.
+   * @exception XuluDataException falls das Objekt unerlaubterweise <code>null</code>
+   *         ist, oder dessen Klasse nicht mit dem Ressourcen-Typ vertraeglich ist
+   */
+  public void checkAndError(Object data) throws XuluDataException {
+    checkTypeAndError(data);
+  }
+}

Added: trunk/src/edu/bonn/xulu/model/StepModel.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/StepModel.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/StepModel.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,31 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model;
+
+/**
+ * Dieses Interface muessen alle Modelle implementieren, deren Ablauf
+ * schrittweise durchgefuehrt werden kann.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public interface StepModel extends XuluModel {
+  /**
+   * Modelliert genau einen Zeitschritt.
+   * @param stepNo Nummer des Zeitschritts
+   */
+  public void performModelStep(int stepNo);
+
+  /**
+   * Liefert die Anzahl der durchzufuehrenden Modellierungsschritte.
+   */
+  public int getStepCount();
+}

Added: trunk/src/edu/bonn/xulu/model/StepModelThread.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/StepModelThread.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/StepModelThread.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,79 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model;
+
+import edu.bonn.xulu.model.XuluModel;
+import edu.bonn.xulu.model.XuluModelThread;
+import edu.bonn.xulu.model.StepModel;
+import edu.bonn.xulu.model.event.ModelListener;
+import edu.bonn.xulu.model.event.StepModelAdapter;
+
+/**
+ * Diese Klasse implementiert einen Thread fuer ein Modell, welches schrittweise
+ * ausgefuehrt wird. Diese Modell muss das Interface {@link StepModel}
+ * implementieren, z.B. {@link AbstractStepModel}.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class StepModelThread extends XuluModelThread {
+  /** Modus "Thread fuehrt aktuellen Schritt zu Ende und wechselt dann in
+   *  'Pause'". */
+  public static final int MODE_STEP = 5;
+
+  private ModelListener modelListener = null;
+
+  /**
+   * Erzeugt einen neuen Modell-Prozess.
+   * @param model zu startendes Modell
+   */
+  public StepModelThread(StepModel model) {
+    super(model);
+    modelListener = new StepModelAdapter() {
+      public void modelStepFinished(XuluModel model, int stepNo) {
+        if ( mode == MODE_STEP && model instanceof StepModel && stepNo < ((StepModel)model).getStepCount() )
+          pause();
+        checkBreakingCommands();
+      }
+    };
+    model.addModelListener( modelListener );
+  }
+
+  /**
+   * Fuehrt einen einzelnen Arbeitsschritt aus. Danach wird der Thread
+   * wieder schlafen gelegt.
+   */
+  public void step() {
+    boolean wasSleeping = isSleeping();
+
+    this.mode = MODE_STEP;
+    // beim allerersten Mal muss der Thread gestartet werden
+    if ( !isAlive() ) {
+      super.start();
+      this.mode = MODE_STEP;
+    } else
+      if ( wasSleeping )
+        wakeUp();
+  }
+
+  /**
+   * Entfernt die gesetzten Listener wieder vom Modell, damit der Thread nicht
+   * weiterhin ueber Model-Aktivitaeten informiert wird.
+   */
+  public void performDispose() {
+    // WICHTIG!! ModelListener wieder entfernen!! Ansonsten wird der Thread
+    // immer wieder informiert, was zu einem Abbruch ALLER anderen Threads
+    // fuehrt, da checkBreakingCommands() fuer diesen Thread eine
+    // ThreadDeath-Exception wirft!
+    model.removeModelListener( modelListener );
+    super.performDispose();
+  }
+}

Added: trunk/src/edu/bonn/xulu/model/ValuePropertyResource.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/ValuePropertyResource.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/ValuePropertyResource.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,147 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model;
+
+import edu.bonn.xulu.data.XuluDataException;
+import schmitzm.data.property.ValueProperty;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.ValuePropertyType;
+import schmitzm.temp.BaseTypeUtil;
+
+/**
+ * Diese Implementierung von <code>ModelResource</code> laesst nur
+ * {@linkplain ValueProperty}-Objekte eines bestimmten Datentyps als
+ * Datenobjekt zu. Ausserdem darf das Daten-Objekt der Ressource (wahlweise)
+ * nicht auf <code>null</code> gesetzt werden.<br>
+ * Details zur Funktionalitaet und Bestimmung dieser Klasse sind in
+ * {@link ModelResource} zu finden.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class ValuePropertyResource extends PropertiesResource {
+  /** Speichert den Inhaltstyp der {@link ValueProperty}. */
+  protected ValuePropertyType propType = null;
+
+  /**
+   * Erzeugt eine neue Ressource
+   * @param category Ordnet die Ressource in eine Kategorie ein (siehe
+   *                 {@link #setCategory(int)})
+   * @param desc Beschreibung der Ressource
+   * @param prop Beispiel-Property, die die Ressource aufnehmen darf
+   * @param nullable gibt an, ob die Ressource unbelegt bleiben darf
+   */
+  public ValuePropertyResource(int category, String desc, ValueProperty prop, boolean nullable) {
+    this(category,desc,prop.getClass(),prop.getPropertyType(),nullable);
+  }
+
+  /**
+   * Erzeugt eine neue Ressource
+   * @param category Ordnet die Ressource in eine Kategorie ein (siehe
+   *                 {@link #setCategory(int)})
+   * @param desc Beschreibung der Ressource
+   * @param propClass (Unter)Klasse von {@link ValueProperty}, die die Art
+   *                  der Ressource bestimmt (z.B. Skalar, Matrix, Liste)
+   * @param propType  Typ den die Property als Wert aufnehmen/liefern soll
+   * @param nullable gibt an, ob die Ressource unbelegt bleiben darf
+   */
+  public ValuePropertyResource(int category, String desc, Class propClass, Class propType, boolean nullable) {
+    this(category,desc,propClass,ValuePropertyType.createValuePropertyType(propType),nullable);
+  }
+
+  /**
+   * Erzeugt eine neue Ressource
+   * @param category Ordnet die Ressource in eine Kategorie ein (siehe
+   *                 {@link #setCategory(int)})
+   * @param desc Beschreibung der Ressource
+   * @param propClass (Unter)Klasse von {@link ValueProperty}, die die Art
+   *                  der Ressource bestimmt (z.B. Skalar, Matrix, Liste)
+   * @param propType  Typ den die Property als Wert aufnehmen/liefern soll
+   * @param nullable gibt an, ob die Ressource unbelegt bleiben darf
+   */
+  public ValuePropertyResource(int category, String desc, Class propClass, ValuePropertyType propType, boolean nullable) {
+    super(category,desc,propClass,nullable);
+    if ( !ValueProperty.class.isAssignableFrom(propClass) )
+      throw new IllegalArgumentException("Resource '"+desc+": Parameter 'propClass' muss bei a subclass of ValueProperty!");
+    this.propType = propType;
+  }
+
+  /**
+   * Erzeugt eine neue Ressource
+   * @param desc Beschreibung der Ressource
+   * @param prop Beispiel-Property, die die Ressource aufnehmen darf
+   * @param nullable gibt an, ob die Ressource unbelegt bleiben darf
+   */
+  public ValuePropertyResource(String desc, ValueProperty prop, boolean nullable) {
+    this(desc,prop.getClass(),prop.getPropertyType(),nullable);
+  }
+
+  /**
+   * Erzeugt eine neue Ressource
+   * @param desc Beschreibung der Ressource
+   * @param propClass (Unter)Klasse von {@link ValueProperty}, die die Art
+   *                  der Ressource bestimmt (z.B. Skalar, Matrix, Liste)
+   * @param propType  Typ den die Property als Wert aufnehmen/liefern soll
+   * @param nullable gibt an, ob die Ressource unbelegt bleiben darf
+   */
+  public ValuePropertyResource(String desc, Class propClass, Class propType, boolean nullable) {
+    this(desc,propClass,ValuePropertyType.createValuePropertyType(propType),nullable);
+  }
+
+  /**
+   * Erzeugt eine neue Ressource
+   * @param desc Beschreibung der Ressource
+   * @param propClass (Unter)Klasse von {@link ValueProperty}, die die Art
+   *                  der Ressource bestimmt (z.B. Skalar, Matrix, Liste)
+   * @param propType  Typ den die Property als Wert aufnehmen/liefern soll
+   * @param nullable gibt an, ob die Ressource unbelegt bleiben darf
+   */
+  public ValuePropertyResource(String desc, Class propClass, ValuePropertyType propType, boolean nullable) {
+    this(CATEGORY_OTHER,desc,propClass,propType,nullable);
+  }
+
+  /**
+   * Liefert den Datentyp, der in der Prop
+   * @return ValuePropertyType
+   */
+  public ValuePropertyType getPropertyType() {
+    return this.propType;
+  }
+
+  /**
+   * Neben den Checks der
+   * {@linkplain PropertiesResource#checkTypeAndError(Object) Oberklasse},
+   * prueft diese Methode, ob der Inhaltstyp der Property <code>data</code>
+   * dem fuer die Ressource verlangten Typ entspricht.
+   * @param data Instanz von {@link ValueProperty}
+   */
+  public void checkTypeAndError(Object data) {
+    super.checkTypeAndError(data);
+
+    // null-Daten koennen nicht auf Typ geprueft werden, werden also
+    // als korrekt angenommen
+    if ( data == null )
+      return;
+
+    Class objDataType = ((ValueProperty)data).getType();
+    Class resDataType = getPropertyType().getType();
+
+    // Numberische Properties koennen u.U. in Ressourcen-Typ umgewandelt werden
+    if ( Number.class.isAssignableFrom( objDataType ) &&
+         Number.class.isAssignableFrom( resDataType ) &&
+         BaseTypeUtil.isConvertable(objDataType, resDataType) )
+      return;
+
+    // Datenobjekt auf den richtigen Property-Inhaltstyp checken
+    if ( data!= null && !resDataType.isAssignableFrom(objDataType) )
+      throwDataException(resDataType.getSimpleName().concat(" property"));
+  }
+}

Added: trunk/src/edu/bonn/xulu/model/XuluModel.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/XuluModel.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/XuluModel.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,144 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model;
+
+import java.io.PrintStream;
+import java.awt.Component;
+import schmitzm.lang.NamedObject;
+import schmitzm.lang.ResourceProvider;
+import schmitzm.swing.CaptionsChangeable;
+import edu.bonn.xulu.model.ModelContentManager;
+import edu.bonn.xulu.model.event.ModelListener;
+import edu.bonn.xulu.model.event.ModelEvent;
+
+/**
+ * Dieses Interface definiert, wie eine Modell-Klasse aufgebaut sein muss,
+ * damit das Modell in die Xulu-Modelling-Platform integiert werden kann.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public interface XuluModel extends NamedObject, CaptionsChangeable {
+  /**
+   * Liefert den ContentManager des Modells.
+   */
+  public ModelContentManager getContentManager();
+
+  /**
+   * Diese Methode setzt alle <b>internen</b> Modell-Ressourcen auf einen
+   * Ausgangszustand zurueck, so dass das Modell komplett neu gestartet werden
+   * kann.<br>
+   * <b>Bemerke:</b> Auf die Ruecksetzung der externen Ressourcen, die von der
+   * Modellierungsplatform bereitgestellt werden hat das Modell i.d.R. keinen
+   * Einfluss. Hierfuer ist der Anwender verantwortlich.
+   */
+  public void initModel();
+
+  /**
+   * Prueft, ob das Modell initialisiert ist - sich also im Ausgangszustand
+   * befindet - und bereit ist gestartet zu werden.<br>
+   * Nach dem Modell-Start sollte diese Methode <code>false</code> liefern, da
+   * sich die internen Ressourcen dann nicht mehr im Ausgangszustand befinden!
+   */
+  public boolean isInitialised();
+
+  /**
+   * Diese Methode loescht alle <b>internen</b> Modell-Ressourcen aus dem Speicher
+   * und gibt die externen wieder frei.
+   */
+  public void disposeModel();
+
+  /**
+   * Prueft, ob das Modell (dessen interen Ressourcen) "zerstoert" sind.
+   */
+  public boolean isDisposed();
+
+  /**
+   * Diese Methode startet den Modell-Ablauf.
+   * @return {@code false} wenn das Modell auf irgendeine Art (kontrolliert oder
+   *         Fehler) abgebrochen wurde; {@code true} nur wenn das Modell komplett
+   *         durchgelaufen ist
+   */
+  public boolean startModelling();
+
+
+  /**
+   * Prueft, ob die Modellierung gerade am Laufen ist.
+   */
+  public boolean isRunning();
+
+  /**
+   * Diese Methode unterbricht den Modellablauf komplett. Ein Fortsetzen ist
+   * nicht moeglich.
+   * Alle Modell-Ressourcen sollten beim Aufrufen dieser Methode wieder
+   * freigegeben werden.
+   */
+  public void stopModelling();
+
+  /**
+   * Prueft, ob die Modellierung beendet ist.
+   */
+  public boolean isStopped();
+
+  /**
+   * Diese Methode wird aufgrufen, wenn ein unerwarteter Fehler bei der
+   * Modellierung auftritt, welcher das Beenden der Modellierung zu Folge
+   * hat. In dieser Methode muss das Modell dafuer sorgen, dass alle
+   * Ressourcen - die internen und insbesondere auch die externen -
+   * wieder freigegenen und ggf. aus dem Speicher entfernt werden.
+   */
+  public void performError();
+
+  /**
+   * Fuegt dem Model einen Listener hinzu.
+   * @param listener neuer ModelListener
+   */
+  public boolean addModelListener(ModelListener listener);
+
+  /**
+   * Entfernt einen Listener von dem Modell.
+   * @param listener zu entfernender ModelListener
+   */
+  public boolean removeModelListener(ModelListener listener);
+
+  /**
+   * Liefert den Stream fuer die Status-Ausgaben des Modells.
+   */
+  public PrintStream getStatusOut();
+
+  /**
+   * Setzt den Stream fuer die Status-Ausgaben des Modells.
+   */
+  public void setStatusOut(PrintStream out);
+
+
+  /**
+   * Liefert (optional) eine modellspezifische GUI-Komponente.
+   * @return <code>null</code> wenn das Modell keine zusaetzliche GUI
+   *         zur Verfuegung stellt
+   */
+  public Component getModelSpecificGUI();
+
+  /**
+   * Liefert alle Ereignis-Typen, die waehrend  des Modellablaufs initiiert werden.
+   * @return leerer Array, falls keine Ereignisse initiiert werden
+   */
+  public Class<ModelEvent>[] getEvents();
+  
+  /**
+   * Liefert den {@link ResourceProvider}, der die Uebersetzungen
+   * fuer Modell-Ausgaben und modellspezifische GUI verwaltet.
+   * @return {@code null}, wenn das Modell nicht multi-lingual ist
+   */
+  public ResourceProvider getResourceProvider();
+
+}
+

Added: trunk/src/edu/bonn/xulu/model/XuluModelThread.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/XuluModelThread.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/XuluModelThread.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,72 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model;
+
+import schmitzm.lang.WorkingThread;
+import edu.bonn.xulu.model.XuluModel;
+
+/**
+ * Diese Klasse stellt einen Thread dar, der ein {@link XuluModel} ausfuehrt.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class XuluModelThread extends WorkingThread {
+  /** Speichert das Modell, welches ausgefuehrt wird. */
+  protected XuluModel model = null;
+
+  /**
+   * Erzeugt einen neuen Thread.
+   * @param model auszufuehrendes Modell
+   */
+  public XuluModelThread(XuluModel model) {
+    super();
+    this.model = model;
+  }
+
+  /**
+   * Initialisiert den Thread, in dem das Modell initialisiert wird. Loest
+   * {@link WorkingThread#fireThreadInitialised()} aus.
+   * @see XuluModel#initModel()
+   */
+  public void performInit() {
+    if ( !model.isInitialised() )
+      model.initModel();
+    fireThreadInitialised();
+  }
+
+  /**
+   * Implementiert den Arbeitsschritt des Threads, in dem das Modell gestartet wird.
+   * @see XuluModel#startModelling()
+   */
+  public void performWork() {
+    model.startModelling();
+  }
+
+  /**
+   * Macht nichts, da diese Klasse keine Ressourcen gesperrt hat, die vor
+   * dem Auslaufen des Threads wieder freigegeben werden muessten.
+   * Sub-Klassen muessen diese Methode ggf. ueberschreiben.
+   */
+  public void performDispose() {
+    model.disposeModel();
+  }
+
+  /**
+   * Beendet das Modell und den Thread.
+   * @see XuluModel#stopModelling()
+   */
+  public void terminate() {
+    model.stopModelling();
+    super.terminate();
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/model/event/AbstractIterationStepEvent.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/event/AbstractIterationStepEvent.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/event/AbstractIterationStepEvent.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,42 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model.event;
+
+import edu.bonn.xulu.model.XuluModel;
+
+/**
+ * Diese Klasse repraesentiert ein Ereignis, das fuer einen Iterationsschritt
+ * eines Modells ausgeloest wird.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class AbstractIterationStepEvent extends AbstractStepModelEvent {
+  /** Speichert den Iterationsschritt fuer den das Ereignis ausgeloest wurde. */
+  protected int iterStep = 0;
+
+  /**
+   * Erzeugt ein neues Ereignis.
+   * @param model  ausloesendes Modell
+   * @param stepNo Modell-Schritt des Ereignisses
+   */
+  public AbstractIterationStepEvent(XuluModel model, int stepNo, int iterNo) {
+    super(model,stepNo);
+    this.iterStep = iterNo;
+  }
+
+  /**
+   * Liefert den Iterations-Schritt fuer den das Ereignis ausgeloest wurde.
+   */
+  public int getIterNo() {
+    return this.iterStep;
+  }
+}

Added: trunk/src/edu/bonn/xulu/model/event/AbstractModelEvent.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/event/AbstractModelEvent.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/event/AbstractModelEvent.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,41 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model.event;
+
+import schmitzm.data.event.AbstractObjectEvent;
+import edu.bonn.xulu.model.XuluModel;
+
+/**
+ * Diese Klasse bildet eine Basis-Implementierung fuer Modell-Ereignisse.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of  Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class AbstractModelEvent extends AbstractObjectEvent implements ModelEvent {
+  /** Speichert das Modell, das das Ereignis ausgeloest hat. */
+  protected XuluModel model = null;
+
+  /**
+   * Erzeugt ein neues Ereignis.
+   * @param model ausloesendes Modell
+   */
+  public AbstractModelEvent(XuluModel model) {
+    super(model,0);
+    this.model = model;
+  }
+
+  /**
+   * Liefert das Modell, das das Ereignis ausgeloest hat.
+   */
+  public XuluModel getSourceModel() {
+    return model;
+  }
+}

Added: trunk/src/edu/bonn/xulu/model/event/AbstractStepModelEvent.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/event/AbstractStepModelEvent.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/event/AbstractStepModelEvent.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,42 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model.event;
+
+import edu.bonn.xulu.model.XuluModel;
+
+/**
+ * Diese Klasse repraesentiert ein Ereignis, das fuer einen Modell-Schnitt
+ * ausgeloest wird.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class AbstractStepModelEvent extends AbstractModelEvent {
+  /** Speichert den Zeitschritt fuer den das Ereignis ausgeloest wurde. */
+  protected int modelStep = 0;
+
+  /**
+   * Erzeugt ein neues Ereignis.
+   * @param model  ausloesendes Modell
+   * @param stepNo Modell-Schritt des Ereignisses
+   */
+  public AbstractStepModelEvent(XuluModel model, int stepNo) {
+    super(model);
+    this.modelStep = stepNo;
+  }
+
+  /**
+   * Liefert den Modell-Schritt fuer den das Ereignis ausgeloest wurde.
+   */
+  public int getStepNo() {
+    return this.modelStep;
+  }
+}

Added: trunk/src/edu/bonn/xulu/model/event/ModelAdapter.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/event/ModelAdapter.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/event/ModelAdapter.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,111 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model.event;
+
+import schmitzm.data.event.ObjectEvent;
+import edu.bonn.xulu.model.XuluModel;
+import edu.bonn.xulu.model.event.ModelListener;
+
+/**
+ * Diese Klasse stellt eine Basis-Implementierung des Interfaces
+ * {@link ModelListener} dar, welche nach den Ereignissen...
+ * <ul>
+ *   <li>{@link ModelInitialisedEvent}</li>
+ *   <li>{@link ModelStartedEvent}</li>
+ *   <li>{@link ModelStoppedEvent}</li>
+ *   <li>{@link ModelDisposedEvent}</li>
+ * </ul>
+ * ... unterscheidet. Fuer jedes Ereignis wird durch {@link #performModelEvent(ModelEvent)}
+ * eine eigene Adapter-Methode aufgerufen. Handelt es sich bei einem Ereignis
+ * um keines der oben genannten, wird dies an {@link #performOtherEvent(ModelEvent)}
+ * weitergereicht.<br>
+ * <b>Die implementierten Methoden {@link #modelInitialised(XuluModel)},
+ * {@link #modelStarted(XuluModel)}, {@link #modelStopped(XuluModel)},
+ * {@link #modelDisposed(XuluModel)} und {@link #performOtherEvent(ModelEvent)}
+ * machen allesamt nichts.</b> Sie dienen lediglich der Vereinfachung,
+ * dass nicht benoetigte Methoden auch nicht implementiert werden muessen.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class ModelAdapter implements ModelListener {
+  /**
+   * Leitet das Ereignis an {@link #performModelEvent(ModelEvent)} weiter.
+   * @param e Modell-Ereignis
+   * @exception IllegalArgumentException falls das uebergebene Ereignis
+   *            kein {@link ModelEvent} ist.
+   */
+  public void performObjectEvent(ObjectEvent e) {
+    if ( !(e instanceof ModelEvent) )
+      throw new IllegalArgumentException("ModelListener.performObjectEvent(.) can only be applied for ModelEvents!");
+    performModelEvent((ModelEvent)e);
+  }
+
+  /**
+   * Wird fuer jedes Modell-Ereignis ausgeloest. Je nach Event-Typ wird die
+   * entsprechende Adapter-Methode aufgerufen.
+   * @param e Modell-Ereignis
+   * @see #modelInitialised(XuluModel)
+   * @see #modelStarted(XuluModel)
+   * @see #modelStopped(XuluModel)
+   * @see #modelDisposed(XuluModel)
+   * @see #performOtherEvent(ModelEvent e)
+   */
+  public void performModelEvent(ModelEvent e) {
+    if ( e instanceof ModelInitialisedEvent )
+      this.modelInitialised(e.getSourceModel());
+    else if ( e instanceof ModelStartedEvent )
+      this.modelStarted(e.getSourceModel());
+    else if ( e instanceof ModelStoppedEvent )
+      this.modelStopped(e.getSourceModel());
+    else if ( e instanceof ModelDisposedEvent )
+      this.modelDisposed(e.getSourceModel());
+    else
+      this.performOtherEvent(e);
+  }
+
+
+  /**
+   * Wird ausgeloest, nachdem ein Modell initialisiert wurde.
+   * @param model Xulu-Modell das initialisiert wurde
+   */
+  public void modelInitialised(XuluModel model) {
+  }
+
+  /**
+   * Wird ausgeloest, nachdem ein Modell gestartet wurde.
+   * @param model Xulu-Modell das gestartet wurde
+   */
+  public void modelStarted(XuluModel model) {
+  }
+
+  /**
+   * Wird ausgeloest, nachdem ein Modell komplett gestoppt hat.
+   * @param model Xulu-Modell das gestoppt wurde
+   */
+  public void modelStopped(XuluModel model) {
+  }
+
+  /**
+   * Wird ausgeloest, nachdem ein Modell "zerstoert" wurde.
+   * @param model Xulu-Modell das zerstoert wurde
+   */
+  public void modelDisposed(XuluModel model) {
+  }
+
+  /**
+   * Wird von {@link #performModelEvent(ModelEvent)} ausgeloest, wenn ein Ereignis
+   * "unbekannt" ist.
+   * @param e unbekanntes Modell-Ereignis
+   */
+  public void performOtherEvent(ModelEvent e) {
+  }
+}

Added: trunk/src/edu/bonn/xulu/model/event/ModelDisposedEvent.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/event/ModelDisposedEvent.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/event/ModelDisposedEvent.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,30 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model.event;
+
+import edu.bonn.xulu.model.XuluModel;
+
+/**
+ * Diese Klasse repraesentiert ein Ereignis, das ausgeloest wird, wenn die
+ * Dispose-Phase eines {@linkplain XuluModel Xulu-Modells} abgeschlossen wurde.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class ModelDisposedEvent extends AbstractModelEvent {
+  /**
+   * Erzeugt ein neues Ereignis.
+   * @param model ausloesendes Modell
+   */
+  public ModelDisposedEvent(XuluModel model) {
+    super(model);
+  }
+}

Added: trunk/src/edu/bonn/xulu/model/event/ModelEvent.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/event/ModelEvent.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/event/ModelEvent.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,28 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model.event;
+
+import schmitzm.data.event.ObjectEvent;
+import edu.bonn.xulu.model.XuluModel;
+
+/**
+ * Dieses Interface stellt ein allgemeines Ereignis dar, welches von einem
+ * Modell initiiert wird.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public interface ModelEvent extends ObjectEvent {
+  /**
+   * Liefert das Modell, das das Ereignis ausgeloest hat.
+   */
+  public XuluModel getSourceModel();
+}

Added: trunk/src/edu/bonn/xulu/model/event/ModelInitialisedEvent.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/event/ModelInitialisedEvent.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/event/ModelInitialisedEvent.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,30 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model.event;
+
+import edu.bonn.xulu.model.XuluModel;
+
+/**
+ * Diese Klasse repraesentiert ein Ereignis, das ausgeloest wird, wenn ein
+ * {@linkplain XuluModel Xulu-Modell} initialisiert wurde.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class ModelInitialisedEvent extends AbstractModelEvent {
+  /**
+   * Erzeugt ein neues Ereignis.
+   * @param model ausloesendes Modell
+   */
+  public ModelInitialisedEvent(XuluModel model) {
+    super(model);
+  }
+}

Added: trunk/src/edu/bonn/xulu/model/event/ModelIterationStepFinishedEvent.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/event/ModelIterationStepFinishedEvent.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/event/ModelIterationStepFinishedEvent.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,32 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model.event;
+
+import edu.bonn.xulu.model.XuluModel;
+
+/**
+ * Diese Klasse repraesentiert ein Ereignis, das zu Ende eines jeden
+ * Iterationsschritts eines Modells ausgeloest wird.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class ModelIterationStepFinishedEvent extends AbstractIterationStepEvent {
+  /**
+   * Erzeugt ein neues Ereignis.
+   * @param model ausloesendes Modell
+   * @param stepNo Modell-Schritt des Ereignisses
+   * @param iterNo Iterationsschritt des Ereignisses
+   */
+  public ModelIterationStepFinishedEvent(XuluModel model, int stepNo, int iterNo) {
+    super(model,stepNo,iterNo);
+  }
+}

Added: trunk/src/edu/bonn/xulu/model/event/ModelIterationStepStartedEvent.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/event/ModelIterationStepStartedEvent.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/event/ModelIterationStepStartedEvent.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,32 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model.event;
+
+import edu.bonn.xulu.model.XuluModel;
+
+/**
+ * Diese Klasse repraesentiert ein Ereignis, das zu Begin eines jeden
+ * Iterationsschritts eines Modells ausgeloest wird.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class ModelIterationStepStartedEvent extends AbstractIterationStepEvent {
+  /**
+   * Erzeugt ein neues Ereignis.
+   * @param model ausloesendes Modell
+   * @param stepNo Modell-Schritt des Ereignisses
+   * @param iterNo Iterationsschritt des Ereignisses
+   */
+  public ModelIterationStepStartedEvent(XuluModel model, int stepNo, int iterNo) {
+    super(model,stepNo,iterNo);
+  }
+}

Added: trunk/src/edu/bonn/xulu/model/event/ModelListener.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/event/ModelListener.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/event/ModelListener.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,30 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model.event;
+
+import schmitzm.data.event.ObjectListener;
+
+import edu.bonn.xulu.model.XuluModel;
+
+/**
+ * Diese Klasse stellt einen Listener dar, der bei bestimmten Modell-Aktivitaeten
+ * informiert wird.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public interface ModelListener extends ObjectListener {
+  /**
+   * Wird fuer jedes Modell-Ereignis ausgeloest.
+   * @param e Modell-Ereignis
+   */
+  public void performModelEvent(ModelEvent e);
+}

Added: trunk/src/edu/bonn/xulu/model/event/ModelStartedEvent.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/event/ModelStartedEvent.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/event/ModelStartedEvent.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,30 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model.event;
+
+import edu.bonn.xulu.model.XuluModel;
+
+/**
+ * Diese Klasse repraesentiert ein Ereignis, das ausgeloest wird, wenn der Ablauf
+ * eines {@linkplain XuluModel Xulu-Modells} gestartet wurde.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class ModelStartedEvent extends AbstractModelEvent {
+  /**
+   * Erzeugt ein neues Ereignis.
+   * @param model ausloesendes Modell
+   */
+  public ModelStartedEvent(XuluModel model) {
+    super(model);
+  }
+}

Added: trunk/src/edu/bonn/xulu/model/event/ModelStepFinishedEvent.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/event/ModelStepFinishedEvent.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/event/ModelStepFinishedEvent.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,31 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model.event;
+
+import edu.bonn.xulu.model.XuluModel;
+
+/**
+ * Diese Klasse repraesentiert ein Ereignis, das zum Ende eines Modell-Schnitts
+ * ausgeloest wird.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class ModelStepFinishedEvent extends AbstractStepModelEvent {
+  /**
+   * Erzeugt ein neues Ereignis.
+   * @param model ausloesendes Modell
+   * @param stepNo Modell-Schritt des Ereignisses
+   */
+  public ModelStepFinishedEvent(XuluModel model, int stepNo) {
+    super(model,stepNo);
+  }
+}

Added: trunk/src/edu/bonn/xulu/model/event/ModelStepStartedEvent.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/event/ModelStepStartedEvent.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/event/ModelStepStartedEvent.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,32 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model.event;
+
+import edu.bonn.xulu.model.XuluModel;
+
+/**
+ * Diese Klasse repraesentiert ein Ereignis, das zu Begin eines Modell-Schnitts
+ * ausgeloest wird.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class ModelStepStartedEvent extends AbstractStepModelEvent {
+  /**
+   * Erzeugt ein neues Ereignis.
+   * @param model ausloesendes Modell
+   * @param stepNo Modell-Schritt des Ereignisses
+   */
+  public ModelStepStartedEvent(XuluModel model, int stepNo) {
+    super(model,stepNo);
+
+  }
+}

Added: trunk/src/edu/bonn/xulu/model/event/ModelStoppedEvent.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/event/ModelStoppedEvent.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/event/ModelStoppedEvent.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,31 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model.event;
+
+import edu.bonn.xulu.model.XuluModel;
+
+/**
+ * Diese Klasse repraesentiert ein Ereignis, das ausgeloest wird, wenn der Ablauf
+ * eines {@linkplain XuluModel Xulu-Modells} beendet wurde.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of
+ *   Bonn/Germany)
+ * @version 1.0
+ */
+public class ModelStoppedEvent extends AbstractModelEvent {
+  /**
+   * Erzeugt ein neues Ereignis.
+   * @param model ausloesendes Modell
+   */
+  public ModelStoppedEvent(XuluModel model) {
+    super(model);
+  }
+}

Added: trunk/src/edu/bonn/xulu/model/event/StepModelAdapter.java
===================================================================
--- trunk/src/edu/bonn/xulu/model/event/StepModelAdapter.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/event/StepModelAdapter.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,67 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.model.event;
+
+import edu.bonn.xulu.model.StepModel;
+import edu.bonn.xulu.model.event.ModelAdapter;
+import edu.bonn.xulu.model.XuluModel;
+
+/**
+ * Erweitert den normalen {@link ModelAdapter} um die Ereignisse...
+ * <ul>
+ *   <li>{@link ModelStepStartedEvent}</li>
+ *   <li>{@link ModelStepFinishedEvent}</li>
+ * </ul>
+ * @see ModelAdapter
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class StepModelAdapter extends ModelAdapter {
+    /**
+     * Wird fuer jedes Modell-Ereignis ausgeloest. Je nach Event-Typ wird die
+     * entsprechende Adapter-Methode aufgerufen.
+     * @param e Modell-Ereignis
+     * @see #modelInitialised(XuluModel)
+     * @see #modelStarted(XuluModel)
+     * @see #modelStopped(XuluModel)
+     * @see #modelDisposed(XuluModel)
+     * @see #modelStepStarted(StepModel,int)
+     * @see #modelStepFinished(StepModel,int)
+     * @see #performOtherEvent(ModelEvent e)
+     */
+    public void performModelEvent(ModelEvent e) {
+      if ( e instanceof ModelStepStartedEvent )
+        this.modelStepStarted(((ModelStepStartedEvent)e).getSourceModel(),((ModelStepStartedEvent)e).getStepNo());
+      else if ( e instanceof ModelStepFinishedEvent )
+        this.modelStepFinished(((ModelStepFinishedEvent)e).getSourceModel(),((ModelStepFinishedEvent)e).getStepNo());
+      else
+        super.performModelEvent(e);
+    }
+
+  /**
+   * Wird ausgeloest, bevor <code>Steppable</code>-Modell einen
+   * Modellierungsschritt beginnt
+   * @param model Xulu-Modell das des Schritt ausfuehrt
+   * @param stepNo Nummer des gestarteten Modellierungsschritts
+   */
+  public void modelStepStarted(XuluModel model, int stepNo) {
+  }
+
+  /**
+   * Wird ausgeloest, nachdem <code>Steppable</code>-Modell einen
+   * Modellierungsschritt beendet hat
+   * @param model Xulu-Modell das des Schritt ausgefuehrt hat
+   * @param stepNo Nummer des beendeten Modellierungsschritts
+   */
+  public void modelStepFinished(XuluModel model, int stepNo) {
+  }
+}

Added: trunk/src/edu/bonn/xulu/model/package.html
===================================================================
--- trunk/src/edu/bonn/xulu/model/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/model/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,11 @@
+<html>
+<body>
+	Dieses Paket enthält Klassen/Interfaces, die für die Xulu-spezifische Modell-Verwaltung
+	benötigt werden. Hierzu zählt insbesondere die Klasse
+	{@link edu.bonn.xulu.model.XuluModel} von der alle Modelle abgeleitet werden müssen,
+	die in der Xulu-Modelling-Platform laufen sollen. Hierbei sind ausserdem noch die
+	Interfaces {@link edu.bonn.xulu.model.ModelContentManager} und {@link edu.bonn.xulu.model.ModelResource}
+	von besonderer Bedeutung, ueber die der Plattform mitgeteilt wird, welche Objekte aus dem
+	Datenpool das Modell zur Ausfuehrung benoetigt.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/edu/bonn/xulu/package.html
===================================================================
--- trunk/src/edu/bonn/xulu/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,8 @@
+<html>
+<body>
+	Dieses Paket stellt das Hauptpaket der Xulu-Modelling-Plattform dar. Alles Klassen
+	unterhalb dieses Pakets sind speziell auf die Xulu-Anwendung abgestimmt.<br>
+	Die Klasse {@link edu.bonn.xulu.XuluModellingPlatform} enthält die
+	<code>main</code>-Methode zum Starten der Xulu-Modelling-Plattform.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/edu/bonn/xulu/plugin/appl/AbstractMenuPlugin.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/appl/AbstractMenuPlugin.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/appl/AbstractMenuPlugin.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,130 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.appl;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import javax.swing.JMenuItem;
+
+import schmitzm.lang.LangUtil;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.AbstractXuluPlugin;
+import edu.bonn.xulu.gui.XuluInternalFrame;
+import edu.bonn.xulu.gui.XuluGUIMessages;
+
+/**
+ * Diese Klasse stellt eine abstrakte Oberklasse fuer Plugins dar, die
+ * sich (bzw. ein zum Plugin gehoerendes Anwendungsfenster) in das Xulu-Menue
+ * integrieren.<br>
+ * Diese Oberklasse sorgt automatisch dafuer, dass beim Starten des Plugins
+ * ein Menue-Eintrag erzeugt wird, bei dessen Aktivierung das Plugin-Fenster
+ * angezeigt wird. Beim Beenden des Plugins wird das Plugin-Fenster verborgen und
+ * der Menue-Eintrag wieder entfernt.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class AbstractMenuPlugin extends AbstractXuluPlugin {
+  /** Speichert die Menue-Nummer, in der der Eintrag zum Anzeigen des
+   *  des Applikationsfensters eingebunden wird. */
+  protected int xuluMenuNo = 0;
+  /** Speichert den Menue-Eintrag, der zum Anzeigen des Applikationsfensters
+   *  dient wird. */
+  protected JMenuItem         menuItem   = null;
+  /** Speichert die Instanz des Applikationsfensters (wird beim Starten des
+   *  Plugins befuellt). */
+  protected XuluInternalFrame pluginAppl = null;
+
+  /**
+   * Erzeugt eine neue Plugin-Instanz.
+   * @param xuluMenuNo Nummer des Xulu-Menues in das der Menue-Eintrag eingebettet wird
+   * @param menuItem   Menue-Eintrag fuer das Plugin-Fenster
+   * @param hasGUI     Flag, ob das Plugin (zusaetzlich) eine Konfigurations-GUI besitzt
+   */
+  public AbstractMenuPlugin(int xuluMenuNo, JMenuItem menuItem, boolean hasGUI) {
+    super(hasGUI);
+    this.xuluMenuNo  = xuluMenuNo;
+    this.menuItem    = menuItem;
+    this.menuItem.addActionListener( new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        if ( pluginAppl != null ) {
+          pluginAppl.setVisible(true);
+          pluginAppl.toFront();
+        }
+      }
+    });
+  }
+
+  /**
+   * Erzeugt eine neue Plugin-Instanz ohne Konfigurations-GUI.
+   * @param xuluMenuNo Nummer des Xulu-Menues in das der Menue-Eintrag eingebettet wird
+   * @param menuItem   Menue-Eintrag fuer das Plugin-Fenster
+   */
+  public AbstractMenuPlugin(int xuluMenuNo, JMenuItem menuItem) {
+    this(xuluMenuNo,menuItem,false);
+  }
+
+  /**
+   * Erzeugt eine neue Plugin-Instanz ohne Konfigurations-GUI.
+   * @param xuluMenuNo   Nummer des Xulu-Menues in das der Menue-Eintrag eingebettet wird
+   * @param menuItemName Name fuer den Menue-Eintrag des Plugin-Fensters
+   */
+  public AbstractMenuPlugin(int xuluMenuNo, String menuItemName) {
+    this(xuluMenuNo, new JMenuItem(menuItemName));
+  }
+
+  /**
+   * Erzeugt das Applikations-Fenster fuer das Plugin. Dieses wird mit dem
+   * Menue-Eintrag verbunden.
+   * Wird erst aufgerufen, wenn das Plugin gestartet wird.
+   * @see #execute(XuluModellingPlatform)
+   */
+  protected abstract XuluInternalFrame createPluginApplication() throws Exception;
+
+
+  /**
+   * Startet das Plugin. Dabei wird die Plugin-Applikation neu erzeugt und
+   * ein Menu-Punkt im Xulu-Menue angelegt.
+   * @param appl Xulu-Instanz
+   */
+  public void execute(XuluModellingPlatform appl) {
+    super.execute(appl);
+    try {
+      // Instanz der Plugin-Applikation erzeugen
+      pluginAppl = createPluginApplication();
+      // Plugin-Applikation in Menu einbinden
+      appl.getMainFrame().getJMenuBar().getMenu(xuluMenuNo).add(menuItem);
+      // Plugin-Applikation (InternalFrame) dem Hauptfenster hinzufuegen
+      appl.getMainFrame().getContentPane().add(pluginAppl);
+      started = true;
+    } catch (Exception err) {
+      XuluGUIMessages.showError(appl.getMainFrame(),err);
+    }
+  }
+
+  /**
+   * Stoppt das Plugin. Der Menu-Punkt wird wieder entfernt.
+   */
+  public void stop() {
+    super.stop();
+    // Plugin-Applikation schliessen
+    if ( pluginAppl != null ) {
+      pluginAppl.setVisible(false);
+      pluginAppl.dispose();
+    }
+    // Plugin-Applikation (InternalFrame) aus dem Hauptfenster entfernen
+    appl.getMainFrame().getContentPane().remove(pluginAppl);
+    // Code-Generator aus Menu entfernen
+    appl.getMainFrame().getJMenuBar().getMenu(xuluMenuNo).remove(menuItem);
+    pluginAppl = null;
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/appl/DataExportHandler.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/appl/DataExportHandler.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/appl/DataExportHandler.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,136 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.appl;
+
+import schmitzm.data.event.ObjectEvent;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.AbstractHandler;
+import edu.bonn.xulu.appl.VisualisationTool;
+import edu.bonn.xulu.gui.XuluGUIMessages;
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.io.ExportFactory;
+
+/**
+ * Diese Klasse stellt einen Handler dar, mit dem ein Objekt des Datenpools
+ * (automatisiert) exportiert wird.
+ * Instanzen dieses Handlers werden (interaktiv)
+ * ueber eine {@link DataExportHandlerFactory} erzeugt, bzw. modifiziert.
+ * @author <a href="mailto:schmitzm at bonn.edu">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class DataExportHandler extends AbstractHandler {
+  /** Speichert das Objekt, das vom Handler exportiert wird. */
+  protected Object object = null;
+
+  /** Speichert die Factory, mit der das Objekt exportiert wird. */
+  protected ExportFactory exportFactory = null;
+
+  /** Speichert das Objekt, in das der Export vorgenommen wird (z.B. eine Datei). */
+  protected Object destObject = null;
+
+  /** Speichert eine Referenz auf die Xulu-Applikation. */
+  protected XuluModellingPlatform appl = null;
+
+  /**
+   * Erzeugt einen neuen Handler. Dem Handler ist noch kein konkretes Objekt und
+   * auch noch keine Factory (fuer den Export) zugeordnet.
+   * @param fac Factory, die fuer den Handler zustaendig ist.
+   * @param appl Instanz der Xulu-Applikation
+   * @see #setObject(Object)
+   * @see #setExportFactory(ExportFactory)
+   */
+  public DataExportHandler(DataExportHandlerFactory fac, XuluModellingPlatform appl) {
+    this(fac,(ExportFactory)null,null,null,appl);
+  }
+
+  /**
+   * Erzeugt einen neuen Handler.
+   * @param obj zu exportierendes Objekt
+   * @param expFac Factory Export-Factory, mit der das Objekt exportiert wird
+   * @param fac Factory, die fuer den Handler zustaendig ist.
+   * @param destObj Objekt in das der Export vorgenommen wird (z.B. eine Datei)
+   * @param appl Instanz der Xulu-Applikation
+   */
+  public DataExportHandler(Object obj, ExportFactory expFac, Object destObj, DataExportHandlerFactory fac, XuluModellingPlatform appl) {
+    super(fac);
+    this.object  = obj;
+    this.exportFactory = expFac;
+    this.destObject = destObj;
+    this.appl = appl;
+  }
+
+  /**
+   * Schliesst den Handler. Macht nichts.
+   */
+  public void close() {
+  }
+
+  /**
+   * Fuehrt den Handler aus. Das Objekt wird durch die Export-Factory in
+   * eine Datei (oder je nach Factory mehrere Dateien) exportiert. Bereits
+   * existierede Dateien werden automatisch ueberschrieben.
+   * @param e Ereignis fuer das der Handler ausgefuehrt wird (wird nicht verwendet!).
+   */
+  public void execute(ObjectEvent e) {
+    try {
+      exportFactory.exportObject( object, destObject );
+    } catch (Exception err) {
+      XuluGUIMessages.showError(null,err);
+    }
+  }
+
+
+  /**
+   * Liefert das Objekt, das vom Handler exportiert wird.
+   */
+  public Object getObject() {
+    return object;
+  }
+
+  /**
+   * Setzt das Objekt, das vom Handler exportiert wird.
+   * @param obj zu visualisierendes Objekt
+   */
+  public void setObject(Object obj) {
+    this.object = obj;
+  }
+
+  /**
+   * Liefert die Factory, mit der das Objekt exportiert wird.
+   */
+  public ExportFactory getExportFactory() {
+    return exportFactory;
+  }
+
+  /**
+   * Setzt die Factory, mit der das Objekt exportiert wird.
+   * @param expFac Factory fuer den Datenexport
+   */
+  public void setExportFactory(ExportFactory expFac) {
+    this.exportFactory = expFac;
+  }
+
+  /**
+   * Liefert das Objekt, in das der Export vorgenommen wird. z.B. eine Datei.
+   */
+  public Object getExportDestination() {
+    return this.destObject;
+  }
+
+  /**
+   * Setzt das Objekt, in das der Export vorgenommen wird.
+   * @param destObject Objekt in das exportiert wird (z.B. eine Datei)
+   */
+  public void setExportDestination(Object destObject) {
+    this.destObject = destObject;
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/appl/DataExportHandlerFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/appl/DataExportHandlerFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/appl/DataExportHandlerFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,94 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.appl;
+
+import schmitzm.swing.MultipleOptionPane;
+import schmitzm.swing.InputOption;
+import schmitzm.swing.SelectionInputOption;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.Handler;
+import edu.bonn.xulu.appl.HandlerFactory;
+import edu.bonn.xulu.appl.VisualisationTool;
+import edu.bonn.xulu.appl.XuluConstants;
+import edu.bonn.xulu.io.Factory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.gui.DataPoolInputOption;
+import edu.bonn.xulu.io.ExportFactory;
+
+/**
+ * Diese Klasse stellt eine abstrakte Oberklasse fuer alle Factories dar,
+ * mit denen Instanzen des {@link DataExportHandler} erstellt und modifiziert
+ * werden. Unterklassen muessen nur noch die Methoden implementieren, ueber
+ * die benoetigten Informationen interaktiv (ueber Dialoge) vom Anwender abgefragt
+ * werden.
+ * @author <a href="mailto:schmitzm at bonn.edu">Martin Schmitz</a> (University of  Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class DataExportHandlerFactory extends AbstractFactory implements HandlerFactory {
+  /**
+   * Erzeugt eine neue Handler-Factory.
+   */
+  public DataExportHandlerFactory() {
+    this("");
+  }
+
+  /**
+   * Erzeugt eine neue Handler-Factory.
+   * @param name Beschreibung der Factory
+   */
+  public DataExportHandlerFactory(String name) {
+    super(name);
+  }
+
+  /**
+   * Erzeugt einen neuen {@link DataExportHandler}.
+   * @param appl Instanz der Xulu-Applikation
+   */
+  public DataExportHandler createHandler(XuluModellingPlatform appl) {
+    Object[] input = showDialog(appl,null,null,null);
+    if ( input == null || input.length < 3 )
+      return null;
+    return new DataExportHandler(input[0],(ExportFactory)input[1],input[2],this,appl);
+  }
+
+  /**
+   * Veraendert einen bestehenden {@link FileExportHandler}.
+   * @param appl Instanz der Xulu-Applikation
+   * @param handler Handler, der veraendert werden soll
+   * @exception UnsupportedOperationException falls der uebergebene Handler
+   *            kein {@link FileExportHandler} ist
+   */
+  public void modifyHandler(XuluModellingPlatform appl, Handler handler) {
+    if ( !(handler instanceof DataExportHandler) )
+      throw new UnsupportedOperationException("FileExportHandlerFactory can only modify instances of FileExportHandler.");
+    DataExportHandler exportHandler = (DataExportHandler)handler;
+    Object[] input = showDialog(appl,exportHandler.getObject(), exportHandler.getExportFactory(), exportHandler.getExportDestination());
+    if ( input != null && input.length >= 3 ) {
+      exportHandler.setObject(input[0]);
+      exportHandler.setExportFactory( (ExportFactory)input[1] );
+      exportHandler.setExportDestination( input[2] );
+    }
+  }
+
+  /**
+   * Ermittelt die fuer den {@link DataExportHandler} benoetigten Informationen
+   * ueber einen Anwender-Dialog.
+   * @param appl Instanz der XuluModellingPlatform
+   * @param object vorgeblendetes Objekt, welches exportiert wird (kann {@code null} sein)
+   * @param expFac vorgeblendete Export-Factory (kann {@code null} sein)
+   * @param destObj vorgeblendetes Objekt, in welches der Export vorgenommen wird (kann {@code null} sein)
+   * @return Array in dem in Element 0 das Objekt, in Element 1 die Export-Factory und in
+   *         Element 2 das Ziel-Objekt enthalten ist
+   */
+  protected abstract Object[] showDialog(XuluModellingPlatform appl, Object object, ExportFactory expFac, Object destObj);
+}

Added: trunk/src/edu/bonn/xulu/plugin/appl/DataScriptInterpreter_Basic.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/appl/DataScriptInterpreter_Basic.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/appl/DataScriptInterpreter_Basic.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,914 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.appl;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+
+import java.util.Vector;
+import java.util.StringTokenizer;
+
+import schmitzm.io.IOUtil;
+import schmitzm.lang.LangUtil;
+
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.data.XuluDataException;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.AbstractCommandInterpreter;
+import edu.bonn.xulu.appl.ScriptablePlugin;
+import edu.bonn.xulu.appl.XuluPlugin;
+import edu.bonn.xulu.gui.XuluGUIUtil;
+import edu.bonn.xulu.io.IODefinition;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.io.TypeMappingException;
+import schmitzm.lang.OperationCanceledException;
+import schmitzm.lang.AlreadyHandledException;
+
+/**
+ * Dieser Interpreter fuehrt IO-Befehle des Datenpools aus. Einleitender Tag und
+ * die einzelnen Parameter stehen jeweils in eigenen Datei-Zeilen. Leerzeilen
+ * und {@linkplain IOUtil#isCommentLine(String) Kommentarteilen} werden ignoriert.
+ * <table align=center border=2 cellpadding=5>
+ *    <tr><th>Befehl</th>
+ *        <th>einleitende Tag</th>
+ *        <th>Parameter</th>
+ *        </tr>
+ *    <tr><td valign="top">Xulu-Objekt neu erzeugen</td>
+ *        <td valign="top"><code>[Create]</code></td>
+ *        <td valign="top"><code>type = ...</code><br>
+ *            Klasse des Datentyps (passende Factory wird aus der Registry ermittelt)<br>
+ *            <code>name = ...</code><br>
+ *            Name fuer das Objekt<br>
+ *            <code>sample = ...</code> (optional)<br>
+ *            Name des Objekts, das als Vorlage dient<br>
+ *            <code>dialog = true|false</code> (optional)<br>
+ *            Flag, ob ein Dialog von der Factory angezeigt werden darf</td>
+ *        </tr>
+ *    <tr><td valign="top">Xulu-Objekt aus Datei importieren</td>
+ *        <td valign="top"><code>[Import]</code></td>
+ *        <td valign="top"><code>factory = ...</code><br>
+ *            Bezeichnung (oder Klasse) einer registrierten Import-Factory<br>
+ *            <code>name = ...</code><br>
+ *            Name fuer das Objekt<br>
+ *            <code>source = ...</code><br>
+ *            Datei aus der das Objekt gelesen wird (Parameter kann mehrfach angegeben werden!)</td>
+ *        </tr>
+ *    <tr><td valign="top">Struktur eines Xulu-Objekt kopieren</td>
+ *        <td valign="top"><code>[CopyStructure]</code></td>
+ *        <td valign="top"><code>source = ...</code><br>
+ *            Name des Objekts, das kopiert werden soll<br>
+ *            <code>dest = ...</code><br>
+ *            Name fuer das neue Objekt<br>
+ *            <code>dialog = true|false</code> (optional)<br>
+ *            Flag, ob ein Dialog von der Factory angezeigt werden darf</td>
+ *        </tr>
+ *    <tr><td valign="top">Xulu-Objekt umbenennen</td>
+ *        <td valign="top"><code>[Rename]</code></td>
+ *        <td valign="top"><code>source = ...</code><br>
+ *            Name des Objekts, das umbenannt werden soll<br>
+ *            <code>dest = ...</code><br>
+ *            Neuer Name fuer das Objekt</td>
+ *        </tr>
+ *
+ *          <tr><td valign="top">Neues Model erzeugen</td>
+ *        <td valign="top"><code>[CreateModel]</code></td>
+ *        <td valign="top"><code>modelClass = ...</code><br>
+ *            Klasse des Modells, dass geladen werden soll<br>
+ *            <code>name = ...</code><br>
+ *            Name fuer das Modell</td>
+ *        </tr>
+ *
+ *          <tr><td valign="top">Modell-Ressource-Mapping laden</td>
+ *        <td valign="top"><code>[LoadMapping]</code></td>
+ *        <td valign="top"><code>path = ...</code><br>
+ *            Pfad zum Skript, dass das Mapping durchf�hrt<br>
+ *            <code>name = ...</code><br>
+ *            Das Mapping wird f�r alle Modelle mit diesem Namen durchgef�hrt</td>
+ *        </tr>
+ * </table>
+ * <br>
+ * Darueber hinaus kann zwischen den einzelnen Befehlen ueber das Kommando
+ * <code>[BaseDir]</code> (gefolgt von eine Zeile mit Pfad-Angabe) das Basis-Verzeichnis
+ * gewechselt werden, relativ zu dem Pfade beim Importieren interpretiert werden.
+ * Dies verhindert lange und unuebersichtliche Datei-Angaben.
+ * </ul>
+ * @see edu.bonn.xulu.plugin.appl.ModelResourceMappingScriptInterpreter_Basic
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class DataScriptInterpreter_Basic extends AbstractCommandInterpreter {
+  // speichert die eingelesenen Befehle
+  private Vector commands = new Vector();
+  // speichert die aktuelle Zeilennummer
+  private int     lineNo  = 0;
+  // speichert den aktuell eingelesenen Befehl
+  private Command command = null;
+  // speichert, ob Einfuege-Operationen bei einem Duplikat-Fehler autom.
+  // uebergangen werden sollen
+  private static boolean autoSkipDupl = false;
+
+  private void showError(String errString) {
+    System.out.println(errString);
+    errorCount++;
+  }
+
+  /**
+   * Fuehrt ein Script aus.
+   * @param in   Eingabe-Stream in dem das Skript zu finden ist.
+   * @param appl Applikation, in der das Skript auszufuehren ist
+   */
+  public void execute(InputStream in, XuluModellingPlatform appl) {
+    // Waehrend der Einfuegung von mehreren Objekten kann der Anwender im
+    // Konfliktfall auswaehlen, wie automatisch mit folgenden Konflikten
+    // umgegangen werden soll
+    // --> Entsprechend werden Einstellungen am Datenpool vorgenommen
+    // --> Nach der kollektiven Einfuegung sollen die alten Einstellungen
+    //     wieder hergestellt werden
+    boolean oldOverwriteOption = appl.getDataPool().getAutoOverwrideDuplicateNames();
+    boolean oldDuplicateOption = appl.getDataPool().getDuplicateNamesAllowed();
+    // Bei Duplikat-Fehlern soll die Operation nicht autom.
+    // uebergangen werden, sondern ein Dialog erscheinen
+    this.autoSkipDupl = false;
+    // Operationen ausfuehren
+    super.execute(in,appl);
+    // alte Datenpool-Einstellungen wieder herstellen
+    appl.getDataPool().setAutoOverwriteDuplicateNames(oldOverwriteOption);
+    appl.getDataPool().setDuplicateNamesAllowed(oldDuplicateOption);
+  }
+
+  /**
+   * Interpretiert einen Eingabestream, wie oben beschrieben und erzeugt
+   * daraus einzelne Kommandos.
+   * @param in Stream auf das Skript
+   */
+  protected Command[] readCommands(InputStream in) {
+    commands.clear(); // alte Befehlsliste loeschen
+    command = null;   // letzten eingelesenene Befehl initialisieren
+    // Stream parsen
+    BufferedReader input = new BufferedReader( new InputStreamReader(in) );
+    String  line    = null;
+    File    baseDir = appl.getWorkingDirectory(); //new File(".");
+    try {
+      // Zeilenweise einlesen
+      for(lineNo=1; (line = input.readLine()) != null; lineNo++) {
+        line = line.trim();
+        // Leerzeilen und Kommentare ignorieren
+        if ( line.equals("") || IOUtil.isCommentLine(line) )
+          continue;
+
+        // Befehl-Zeile interpretieren
+        if ( line.startsWith("[") && line.endsWith("]") ) {
+          // alten Befehl abschliessen
+          checkAndAddCommand("line "+lineNo);
+          // neuen Befehl erzeugen
+          command = null;
+          if ( line.equalsIgnoreCase("[BaseDir]") )
+            baseDir = new File(input.readLine());
+          if ( line.equalsIgnoreCase("[Import]") )
+            command = new Command_ImportFromFile();
+          if ( line.equalsIgnoreCase("[Rename]") )
+            command = new Command_Rename();
+          if ( line.equalsIgnoreCase("[Create]") )
+            command = new Command_New();
+          if ( line.equalsIgnoreCase("[CopyStructure]") )
+            command = new Command_CopyStructure();
+          if ( line.equalsIgnoreCase("[CreateModel]") )
+              command = new Command_CreateModel();
+          if ( line.equalsIgnoreCase("[LoadMapping]") )
+              command = new Command_LoadMapping();
+          if ( line.equalsIgnoreCase("[Plugin]") )
+              command = new Command_Plugin();
+          // zur naechsten Zeile uebergehen
+          continue;
+        }
+
+        // Eine Parameter-Zeile kann nur interpretiert werden,
+        // wenn vorher ein Befehl definiert wurde
+        if ( command == null )
+          showError("error line " + lineNo + " > Command in outside section!");
+
+        // Parameter-Zeile intepretieren
+        try {
+          if ( command instanceof Command_New )
+            parseLineForCommand_New((Command_New)command,line);
+          else if ( command instanceof Command_Rename )
+            parseLineForCommand_Rename((Command_Rename)command,line);
+          else if ( command instanceof Command_CopyStructure )
+            parseLineForCommand_CopyStructure((Command_CopyStructure)command,line);
+          else if ( command instanceof Command_ImportFromFile )
+            parseLineForCommand_ImportFromFile((Command_ImportFromFile)command,line,baseDir);
+          else if ( command instanceof Command_CreateModel )
+              parseLineForCommand_CreateModel((Command_CreateModel)command,line);
+          else if ( command instanceof Command_LoadMapping )
+              parseLineForCommand_LoadMapping((Command_LoadMapping)command,line,baseDir);
+          else if ( command instanceof Command_Plugin)
+              parseLineForCommand_Plugin((Command_Plugin)command,line);
+        } catch (Exception err) {
+          showError("error line "+lineNo+" > "+err.getMessage());
+        }
+      }
+      // letzten Befehl abschliessen
+      checkAndAddCommand("at end of file");
+
+      // Stream schliessen
+      in.close();
+    } catch ( Exception err ) {
+      showError("Unknown error while parsing line "+lineNo);
+//      err.printStackTrace();
+    }
+    return (Command[])commands.toArray(new Command[0]);
+  }
+
+  /**
+   * Prueft ein Command auf Korrektheit und fuegt es der Kommandoliste hinzu.
+   * @param lineDesc Bezeichnung der aktuell eingelesenen Zeile (Hinweis fuer
+   *                 etwaige Fehlermeldung)
+   */
+  private void checkAndAddCommand(String lineDesc) {
+    // alten Befehl checken und der Liste hinzufuegen
+    if (command != null) {
+      try {
+        command.check();
+        commands.add(command);
+      }
+      catch (Exception err) {
+        showError("error "+lineDesc+" > Creation of last command failed: " + err.getMessage());
+      }
+    }
+  }
+
+  /**
+   * Teilt eine Parameter-Zeile ein in Tag (vor Gleichheitszeichen) und
+   * Wert (alles nach Gleichheitszeichen). Liefert in Array-Position 0 den
+   * Tag-Namen und in Position 1 den Wert.
+   * @param line Parameter-Zeile
+   * @return 2-dim. Array
+   */
+  private String[] parseLineInTagAndValue(String line) {
+    int pos = line.indexOf("=");
+    if ( pos < 0 )
+      throw new UnsupportedOperationException("Illegal line format");
+    return new String[] {
+        line.substring(0,pos).trim(),
+        line.substring(pos+1).trim()
+    };
+  }
+
+  /**
+   * Interpretiert eine Zeile als Parameter fuer den Befehl
+   * "Neues Objekt".
+   * @param command  aktueller Befehl
+   * @param line     Zeile
+   */
+  private void parseLineForCommand_New(Command_New command, String line) {
+    String[] tok = parseLineInTagAndValue(line);
+    if ( tok[0].equalsIgnoreCase("type") )
+      try {
+        command.objectType = Class.forName(tok[1]);
+      } catch (ClassNotFoundException err) {
+        throw new UnsupportedOperationException("class of type '"+tok[1]+"' not found");
+      }
+    else if ( tok[0].equalsIgnoreCase("sample") )
+      command.sampleName = tok[1];
+    else if ( tok[0].equalsIgnoreCase("name") )
+      command.objectName = tok[1];
+    else if ( tok[0].equalsIgnoreCase("dialog") )
+      command.dialog = new Boolean(tok[1]);
+    else
+      throw new UnsupportedOperationException("Unknown tag '"+tok[0]+"'");
+  }
+
+  /**
+   * Interpretiert eine Zeile als Parameter fuer den Befehl
+   * "Objekt umbenennen".
+   * @param command  aktueller Befehl
+   * @param line     Zeile
+   */
+  private void parseLineForCommand_Rename(Command_Rename command, String line) {
+    String[] tok = parseLineInTagAndValue(line);
+    if ( tok[0].equalsIgnoreCase("source") )
+      command.objectName = tok[1];
+    else if ( tok[0].equalsIgnoreCase("dest") )
+      command.newObjectName = tok[1];
+    else
+      throw new UnsupportedOperationException("Unknown tag '"+tok[0]+"'");
+  }
+
+  /**
+   * Interpretiert eine Zeile als Parameter fuer den Befehl
+   * "Objektstruktur kopieren".
+   * @param command  aktueller Befehl
+   * @param line     Zeile
+   */
+  private void parseLineForCommand_CopyStructure(Command_CopyStructure command, String line) {
+    String[] tok = parseLineInTagAndValue(line);
+    if ( tok[0].equalsIgnoreCase("source") )
+      command.sampleName = tok[1];
+    else if ( tok[0].equalsIgnoreCase("dest") )
+      command.objectName = tok[1];
+    else if ( tok[0].equalsIgnoreCase("dialog") )
+      command.dialog = new Boolean(tok[1]);
+    else
+      throw new UnsupportedOperationException("Unknown tag '"+tok[0]+"'");
+  }
+
+  /**
+   * Interpretiert eine Zeile als Parameter fuer den Befehl
+   * "Objekt aus Datei importieren".
+   * @param command  aktueller Befehl
+   * @param line     Zeile
+   * @param baseDir  aktuell gesetztes Basisverzeichnis fuer die Eingabedateien
+   */
+  private void parseLineForCommand_ImportFromFile(Command_ImportFromFile command, String line, File baseDir) {
+    String[] tok = parseLineInTagAndValue(line);
+    if ( tok[0].equalsIgnoreCase("factory") )
+      command.facName = tok[1];
+    else if ( tok[0].equalsIgnoreCase("name") )
+      command.objectName = tok[1];
+    else if ( tok[0].equalsIgnoreCase("source") )
+      command.sourceVec.add( IOUtil.createRelativeFile(baseDir, tok[1]) );
+    else
+      throw new UnsupportedOperationException("Unknown tag '"+tok[0]+"'");
+  }
+
+  /**
+   * Interpretiert eine Zeile als Parameter fuer den Befehl
+   * "Erzeuge neues Modell".
+   * @param command  aktueller Befehl
+   * @param line     Zeile
+   */
+  private void parseLineForCommand_CreateModel(Command_CreateModel command, String line) {
+    String[] tok = parseLineInTagAndValue(line);
+    if ( tok[0].equalsIgnoreCase("modelClass") )
+      command.modelClass = tok[1];
+    else if ( tok[0].equalsIgnoreCase("name") )
+      command.modelName = tok[1];
+    else
+      throw new UnsupportedOperationException("Unknown tag '"+tok[0]+"'");
+  }
+
+
+  /**
+   * Interpretiert eine Zeile als Parameter fuer den Befehl
+   * "Lade ein Modell - Ressource - Mapping".
+   * @param command  aktueller Befehl
+   * @param line     Zeile
+   * @param baseDir  aktuell gesetztes Basisverzeichnis fuer die Eingabedateien
+   */
+  private void parseLineForCommand_LoadMapping(Command_LoadMapping command, String line, File baseDir) {
+    String[] tok = parseLineInTagAndValue(line);
+    if (tok[0].equalsIgnoreCase("name"))
+      command.modelName = tok[1];
+    else if (tok[0].equalsIgnoreCase("path"))
+      command.scriptPath = IOUtil.createRelativeFile(baseDir, tok[1]).
+          getAbsolutePath();
+    else
+      throw new UnsupportedOperationException("Unknown tag '" + tok[0] + "'");
+  }
+  /**
+   * Interprets a line as command for a plugin. The "pluginname"-tag should
+   * the fully qualified name of an existing and loaded {@link XuluPlugin}. All other lines
+   * will be forwarded to the specified plugin, which is responsible for
+   * correct interpretation.
+   *
+   * @author Dominik Appl
+   * @param command actual command
+   * @param line line to interpret by the the plugin
+   *
+   */
+  private void parseLineForCommand_Plugin(Command_Plugin command, String line) {
+    String[] tok = parseLineInTagAndValue(line);
+    if (tok[0].equalsIgnoreCase("pluginname"))
+      command.pluginName = tok[1];
+    else
+      command.pluginCommands.add(line);
+  }
+
+  /**
+   * Dieser Befehl erzeugt ein neues Xulu-Objekts im Datenpool.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  protected class Command_New implements Command {
+    private Class   objectType = null;
+    private boolean dialog     = false;
+    private String  objectName = null;
+    private String  sampleName = null;
+
+    private Command_New() {
+    }
+
+    /**
+     * Erzeugt einen neuen Befehl.
+     * @param objectType Typ des zu erzeugenden Objekts
+     * @param objName    Bezeichnung des Objekts im Datenpool
+     * @param sampleName Name des Objekts, welches als (strukturelle) Vorlage
+     *                   fuer das neue Objekt verwendet wird (kann {@code null} sein)
+     * @param dialog     bestimmt, ob ein Anwender-Dialog bei der Erzeugung
+     *                   des Objekts angezeigt werden darf
+     */
+    public Command_New(Class objectType, String objName, String sampleName, boolean dialog) {
+      this.objectType  = objectType;
+      this.objectName  = objName;
+      this.dialog      = dialog;
+      this.sampleName  = sampleName;
+    }
+
+    /**
+     * Liefert eine Beschreibung des Kommandos.
+     */
+    public String getDescription() {
+      return "Create new object '"+objectName+"' ("+objectType.getSimpleName()+")";
+    }
+
+    /**
+     * Fuehrt den Befehl aus.
+     * @param appl Applikation unter der der Befehl ausgefuehrt wird
+     * @exception TypeMappingException falls keine InstantiationFactory fuer den
+     *            Datentyp registriert ist.
+     * @exception XuluDataException die gefundenen Factory kein XuluObject instanziiert
+     * @exception Exception falls die Instanziierung des Objekts fehl schlaegt
+     */
+    public void execute(XuluModellingPlatform appl) throws Exception, TypeMappingException, XuluDataException {
+      XuluObject sample = (sampleName != null) ? findObjectInDataPool(sampleName,appl) : null;
+      createNewObject(objectType,objectName,sample,dialog,appl);
+    }
+
+    /**
+     * Prueft, ob alle Parameter korrekt gesetzt sind. Ggf. wird eine
+     * Exception geworfen.
+     */
+    public void check() {
+      if ( objectType == null )
+        throw new UnsupportedOperationException("No object type specified!");
+      if ( objectName == null || objectName.equals("") )
+        throw new UnsupportedOperationException("No object name specified!");
+    }
+  }
+
+  /**
+   * Dieser Befehl importiert ein neues Xulu-Objekts in den Datenpool.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  protected class Command_ImportFromFile implements Command {
+    private String   facName    = null;
+    private boolean  dialog     = false;
+    private String   objectName = null;
+    private Vector   sourceVec  = new Vector<File>();
+
+    /**
+     * Erzeugt einen neuen Befehl.
+     * @param facName    Bezeichnung der zu verwendenden ImportFactory
+     * @param source     Eingabe-Dateien
+     * @param objName    Bezeichnung des Objekts im Datenpool
+     * @param dialog     bestimmt, ob ein Anwender-Dialog bei der Erzeugung
+     *                   des Objekts angezeigt werden darf
+     */
+    public Command_ImportFromFile(String facName, File[] source, String objName, boolean dialog) {
+      this.facName     = facName;
+      this.objectName  = objName;
+      this.dialog      = dialog;
+      for (int i=0; i<source.length; i++)
+        sourceVec.add(source[i]);
+    }
+
+    private Command_ImportFromFile() {
+    }
+
+    /**
+     * Liefert eine Beschreibung des Kommandos.
+     */
+    public String getDescription() {
+      return "Import object '"+objectName+"' by "+facName;
+    }
+
+    /**
+     * Fuehrt den Befehl aus.
+     * @param appl Applikation unter der der Befehl ausgefuehrt wird
+     * @exception TypeMappingException falls keine InstantiationFactory fuer den
+     *            Datentyp registriert ist.
+     * @exception XuluDataException die gefundenen Factory kein XuluObject instanziiert
+     * @exception Exception falls die Instanziierung des Objekts fehl schlaegt
+     */
+    public void execute(XuluModellingPlatform appl) throws Exception, TypeMappingException, XuluDataException {
+      importObjectFromFile(facName,(File[])sourceVec.toArray(new File[0]),objectName,dialog,appl);
+    }
+
+    /**
+     * Prueft, ob alle Parameter korrekt gesetzt sind. Ggf. wird eine
+     * Exception geworfen.
+     */
+    public void check() {
+      if ( facName == null || facName.equals("") )
+        throw new UnsupportedOperationException("No factory specified!");
+      if ( objectName == null || objectName.equals("") )
+        throw new UnsupportedOperationException("No object name specified!");
+      if ( sourceVec == null || sourceVec.size() == 0 )
+        throw new UnsupportedOperationException("No source files specified!");
+    }
+  }
+
+  /**
+   * Dieser Befehl erzeugt ein neues Xulu-Objekts im Datenpool auf Basis eines
+   * bestehenden Objekts.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  protected class Command_CopyStructure implements Command {
+    private boolean dialog     = false;
+    private String  sampleName = null;
+    private String  objectName = null;
+
+    private Command_CopyStructure() {
+    }
+
+    /**
+     * Erzeugt einen neuen Befehl.
+     * @param sampleName  Name des zu kopierenden Objekts
+     * @param objectName  Bezeichnung des neuen Objekts im Datenpool
+     * @param dialog      bestimmt, ob ein Anwender-Dialog beim Kopieren
+     *                    des Objekts angezeigt werden darf
+     */
+    public Command_CopyStructure(String sampleName, String objectName, boolean dialog) {
+      this.sampleName = sampleName;
+      this.objectName = objectName;
+      this.dialog     = dialog;
+    }
+
+    /**
+     * Liefert eine Beschreibung des Kommandos.
+     */
+    public String getDescription() {
+      return "Create new object '"+objectName+"' from '"+sampleName+"'";
+    }
+
+    /**
+     * Fuehrt den Befehl aus.
+     * @param appl Applikation unter der der Befehl ausgefuehrt wird
+     * @exception TypeMappingException falls keine InstantiationFactory fuer den
+     *            Datentyp registriert ist.
+     * @exception XuluDataException die gefundenen Factory kein XuluObject instanziiert
+     * @exception Exception falls die Instanziierung des Objekts fehl schlaegt
+     */
+    public void execute(XuluModellingPlatform appl) throws Exception, TypeMappingException, XuluDataException {
+      XuluObject sample = findObjectInDataPool(sampleName,appl);
+      createNewObject(sample.getClass(),objectName,sample,dialog,appl);
+    }
+
+    /**
+     * Prueft, ob alle Parameter korrekt gesetzt sind. Ggf. wird eine
+     * Exception geworfen.
+     */
+    public void check() {
+      if ( sampleName == null || sampleName.equals("") )
+        throw new UnsupportedOperationException("No sample object specified!");
+      if ( objectName == null || objectName.equals("") )
+        throw new UnsupportedOperationException("No object name specified!");
+    }
+  }
+
+  /**
+   * Dieser Befehl aendert den Namen eines Xulu-Objekts im Datenpool.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  protected class Command_Rename implements Command {
+    private String  objectName = null;
+    private String  newObjectName = null;
+
+    private Command_Rename() {
+    }
+
+    /**
+     * Erzeugt einen neuen Befehl.
+     * @param objectName    Name des umzubenennenden Objekts
+     * @param newObjectName neuer Name
+     */
+    public Command_Rename(String objectName, String newObjectName) {
+      this.objectName    = objectName;
+      this.newObjectName = newObjectName;
+    }
+
+    /**
+     * Liefert eine Beschreibung des Kommandos.
+     */
+    public String getDescription() {
+      return "Rename object '" + objectName + "' to '"+newObjectName+"'";
+    }
+
+    /**
+     * Fuehrt den Befehl aus.
+     * @param appl Applikation unter der der Befehl ausgefuehrt wird
+     * @exception XuluDataException falls es kein oder mehr als ein Objekt
+     *            mit dem Namen im Datenpool gibt
+     */
+    public void execute(XuluModellingPlatform appl) throws Exception {
+      findObjectInDataPool(objectName,appl).setDescription(newObjectName);
+    }
+
+    /**
+     * Prueft, ob alle Parameter korrekt gesetzt sind. Ggf. wird eine
+     * Exception geworfen.
+     */
+    public void check() {
+      if ( objectName == null || objectName.equals("") )
+        throw new UnsupportedOperationException("No object name specified!");
+      if ( newObjectName == null || newObjectName.equals("") )
+        throw new UnsupportedOperationException("No new name specified!");
+    }
+  }
+
+  /**
+   * Erzeugt ein neues Modell
+   * @author Dominik Appl - University of Bonn/Germany
+   * @version 1.0
+   */
+  protected class Command_CreateModel implements Command {
+    private String  modelClass = null;
+    private String  modelName = null;
+
+    private Command_CreateModel() {
+    }
+
+    /**
+     * Erzeugt einen neuen Befehl.
+     * @param modelClass Klasse des zu ladenen Modells
+     * @param modelName Name fuer die neue Modell-Instanz
+     */
+    public Command_CreateModel(String modelClass, String modelName) {
+      this.modelClass = modelClass;
+      this.modelName = modelName;
+    }
+
+    /**
+     * Liefert eine Beschreibung des Kommandos.
+     */
+    public String getDescription() {
+      return "Create Model \"" + modelName + "\" from class " + modelClass;
+    }
+
+    /**
+     * Fuehrt den Befehl aus.
+     * @param appl Applikation unter der der Befehl ausgefuehrt wird
+     */
+    public void execute(XuluModellingPlatform appl) throws Exception {
+      try{
+        Class model = LangUtil.loadClass(modelClass,appl.getDynamicClassRootDirectory().toURI().toURL());
+        XuluGUIUtil.createNewModel(appl.getMainFrame(), model, modelName, appl);
+      } catch (Exception e){
+        System.err.println("Unable to create instance of " + modelName);
+        e.printStackTrace();
+        throw (e);
+      }
+    }
+    /**
+     * Prueft, ob alle Parameter korrekt gesetzt sind. Ggf. wird eine
+     * Exception geworfen.
+     */
+    public void check() {
+        if ( modelName == null || modelName.equals("") )
+            throw new UnsupportedOperationException("No Modelname specified!");
+        if ( modelClass == null || modelClass.equals("") )
+            throw new UnsupportedOperationException("No Model Classname specified!");
+
+      }
+    }
+
+    /**
+     * F�hrt mittels eines Skripts ein Mapping von Ressourcen
+     * auf ein Modell durch
+     * @author Dominik Appl - University of Bonn/Germany
+     * @version 1.0
+     */
+    protected class Command_LoadMapping implements Command {
+      private String  scriptPath = null;
+      private String  modelName = null;
+
+      private Command_LoadMapping() {
+      }
+
+      /**
+       * Erzeugt einen neuen Befehl.
+       * @param modelName Name des (geladenen) Modells
+       * @param scriptPath Pfad zu dem Skript das das Mapping durch f�hrt
+       *
+       * @see ModelResourceMappingScriptInterpreter_Basic
+       */
+
+      public Command_LoadMapping(String scriptPath, String modelName) {
+        this.scriptPath = scriptPath;
+        this.modelName = modelName;
+      }
+
+      /**
+       * Liefert eine Beschreibung des Kommandos.
+       */
+      public String getDescription() {
+        return "Loading Mapping for Model :\"" + modelName + "\" from path " + scriptPath;
+      }
+
+      /**
+       * Fuehrt den Befehl aus.
+       * @param appl Applikation unter der der Befehl ausgefuehrt wird
+       */
+      public void execute(XuluModellingPlatform appl) throws Exception {
+        try{
+              InputStream in = new FileInputStream(scriptPath);
+              new ModelResourceMappingScriptInterpreter_Basic().execute(in ,modelName,appl);
+        }
+          catch (Exception e){
+            System.err.println("Unable to load mapping: " + e.getMessage());
+        }
+      }
+
+    /**
+     * Prueft, ob alle Parameter korrekt gesetzt sind. Ggf. wird eine
+     * Exception geworfen.
+     */
+    public void check() {
+        if ( modelName == null || modelName.equals("") )
+            throw new UnsupportedOperationException("No Modelname specified!");
+        if ( scriptPath == null || scriptPath.equals("") )
+            throw new UnsupportedOperationException("No ScriptPath specified!");
+      }
+    }
+
+
+    /**
+     * Forwards scripting to a method in a plugin
+     *
+     * @author Dominik Appl - University of Bonn/Germany
+     *      */
+    protected class Command_Plugin implements Command {
+      private String  pluginName = null;
+      private Vector pluginCommands = new Vector<String>();
+
+      private Command_Plugin() {
+      }
+
+      /**
+         * Creates a new plugin command. The command will be forwarded to the
+         * specified plugin, which is responsible for interpreting it correctly.
+         *
+         * @param pluginname
+         *            the exact java-name to the class of the plugin
+         * @param pluginCommands
+         *            Vector of tokenized commands which are forwared to the
+         *            plugin. Each command is a String array with position 0
+         *            containing the tagname and further positions containing
+         *            the values for this tag.
+         *
+         * @see ModelResourceMappingScriptInterpreter_Basic
+         */
+
+      public Command_Plugin(String pluginname, Vector pluginCommands) {
+        this.pluginName = pluginname;
+        this.pluginCommands = pluginCommands;
+      }
+
+      /**
+       * returns a description of the command
+       */
+      public String getDescription() {
+        return "Forwarding Commands to plugin :\""  + pluginName + "\"";
+      }
+
+      /**
+         * Executes the commands
+         *
+         * @param appl
+         *            Application which executes the command
+         */
+        public void execute(XuluModellingPlatform appl) throws Exception {
+            ScriptablePlugin plugin = (ScriptablePlugin) getPluginForName(pluginName);
+            if (plugin == null)
+                return;
+            else
+                plugin.executeScript((String[]) pluginCommands.toArray());
+        }
+
+      /**
+         * Returns a {@link XuluPlugin} for a fully qualified name.
+         *
+         * @return the plugin, if one was found. Null if no plugin with the
+         *         given name is loaded
+         */
+        public XuluPlugin getPluginForName(String name) {
+            XuluPlugin[] plugins = appl.getRegistry().getPlugins();
+            for (XuluPlugin xp : plugins)
+                if (xp.getName().equals(name))
+                   return xp;
+            return null;
+        }
+
+    /**
+     * Checks if the parameters are set correctly
+     */
+    public void check() {
+        if ( pluginName == null || pluginName.equals("") )
+            throw new UnsupportedOperationException("No plugin specified!");
+        if ( pluginCommands.isEmpty() )
+            throw new UnsupportedOperationException("No commands specified!");
+        XuluPlugin plugin = getPluginForName(pluginName);
+        //check if a plugin with the name is loaded
+        if(plugin==null) throw new UnsupportedOperationException("Specified plugin with name: " + pluginName + " is not loaded!");
+        if(!(plugin instanceof ScriptablePlugin))
+            throw  new UnsupportedOperationException("Plugin keine Instanz von ScriptablePlugin");
+      }
+    }
+
+
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////////  statische Hilfsmethoden  //////////////////////////
+  ////////////////////////////////////////////////////////////////////////
+  private static XuluObject findObjectInDataPool(String name, XuluModellingPlatform appl) throws Exception {
+    // Objekt im Datenpool suchen
+    XuluObject[] o = appl.getDataPool().getObjects(name);
+    if ( o.length == 0 )
+      throw new XuluDataException("No XuluObject with name '"+name+"' found in the data pool!");
+    if ( o.length > 1 )
+      throw new XuluDataException(o.length+" XuluObjects with name '"+name+"' found in the data pool!");
+    return o[0];
+  }
+
+  private static InstantiationFactory findInstantiationFactoryInRegistry(Class type, boolean dialog, XuluModellingPlatform appl) throws Exception {
+    // Factory zum Datentyp in Registry suchen
+    InstantiationFactory fac = appl.getRegistry().getDefaultFactory(type);
+    if ( fac == null )
+      throw new TypeMappingException("No factory found to instantiate "+type.getName());
+    return fac;
+  }
+
+  private static ImportFactory findImportFactoryInRegistry(String facName, boolean dialog, XuluModellingPlatform appl) throws Exception {
+//    return (ImportFactory)Class.forName(facName).newInstance();
+    // Factory zum Datentyp in Registry suchen
+    ImportFactory[] fac = appl.getRegistry().getImportFactories(facName);
+    if ( fac == null || fac.length == 0 )
+      throw new TypeMappingException("No factory with name '"+facName+"' found in registry!");
+    if ( fac.length > 1 )
+      throw new TypeMappingException(fac.length+" factories with name '"+facName+"' found in registry!");
+    return fac[0];
+  }
+
+  private static void createNewObject(Class type, String name, Object sample, boolean dialog, XuluModellingPlatform appl) throws Exception {
+    InstantiationFactory fac = findInstantiationFactoryInRegistry(type,dialog,appl);
+    if ( !XuluObject.class.isAssignableFrom( fac.getInstanceType() ) )
+      throw new XuluDataException("Factory does not create a XuluObject (only XuluObjects can be handled by the data pool!)");
+    // Objekt erzeugen
+    Object o = (sample==null) ? fac.newInstance(dialog) : fac.newInstance(dialog,sample);
+    // Objekt in Datenpool einfuegen
+    ((XuluObject)o).setDescription(name);
+    try {
+      XuluGUIUtil.insertObjectToDataPool( appl.getMainFrame(), o, appl.getDataPool(), true, autoSkipDupl );
+    } catch ( AlreadyHandledException err ) {
+      // Einfuegung wurde (ueber Anwender-Dialog) fuer das Objekt uebergangen
+      // und soll auch fuer alle alle Folge-Konflikte uebergangen werden
+      // --> Schleife fortsetzen, aber mit autoSkip
+      autoSkipDupl = true;
+    }
+  }
+
+  private static void importObjectFromFile(String facName, File[] sourceFile, String name, boolean dialog, XuluModellingPlatform appl) throws Exception {
+    ImportFactory fac = findImportFactoryInRegistry(facName,dialog,appl);
+    if ( !XuluObject.class.isAssignableFrom( fac.getImportType() ) )
+      throw new XuluDataException("Factory does not create a XuluObject (only XuluObjects can be handled by the data pool!)");
+
+    // Eingabe-Daten umformatieren
+    Object facSource = sourceFile;
+    if ( !Object[].class.isAssignableFrom( fac.getImportSourceType() ) )
+      // nur die erste gegebene Datei beruecksichtigen
+      facSource = sourceFile[0];
+
+    // Import in Recent-Imports aufnehmen
+    appl.getRegistry().getRecentImports().add( new IODefinition.ImportDefinition(facSource,fac,appl.getRegistry()) );
+    // Objekt erzeugen
+    Object o = fac.importObject( XuluGUIUtil.convertImportSourceAsNeeded(fac,facSource),appl.getRegistry());
+    // Objekt in Datenpool einfuegen
+    ((XuluObject)o).setDescription(name);
+    try {
+      XuluGUIUtil.insertObjectToDataPool( appl.getMainFrame(), o, appl.getDataPool(), true, autoSkipDupl );
+    } catch ( AlreadyHandledException err ) {
+      // Einfuegung wurde (ueber Anwender-Dialog) fuer das Objekt uebergangen
+      // und soll auch fuer alle alle Folge-Konflikte uebergangen werden
+      // --> Schleife fortsetzen, aber mit autoSkip
+      autoSkipDupl = true;
+    }
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/appl/DateTimePlugin.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/appl/DateTimePlugin.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/appl/DateTimePlugin.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,150 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.appl;
+
+import java.text.DateFormat;
+import java.util.GregorianCalendar;
+import java.awt.BorderLayout;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+
+import schmitzm.lang.AbstractNamedObject;
+import schmitzm.lang.WorkingThread;
+import schmitzm.swing.SwingWorker;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.XuluPlugin;
+
+
+/**
+ * Diese Klasse stellt ein Plugin fuer die Xulu-Applikation dar, welches die
+ * aktuelle Uhrzeit (und Datum) in der Titel-Leiste des Xulu-Hauptfensters
+ * anzeigt.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class DateTimePlugin implements XuluPlugin {
+  private String                name        = "";
+  private ClockThread           clockThread = null;
+
+  /**
+   * Erzeugt ein neues Plugin.
+   */
+  public DateTimePlugin() {
+  }
+
+  /**
+   * Startet die Ausfuehrung des Plugins.
+   * @param appl Instanz der Xulu-Applikation
+   */
+  public void execute(XuluModellingPlatform appl) {
+    // alten Titel des Fensters merken
+    this.clockThread = new ClockThread(appl);
+    clockThread.start();
+  }
+
+  /**
+   * Stoppt die Ausfuehrung des Plugins.
+   */
+  public void stop() {
+    clockThread.terminate();
+  }
+
+  /**
+   * Prueft, ob das Plugin gestartet ist.
+   */
+  public boolean isStarted() {
+    return clockThread != null && clockThread.isRunning();
+  }
+
+  /**
+   * Liefert eine Beschreibung des Plugins.
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Setzt die Beschreibung des Plugins.
+   * @param name neue Bezeichnung
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * Macht nichts, da das Plugin keine GUI besitzt.
+   */
+  public void setVisible(boolean visible) {
+  }
+
+  /**
+   * Liefert immer <code>false</code>, da das Plugin keine GUI besitzt.
+   */
+  public boolean isVisible() {
+    return false;
+  }
+
+  /**
+   * Diese Klasse stellt den Uhrzeit-Thread dar, der die Uhrzeit in der
+   * Titelleiste des Xulu-Hauptfensters aktualisiert.
+   */
+  private class ClockThread extends WorkingThread {
+    private int                   lastSec;
+    private String                baseTitle;
+    private XuluModellingPlatform appl        = null;
+    private DateFormat            dateFormat  = DateFormat.getDateTimeInstance();
+
+    /**
+     * Erzeugt einen neuen Uhrzeit-Thread.
+     * @param appl Instanz der Xulu-Applikation
+     */
+    public ClockThread(XuluModellingPlatform appl) {
+      this.appl = appl;
+    }
+
+    /**
+     * Initialisiert den Thread.
+     */
+    public void performInit() {
+      this.lastSec  = -1;
+      this.baseTitle = appl.getMainFrame().getTitle();
+    }
+
+    /**
+     * Implementiert die Aktualisierung der Zeit-Anzeige.
+     */
+    public void performWork() {
+      while (true) {
+        this.checkBreakingCommands();
+        GregorianCalendar calendar = new GregorianCalendar();
+        int actSec = calendar.get(GregorianCalendar.SECOND);
+        if ( actSec != lastSec && appl.getMainFrame() != null )
+          appl.getMainFrame().setTitle( baseTitle + "  [" + dateFormat.format( calendar.getTime() ) + "]");
+        lastSec = actSec;
+        try {
+          this.sleep(100);
+        }
+        catch (InterruptedException err) {
+        }
+      }
+    }
+
+    /**
+     * Wird der Thread gestoppt, wird die Titelleiste des Xulu-Hauptfensters
+     * auf ihren urspruenglichen Wert zurueckgesetzt.
+     */
+    public void performDispose() {
+      appl.getMainFrame().setTitle(baseTitle);
+    }
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/appl/DateTimeWindowPlugin.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/appl/DateTimeWindowPlugin.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/appl/DateTimeWindowPlugin.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,141 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.appl;
+
+import java.text.DateFormat;
+import java.util.GregorianCalendar;
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+
+import schmitzm.lang.WorkingThread;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.XuluPlugin;
+
+/**
+ * Diese Klasse stellt ein Plugin fuer die Xulu-Applikation dar, welches die
+ * aktuelle Uhrzeit (und Datum) in einem eigenen (kleinen) Fester anzeigt.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class DateTimeWindowPlugin extends JFrame implements XuluPlugin {
+  private String      name        = "";
+  private ClockThread clockThread = null;
+  private JLabel      clockLabel  = new JLabel(" ");
+
+  /**
+   * Erzeugt ein neues Plugin.
+   */
+  public DateTimeWindowPlugin() {
+    super("Current Date/Time");
+    this.setLayout( new BorderLayout() );
+    this.setAlwaysOnTop(true);
+    this.setDefaultCloseOperation( JFrame.DO_NOTHING_ON_CLOSE );
+    this.setPreferredSize( new Dimension(200,60) );
+    this.getContentPane().add( clockLabel );
+    this.clockLabel.setHorizontalAlignment(JLabel.CENTER);
+    this.pack();
+
+  }
+
+  /**
+   * Startet die Ausfuehrung des Plugins.
+   * @param appl Instanz der Xulu-Applikation
+   */
+  public void execute(XuluModellingPlatform appl) {
+    this.clockThread = new ClockThread(clockLabel);
+    clockThread.start();
+    setVisible(true);
+  }
+
+  /**
+   * Stoppt die Ausfuehrung des Plugins.
+   */
+  public void stop() {
+    setVisible(false);
+    clockThread.terminate();
+  }
+
+  /**
+   * Prueft, ob das Plugin gestartet ist.
+   */
+  public boolean isStarted() {
+    return clockThread != null && clockThread.isRunning();
+  }
+
+  /**
+   * Liefert eine Beschreibung des Plugins.
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Setzt die Beschreibung des Plugins.
+   * @param name neue Bezeichnung
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * Diese Klasse stellt den Uhrzeit-Thread dar, der die Uhrzeit in dem
+   * Fenster aktualisiert.
+   */
+  private static class ClockThread extends WorkingThread {
+    private JLabel            clockLabel;
+    private DateFormat        dateFormat  = DateFormat.getDateTimeInstance();
+    private int               lastSec;
+
+    /**
+     * Erzeugt einen neuen Uhrzeit-Thread.
+     * @param clockLabel Label, in dem die Uhrzeit dargestellt werden soll
+     */
+    public ClockThread(JLabel clockLabel) {
+      this.clockLabel = clockLabel;
+    }
+
+    /**
+     * Initialisiert den Thread.
+     */
+    public void performInit() {
+      this.lastSec  = -1;
+    }
+
+    /**
+     * Implementiert die Aktualisierung der Zeit-Anzeige.
+     */
+    public void performWork() {
+      while (true) {
+        this.checkBreakingCommands();
+        GregorianCalendar calendar = new GregorianCalendar();
+        int actSec = calendar.get(GregorianCalendar.SECOND);
+        if ( actSec != lastSec )
+          clockLabel.setText( dateFormat.format( calendar.getTime() ) );
+        lastSec = actSec;
+        try {
+          this.sleep(100);
+        }
+        catch (InterruptedException err) {
+        }
+      }
+    }
+
+    /**
+     * Macht nichts.
+     */
+    public void performDispose() {
+    }
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/appl/FileExportHandlerFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/appl/FileExportHandlerFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/appl/FileExportHandlerFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,185 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.appl;
+
+import schmitzm.swing.MultipleOptionPane;
+import schmitzm.swing.InputOption;
+import schmitzm.swing.SelectionInputOption;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.Handler;
+import edu.bonn.xulu.appl.HandlerFactory;
+import edu.bonn.xulu.appl.VisualisationTool;
+import edu.bonn.xulu.appl.XuluConstants;
+import edu.bonn.xulu.io.Factory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.gui.DataPoolInputOption;
+import edu.bonn.xulu.io.ExportFactory;
+import schmitzm.swing.FileInputOption;
+import java.io.File;
+import schmitzm.swing.event.InputOptionAdapter;
+import edu.bonn.xulu.gui.XuluGUIMessages;
+import java.util.Vector;
+import schmitzm.data.event.ObjectEvent;
+import schmitzm.io.IOUtil;
+import java.text.DecimalFormat;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import edu.bonn.xulu.model.event.AbstractStepModelEvent;
+import edu.bonn.xulu.model.event.AbstractIterationStepEvent;
+
+/**
+ * Mit dieser Factory werden Instanzen des {@link FileExportHandler}
+ * erstellt und modifiziert. Die benoetigten Informationen (zu exportierendes
+ * Datenpool-Objekt, Ausgabe-Datei und Export-Factory) werden interaktiv
+ * ueber Dialoge vom Anwender abgefragt.
+ * @author <a href="mailto:schmitzm at bonn.edu">Martin Schmitz</a> (University of  Bonn/Germany)
+ * @version 1.0
+ */
+public class FileExportHandlerFactory extends DataExportHandlerFactory {
+  private File          originalDestFile      = null;
+  private Matcher       counterPatternMatcher = null;
+  private DecimalFormat counterFormat         = null;
+
+  /**
+   * Erzeugt eine neue Handler-Factory.
+   */
+  public FileExportHandlerFactory() {
+    this("");
+  }
+
+  /**
+   * Erzeugt eine neue Handler-Factory.
+   * @param name Beschreibung der Factory
+   */
+  public FileExportHandlerFactory(String name) {
+    super(name);
+  }
+
+  /**
+   * Erzeugt einen neuen {@link DataExportHandler}.
+   * @param appl Instanz der Xulu-Applikation
+   */
+  public DataExportHandler createHandler(XuluModellingPlatform appl) {
+    DataExportHandler handler = super.createHandler(appl);
+    if ( handler == null )
+      return null; // Dialog abgebrochen
+
+    // neue Handler-Instanz erzeugen, die vor dem Datei-Schreiben den
+    // Dateinamen je nach Event um eine ID erweitert, damit die Datei nicht
+    // ueberschrieben wird
+    handler = new DataExportHandler(handler.getObject(),handler.getExportFactory(),handler.getExportDestination(),(DataExportHandlerFactory)handler.getFactory(),appl) {
+                    public void execute(ObjectEvent e) {
+                      if ( counterFormat != null ) {
+                        String eventID = "";
+                        // Bei StepModelEvent wird der Dateiname um die Step-No.
+                        // erweitert
+                        if ( e instanceof AbstractStepModelEvent )
+                          eventID += counterFormat.format( ((AbstractStepModelEvent)e).getStepNo() );
+                        // Bei IterationStepEvent wird der Dateiname ZUDEM
+                        // um die Iteration-No. erweitert
+                        if ( e instanceof AbstractIterationStepEvent )
+                          eventID += "." + counterFormat.format( ((AbstractIterationStepEvent)e).getIterNo() );
+                        // Export-Ziel durch neue Datei ersetzen
+                        destObject = new File(
+                            counterPatternMatcher.replaceFirst(eventID)
+                        );
+                      }
+                      // Export durchfuehren
+                      super.execute(e);
+                      // Export-Ziel wieder durch Original ersetzen, damit
+                      // EventHandler unveraendert bleibt
+                      destObject = originalDestFile;
+                    }
+    };
+
+    return handler;
+  }
+
+  /**
+   * Ermittelt die fuer den {@link DataExportHandler} benoetigten Informationen
+   * ueber einen Anwender-Dialog.
+   * @param appl Instanz der XuluModellingPlatform
+   * @param defObject vorgeblendetes Objekt, welches exportiert wird (kann {@code null} sein)
+   * @param defExpFac vorgeblendete Export-Factory (kann {@code null} sein)
+   * @param defDestObj vorgeblendete Export-Datei (kann {@code null} sein)
+   * @return Array in dem in Element 0 das ausgewaehlte Datenpool-Objekt,
+   *         in Element 1 die Export-Factory und in Element 2 die Ziel-Datei
+   *         enthalten ist
+   * @exception IllegalArgumentException falls {@code defDestObj} kein {@link File} ist
+   */
+  protected Object[] showDialog(final XuluModellingPlatform appl, Object defObject, ExportFactory defExpFac, Object defDestObj) {
+    if ( defDestObj != null && !(defDestObj instanceof File) )
+      throw new IllegalArgumentException(getClass().getSimpleName()+" only accepts File as destination Object: "+defDestObj.getClass().getSimpleName());
+
+    // existierende Export-Factories ermitteln
+    ExportFactory[] expFactory     = appl.getRegistry().getExportFactories();
+    String[]        expFactoryDesc = new String[expFactory.length];
+    for (int i=0; i<expFactoryDesc.length; i++)
+      expFactoryDesc[i] = expFactory[i].getName();
+
+    final DataPoolInputOption  dataPoolOption = new DataPoolInputOption(appl.getDataPool(),XuluConstants.XULUGUI_RES.getString("ExportSource"),true,null);
+    final SelectionInputOption factoryOption  = new SelectionInputOption.Combo(XuluConstants.XULUGUI_RES.getString("ExportFactory")+":",true);
+    final FileInputOption      fileOption     = new FileInputOption(XuluConstants.XULUGUI_RES.getString("ExportDest")+":",true);
+
+    // wenn sich das zu Datenpool-Objekt aendert, muss die Auswahl der
+    // moeglichen Export-Factories entsprechend aktualisiert werden
+    dataPoolOption.addInputOptionListener( new InputOptionAdapter() {
+      public void optionChanged(InputOption option, Object oldValue, Object newValue) {
+        // Export-Factories ermitteln, die den Datentyp unterstuetzen und
+        // in eine Datei exportieren
+        ExportFactory[] allExpFactory     = appl.getRegistry().getExportFactories();
+        Vector<ExportFactory> expFactoryVec = new Vector();
+        for ( ExportFactory expFac : allExpFactory )
+          if ( File.class.isAssignableFrom( expFac.getExportDestinationType() ) &&
+               expFac.isExportable( newValue ) )
+            expFactoryVec.add( expFac );
+        ExportFactory[] expFactory = expFactoryVec.toArray( new ExportFactory[0] );
+        String[]        expFactoryDesc = new String[expFactory.length];
+        for (int i=0; i<expFactoryDesc.length; i++)
+          expFactoryDesc[i] = expFactory[i].getName();
+        factoryOption.setSelectionObjects(expFactory,expFactoryDesc);
+      }
+    });
+
+    // etwaigen Default-Werte fuer Datenpool-Objekt erst jetzt setzen, damit
+    // Listener aufgerufen wird
+    dataPoolOption.setValue( defObject );
+    factoryOption.setValue( defExpFac );
+    fileOption.setValue( (File)defDestObj );
+
+    // Dialog erzeugen
+    Object[] input = MultipleOptionPane.showMultipleInputDialog(null,XuluConstants.XULUGUI_RES.getString("Handler"), new InputOption[] {
+        dataPoolOption,
+        factoryOption,
+        fileOption
+    });
+
+    // Dialog abgebrochen
+    if ( input == null || input.length < 3 )
+      return null;
+
+    // Wildcard "{number_format}" fuer Datei-Nummerierung aus
+    // Ziel-Dateinamen parsen und daraus ein NumberFormat erstellen
+    originalDestFile      = (File)input[2];
+    String exportFileName = originalDestFile.getAbsolutePath();
+    counterPatternMatcher = Pattern.compile("\\{.+\\}").matcher(exportFileName);
+    if ( counterPatternMatcher.find() ) {
+      String matchPattern = counterPatternMatcher.group();   // = "{000...00}"
+      String counterPattern = matchPattern.substring(1,matchPattern.length()-1); // = "000...00"
+      counterFormat = new DecimalFormat(counterPattern);
+    } else
+      counterFormat = null; // WICHTIG, da Variable auch als Flag verwendet wird!!
+
+    return input;
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/appl/GTVisualisationColorMapPlugin.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/appl/GTVisualisationColorMapPlugin.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/appl/GTVisualisationColorMapPlugin.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,249 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.appl;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.StringTokenizer;
+import java.awt.Color;
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+import org.geotools.styling.ColorMap;
+import org.geotools.styling.ColorMapImpl;
+
+import schmitzm.io.IOUtil;
+import schmitzm.lang.AbstractNamedObject;
+import schmitzm.data.event.ObjectListener;
+import schmitzm.data.event.ObjectEvent;
+import schmitzm.swing.SwingUtil;
+
+import schmitzm.geotools.gui.LayeredMapFrame;
+import schmitzm.geotools.styling.StylingUtil;
+import schmitzm.geotools.styling.ColorMapManager;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.gui.XuluGUIMessages;
+import edu.bonn.xulu.appl.XuluPlugin;
+import edu.bonn.xulu.appl.XuluPlugin;
+import edu.bonn.xulu.appl.VisualisationManager;
+// nur fuer Doku
+import edu.bonn.xulu.appl.VisualisationTool;
+import edu.bonn.xulu.plugin.vis.GTVisualisationTool;
+
+/**
+ * Dieses Plugin liest Farbpaletten aus der Datei <code>gtcolormaps.xif</code>
+ * und fuegt sie automatisch den {@link GTVisualisationTool}-Instanzen hinzu,
+ * sobald diese in Xulu geoeffnet werden. Die Datei muss im Verzeichnis
+ * "GTVisualisationColorMapPlugin" unterhalb des
+ * {@linkplain XuluModellingPlatform#getPluginDirectory() Xulu-Plugin-Verzeichnisses}
+ * abgelegt sein.<br><br>
+ * Die Datei kann mehrere Farbpaletten enthalten. Jede Farbpalette wird
+ * von einem <code>[..]</code>-Tag eingeleitet, wobei die Bezeichnung zwischen den
+ * Klammern als Name fuer die Farbpalette verwendet wird.
+ * Nach dem <code>[..]</code>-Tag folgen die Farbpaletten-Eintraege der Form
+ * <center><code><i>rasterwert</i> <i>color</i> [<i>label</i>]</code></center>
+ * Die Farbe kann auf mehrere Arten spezifiziert werden:
+ * <ol>
+ *   <li>Als RGB-Werte der Form <code>"RGB(<i>red</i>,<i>green</i>,<i>blue</i>)"</code>.<br>
+ *       Die RGB-Werte muessen durch Komma und OHNE Leerzeichen voneinander
+ *       getrennt sein.</li>
+ *   <li>Als dezimaler (1234) oder hexadezimaler Integer-Wert (0x123456),
+ *       aus dem die 3 RGB-Komponenten extrahiert werden.</li>
+ *   <li>Als String, der die Farbe identifiziert. Hierfuer sind alle
+ *       Farb-Bezeichnungen zulaessig, die in der Klasse {@link Color java.awt.Color}
+ *       als (statische) Felder deklariert sind.<br>
+ *       z.B. Black, Blue, Cyan, Gray, Green, Magenta, Orange, Pink,  Red, White,
+ *            Yellow</li>
+ * </ol>
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class GTVisualisationColorMapPlugin extends AbstractNamedObject implements XuluPlugin, ObjectListener {
+  /** Die Datei, aus der die {@linkplain ColorMap Farbpaletten} eingelesen werden
+   * (<code>gtcolormaps.xif</code>). */
+  public static final String INFILE = "GTVisualisationColorMapPlugin"+File.separatorChar+"gtcolormaps.xif";
+
+  /** Flag, ob das Plugin gestartet ist, oder nicht */
+  protected boolean started = false;
+
+  /** Speichert die aus der Datei eingelesenen Farbpaletten */
+  private Hashtable<String,ColorMap> colorMaps = new Hashtable<String,ColorMap>();
+  private String                     defaultColorMap = null;
+
+  /**
+   * Erzeugt eine neue Instanz des Plugins.
+   */
+  public GTVisualisationColorMapPlugin() {
+  }
+
+  /**
+   * Startet die Ausfuehrung des Plugins. Die {@linkplain ColorMap Farbpaletten}
+   * werden aus der Datei eingelesen
+   * @param appl Instanz der Xulu-Applikation
+   */
+  public void execute(XuluModellingPlatform appl) {
+    started = true;
+    try {
+      readColorMapsFromFile(new File(appl.getPluginDirectory(),INFILE));
+    } catch (Exception err) {
+      XuluGUIMessages.showError(appl.getMainFrame(), err, "Plugin execution of "+getClass().getSimpleName()+" aborted!");
+      stop();
+    }
+    if ( !appl.getVisualisationManager().containsObjectListener(this) )
+      appl.getVisualisationManager().addObjectListener( this );
+  }
+
+  /**
+   * Wird aufgerufen, wenn sich der Inhalt des {@link VisualisationManager Xulu-Visualisierungsmanagers}
+   * aendert. Wurde ein neues {@link GTVisualisationTool} hinzugefuegt (oder ein
+   * anderers von {@link LayeredMapFrame} abgeleitetes Tool), werden dessen
+   * Farbpaletten alle eingelesenen Paletten hinzugefuegt.
+   * @param e Ereignis
+   */
+  public void performObjectEvent(ObjectEvent e) {
+    if ( !isStarted() || !(e instanceof VisualisationManager.ChangeEvent) )
+      return;
+    VisualisationManager.ChangeEvent event = (VisualisationManager.ChangeEvent)e;
+    // ColorMaps nur hinzufuegen, wenn VisualisationTool neu hinzugefuegt
+    // wurde und wenn es sich um ein GTVisualisationTool handelt
+    if ( event.getOldValue()==null && event.getNewValue()!=null && event.getNewValue() instanceof GTVisualisationTool ) {
+      ColorMapManager colorMapManager = ((GTVisualisationTool)event.getNewValue()).getLayeredMapFrame().getLayeredMapPane().getColorMapManager();
+      Enumeration<String> colorMapNames = colorMaps.keys();
+      for (; colorMapNames.hasMoreElements();) {
+        String name = colorMapNames.nextElement();
+        boolean isDefault = name.equals(defaultColorMap);
+        colorMapManager.put(name,colorMaps.get(name),isDefault);
+      }
+    }
+  }
+
+  /**
+   * Prueft, ob das Plugin gestartet ist.
+   */
+  public boolean isStarted() {
+    return started;
+  }
+
+  /**
+   * Prueft, ob die GUI zur Plugin-Konfiguration angezeigt wird.
+   * @return immer <code>false</code>, da das Plugin keine eigene GUI besitzt
+   */
+  public boolean isVisible() {
+    return false;
+  }
+
+  /**
+   * Macht nichts, da das Plugin keine GUI besitzt.
+   */
+  public void setVisible(boolean visible) {
+  }
+
+  /**
+   * Stoppt die Ausfuehrung des Plugins. Neuen Visualisierungs-Fenstern werden
+   * keine Farbpaletten mehr hinzugefuegt.
+   */
+  public void stop() {
+    started = false;
+  }
+
+  /**
+   * Liest die Farbpaletten aus einer Datei.
+   * @param inFile Eingabe-Datei
+   */
+  private void readColorMapsFromFile(File inFile) throws Exception {
+    colorMaps.clear();
+    BufferedReader input  = new BufferedReader( new FileReader(inFile) );
+    String   line         = null;
+    int      lineNo       = 0;
+    ColorMap colorMap     = null;
+    String   colorMapName = null;
+    for(lineNo=1; input.ready() && (line=input.readLine().trim())!=null; lineNo++ ) {
+      // Kommentarzeilen und Leerzeilen uebergehen
+      if ( line.equals("") || IOUtil.isCommentLine(line) )
+        continue;
+
+      // Bei einem [<name>]-Tag beginnt eine neue ColorMap mit dem Namen <name>
+      if ( line.startsWith("[") && line.endsWith("]") ) {
+        colorMapName = line.substring(1,line.length()-1);
+        colorMap     = new ColorMapImpl();
+        colorMap.setType(ColorMap.TYPE_VALUES);
+        colorMaps.put(colorMapName,colorMap);
+        continue;
+      }
+
+      // Beim Tag DEFAULT wird die aktuelle ColorMap als Standard festgelegt
+      if ( line.equals("DEFAULT") ) {
+        defaultColorMap = colorMapName;
+        continue;
+      }
+
+      // Ansonsten Zeile als ColorMapEntry interpretieren:
+      //     <Quantity> <Color> [<Label>]
+      if ( colorMap == null )
+        throw new IOException("Line "+lineNo+": ColorMapEnty outside of [..]-section");
+      StringTokenizer tok      = new StringTokenizer(line);
+      Double          quantity = null;
+      Color           color    = null;
+      String          label    = "";
+      // 1) Wert
+      try {
+        quantity = Double.parseDouble(tok.nextToken());
+      } catch (Exception err) {
+        String mess = "Line "+lineNo+": Quantity expected (double value) >> ";
+        if ( err.getMessage() == null || err.getMessage().trim().equals("") )
+          mess = mess + err.getClass().getSimpleName();
+        else
+          mess = mess + err.getMessage();
+        throw new Exception(mess);
+      }
+      // 2) Farbe
+      try {
+        color = SwingUtil.parseColor(tok.nextToken());
+      } catch (Exception err) {
+        String mess = "Line "+lineNo+": Color specification expected (rgb or color name) >> ";
+        if ( err.getMessage() == null || err.getMessage().trim().equals("") )
+          mess = mess + err.getClass().getSimpleName();
+        else
+          mess = mess + err.getMessage();
+        throw new Exception(mess);
+      }
+      // 3) Label (optional)
+      try {
+        String labelStr = tok.nextToken("#\n").trim();
+        if ( !IOUtil.isCommentLine(labelStr) )
+          label = labelStr;
+      } catch (Exception err) {
+        // Label ignorieren (wenn keine Token mehr uebrig sind)
+        label = "";
+      }
+
+      // neuen Eintrag in der Farbpalette aufnehmen
+      colorMap.addColorMapEntry( StylingUtil.createColorMapEntry(label,quantity,color,1.0) );
+    }
+// TEST
+//    colorMaps.put("B/W", StylingUtil.builder.createColorMap(
+//      new String[] { "","" },
+//      new double[] { 0f,  999f },
+//      new Color[]  { Color.BLACK, Color.WHITE },
+//      ColorMap.TYPE_VALUES
+//    ));
+//    colorMaps.put("Test", StylingUtil.builder.createColorMap(
+//      new String[] { "","","","","","" },
+//      new double[] { 0f,  1f,  2f,  3f,  4f, 5f },
+//      new Color[]  { Color.BLUE, Color.GRAY,Color.YELLOW,Color.RED,Color.CYAN, Color.MAGENTA },
+//      ColorMap.TYPE_VALUES
+//    ));
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/appl/GeoModelCodeGenerator.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/appl/GeoModelCodeGenerator.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/appl/GeoModelCodeGenerator.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,511 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.appl;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+
+import java.util.Vector;
+import java.util.StringTokenizer;
+import java.util.Arrays;
+import java.util.Comparator;
+
+import schmitzm.lang.LangUtil;
+import schmitzm.io.dyntxt.DynamicTextGenerator;
+import schmitzm.io.dyntxt.DynamicInputProvider;
+import schmitzm.io.dyntxt.DynamicField;
+import schmitzm.io.dyntxt.DynamicLoop;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.PropertyWriteAccess;
+import schmitzm.data.property.ListPropertyReadAccess;
+import schmitzm.data.property.ListPropertyWriteAccess;
+import schmitzm.data.property.ValueProperty;
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.MatrixProperty;
+import schmitzm.temp.BaseTypeUtil;
+
+import edu.bonn.xulu.model.XuluModel;
+import edu.bonn.xulu.model.AbstractXuluModel;
+import edu.bonn.xulu.model.StepModel;
+import edu.bonn.xulu.model.AbstractStepModel;
+import edu.bonn.xulu.model.AbstractModelContentManager;
+import edu.bonn.xulu.model.ModelResource;
+import edu.bonn.xulu.model.ValuePropertyResource;
+import edu.bonn.xulu.model.PropertiesResource;
+// nur fuer Doku
+import edu.bonn.xulu.model.ModelContentManager;
+
+/**
+ * Diese Klasse stellt einen Sourcecode-Generator dar, mit dem ein Grundgeruest
+ * fuer {@link XuluModel}- und {@link StepModel}-Klassen (mit entsprechendem
+ * {@link ModelContentManager}) erzeugt werden koennen.<br>
+ * Der Generator basiert auf folgenden Vorlagen-Dateien:
+ * <ul>
+ *   <li>{@link #XULUMODEL_TEMPLATE_FILENAME XuluModel.tpl}</li>
+ *   <li>{@link #STEPMODEL_TEMPLATE_FILENAME StepModel.tpl}</li>
+ *   <li>{@link #CM_TEMPLATE_FILENAME        ModelContentManager.tpl}</li>
+ * </ul>
+ * Das Verzeichnis, aus dem die Dateien gezogen werden, wird im Konstruktor
+ * angegeben.<br>
+ * Auf Basis von
+ * <ul>
+ *   <li>Modell-Name</li>
+ *   <li>Modell-Art (Oberklasse vom Typ {@link XuluModel})</li>
+ *   <li>Package-Name</li>
+ *   <li>Klassen-Verzeichnis</li>
+ *   <li>Einer Liste von Ressourcen und Variablen-Namen</li>
+ * </ul>
+ * wird aus den Vorlagen-Dateien eine Klasse für den {@linkplain ModelContentManager ContentManager}
+ * und eine Klasse fuer das {@linkplain XuluModel Xulu-Modell} erzeugt, in denen
+ * die Ressourcen-Spezifikation, das Ressourcen-Handling, sowie deren Referenzierung
+ * in lokalen Variablen bereits implementiert ist.<br>
+ * Der Modell-Entwickler (unmittelbar) mit der Programmierung des
+ * Modell-Algorithmus (z.B. in {@link StepModel#performModelStep(int)}) beginnen.
+ * @see schmitzm.io.dyntxt.DynamicTextGenerator
+ * @see schmitzm.io.dyntxt.DynamicInputProvider
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class GeoModelCodeGenerator {
+  /** Name der Vorlagen-Datei fuer {@link XuluModel}. */
+  public static final String XULUMODEL_TEMPLATE_FILENAME = "XuluModel.tpl";
+  /** Name der Vorlagen-Datei fuer {@link StepModel}. */
+  public static final String STEPMODEL_TEMPLATE_FILENAME = "StepModel.tpl";
+  /** Vorlagen-Datei fuer {@link ModelContentManager}. */
+  public static final String CM_TEMPLATE_FILENAME        = "ModelContentManager.tpl";
+
+  private File                     tplDir = null;
+  private File                     modelFile = null;
+  private File                     cmFile = null;
+  private String                   modelName = null;
+  private String                   packageName = null;
+  private Class<XuluModel>         modelClass = null;
+  private ModelResource[]          resource = null;
+  private String[]                 resourceVarName = null;
+  private ValuePropertyResource[]  propResource = null;
+  private Integer[]                propResourceRefIdx = null;
+  private Class[]                  neededImports = null;
+  private DynamicInputProvider     inputProvider = null;
+
+
+  /**
+   * Erzeugt einen neuen ModellCode-Generator.
+   * @param modelName       Name des Modells (darf keine Leer/Sonderzeichen enthalten)
+   * @param packageName     Name des Pakets in dem Modell und ContentManager
+   *                        implementiert werden
+   * @param classDir File   Pfad unterhalb dem die Klassen abgelegt werden
+   * @param modelClass      Typ der Modell-Klasse (nur {@link StepModel} oder {@link XuluModel} erlaubt)
+   * @param resource        fuer das Modell benoetigte Ressourcen
+   * @param resourceVarName Variablen-Namen fuer die modell-Internen Referenzen
+   *                        auf die Ressourcen
+   * @param tplDir          Verzeichnis, in dem die Vorlagen-Dateien zur Code-Generierung
+   *                        zu finden sind
+   */
+  public GeoModelCodeGenerator(String modelName, String packageName, File classDir, Class<XuluModel> modelClass, ModelResource[] resource, String[] resourceVarName, File tplDir) {
+    checkInputs(modelName,packageName,classDir,modelClass,resource,resourceVarName,tplDir);
+    this.tplDir          = tplDir;
+    this.modelFile       = new File(classDir, packageName.replace('.',File.separatorChar) + File.separator + modelName + ".java");
+    this.cmFile          = new File(classDir, packageName.replace('.',File.separatorChar) + File.separator + modelName + "ContentManager.java");
+    this.modelName       = modelName;
+    this.packageName     = packageName;
+    this.modelClass      = modelClass;
+    this.resource        = resource;
+    this.resourceVarName = resourceVarName;
+    // Property-Ressourcen werden an einigen Stellen anders behandelt
+    // -> Ressoucen und Referenz-Index auf normale Ressourcen-Arrays isolieren
+    Vector<ValuePropertyResource> propRes       = new Vector<ValuePropertyResource>();
+    Vector<Integer>               propResRefIdx = new Vector<Integer>();
+    for (int i=0; i<resource.length; i++)
+      if ( resource[i] instanceof ValuePropertyResource ) {
+        propRes.add( (ValuePropertyResource)resource[i] );
+        propResRefIdx.add( i );
+      }
+    this.propResource        = propRes.toArray( new ValuePropertyResource[0] );
+    this.propResourceRefIdx  = propResRefIdx.toArray( new Integer[0] );
+
+    // InputProvider fuer die Template-Dateien
+    inputProvider = new GeoModelInputProvider();
+  }
+
+  /**
+   * Prueft die Parameter des Konstruktors auf Korrektheit
+   * @param modelName       Name des Modells (darf keine Leer/Sonderzeichen enthalten)
+   * @param packageName     Name des Pakets in dem Modell und ContentManager
+   *                        implementiert werden
+   * @param classDir File   Pfad unterhalb dem die Klassen abgelegt werden
+   * @param modelClass      Typ der Modell-Klasse (nur {@link StepModel} oder {@link XuluModel} erlaubt)
+   * @param resource        fuer das Modell benoetigte Ressourcen
+   * @param resourceVarName Variablen-Namen fuer die modell-Internen Referenzen
+   *                        auf die Ressourcen
+   * @exception IllegalArgumentException falls ein Parameter nicht korrekt ist
+   */
+  protected void checkInputs(String modelName, String packageName, File classDir, Class<XuluModel> modelClass, ModelResource[] resource, String[] resourceVarName, File tplDir) {
+    // Verzeichnis fuer Vorlagen-Dateien muss existieren
+    if ( tplDir == null || !tplDir.isDirectory() || !tplDir.exists() )
+      throw new IllegalArgumentException("Directory for template files does not exist: "+(tplDir == null ? "null" : tplDir.getAbsolutePath()));
+    // Modell-Namen pruefen
+    try {
+      LangUtil.checkIdentifierAndError(modelName);
+    } catch (Exception err) {
+      throw new IllegalArgumentException("Illegal model name: "+err.getMessage());
+    }
+
+    // Paket-Namen pruefen
+    try {
+      if ( packageName.startsWith(".") || packageName.endsWith(".") )
+        throw new IllegalArgumentException("'.' not allowed as first or last charakter!");
+      StringTokenizer tok = new StringTokenizer(packageName);
+      for (;tok.hasMoreTokens();)
+        LangUtil.checkIdentifierAndError(tok.nextToken(".\n"));
+    } catch (Exception err) {
+      throw new IllegalArgumentException("Illegal package name: "+err.getMessage());
+    }
+
+    // nur XuluModel oder StepModel zugelassen als Modell-Typ
+    if ( modelClass == null )
+      throw new IllegalArgumentException("NULL not allowed for model type!");
+    if ( !modelClass.equals( XuluModel.class ) &&
+         !modelClass.equals( StepModel.class ) )
+      throw new IllegalArgumentException("Only XuluModel or StepModel allowed for model type!");
+
+    // Ressourcen-Array und Variablennamen-Array muessen dieselbe Laenge haben
+    if ( resource == null )
+      throw new IllegalArgumentException("Resource array required (NULL not allowed)");
+    if ( resourceVarName == null )
+      throw new IllegalArgumentException("Variable name array required (NULL not allowed)");
+    if ( resource.length != resourceVarName.length )
+      throw new IllegalArgumentException("Arrays for resources and variable names must have the same length");
+
+    // Variablen-Namen muessen Identifier sein
+    int i = -1;
+    try {
+      for (i=0; i<resourceVarName.length; i++)
+        LangUtil.checkIdentifierAndError(resourceVarName[i]);
+    } catch (Exception err) {
+      throw new IllegalArgumentException("Illegal variable name '"+resourceVarName[i]+"': "+err.getMessage());
+    }
+  }
+
+  /**
+   * Fuehrt die Generierung der Quell-Dateien fuer ContentManager und Modell aus.
+   * @exception Exception wenn irgendein Fehler auftritt
+   */
+  public void generateSource() throws Exception {
+    modelFile.getParentFile().mkdirs(); // Verzeichnisstruktur erzeugen
+    generateModelContentManagerClass();
+    generateModelClass();
+  }
+
+  /**
+   * Generierung der Content-Manager-Klasse.
+   * @exception Exception wenn irgendein Fehler auftritt
+   */
+  private void generateModelContentManagerClass() throws Exception {
+    // Fuer ContentManager benoetigte Import-Klassen bestimmen
+    Vector<Class> neededImp = new Vector<Class>();
+    neededImp.add( AbstractModelContentManager.class );
+    neededImp.add( ModelResource.class );
+
+    for (int i=0; i<resource.length; i++) {
+      // Basis-Klassen fuer Ressourcen
+      if ( resource[i] instanceof PropertiesResource && !neededImp.contains( PropertiesResource.class ) )
+        neededImp.add( PropertiesResource.class );
+      if ( resource[i] instanceof ValuePropertyResource && !neededImp.contains( ValuePropertyResource.class ) )
+        neededImp.add( ValuePropertyResource.class );
+      // Ressourcen-Typ
+      if ( !neededImp.contains( resource[i].getType() ) )
+        neededImp.add( resource[i].getType() );
+      // Datentyp eine ValuePropertyResource
+      if ( resource[i] instanceof ValuePropertyResource &&
+          !BaseTypeUtil.isBaseType(((ValuePropertyResource)resource[i]).getPropertyType().getType()) &&
+          !neededImp.contains( ((ValuePropertyResource)resource[i]).getPropertyType().getType() ) )
+        neededImp.add( ((ValuePropertyResource)resource[i]).getPropertyType().getType() );
+    }
+    neededImports = neededImp.toArray(new Class[0]);
+    sortClassesByName( neededImports );
+
+    // Ausgabe-Datei fuer den Content-Manager erzeugen
+    FileInputStream  template = new FileInputStream( new File(tplDir,CM_TEMPLATE_FILENAME) );
+    FileOutputStream output   = new FileOutputStream(cmFile);
+    new DynamicTextGenerator(template).generateDynamicText(output,inputProvider);
+    output.flush();
+    output.close();
+
+    // Klasse kompilieren
+//    System.out.println( packageName+"."+modelName+".java --> "+ Compiler.compileClasses(packageName+"."+modelName+".java") );
+  }
+
+  /**
+   * Generierung der Modell-Klasse.
+   * @exception Exception wenn irgendein Fehler auftritt
+   */
+  private void generateModelClass() throws Exception  {
+      // Fuer Modell benoetigte Import-Klassen bestimmen
+      Vector<Class> neededImp = new Vector<Class>();
+      neededImp.add( modelClass.equals(StepModel.class) ? AbstractStepModel.class : AbstractXuluModel.class );
+      for (int i=0; i<resource.length; i++) {
+        // Basis-Klassen fuer Ressourcen
+        if ( resource[i] instanceof ValuePropertyResource ) {
+          if ( ScalarProperty.class.isAssignableFrom(resource[i].getType()) ||
+               MatrixProperty.class.isAssignableFrom(resource[i].getType()) ) {
+            if ( !neededImp.contains( PropertyReadAccess.class ) )
+              neededImp.add( PropertyReadAccess.class );
+            if ( !neededImp.contains( PropertyWriteAccess.class ) )
+              neededImp.add( PropertyWriteAccess.class );
+          }
+          if ( ListProperty.class.isAssignableFrom(resource[i].getType())  ) {
+            if ( !neededImp.contains( ListPropertyReadAccess.class ) )
+              neededImp.add( ListPropertyReadAccess.class );
+            if ( !neededImp.contains( ListPropertyWriteAccess.class ) )
+              neededImp.add( ListPropertyWriteAccess.class );
+          }
+        }
+        // Ressourcen-Typ
+        if ( !neededImp.contains( resource[i].getType() ) )
+          neededImp.add( resource[i].getType() );
+        // Datentyp eine ValuePropertyResource
+        if ( resource[i] instanceof ValuePropertyResource &&
+            !BaseTypeUtil.isBaseType(((ValuePropertyResource)resource[i]).getPropertyType().getType()) &&
+            !neededImp.contains( ((ValuePropertyResource)resource[i]).getPropertyType().getType() ) )
+          neededImp.add( ((ValuePropertyResource)resource[i]).getPropertyType().getType() );
+      }
+      neededImports = neededImp.toArray(new Class[0]);
+      sortClassesByName( neededImports );
+
+      // Ausgabe-Datei fuer die Modell-Klasse erzeugen
+      String modelTemplateFileName = modelClass.equals(StepModel.class) ? STEPMODEL_TEMPLATE_FILENAME : XULUMODEL_TEMPLATE_FILENAME;
+      FileInputStream  template = new FileInputStream( new File(tplDir,modelTemplateFileName) );
+      FileOutputStream output   = new FileOutputStream( modelFile );
+      new DynamicTextGenerator(template).generateDynamicText(output,inputProvider);
+      output.flush();
+      output.close();
+  }
+
+  private class GeoModelInputProvider implements DynamicInputProvider {
+    /**
+     * Definiert die Ersetzung der {@link DynamicTextGenerator}-Felder.
+     * @param field zu verarbeitendes Feld
+     * @exception UnsupportedOperationException falls das uebergebene Feld nicht
+     *            verarbeitet werden kann
+     */
+    public String performField(DynamicField field) {
+      // Java-Paket, in dem Modell und Content-Manager implementiert sind
+      if (field.getID().equalsIgnoreCase("Package"))
+        return packageName;
+      // Ein benoetigter Klassen-Import (innerhalb der ClassImport-Schleife)
+      if (field.getID().equalsIgnoreCase("ClassImport"))
+        return neededImports[ ( (DynamicLoop) field.getFather(DynamicLoop.class)).
+            getActualLoop()].getName();
+      // Modell-Name (= Klassenname+Konstruktor des Modells)
+      if (field.getID().equalsIgnoreCase("ModelName"))
+        return modelName;
+      // Modell-OberKlasse
+      if (field.getID().equalsIgnoreCase("ModelSuperClass"))
+        return modelClass.equals(StepModel.class) ? "AbstractStepModel" : "AbstractXuluModel";
+      // ContentManager-Name (= Klassenname+Konstruktor des Content-Manager)
+      if (field.getID().equalsIgnoreCase("ModelCMName"))
+        return modelName + "ContentManager";
+      // ContentManager-OberKlasse
+      if (field.getID().equalsIgnoreCase("ModelCMSuperClass"))
+        return "AbstractModelContentManager";
+      // Anzahl an Ressourcen
+      if (field.getID().equalsIgnoreCase("ResourceCount"))
+        return String.valueOf(resource.length);
+      // Nummer einer Ressource (innerhalb einer Schleife ueber die Resourcen)
+      if (field.getID().equalsIgnoreCase("ResourceNo"))
+        return String.valueOf( ( (DynamicLoop) field.getFather(DynamicLoop.class)).getActualLoop());
+      // Beschreibung einer Ressource (innerhalb einer Schleife ueber die Resourcen)
+      if (field.getID().equalsIgnoreCase("ResourceDesc"))
+        return resource[ ( (DynamicLoop) field.getFather(DynamicLoop.class)).getActualLoop()].getDesc();
+      // Variable einer Ressource (innerhalb einer Schleife ueber die Resourcen)
+      if (field.getID().equalsIgnoreCase("ResourceVar"))
+        return resourceVarName[ ( (DynamicLoop) field.getFather(DynamicLoop.class)).getActualLoop()];
+      // Typ einer Ressource (innerhalb einer Schleife ueber die Resourcen)
+      if (field.getID().equalsIgnoreCase("ResourceType"))
+        return resource[ ( (DynamicLoop) field.getFather(DynamicLoop.class)).getActualLoop()].getType().getSimpleName();
+      // Instanziierung einer Ressource (innerhalb einer Schleife ueber die Resourcen)
+      if (field.getID().equalsIgnoreCase("ResourceDefinition")) {
+        int idx = ( (DynamicLoop) field.getFather(DynamicLoop.class)).getActualLoop();
+        StringBuffer buffer = new StringBuffer();
+        if (resource[idx] instanceof ValuePropertyResource) {
+          buffer.append("new ValuePropertyResource(")
+                .append(getResourceCategoryString(resource[idx])).append(",")
+                .append("\"").append(resource[idx].getDesc()).append("\",")
+                .append(resource[idx].getType().getSimpleName()).append(".class,")
+                .append( ( (ValuePropertyResource) resource[idx]).getPropertyType().getType().getSimpleName()).append(".class,")
+                .append(resource[idx].isNullable())
+                .append(")");
+          return buffer.toString();
+        }
+        if (resource[idx] instanceof PropertiesResource) {
+          buffer.append("new PropertiesResource(")
+                .append(getResourceCategoryString(resource[idx])).append(",")
+                .append("\"").append(resource[idx].getDesc()).append("\",")
+                .append(resource[idx].getType().getSimpleName()).append(".class,")
+                .append(resource[idx].isNullable())
+                .append(")");
+          return buffer.toString();
+        }
+      }
+      // Deklaration der Access-Variable zu einer Ressource (innerhalb einer Schleife
+      // ueber die Property-Resourcen)
+      if (field.getID().equalsIgnoreCase("ResourceAccessType")) {
+        int idx = ( (DynamicLoop) field.getFather(DynamicLoop.class)).getActualLoop();
+        if (categoryHandledByWriteAccess(propResource[idx].getCategory()))
+          return ListProperty.class.isAssignableFrom(propResource[idx].getType()) ? "ListPropertyWriteAccess" : "PropertyWriteAccess";
+        else
+          return ListProperty.class.isAssignableFrom(propResource[idx].getType()) ? "ListPropertyReadAccess" : "PropertyReadAccess";
+      }
+      if (field.getID().equalsIgnoreCase("ResourceAccessVar")) {
+        int idx = ( (DynamicLoop) field.getFather(DynamicLoop.class)).getActualLoop();
+        if (categoryHandledByWriteAccess(propResource[idx].getCategory()))
+          return "WA_" + resourceVarName[propResourceRefIdx[idx]];
+        else
+          return "RA_" + resourceVarName[propResourceRefIdx[idx]];
+      }
+      if (field.getID().equalsIgnoreCase("PropertyResourceDesc"))
+        return propResource[ ( (DynamicLoop) field.getFather(DynamicLoop.class)).getActualLoop()].getDesc();
+      if (field.getID().equalsIgnoreCase("PropertyResourceNo"))
+        return String.valueOf(propResourceRefIdx[ ( (DynamicLoop) field.getFather(DynamicLoop.class)).getActualLoop()]);
+      if (field.getID().equalsIgnoreCase("PropertyResourceType"))
+        return propResource[ ( (DynamicLoop) field.getFather(DynamicLoop.class)).getActualLoop()].getType().getSimpleName();
+      // Deklaration der Zugriffs-Variable zu einer Ressource (innerhalb einer Schleife
+      // ueber die Resourcen)
+      if (field.getID().equalsIgnoreCase("ResourceVarType")) {
+        int idx = ( (DynamicLoop) field.getFather(DynamicLoop.class)).getActualLoop();
+        // Nicht-Property-Ressource werden direkt ueber das Objekt angesprochen
+        if (! (resource[idx] instanceof ValuePropertyResource))
+          return resource[idx].getType().getSimpleName();
+        ValuePropertyResource propRes = (ValuePropertyResource) resource[idx];
+        // Aus skalaren Propertys, die keinen Basis-Typ beinhalten, wird das
+        // Objekt herausgeholt
+        if (ScalarProperty.class.isAssignableFrom(propRes.getType()) &&
+            !BaseTypeUtil.isBaseType(propRes.getPropertyType().getType()))
+          return propRes.getPropertyType().getType().getSimpleName();
+        // Andernfalls wird ueber das Lese/Schreibrecht auf die Property zugegriffen
+        if (ListProperty.class.isAssignableFrom(propRes.getType()))
+          return categoryHandledByWriteAccess(propRes.getCategory()) ? "ListPropertyWriteAccess" : "ListPropertyReadAccess";
+        else
+          return categoryHandledByWriteAccess(propRes.getCategory()) ? "PropertyWriteAccess" : "PropertyReadAccess";
+      }
+      // Wertzuweisung an die Access-Variable einer Ressource (innerhalb einer Schleife
+      // ueber die Property-Resourcen)
+      if (field.getID().equalsIgnoreCase("ResourceAccessAlloc")) {
+        int idx = ( (DynamicLoop) field.getFather(DynamicLoop.class)).getActualLoop();
+        if (categoryHandledByWriteAccess(propResource[idx].getCategory()))
+          return ".getWriteAccess(this)";
+        else
+          return ".getReadAccess(this)";
+      }
+      // Wertzuweisung an die Zugriffs-Variable einer Ressource (innerhalb einer Schleife
+      // ueber die Resourcen)
+      if (field.getID().equalsIgnoreCase("ResourceVarAlloc")) {
+        int idx = ( (DynamicLoop) field.getFather(DynamicLoop.class)).getActualLoop();
+        // Nicht-Property-Ressource werden direkt ueber das Objekt angesprochen
+        if (! (resource[idx] instanceof ValuePropertyResource))
+          return "(" + resource[idx].getType().getSimpleName() + ")contManager.getResource(" + idx + ").getData()";
+        ValuePropertyResource propRes = (ValuePropertyResource) resource[idx];
+        // Aus skalaren Propertys, die keinen Basis-Typ beinhalten, wird das
+        // Objekt herausgeholt
+        if (ScalarProperty.class.isAssignableFrom(propRes.getType()) &&
+            !BaseTypeUtil.isBaseType(propRes.getPropertyType().getType())) {
+          StringBuffer buffer = new StringBuffer();
+          buffer.append("(")
+                .append(propRes.getPropertyType().getType().getSimpleName())
+                .append(")")
+                .append(categoryHandledByWriteAccess(propRes.getCategory()) ? "WA_" : "RA_")
+                .append(resourceVarName[idx])
+                .append(".getValue()");
+          return buffer.toString();
+        }
+        // Andernfalls wird ueber das Lese/Schreibrecht auf die Property zugegriffen
+        StringBuffer buffer = new StringBuffer();
+        buffer.append(categoryHandledByWriteAccess(propRes.getCategory()) ? "WA_" : "RA_")
+              .append(resourceVarName[idx]);
+        return buffer.toString();
+      }
+
+      // Unbekanntes Feld
+      throw new UnsupportedOperationException("Unknown field-ID: " + field.getID());
+    }
+
+    /**
+     * Definiert das Abbruch-Kriterium der {@link DynamicTextGenerator}-Schleifen.
+     * @param field zu verarbeitende Schleife
+     * @exception UnsupportedOperationException falls die uebergebene Schleife nicht
+     *            verarbeitet werden kann
+     */
+    public boolean performLoop(DynamicLoop loop) {
+      // Schleife fuer alle zu importierenden Klassen
+      if (loop.getID().equalsIgnoreCase("ClassImport"))
+        return loop.getActualLoop() < neededImports.length;
+      // Schleife ueber alle Ressourcen
+      if (loop.getID().equalsIgnoreCase("Resources"))
+        return loop.getActualLoop() < resource.length;
+      // Schleife ueber alle Property-Ressourcen
+      if (loop.getID().equalsIgnoreCase("PropertyResources"))
+        return loop.getActualLoop() < propResource.length;
+
+      throw new UnsupportedOperationException("Unknown loop-ID: " + loop.getID());
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////////
+  ////////////////////   statische Hilfsmethoden   ////////////////////////
+  /////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft anhand der Ressourcen-Kategorie, ob eine Ressource ueber ein
+   * Schreibrecht angesprochen wird
+   * @param category Ressourcen-Kategorie
+   */
+  private static boolean categoryHandledByWriteAccess(int category) {
+    return (category & (ModelResource.CATEGORY_OUTPUT | ModelResource.CATEGORY_TEMP)) > 0 ||
+            category == ModelResource.CATEGORY_OTHER;
+  }
+
+  /**
+   * Liefert die Bezeichnung einer Kategorie-Konstante fuer eine Modell-Ressource.
+   * @param resource Model-Ressource
+   */
+  public static String getResourceCategoryString(ModelResource resource) {
+    StringBuffer catString = new StringBuffer();
+    if ( resource.isCategory( ModelResource.CATEGORY_INPUT ) )
+      catString.append( "ModelResource.CATEGORY_INPUT" );
+    if ( resource.isCategory( ModelResource.CATEGORY_OUTPUT ) )
+      catString.append( catString.length() > 0 ? " | " : "").append( "ModelResource.CATEGORY_OUTPUT" );
+    if ( resource.isCategory( ModelResource.CATEGORY_TEMP ) )
+      catString.append( catString.length() > 0 ? " | " : "").append( "ModelResource.CATEGORY_TEMP" );
+    if ( resource.isCategory( ModelResource.CATEGORY_OTHER ) )
+      catString.append( catString.length() > 0 ? " | " : "").append( "ModelResource.CATEGORY_OTHER" );
+    return catString.toString();
+  }
+
+  /**
+   * Sortiert einen Array von Klassen nach der natuerlichen Sortierung ihrer
+   * Namen (inklusive Package).
+   * @param clazz Klassen
+   * @see Class#getName()
+   */
+  public static void sortClassesByName(Class[] clazz) {
+    Arrays.sort( clazz, new Comparator<Class>() {
+      public int compare(Class c1, Class c2) {
+        if ( c1 == null )
+          return -1;
+        return c1.getName().compareTo(c2.getName());
+      }
+    });
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/appl/GeoModelCodeGeneratorGUI.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/appl/GeoModelCodeGeneratorGUI.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/appl/GeoModelCodeGeneratorGUI.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,729 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.appl;
+
+import java.io.File;
+import java.awt.Dimension;
+import java.awt.GridBagLayout;
+import java.awt.GridBagConstraints;
+import java.awt.Insets;
+import java.awt.Container;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.KeyAdapter;
+import javax.swing.JLabel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+import javax.swing.JComboBox;
+import javax.swing.JCheckBox;
+import javax.swing.JButton;
+import javax.swing.JFileChooser;
+import javax.swing.ListSelectionModel;
+import javax.swing.DefaultCellEditor;
+import java.util.Vector;
+
+import org.geotools.feature.FeatureCollection;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.ValueProperty;
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.MatrixProperty;
+import schmitzm.lang.LangUtil;
+import schmitzm.swing.SwingUtil;
+import schmitzm.swing.SwingWorker;
+import schmitzm.swing.InputOption;
+import schmitzm.swing.MultipleOptionPane;
+import schmitzm.swing.ManualInputOption;
+import schmitzm.swing.FileInputOption;
+import schmitzm.swing.BooleanInputOption;
+import schmitzm.swing.SelectionInputOption;
+import schmitzm.swing.event.InputOptionAdapter;
+import schmitzm.swing.table.AbstractMutableTableModel;
+import schmitzm.swing.table.MutableTable;
+import schmitzm.swing.table.MutableTableModel;
+import schmitzm.swing.table.ComponentRenderer;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.XuluConstants;
+import edu.bonn.xulu.gui.XuluInternalFrame;
+import edu.bonn.xulu.gui.XuluGUIMessages;
+import edu.bonn.xulu.model.ModelResource;
+import edu.bonn.xulu.model.ValuePropertyResource;
+import edu.bonn.xulu.model.PropertiesResource;
+import edu.bonn.xulu.model.StepModel;
+import edu.bonn.xulu.model.XuluModel;
+
+// nur fuer Doku
+import javax.swing.table.TableModel;
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.model.ModelContentManager;
+import edu.bonn.xulu.plugin.appl.GeoModelCodeGeneratorPlugin;
+
+/**
+ * Diese Klasse stellt eine GUI zur Vefuegung, mit der der {@link GeoModelCodeGenerator}
+ * gesteuert werden kann. Sie ist als {@linkplain XuluInternalFrame internes}
+ * Fenster der {@linkplain XuluModellingPlatform Xulu-Modelling-Platform}
+ * realisiert. Ueber das Xulu-Plugin {@link GeoModelCodeGeneratorPlugin} wird
+ * sie automatisch in das Xulu-Menue eingebunden.<br>
+ * Ueber die GUI spezifiert der Modell-Entwickler
+ * <ul>
+ *   <li>den Modell-Typ</li>
+ *   <li>den Modell-Namen</li>
+ *   <li>die zur Modelllierung benoetigten Ressourcen</li>
+ *   <li>Variablennamen, ueber die die Ressourcen Modell-<b>intern</b>
+ *       angesprochen werden sollen</li>
+ * </ul>
+ * Daraus erzeugt der {@link GeoModelCodeGenerator} je eine Java-Klasse (als
+ * Source-Code) fuer {@linkplain ModelContentManager Content-Manager} und
+ * {@linkplain XuluModel Xulu-Modell}, in denen die Ressourcen-Spezifikation,
+ * das Ressourcen-Handling, sowie deren Referenzierung in lokalen Variablen
+ * bereits implementiert ist.<br>
+ * Der Modell-Entwickler (unmittelbar) mit der Programmierung des
+ * Modell-Algorithmus (z.B. in {@link StepModel#performModelStep(int)}) beginnen.<br>
+ * Der {@link GeoModelCodeGenerator} benoetigt einige Vorlagen-Dateien, aus denen
+ * der Sourcecode generiert wird. Diese muessen im Verzeichnis "GeoModelCodeGenerator"
+ * unterhalb des {@linkplain XuluModellingPlatform#getPluginDirectory() Xulu-Plugin-Verzeichnisses}
+ * abgelegt sein.
+ * @see GeoModelCodeGenerator
+ * @see GeoModelCodeGeneratorPlugin
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class GeoModelCodeGeneratorGUI extends XuluInternalFrame {
+  /** Verzeichnis-Name (unterhalb des {@linkplain XuluModellingPlatform#getPluginDirectory() Xulu-Plugin-Verzeichnisses}
+   *  in dem die Vorlagen-Dateien fuer Code-Generierung hinterlegt sind. */
+  public static final String tplDirName = "GeoModelCodeGenerator";
+
+  /**
+   * Vorgabe, aus welchen Modell-Typen der Anwender auswaehlen kann.
+   */
+  public static final Class[] MODELTYPE = new Class[] {
+      StepModel.class,
+      XuluModel.class
+  };
+
+  /**
+   * Vorgabe, aus welchen Ressourcen-Categorien der Anwender auswaehlen kann.
+   */
+  public static final Integer[] CATEGORY = new Integer[] {
+      ModelResource.CATEGORY_OTHER,
+      ModelResource.CATEGORY_INPUT,
+      ModelResource.CATEGORY_OUTPUT,
+      ModelResource.CATEGORY_INPUT | ModelResource.CATEGORY_OUTPUT,
+      ModelResource.CATEGORY_TEMP,
+  };
+
+  /**
+   * Beschreibungen fuer die Ressourcen-Categorien, aus welchen der Anwender auswaehlen kann.
+   */
+  public static final String[] CATEGORY_DESC = new String[] {
+      "",
+      "Input",
+      "Output",
+      "Input/Output",
+      "Temporal",
+  };
+
+  /**
+   * Vorgabe, aus welchen Ressourcen-Typen der Anwender auswaehlen kann (
+   * {@link ScalarProperty} , {@link ListProperty}, {@link MatrixProperty}).
+   */
+  public static final Class[] RESOURCETYPE = new Class[] {
+      ScalarProperty.class,
+      ListProperty.class,
+      MatrixProperty.class
+  };
+
+  /**
+   * Vorgabe, aus welchen Property-Datentypen der Anwender auswaehlen kann (
+   * {@link Integer} , {@link Float}, {@link Long}, {@link Double}, {@link Byte},
+   * {@link Short}, {@link Boolean}, {@link WritableGrid} , {@link FeatureCollection}).
+   */
+  public static final Class[] DATATYPE = new Class[] {
+      Integer.class,
+      Float.class,
+      Long.class,
+      Double.class,
+      Byte.class,
+      Short.class,
+      Boolean.class,
+      WritableGrid.class,
+      FeatureCollection.class,
+  };
+
+  /** Speichert alle zur Auswahl stehende Ressourcen-Typen ({@link #RESOURCETYPE} + alle
+   *  in Xulu registrierten {@link XuluObject}-Typen). */
+  protected Class[] resourceType = null;
+  /** Speichert eine Referenz auf die Xulu-Applikation, in der der Code-Generator
+   *  ausgefuehrt wird. */
+  protected XuluModellingPlatform appl = null;
+  /** Auswahlfeld fuer den Modell-Typ. */
+  protected SelectionInputOption.Combo modelType = null;
+  /** Eingabefeld fuer den Modell-Namen. */
+  protected ManualInputOption.Text modelName = null;
+  /** Tabelle in der die Ressourcen spezifiziert werden. */
+  protected MutableTable resources = null;
+  /** Butten zum Starten der Generierung. */
+  protected JButton startButton = null;
+  /** Referenz auf den Container des Fensters. */
+  protected Container contentPane = null;
+
+  /**
+   * Erzeugt eine neue GUI fuer den {@link GeoModelCodeGenerator}.
+   * @param appl Instanz der Xulu-Applikation, in der der Code-Generator
+   *             ausgefuehrt wird
+   */
+  public GeoModelCodeGeneratorGUI(XuluModellingPlatform appl) {
+    super("Source code generator for geo models");
+    this.appl = appl;
+    resourceType = this.appendXuluTypesToResourceTypes(appl);
+
+    this.setVisible(false);
+    this.setSize( new Dimension(500,500) );
+    this.setClosable(true);
+    this.setDefaultCloseOperation( HIDE_ON_CLOSE );
+    this.getContentPane().setLayout( new GridBagLayout() );
+    contentPane  = this.getContentPane();
+    initGUI();
+  }
+
+  /**
+   * Initalisiert die GUI des Fensters.
+   */
+  protected void initGUI() {
+    modelType = new SelectionInputOption.Combo(null,true,MODELTYPE,LangUtil.getClassNames(MODELTYPE,true));
+    modelName = new ManualInputOption.Text(null,true) {
+      public boolean performIsInputValid() {
+        // Modell-Name darf keine Leerzeichen, Punkte, Slashes und Backslashes enthalten
+        return super.performIsInputValid() &&
+              ((String)performGetValue()).indexOf(" ") < 0 &&
+              ((String)performGetValue()).indexOf(".") < 0 &&
+              ((String)performGetValue()).indexOf("/") < 0 &&
+              ((String)performGetValue()).indexOf("\\") < 0;
+      }
+    };
+    // Modellname soll immer mit einem Grossbuchstaben beginnen,
+    // wegen Java-Konvention fuer Klassen-Namen
+    modelName.addInputOptionListener(new InputOptionAdapter() {
+      public void optionChanged(InputOption option, Object oldValue, Object newValue) {
+        String newName = (String)newValue;
+        if ( newName == null )
+          return;
+        newName = newName.trim();
+        if ( newName.length() > 1 )
+          newName = newName.substring(0,1).toUpperCase() + newName.substring(1);
+        modelName.setValue( newName );
+      }
+    });
+
+    resources = new MutableTable( new ResourceTableModel(), MutableTable.ITEM_ADD | MutableTable.ITEM_REMOVE );
+    resources.setColumnSelectionAllowed(false);
+    resources.setSelectionMode( ListSelectionModel.MULTIPLE_INTERVAL_SELECTION );
+    resources.setRowHeight( new JComboBox(new String[] {"Dummy"}).getPreferredSize().height );
+    // Renderer fuer die Tabelle setzen
+    resources.getColumnModel().getColumn(0).setCellRenderer( new ComponentRenderer.JComboBox() );
+    resources.getColumnModel().getColumn(1).setCellRenderer( new ComponentRenderer.JTextField() );
+    resources.getColumnModel().getColumn(2).setCellRenderer( new ComponentRenderer.JTextField() );
+    resources.getColumnModel().getColumn(3).setCellRenderer( new ComponentRenderer.JComboBox() );
+    resources.getColumnModel().getColumn(4).setCellRenderer( new ComponentRenderer.JComboBox() );
+    resources.getColumnModel().getColumn(5).setCellRenderer( new ComponentRenderer.JCheckBox() );
+    // Editoren fuer die Tabelle setzen
+    resources.getColumnModel().getColumn(0).setCellEditor( new DefaultCellEditor( new JComboBox( CATEGORY_DESC ) ) );
+    resources.getColumnModel().getColumn(1).setCellEditor( new DefaultCellEditor( new JTextField() ) );
+    resources.getColumnModel().getColumn(2).setCellEditor( new DefaultCellEditor( new JTextField()) );
+    resources.getColumnModel().getColumn(3).setCellEditor( new DefaultCellEditor( new JComboBox( LangUtil.getClassNames(resourceType,true) ) ) );
+    resources.getColumnModel().getColumn(4).setCellEditor( new DefaultCellEditor( new JComboBox( LangUtil.getClassNames(DATATYPE,true) ) ) );
+    resources.getColumnModel().getColumn(5).setCellEditor( new DefaultCellEditor( new JCheckBox() {
+      public int getHorizontalAlignment() {
+        return this.CENTER;
+      }
+      public int getVerticalAlignment() {
+        return this.CENTER;
+      }
+    }));
+
+    // Button zum Starten
+    startButton = new JButton("Generate...");
+    startButton.addActionListener( new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        startGeneration();
+      }
+    });
+
+    // Komponenten in Fenster anordnen
+    contentPane.add( new JLabel("Modell-Typ:"),   new GridBagConstraints(0,0,1,1,  0,0,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5,10,5,10),0,5) );
+    contentPane.add( modelType,                   new GridBagConstraints(1,0,1,1,1.0,0,GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(5,10,5,10),0,5) );
+    contentPane.add( new JLabel("Modell-Name:"),  new GridBagConstraints(0,1,1,1,  0,0,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5,10,5,10),0,0) );
+    contentPane.add( modelName,                   new GridBagConstraints(1,1,1,1,1.0,0,GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(5,10,5,10),0,0) );
+    contentPane.add( new JLabel("Ressourcen:"),   new GridBagConstraints(0,2,1,1,  0,0,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5,10,0,10),0,0) );
+    contentPane.add( resources.createScrollPane(),new GridBagConstraints(0,3,2,1,1.0,1.0,GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(5,10,5,10),0,0) );
+    contentPane.add( startButton,                 new GridBagConstraints(0,4,1,1,0.0,0.0,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5,10,5,10),0,0) );
+  }
+
+  /**
+   * Aktualisiert die Anzeige des Xulu-internen Fensters, in dem die
+   * Ressourcen-Tabelle aktualisiert wird.
+   */
+  public void refresh() {
+    ((MutableTableModel)resources.getModel()).fireTableDataChanged();
+  }
+
+  /**
+   * Prueft die in der Maske spezifizierten Angaben auf Korrektheit. Ist eine
+   * Angabe nicht korrekt, wird ein entsprechender Fehler-Dialog angezeigt.
+   */
+  private boolean checkInputs() {
+    int i = -1;
+    try {
+      // Modell-Angaben checken
+      if ( !modelType.isInputValid() )
+        throw new IllegalArgumentException("Der angegebene Modelltyp ist ungueltig!");
+      if ( !modelName.isInputValid() || !LangUtil.checkIdentifier(modelName.getValue()) )
+        throw new IllegalArgumentException("Der angegebene Modellname ist ungueltig (keine Leer- oder Sonderzeichen erlaubt)!");
+
+      // Ressourcen checken
+      ResourceTableModel.ResourceDefinition[] resourceDef = ((ResourceTableModel)resources.getModel()).getResources();
+      for (i=0; i<resourceDef.length; i++) {
+        if ( !resourceDef[i].category.isInputValid() )
+          throw new IllegalArgumentException("Kategorie ungueltig!");
+        if ( !resourceDef[i].name.isInputValid() || !LangUtil.checkIdentifier(resourceDef[i].name.getValue()) )
+          throw new IllegalArgumentException("Variablen-Name ungueltig (keine Leer- oder Sonderzeichen erlaubt)!");
+        if ( !resourceDef[i].desc.isInputValid() )
+          throw new IllegalArgumentException("Beschreibung ungueltig!");
+        if ( !resourceDef[i].type.isInputValid() )
+          throw new IllegalArgumentException("Ressourcen-Typ ungueltig!");
+        if ( !resourceDef[i].datatype.isInputValid() )
+          throw new IllegalArgumentException("Datentyp ungueltig!");
+        if ( ValueProperty.class.isAssignableFrom( (Class)resourceDef[i].type.getValue() ) &&
+             resourceDef[i].datatype == null )
+          throw new IllegalArgumentException("Es muss ein Property-Typ angegeben werden!");
+      }
+    } catch (Exception err) {
+      if ( i >= 0 )
+        XuluGUIMessages.showError(this,err,"Fehler in Ressource "+(i+1)+": "+err.getMessage());
+      else
+        XuluGUIMessages.showError(this,err);
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * Erzeugt den kompletten Source-Dateinamen aus Klassenname, Paketname und
+   * Source-Basisverzeichnis
+   * @param className          Eingabenfeld fuer Klassenname
+   * @param packageName        Eingabefeld fuer Package-Name
+   * @param classDir           Eingabefeld fuer Source-Verzeichniss
+   * @param contentManagerFile wenn {@code true} wird dem Klassenname das Suffix
+   *                           "ContentManager" angehaengt
+   */
+  private static String generateOutFileName(ManualInputOption.Text className, ManualInputOption.Text packageName, FileInputOption classDir, boolean contentManagerFile) {
+    StringBuffer buffer = new StringBuffer();
+    if ( classDir.getValue() != null )
+//    FileInputOption.getValue() liefert waehrend der Text-Eingabe noch nicht
+//    das neue File-Objekt. Dies wird erst erzeugt, wenn das Text-Feld verlassen wird!
+//    -> Dynamische Anzeige der Dateien waehrend der Text-Eingabe klappt nur
+//       wenn direkt der Wert des Text-Feldes abgegriffen wird!
+//    buffer.append( classDir.getValue().getAbsolutePath() );
+      buffer.append( ((JTextField)classDir.getInputComponent()).getText() );
+    // Seperator nur anhaengen, wenn Klassen-Verzeichnis nicht bereits mit einem
+    // solchen  endet
+    if ( buffer.length() == 0 || buffer.charAt( buffer.length()-1 ) != File.separatorChar )
+      buffer.append( File.separatorChar );
+    // Package als Verzeichnis + Seperator + Klassenname
+    buffer.append( packageName.getValue().replace('.',File.separatorChar) )
+          .append( File.separator )
+          .append( className.getValue() );
+    // Fuer die CM-Klasse noch das entsprechende Suffix anhaengen
+    if ( contentManagerFile )
+      buffer.append( "ContentManager" );
+    // Endung ".java"
+    buffer.append( ".java" );
+    return buffer.toString();
+  }
+
+  /**
+   * Startet die Sourcecode-Generierung, wenn der Start-Button aktiviert wurde.
+   * Zuvor werden noch technische Information (wie Package-Name und Klassen-Verzeichnis)
+   * durch einen Anwender-Dialog abgefragt.
+   */
+  private void startGeneration() {
+    // Eingaben pruefen
+    if ( !checkInputs() )
+      return;
+
+    // Ressourcen erzeugen
+    ResourceTableModel.ResourceDefinition[] resourceDef = ((ResourceTableModel)resources.getModel()).getResources();
+    ModelResource[]                         resource = new ModelResource[resourceDef.length];
+    String[]                                varName  = new String[resourceDef.length];
+    for (int i=0; i<resource.length; i++) {
+      // Variablenname fuer Ressource
+      varName[i] = (String)resourceDef[i].name.getValue();
+      // Wenn "Datentyp" befuellt ist, handelt es sich um eine Property-Ressource,
+      // ansonsten wird eine PropertiesRessource (fuer ein Xulu-Objekt) erzeugt
+      if ( ValueProperty.class.isAssignableFrom( (Class)resourceDef[i].type.getValue() ) )
+        resource[i] = new ValuePropertyResource(
+          (Integer)resourceDef[i].category.getValue(),
+          (String)resourceDef[i].desc.getValue(),
+          (Class)resourceDef[i].type.getValue(),
+          (Class)resourceDef[i].datatype.getValue(),
+          (Boolean)resourceDef[i].optional.getValue()
+        );
+      else
+        resource[i] = new PropertiesResource(
+          (Integer)resourceDef[i].category.getValue(),
+          (String)resourceDef[i].desc.getValue(),
+          (Class)resourceDef[i].type.getValue(),
+          (Boolean)resourceDef[i].optional.getValue()
+        );
+    }
+
+    // Generierungs-Optionen abfragen
+    final ManualInputOption.Text packageName    = new ManualInputOption.Text("Java-Package fuer Modell:",true,"edu.bonn.xulu.plugin.model");
+    final FileInputOption        classDirName   = new FileInputOption("Compile-Verzeichnis:",true,/*"temp"*/appl.getDynamicClassRootDirectory());
+    final ManualInputOption.Text modelFileName  = new ManualInputOption.Text("Ausgabe-Dateien:",true,generateOutFileName(modelName,packageName,classDirName,false));
+    final ManualInputOption.Text cmFileName     = new ManualInputOption.Text(null,true,generateOutFileName(modelName,packageName,classDirName,true));
+    classDirName.getFileChooser().setFileSelectionMode( JFileChooser.DIRECTORIES_ONLY );
+    classDirName.getFileChooser().setDialogType( JFileChooser.OPEN_DIALOG );
+    ((JTextField)modelFileName.getInputComponent()).setEditable(false);
+    ((JTextField)cmFileName.getInputComponent()).setEditable(false);
+    // Angabe der Ausgabe-Datei soll sich dynamisch aendern, sobald sich
+    // Paket oder Klassen-Pfad aendern
+    KeyListener keyListener = new KeyAdapter() {
+      public void keyReleased(KeyEvent e) {
+        modelFileName.setValue( generateOutFileName(modelName,packageName,classDirName,false) );
+        cmFileName.setValue( generateOutFileName(modelName,packageName,classDirName,true) );
+      }
+    };
+    InputOptionAdapter inputListener = new InputOptionAdapter() {
+      public void optionChanged(InputOption option, Object oldValue, Object newValue) {
+        modelFileName.setValue( generateOutFileName(modelName,packageName,classDirName,false) );
+        cmFileName.setValue( generateOutFileName(modelName,packageName,classDirName,true) );
+      }
+    };
+
+    packageName.getInputComponent().addKeyListener( keyListener );
+    classDirName.getInputComponent().addKeyListener( keyListener );
+    classDirName.addInputOptionListener( inputListener );
+
+    SwingWorker worker = null;
+    for (;;) {
+      Object[] output = MultipleOptionPane.showMultipleInputDialog(this,"Output-Configuration", new InputOption[] {
+          packageName,
+          classDirName,
+          modelFileName,
+          cmFileName
+      });
+      // Dialog abgebrochen
+      if ( output == null )
+        return;
+      // Dialog abgeschlossen
+      File modelFile = new File((String)output[2]);
+      File cmFile    = new File((String)output[3]);
+      // Sicherheitsabfrage, falls Dateien bereits existieren
+      if ( modelFile.exists() && MultipleOptionPane.showConfirmDialog(this,"Modell-Datei existiert bereits! Ãœberschreiben?","Warnung...",MultipleOptionPane.OK_CANCEL_OPTION,MultipleOptionPane.WARNING_MESSAGE) == MultipleOptionPane.CANCEL_OPTION )
+        continue; // zum Dialog zurueckkehren
+      if ( cmFile.exists() && MultipleOptionPane.showConfirmDialog(this,"ContentManager-Datei existiert bereits! Ãœberschreiben?","Warnung...",MultipleOptionPane.OK_CANCEL_OPTION,MultipleOptionPane.WARNING_MESSAGE) == MultipleOptionPane.CANCEL_OPTION )
+        continue; // zum Dialog zurueckkehren
+
+      // Generator erzeugen (dabei Check der zusaetzlichen Angaben)
+      try {
+        final GeoModelCodeGenerator generator = new GeoModelCodeGenerator(
+            (String) modelName.getValue(),
+            (String) packageName.getValue(),
+            classDirName.getValue(),
+            (Class) modelType.getValue(),
+            resource,
+            varName,
+            new File(appl.getPluginDirectory(),tplDirName)
+        );
+        // SwingWorker erzeugen, der die Generierung durchfuehrt
+        worker = new SwingWorker(
+          new SwingWorker.Work() {
+            public Object execute() throws Exception {
+              generator.generateSource();
+              return null;
+            }
+            public void performError(Exception err) {
+              // Fehler bei der Code-Generierung verarbeiten
+              XuluGUIMessages.showError(appl.getMainFrame(),err);
+            }
+          },
+          appl.getMainFrame(),
+          XuluConstants.SWING_RES.getString("WaitMess")
+        );
+        // keine Fehler -> Schleife verlassen
+        break;
+      } catch (Exception err) {
+        // Fehler bei der CodeGenerator-Erzeugung verarbeiten
+        XuluGUIMessages.showError(appl.getMainFrame(),err);
+        continue; // zum Dialog zurueckkehren
+      }
+    } // End Loop
+
+    // Generierung starten
+    worker.start();
+    if ( !worker.isCanceled() )
+      XuluGUIMessages.showInfoMessage(appl.getMainFrame(),"Modell-Dateien wurden erfolgreich erzeugt...");
+  }
+
+  /**
+   * Liefert die Eintraege von {@link #RESOURCETYPE} plus alle aktuell in der
+   * Xulu-Applikation geladenen {@link XuluObject}-Typen in einem gemeinsamen
+   * Array.
+   */
+  private static Class[] appendXuluTypesToResourceTypes(XuluModellingPlatform appl) {
+    Class[] xuluType    = appl.getRegistry().getDataTypes();
+    Class[] allResType  = new Class[ RESOURCETYPE.length + xuluType.length ];
+    // die registrierten Xulu-Datentypen an den Array der
+    // Standard-Typen (Propertys) anhaengen
+    for (int i=0; i<allResType.length; i++)
+      allResType[i] = ( i < RESOURCETYPE.length ) ? RESOURCETYPE[i] : xuluType[i-RESOURCETYPE.length];
+    return allResType;
+  }
+
+  /////////////////////////////////////////////////////////////////////////
+  ////////////   Tabellen-Modell fuer die Ressourcen-Tabelle   ////////////
+  /////////////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse stellt ein {@link TableModel} fuer die Ressourcen-Tabelle
+   * der {@link GeoModelCodeGeneratorGUI} dar. Diese enthaelt 6 Spalten:
+   * <ul>
+   *   <li>Ressourcen-Kategorie (Input/Output/Temporaer/.., siehe {@link ModelResource#getCategory()})</li>
+   *   <li>Variablenname, mit dem die Ressource im Source-Code angesprochen werden soll</li>
+   *   <li>Ressourcen-Beschreibung</li>
+   *   <li>Typ des in der Ressourc gespeicherten Objekts</li>
+   *   <li>Property-Typ (falls es sich bei der Ressource um eine Property-Ressource handelt)</li>
+   *   <li>Flag, ob es sich um eine optionale Ressource handelt</li>
+   * </ul>
+   * Die Tabelle ist inital leer und wird sukzessive durch den Anwender befuellt.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  protected class ResourceTableModel extends AbstractMutableTableModel {
+    /** Speichert die Eintraege der Tabelle */
+    protected Vector<ResourceDefinition> resourceDef = new Vector<ResourceDefinition>();
+
+    /**
+     * Erzeugt ein neues Tabellenmodell.
+     */
+    public ResourceTableModel() {
+      super();
+//      resourceDef.add( new ResourceDefinition( ModelResource.CATEGORY_OTHER,
+//                                               "intRes",
+//                                               "Dummy-Ressource 1",
+//                                               ScalarProperty.class,
+//                                               Integer.class,
+//                                               true) );
+//      resourceDef.add( new ResourceDefinition( ModelResource.CATEGORY_INPUT,
+//                                               "gridListRes1",
+//                                               "Dummy-Ressource 2",
+//                                               edu.bonn.xulu.plugin.data.grid.GridList.class,
+//                                               null,
+//                                               true) );
+//      resourceDef.add( new ResourceDefinition( ModelResource.CATEGORY_OUTPUT,
+//                                               "gridListRes2",
+//                                               "Dummy-Ressource 3",
+//                                               ListProperty.class,
+//                                               schmitzm.data.WritableGrid.class,
+//                                               false) );
+//      resourceDef.add( new ResourceDefinition( ModelResource.CATEGORY_OUTPUT,
+//                                               "gridRes",
+//                                               "Dummy-Ressource 4",
+//                                               ScalarProperty.class,
+//                                               schmitzm.data.WritableGrid.class,
+//                                               false) );
+    }
+
+    /**
+     * Liefert die Spaltennamen der Tabelle.
+     */
+    public String[] createColumnNames() {
+      return new String[] {
+          "Kategorie", "Variablen-Name", "Beschreibung", "Ressourcen-Typ", "Datentyp", "Optional"
+      };
+    }
+    
+    /**
+     * Liefert die aktruellen Eintraege der Tabelle.
+     */
+    public ResourceDefinition[] getResources() {
+      return resourceDef.toArray( new ResourceDefinition[0] );
+    }
+
+    /**
+     * Fuegt eine neue (zunaechst leere) Ressouce hinzu.
+     */
+    public void performAddRow() {
+      resourceDef.add( new ResourceDefinition() );
+    }
+
+    /**
+     * Loescht eine Ressouce aus der Liste.
+     */
+    public void performRemoveRow(int row) {
+      resourceDef.remove(row);
+    }
+
+    /**
+     * Machts nichts, da die Werte direkt geaendert werden und nicht auf einen
+     * Doppelklick reagiert wird.
+     * @param row Zeilenindex
+     * @param col Spaltenindex
+     */
+    public void performChangeData(int row, int col) {
+    }
+
+    /**
+     * Liefert die Zeilenanzahl der Tabelle.
+     */
+    public int getRowCount() {
+      return resourceDef.size();
+    }
+
+    /**
+     * Liefert einen Wert der Tabelle.
+     * @param row Zeilenindex
+     * @param col Spaltenindex
+     */
+    public Object getValueAt(int row, int col) {
+      switch (col) {
+        case 0: return resourceDef.elementAt(row).category.getSelectedDisplayItem();
+        case 1: return resourceDef.elementAt(row).name.getValue();
+        case 2: return resourceDef.elementAt(row).desc.getValue();
+        case 3: return resourceDef.elementAt(row).type.getSelectedDisplayItem();
+        case 4: return resourceDef.elementAt(row).datatype.getSelectedDisplayItem();
+        case 5: return resourceDef.elementAt(row).optional.getValue();
+      }
+
+      return null;
+    }
+
+    /**
+     * Liefert nur {@code false}, wenn es sich um Spalte 4 handelt
+     * ("Datentyp") und die betreffende Ressource <b>keine</b> Property-Ressource
+     * ist.
+     * @param row Zeilenindex
+     * @param col Spaltenindex
+     */
+    public boolean isCellEditable(int row, int col) {
+      switch( col ) {
+        case 4: // Datentyp soll nur aktiviert sein, wenn als Resource-Typ eine
+                // ValueProperty angewaehlt ist
+                Class type = (Class)resourceDef.elementAt(row).type.getValue();
+                return type != null && ValueProperty.class.isAssignableFrom(type);
+      }
+      return true;
+    }
+
+    /**
+     * Veraendert einen Wert einer Tabellenzelle.
+     * @param value neuer Zellen-Wert
+     * @param row Zeilenindex
+     * @param col Spaltenindex
+     */
+    public void setValueAt(Object value, int row, int col) {
+      if ( row >= getRowCount() )
+        return;
+      switch (col) {
+        case 0: resourceDef.elementAt(row).category.setSelectedDisplayItem(value); break;
+        case 1: resourceDef.elementAt(row).name.setValue(value); break;
+        case 2: resourceDef.elementAt(row).desc.setValue(value); break;
+        case 3: resourceDef.elementAt(row).type.setSelectedDisplayItem(value); break;
+        case 4: resourceDef.elementAt(row).datatype.setSelectedDisplayItem(value); break;
+        case 5: resourceDef.elementAt(row).optional.setValue( value/*!(Boolean)resourceDef.elementAt(row).optional.getValue()*/ ); break;
+      }
+    }
+
+    /**
+     * Diese Klasse repraesentiert eine Zeile der Ressourcen-Tabelle. Sie besteht
+     * aus 6 Eingabefeldern:
+     * <ul>
+     *   <li>Auswahlfeld fuer Ressourcen-Kategorie</li>
+     *   <li>Text-Eingabe fuer Variablen-Name</li>
+     *   <li>Text-Eingabe fuer Ressourcen-Beschreibung</li>
+     *   <li>Auswahlfeld fuer Ressourcen-Typ</li>
+     *   <li>Auswahlfeld fuer Datentyp einer Property-Ressource</li>
+     *   <li>Checkbox fuer "optional"-Flag</li>
+     * </ul>
+     * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+     * @version 1.0
+     */
+    protected class ResourceDefinition {
+      /** Auswahlfeld fuer die Resourcen-Kategorie. */
+      protected SelectionInputOption.Combo category = null;
+      /** Textfeld fuer den Resourcen-Namen (mit dem die Ressource im Source-
+       *  Code angesprochen wird. */
+      protected ManualInputOption.Text name = null;
+      /** Textfeld fuer die Resourcen-Beschreibung. */
+      protected ManualInputOption.Text desc = null;
+      /** Auswahlfeld fuer den Resourcen-Typ. */
+      protected SelectionInputOption.Combo type = null;
+      /** Auswahlfeld fuer den Datentyp einer Property-Resource. */
+      protected SelectionInputOption.Combo datatype = null;
+      /** Checkbox fuer die Optional-Angabe. */
+      protected BooleanInputOption optional = null;
+
+      /**
+       * Erzeugt eine neue Zeile. Die Eingabefelder sind alle leer.
+       */
+      public ResourceDefinition() {
+        super();
+        category = new SelectionInputOption.Combo(null,true,CATEGORY,CATEGORY_DESC);
+        name     = new ManualInputOption.Text(null,true);
+        SwingUtil.setPreferredWidth(name,150);
+        desc     = new ManualInputOption.Text(null,true);
+        SwingUtil.setPreferredWidth(desc,150);
+        type     = new SelectionInputOption.Combo(null,true,resourceType,LangUtil.getClassNames(resourceType,true));
+        datatype = new SelectionInputOption.Combo(null,true,DATATYPE,LangUtil.getClassNames(DATATYPE,true));
+        optional = new BooleanInputOption(null,false);
+        // Wenn kein ValueProperty-Typ fuer die Ressource ausgewaehlt ist,
+        // wird der Datentyp autom. auf NICHTS gesetzt
+        type.addInputOptionListener(new InputOptionAdapter() {
+          public void optionChanged(InputOption option, Object oldValue, Object newValue) {
+            if (!ValueProperty.class.isAssignableFrom( (Class) newValue) ) {
+              datatype.setValue(null);
+              datatype.setInputNeeded(false);
+              fireTableRowsUpdated(0,0); // klappt merkwuerdigerweise auch fuer andere Zeilen!
+            } else {
+              datatype.setInputNeeded(true);
+            }
+          }
+        });
+      }
+
+      /**
+       * Erzeugt eine neue vorbelegte Zeile.
+       * @param category Ressourcen-Kategorie (siehe {@link ModelResource#getCategory()})
+       * @param name     Name der Ressourcen-Variable
+       * @param desc     Beschreibung der Ressource
+       * @param type     Typ der Ressource
+       * @param datatype Datentyp (falls es sich beim Typ eine {@link ValueProperty} handelt)
+       */
+      public ResourceDefinition(int category, String name, String desc, Class type, Class datatype, boolean optional) {
+        this();
+        this.category.setSelectedItem( category );
+        this.name.setValue(name);
+        this.desc.setValue(desc);
+        this.type.setSelectedItem(type);
+        this.datatype.setSelectedItem(datatype);
+        this.optional.setValue(optional);
+      }
+
+    }
+
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/appl/GeoModelCodeGeneratorPlugin.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/appl/GeoModelCodeGeneratorPlugin.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/appl/GeoModelCodeGeneratorPlugin.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,42 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.appl;
+
+import schmitzm.lang.LangUtil;
+
+import edu.bonn.xulu.gui.XuluInternalFrame;
+
+/**
+ * Dieses Plugin integriert die {@link edu.bonn.xulu.plugin.appl.GeoModelCodeGeneratorGUI}
+ * in das Xulu-Menue "Erweitert".
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class GeoModelCodeGeneratorPlugin extends AbstractMenuPlugin {
+  private static final int MENU_ID = 4; // Erweitert
+//  private static final String GENERATOR_CLASSNAME = "edu.bonn.xulu.plugin.appl.GeoModelCodeGeneratorGUI";
+
+  /**
+   * Erzeugt eine neue Plugin-Instanz.
+   */
+  public GeoModelCodeGeneratorPlugin() {
+    super(MENU_ID,"GeoModel-CodeGenerator");
+  }
+
+  /**
+   * Erzeugt eine Instanz der Plugin-Applikation {@link GeoModelCodeGeneratorGUI}.
+   */
+  protected XuluInternalFrame createPluginApplication() throws Exception {
+//    return (XuluInternalFrame)LangUtil.loadClass(GENERATOR_CLASSNAME,appl.getDynamicClassRootDirectory().toURL()).getConstructor(XuluModellingPlatform.class).newInstance(appl);
+    return new GeoModelCodeGeneratorGUI(appl);
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/appl/LoggerPlugin.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/appl/LoggerPlugin.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/appl/LoggerPlugin.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,87 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.appl;
+
+import java.io.File;
+import javax.swing.JTextField;
+import org.apache.log4j.LogManager;
+
+import schmitzm.swing.log4j.LoggerFrame;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.XuluPlugin;
+
+// fuer Doku
+import org.apache.log4j.Level;
+
+/**
+ * Dieses Xulu-Plugin zeigt alle im {@link LogManager} registrierten Log4j-Logger an
+ * und bietet die Möglichkeit, deren {@link Level} zur Laufzeit veraendern.
+ * Dies gestattet z.B. ein Ein- und Ausschalten von Debug-Informationen.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class LoggerPlugin extends LoggerFrame implements XuluPlugin {
+  /** Log4j-Konfigurationsdatei aus der die Logger gelesen werden.
+   *  {@code <XuluPluginVz>\LoggerPlugin\log4j.cfg} */
+  public static final String CONFIG_FILE_NAME = "LoggerPlugin"+File.separatorChar+"log4j.cfg";
+
+  /** Instanz der Xulu-Applikation innerhalb der das Plugin ausgefuehrt wird. */
+  protected XuluModellingPlatform appl = null;
+  /** Flag speichert, ob das Plugin gestartet ist. */
+  protected boolean started = false;
+
+  /**
+   * Erzeugt eine neue Plugin-Instanz.
+   */
+  public LoggerPlugin() {
+    super();
+//    ((JTextField)configFile.getInputComponent()).setEditable(false);
+  }
+
+  /**
+   * Fuehrt das Plugin aus, in dem die Logger neu aus der Konfigurationsdatei
+   * geladen werden.
+   * @param appl Xulu-Instanz in der das Plugin ausgefuehrt wird
+   * @see XuluModellingPlatform#getPluginDirectory()
+   * @see #CONFIG_FILE_NAME
+   */
+  public void execute(XuluModellingPlatform appl) {
+    // Pruefen, ob ein log-Verzeichnis unterhalb des Start-Verzeichnisses
+    // existiert
+    new File( appl.getStartingDirectory(), "log" ).mkdirs();
+
+    this.appl    = appl;
+    this.started = true;
+    configFileField.setValue( new File(appl.getPluginDirectory(),CONFIG_FILE_NAME) );
+    reload();
+  }
+
+  /**
+   * Prueft, ob das Plugin gestartet ist.
+   */
+  public boolean isStarted() {
+    return started;
+  }
+
+  /**
+   * Stoppt das Plugin.
+   * @see LogManager#resetConfiguration()
+   * @see LogManager#shutdown()
+   */
+  public void stop() {
+    started = false;
+    this.setVisible(false);
+    LogManager.resetConfiguration();
+    LogManager.shutdown();
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/appl/ModelResourceMappingScriptInterpreter_Basic.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/appl/ModelResourceMappingScriptInterpreter_Basic.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/appl/ModelResourceMappingScriptInterpreter_Basic.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,140 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.appl;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+import java.awt.Container;
+
+import schmitzm.io.IOUtil;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.AbstractScriptInterpreter;
+import edu.bonn.xulu.appl.XuluConstants;
+import edu.bonn.xulu.model.XuluModel;
+import edu.bonn.xulu.gui.ModelControlFrame;
+import edu.bonn.xulu.gui.ModelContentManagerContainer;
+import edu.bonn.xulu.gui.XuluGUIUtil;
+
+// nur fuer Doku
+import edu.bonn.xulu.plugin.gui.ModelControlFrame_Basic;
+
+/**
+ * Dieser Interpreter fuehrt ein Mapping zwischen Datenpool-Objekten und
+ * Modell-Ressourcen durch und kann <b>nur in Verbindung mit {@link ModelControlFrame_Basic}
+ * (bzw. {@link ModelContentManagerContainer}) verwendet werden!</b><br>
+ * Leerzeilen und {@linkplain IOUtil#isCommentLine(String)
+ * Kommentarteilen} im Stream werden ignoriert. In jeder Zeile steht der Name eines
+ * Objekts, so wie er im jeweiligen Auswahlfeld des {@link ModelContentManagerContainer}-Fensters
+ * vorgeblendet ist. Die Reihenfolge der im Stream angegebenen Objekte, muss
+ * der Ressourcen-Reihenfolge des Modells (als im Fenster des
+ * {@link ModelContentManagerContainer} zeilenweise von links nach rechts!)
+ * entsprechen. Soll eine Ressource nicht zugeordnet werden, ist in der
+ * jeweiligen Zeile ein Tilde-Zeichen (~) zu setzen.<br>
+ * <b>ACHTUNG: Diese Klasse arbeitet sehr rudimentaer (ein wenig Quick-and-Dirty) und befindet sich noch im Test!!</b>
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class ModelResourceMappingScriptInterpreter_Basic extends AbstractScriptInterpreter implements XuluConstants {
+  /**
+   * Fuehrt das Script aus. Vor dem Einlesen der Ressourcen-Zuordnung wird
+   * zunaechst vom Anwender eine Modell-Instanz abgefragt, auf die das Skript
+   * angewandt werden soll (nur sofern mehrere Modelle geladen sind!).
+   * @param in   Eingabe-Stream in dem das Skript zu finden ist.
+   * @param appl Applikation, in der das Skript auszufuehren ist
+   * @see XuluGUIUtil#askModelFrame(XuluModellingPlatform, boolean)
+   */
+  public void execute(InputStream in, XuluModellingPlatform appl) {
+    // Modell abfragen, auf das das Skript angewandt werden soll
+    ModelControlFrame selectedModelFrame = XuluGUIUtil.askModelFrame(appl,false);
+    // Dialog abgebrochen
+    if (selectedModelFrame == null)
+      return;
+
+    map(in,selectedModelFrame);
+    }
+
+      /**
+     * Führt als InputStream übergebene Script aus. Dabei wird das gefundene
+     * Mapping auf <b>alle</b> geladenen Modelle mit dem angegebenen Namen
+     * angewendet.
+     *
+     * @param in   Eingabe-Stream in dem das Skript zu finden ist.
+     * @param appl Applikation, in der das Skript auszufuehren ist
+     *
+     * @param modelName das Mapping gilt für alle Modelle mit diesem Namen
+     */
+
+  public void execute(InputStream in, String modelName, XuluModellingPlatform appl)
+  {
+     boolean modelFound = false;
+     ModelControlFrame[] controlFrames = appl.getModelControlManager().getAll();
+     for (ModelControlFrame c : controlFrames)
+       if(c != null && c.getTitle().equals(modelName)){
+           modelFound = true;
+           map(in,c);
+       }
+     if(!modelFound)
+         System.err.println("Mapping failed: No Model with the name \"" + modelName + "\" found!" );
+
+  }
+    /** Führt das eigentliche Mapping aus **/
+    private void map(InputStream in, ModelControlFrame controlFrame){
+    // Der ModelControlFrame muss einen ModelContentManagerContainer enthalten,
+    // sonst kann die Zuordnung nicht druchgefuehrt werden kann
+    Container contentPane = controlFrame.getContentPane();
+    XuluModel model       = controlFrame.getModel();
+    ModelContentManagerContainer resourceContainer = null;
+    for (int i=0; i<contentPane.getComponentCount() && resourceContainer==null; i++) {
+      if ( contentPane.getComponent(i) instanceof ModelContentManagerContainer )
+        resourceContainer = (ModelContentManagerContainer)contentPane.getComponent(i);
+    }
+    if(controlFrame instanceof ModelControlFrame_Basic)
+    	resourceContainer = ((ModelControlFrame_Basic) controlFrame).getModelContentManagerContainer();
+    if ( resourceContainer == null )
+      throw new UnsupportedOperationException("The script can be applied only on ModelControlFrames which contain a ModelContentManagerContainer.");
+
+
+    // Stream parsen
+    BufferedReader input      = new BufferedReader( new InputStreamReader(in) );
+    String         line       = null;
+    int            lineNo     = 0;
+    int            resourceNo = 0;
+    System.out.println("\nStart executing script...");
+    try {
+      // Zeilenweise einlesen
+      for(lineNo=1; resourceNo < model.getContentManager().getResourceCount() && (line = input.readLine()) != null; lineNo++) {
+        line = line.trim();
+        // Leerzeilen und Kommentare ignorieren
+        if ( line.equals("") || IOUtil.isCommentLine(line) )
+          continue;
+
+        // Zuordnung erstellen
+        System.out.print(">>>> Model resource " + (resourceNo+1));
+        if ( !line.equals("~") ) {
+          System.out.println(" mapped to '" + line + "'");
+          resourceContainer.setResourceByName(resourceNo, line);
+        } else {
+          System.out.println(" ignored");
+        }
+        resourceNo++;
+      }
+
+      // Stream schliessen
+      in.close();
+    } catch ( Exception err ) {
+      System.err.println("Unknown error while parsing line "+lineNo);
+    }
+    System.out.println("Script finished...\n");
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/appl/ModelTimeSnifferPlugin.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/appl/ModelTimeSnifferPlugin.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/appl/ModelTimeSnifferPlugin.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,184 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.appl;
+
+import java.util.Vector;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.XuluPlugin;
+import edu.bonn.xulu.appl.ModelControlManager;
+import edu.bonn.xulu.model.XuluModel;
+import edu.bonn.xulu.model.event.ModelListener;
+import edu.bonn.xulu.model.event.ModelEvent;
+import edu.bonn.xulu.model.event.ModelStartedEvent;
+import edu.bonn.xulu.model.event.ModelStoppedEvent;
+import edu.bonn.xulu.model.event.ModelStepStartedEvent;
+import edu.bonn.xulu.model.event.ModelStepFinishedEvent;
+import edu.bonn.xulu.model.event.ModelIterationStepStartedEvent;
+import edu.bonn.xulu.model.event.ModelIterationStepFinishedEvent;
+import edu.bonn.xulu.gui.ModelControlFrame;
+
+import schmitzm.lang.AbstractNamedObject;
+import schmitzm.data.event.ObjectListener;
+import schmitzm.data.event.ObjectEvent;
+
+/**
+ * Dieses Plugin koppelt sich an alle in Xulu geladenen Modelle und
+ * gibt deren absolute Laufzeit (in Sekunden aus). Bei Step-Modellen wird
+ * auch die Laufzeit pro Modell-Schitt ausgegeben.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class ModelTimeSnifferPlugin extends AbstractNamedObject implements XuluPlugin, ObjectListener {
+  /** Flag, ob das Plugin gestartet ist, oder nicht */
+  protected boolean started = false;
+  /** Speichert die Xulu-Instanz in der das Plugin ausgefuehrt wird. */
+  protected XuluModellingPlatform appl = null;
+  /** Speichert die Listener, die an die Modelle angeschlossen wurden. */
+  protected Vector<TimeSniffer> sniffers = new Vector<TimeSniffer>();
+
+
+  /**
+   * Erzeugt eine neue Instanz des Plugins.
+   */
+  public ModelTimeSnifferPlugin() {
+  }
+
+
+  /**
+   * Startet die Ausfuehrung des Plugins.
+   * @param appl Instanz der Xulu-Applikation
+   */
+  public void execute(XuluModellingPlatform appl) {
+    this.appl = appl;
+    started = true;
+    if ( !appl.getModelControlManager().containsObjectListener(this) )
+      appl.getModelControlManager().addObjectListener( this );
+    //add Models which are currently loaded
+    for(ModelControlFrame frame : appl.getModelControlManager().getAll())
+    {
+    	 XuluModel model = frame.getModel();
+         TimeSniffer sniffer = new TimeSniffer(model);
+         sniffers.add( sniffer );
+         model.addModelListener( sniffer );
+    }
+  }
+
+
+  /**
+   * Wird aufgerufen, wenn sich der Inhalt des {@link ModelControlManager Xulu-Modellmanagers}
+   * aendert. Wurde ein neues {@link XuluModel} hinzugefuegt, wird diesem
+   * ein Listener hinzugefuegt, der die Modellierungszeit misst.
+   * @param e Ereignis
+   */
+  public void performObjectEvent(ObjectEvent e) {
+    if ( !isStarted() || !(e instanceof ModelControlManager.ChangeEvent) )
+      return;
+    ModelControlManager.ChangeEvent event = (ModelControlManager.ChangeEvent)e;
+    // Listener nur hinzufuegen, wenn Modell neu hinzugefuegt
+    // wurde und wenn es sich um ein XuluModell handelt
+    if ( event.getOldValue()==null && event.getNewValue()!=null && event.getNewValue() instanceof ModelControlFrame ) {
+      XuluModel model = ((ModelControlFrame)event.getNewValue()).getModel();
+      TimeSniffer sniffer = new TimeSniffer(model);
+      sniffers.add( sniffer );
+      model.addModelListener( sniffer );
+    }
+  }
+
+  /**
+   * Stoppt die Ausfuehrung des Plugins.
+   */
+  public void stop() {
+    started = false;
+    appl.getModelControlManager().removeObjectListener(this);
+    for (int i=0; i<sniffers.size(); i++)
+      sniffers.elementAt(i).removeFromModel();
+    sniffers.clear();
+  }
+
+  /**
+   * Prueft, ob das Plugin gestartet ist.
+   */
+  public boolean isStarted() {
+    return started;
+  }
+
+  /**
+   * Prueft, ob die GUI zur Plugin-Konfiguration angezeigt wird.
+   * @return immer {@code false}, da das Plugin keine GUI besitzt
+   */
+  public boolean isVisible() {
+    return false;
+  }
+
+  /**
+   * Macht nichts, da das Plugin keine GUI besitzt.
+   */
+  public void setVisible(boolean visible) {
+  }
+
+
+  private static class TimeSniffer implements ModelListener {
+    private long      modelStartMillis     = -1; // Startzeit des Modells
+    private long      modelStepStartMillis = -1; // Startzeit eines Modellschritts
+    private long      modelIterStartMillis = -1; // Startzeit der Modell-Iteration
+    private long      modelIterCount       = -1;
+    private XuluModel model             = null;
+
+    public TimeSniffer(XuluModel model) {
+      this.model = model;
+    }
+
+    public void performModelEvent(ModelEvent e) {
+      long eventMillis = System.currentTimeMillis();
+      // Beginn des Modells
+      if ( e instanceof ModelStartedEvent ) {
+        modelStartMillis     = eventMillis;
+        modelStepStartMillis = -1;
+        modelIterStartMillis = -1;
+      }
+      // Beginn eines Zeitschritts
+      if ( e instanceof ModelStepStartedEvent ) {
+        modelStepStartMillis = eventMillis;
+        modelIterStartMillis = -1;
+      }
+      // Beginn der eigentlichen Iterationen des Zeitschritts
+      if ( e instanceof ModelIterationStepStartedEvent && ((ModelIterationStepStartedEvent)e).getIterNo() == 1 )
+        modelIterStartMillis = eventMillis;
+      if ( e instanceof ModelIterationStepFinishedEvent )
+        modelIterCount = ((ModelIterationStepFinishedEvent)e).getIterNo();
+      // Ende eines Zeitschritts
+      if ( e instanceof ModelStepFinishedEvent ) {
+        System.out.print(model.getName()+": step "+((ModelStepFinishedEvent)e).getStepNo()+" time = "+(eventMillis-modelStepStartMillis)/1000.0+"s");
+        if ( modelIterStartMillis >= 0) {
+          double secs = (eventMillis-modelIterStartMillis)/1000.0;
+          System.out.println("   (Iteration cnt "+modelIterCount+", time = "+secs+"s avg = "+secs/modelIterCount+")");
+        } else
+          System.out.println();
+      }
+      // Ende des Modells
+      if ( e instanceof ModelStoppedEvent )
+        System.out.println(model.getName()+": model time = "+(eventMillis-modelStartMillis)/1000.0+"s");
+    }
+
+    public void performObjectEvent(ObjectEvent e) {
+      if ( e instanceof ModelEvent )
+        performModelEvent((ModelEvent)e);
+    }
+
+    public void removeFromModel() {
+      model.removeModelListener(this);
+    }
+
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/appl/RasterCalculatorGUI.070821
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/appl/RasterCalculatorGUI.070821	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/appl/RasterCalculatorGUI.070821	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,828 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.appl;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.dnd.DropTarget;
+import java.awt.dnd.DropTargetAdapter;
+import java.awt.dnd.DropTargetDragEvent;
+import java.awt.dnd.DropTargetDropEvent;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.Vector;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JScrollPane;
+
+import schmitzm.data.RasterCalculator;
+import schmitzm.data.RasterFilter;
+import schmitzm.data.WritableGrid;
+import schmitzm.data.event.ObjectEvent;
+import schmitzm.data.event.ObjectListener;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyReadAccess;
+import schmitzm.data.property.MatrixProperty;
+import schmitzm.data.property.Properties;
+import schmitzm.data.property.Property;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.swing.InputOption;
+import schmitzm.swing.ManualInputOption;
+import schmitzm.swing.MultipleOptionPane;
+import schmitzm.swing.SelectionInputOption;
+import schmitzm.swing.SwingWorker;
+import schmitzm.swing.table.MutableTable;
+import schmitzm.swing.table.MutableTableModel;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.DataPool;
+import edu.bonn.xulu.appl.XuluConstants;
+import edu.bonn.xulu.data.DynamicXuluObject;
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.gui.XuluGUIMessages;
+import edu.bonn.xulu.gui.XuluGUIUtil;
+import edu.bonn.xulu.gui.XuluInternalFrame;
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+
+// nur fuer Doku
+
+/**
+ * Diese Klasse stellt eine GUI zur Vefuegung, mit der eine einfache arithmetische
+ * (und boolsche) Berechnung auf Rasterdaten durchgefuehrt werden kann. Zudem
+ * koennen in die Formel Filter eingebunden werden.
+ * @see RasterCalculator
+ * @see RasterCalculatorPlugin
+ * @author <a href="mailto:schmitzm at bonn.edu">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class RasterCalculatorGUI extends XuluInternalFrame {
+  /** Name der Datei, in der die Standard-Filter hinterlegt sind. */
+  public static final String DEFAULT_FILTER_FILENAME = "default_filter.inp";
+
+  /** Speichert eine Referenz auf das Fenster-Objekt, um aus verschachtelten
+   *  Klassen einfach darauf zugreifen zu koennen. */
+  protected final RasterCalculatorGUI THIS = this;
+  /** Speichert eine Referenz auf die Xulu-Applikation, in der der Code-Generator
+   *  ausgefuehrt wird. */
+  protected XuluModellingPlatform appl = null;
+  /** Tabelle in der die Eingabe-Raster angegeben werden. */
+  protected MutableTable          inputRasterTable = null;
+  private   InputRasterTableModel inputRasterTableModel = null;
+  private   JScrollPane           inputRasterScrollPane = null;
+  /** Tabelle in der die Eingabe-Filter angegeben werden. */
+  protected MutableTable          inputFilterTable = null;
+  private   InputFilterTableModel inputFilterTableModel = null;
+  private   JScrollPane           inputFilterScrollPane = null;
+  /** Auswahlfeld fuer das Ausgabe-Raster. */
+  protected SelectionInputOption.Combo outputRaster = null;
+  /** Eingabefeld fuer die Formel. */
+  protected ManualInputOption.Text rule = null;
+  /** Butten zum Starten der Berechnung. */
+  protected JButton startButton = null;
+  /** Butten zum Laden von Standard-Filtern. */
+  protected JButton loadDefaultFilterButton = null;
+  /** Referenz auf den Container des Fensters. */
+  protected Container contentPane = null;
+  /** Speichert die Komponente, von der eine Drag-Aktion ausgeht. */
+  private   Component dragSourceComponent = null;
+
+  /**
+   * Erzeugt eine neue GUI fuer den {@link RasterCalculator}.
+   * @param appl Instanz der Xulu-Applikation, in der der Rechner
+   *             ausgefuehrt wird
+   */
+  public RasterCalculatorGUI(XuluModellingPlatform appl) {
+    super("Raster calculator");
+    this.appl = appl;
+
+    this.setVisible(false);
+    this.setSize( new Dimension(500,400) );
+    this.setClosable(true);
+    this.setDefaultCloseOperation( HIDE_ON_CLOSE );
+    this.getContentPane().setLayout( new GridBagLayout() );
+    contentPane  = this.getContentPane();
+    initGUI();
+    refresh();
+
+    // Listener auf den Datenpool setzen, damit Auswahlfelder automatisch
+    // aktualisiert werden
+    appl.getDataPool().addObjectListener( new ObjectListener() {
+      public void performObjectEvent(ObjectEvent e) {
+        if ( e instanceof DataPool.DataPoolChangeEvent )
+          refresh();
+      }
+    });
+  }
+
+  /**
+   * Initalisiert die GUI des Fensters.
+   */
+  protected void initGUI() {
+    // Input-Raster-Tabelle
+    inputRasterTableModel = new InputRasterTableModel(appl);
+    inputRasterTable      = new InputTable(inputRasterTableModel,"Simply drag raster objects from xulu data pool to this table");
+    inputRasterScrollPane = inputRasterTable.createScrollPane();
+    // Input-Filter-Tabelle
+    inputFilterTableModel = new InputFilterTableModel(appl);
+    inputFilterTable      = new InputTable(inputFilterTableModel,"Simply drag matrix properties from xulu data pool to this table");
+    inputFilterScrollPane = inputFilterTable.createScrollPane();
+    // Output-Raster
+    outputRaster = new SelectionInputOption.Combo("Output raster:",false);
+    outputRaster.setToolTipText("Leave this fiels empty, to create an new raster as output");
+    // Formel
+    rule = new ManualInputOption.Text("Rule:",true);
+    rule.setToolTipText("Insert your arithmetical rule here (Use arithmetical operators, constants and #1, #2, ... as raster reference identifier)");
+    // Button zum Starten
+    startButton = new JButton("Calculate...");
+    startButton.addActionListener( new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        startCalculation();
+      }
+    });
+    // Button zum Laden der Standard-Filter
+    loadDefaultFilterButton = new JButton("Load default filter...");
+    loadDefaultFilterButton.addActionListener( new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        loadDefaultFilter();
+      }
+    });
+
+// PRUEFEN, VON WELCHER KOMPONENTE DIE DRAG-OPERATION AUSGEHT
+// LEIDER WIRD DER DragSourceListener ERST NACH DEM DropTargetListener
+// AUSGEFUEHRT
+//    // Drag & Drop vom Datenpool
+//    DragSource.getDefaultDragSource().addDragSourceListener( new DragSourceAdapter() {
+//      public void dragMouseMoved(DragSourceDragEvent e) {
+//        System.err.println("dragMoved1");
+//        dragSourceComponent = e.getDragSourceContext().getComponent();
+//        System.err.println( dragSourceComponent );
+//      }
+//      public void dragEnter(DragSourceDragEvent e) {
+//        System.err.println("dragEnter1");
+//
+//        dragSourceComponent = e.getDragSourceContext().getComponent();
+//        System.err.println( dragSourceComponent );
+//      }
+//    });
+
+    // Drag & Drop fuer Input-Raster
+    DropTarget dropTarget = new DropTarget( appl.getMainFrame(), new DropTargetAdapter() {
+      public void dragEnter(DropTargetDragEvent e) {
+//        // Drop nur Zulassen, wenn die Drag-Aktion vom Datenpool ausgeht
+//        if ( !SwingUtil.isChildComponent( dragSourceComponent, appl.getMainFrame().getDataPoolFrame() ) ) {
+//          e.rejectDrop();
+//          return;
+//        }
+
+        // Pruefen, ob mind, ein akzeptables Objekt im Datenpool selektiert ist
+        Object[] selObjects = appl.getMainFrame().getDataPoolFrame().getSelectedObjects();
+        for (Object obj : selObjects)
+          if ( getWritableGridsFromObject(obj) != null )
+            return;
+        // Drop zurueckweisen, wenn kein WritableGrid gefunden wurde
+        e.rejectDrag();
+      }
+
+      public void drop(DropTargetDropEvent e) {
+        Object[] selObjects = appl.getMainFrame().getDataPoolFrame().getSelectedObjects();
+        // Alle WritableGrid-Objekte der selektieren Datenpool-Objekte ermitteln
+        for (Object obj : selObjects) {
+          WritableGrid[] grids = getWritableGridsFromObject(obj);
+          if ( grids == null )
+            continue;
+          // WritableGrid-Objekte des Datenpool-Objekts in die Liste einfuegen
+          for ( WritableGrid grid : grids )
+            inputRasterTableModel.addRaster( grid );
+        }
+      }
+    } );
+    inputRasterTable.setDropTarget( dropTarget );
+    inputRasterScrollPane.setDropTarget( dropTarget );
+
+    // Drag & Drop fuer Input-Filter
+    dropTarget = new DropTarget( appl.getMainFrame(), new DropTargetAdapter() {
+      public void dragEnter(DropTargetDragEvent e) {
+//        // Drop nur Zulassen, wenn die Drag-Aktion vom Datenpool ausgeht
+//        if ( !SwingUtil.isChildComponent( dragSourceComponent, appl.getMainFrame().getDataPoolFrame() ) ) {
+//          e.rejectDrop();
+//          return;
+//        }
+
+        // Pruefen, ob mind, ein akzeptables Objekt im Datenpool selektiert ist
+        Object[] selObjects = appl.getMainFrame().getDataPoolFrame().getSelectedObjects();
+        for (Object obj : selObjects)
+          if ( getMatrixPropertiesFromObject(obj) != null )
+            return;
+        // Drop zurueckweisen, wenn keine Matrix gefunden wurde
+        e.rejectDrag();
+      }
+
+      public void drop(DropTargetDropEvent e) {
+        Object[] selObjects = appl.getMainFrame().getDataPoolFrame().getSelectedObjects();
+        // Alle MatrixProperty-Objekte der selektieren Datenpool-Objekte ermitteln
+        for (Object obj : selObjects) {
+          MatrixProperty[] matrices = getMatrixPropertiesFromObject(obj);
+          if ( matrices == null )
+            continue;
+          // MatrixProperty-Objekte des Datenpool-Objekts in die Liste einfuegen
+          for (MatrixProperty matrix : matrices) {
+              try {
+                inputFilterTableModel.addFilterMatrix( matrix/*, matrixName*/);
+              } catch (Exception err) {
+                XuluGUIMessages.showError(THIS,err);//,"Matrix "+matrixName+"not suitable for filter!");
+              }
+          }
+        }
+      }
+    } );
+    inputFilterTable.setDropTarget( dropTarget );
+    inputFilterScrollPane.setDropTarget( dropTarget );
+
+
+
+    // Komponenten in Fenster anordnen
+    contentPane.add( new JLabel("Input-Rasters (use context menu or simply drag rasters from xulu data pool):"),
+                                                        new GridBagConstraints(0,0,2,1,  0,  0,GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5,10,0,10),0,0) );
+    contentPane.add( inputRasterScrollPane,             new GridBagConstraints(0,1,2,1,1.0,1.0,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0,10,5,10),0,0) );
+    contentPane.add( new JLabel("Input-Filter (use context menu or simply drag matrixes from xulu data pool):"),
+                                                        new GridBagConstraints(0,2,2,1,  0,  0,GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5,10,0,10),0,0) );
+    contentPane.add( inputFilterScrollPane,             new GridBagConstraints(0,3,2,1,1.0,1.0,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0,10,5,10),0,0) );
+    contentPane.add( rule,                              new GridBagConstraints(0,4,2,1,1.0,  0,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0,10,5,10),0,0) );
+    contentPane.add( outputRaster,                      new GridBagConstraints(0,5,2,1,1.0,  0,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0,10,5,10),2,2) );
+    contentPane.add( startButton,                       new GridBagConstraints(0,6,1,1,0.0,  0,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,10,5,10),0,0) );
+    contentPane.add( loadDefaultFilterButton,           new GridBagConstraints(1,6,1,1,0.0,  0,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0,10,5,10),0,0) );
+  }
+
+  /**
+   * Aktualisiert die Auswahl-Felder auf Basis des Datenpools.
+   */
+  public void refresh() {
+    // Aktualisierung der Tabelle
+    inputRasterTableModel.refreshInputOption();
+    inputRasterTableModel.fireTableDataChanged();
+
+    // Als Ausgabe-Raster werden alle WritableGrids aus dem Datenpool angeboten
+    Object oldSelection = outputRaster.getValue();
+    Object[][] fitObjects = XuluGUIUtil.determineObjectsFromDataPool(WritableGrid.class, appl.getDataPool());
+    outputRaster.setSelectionObjects(fitObjects[0],fitObjects[1]);
+    outputRaster.setSelectedItem(oldSelection);
+  }
+
+  /**
+   * Prueft die in der Maske spezifizierten Angaben auf Korrektheit. Ist eine
+   * Angabe nicht korrekt, wird ein entsprechender Fehler-Dialog angezeigt.
+   */
+  private boolean checkInputs() {
+    try {
+      if ( !outputRaster.isInputValid() )
+        throw new IllegalArgumentException("Ausgabe-Raster nicht zulaessig!");
+      if ( !rule.isInputValid() )
+        throw new IllegalArgumentException("Formel nicht zulaessig!");
+      RasterCalculator.checkRuleAndError(rule.getValue());
+    } catch (Exception err) {
+      XuluGUIMessages.showError(this,err);
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * Laed Standard-Filter aus der Datei {@code <Plugin-Dir>\RasterCalculator\default_filter.inp}
+   * in den Datenpool.
+   * @see #DEFAULT_FILTER_FILENAME
+   */
+  private void loadDefaultFilter() {
+    try {
+      // (eindeutige) Import-Factory fuer Dynamische Xulu-Objekte ermitteln,
+      // die aus einem File oder FileInputStream importieren kann
+      ImportFactory[] factories = appl.getRegistry().getImportFactories( DynamicXuluObject.class );
+      if ( factories.length < 1 )
+        throw new UnsupportedOperationException("No import factory for DynamicXuluObject found in registry!");
+      if ( factories.length > 1 )
+        throw new UnsupportedOperationException("More than one import factories for DynamicXuluObject found in registry!");
+      ImportFactory importFac = factories[0];
+      if ( !importFac.getImportSourceType().isAssignableFrom(File.class) &&
+           !importFac.getImportSourceType().isAssignableFrom(FileInputStream.class) )
+        throw new UnsupportedOperationException("Registrated import factories for DynamicXuluObject can neither import from File nor from FileInputStream!");
+
+      // Dynamisches Xulu-Objekt importieren
+      File   importFile = new File( appl.getPluginDirectory(), "RasterCalculator"+File.separator+DEFAULT_FILTER_FILENAME );
+      Object importObject = null;
+      if ( importFac.getImportSourceType().isAssignableFrom(File.class) )
+        importObject = importFile;
+      if ( importFac.getImportSourceType().isAssignableFrom(FileInputStream.class) )
+        importObject = new FileInputStream(importFile);
+      DynamicXuluObject dynXuluObj = (DynamicXuluObject)importFac.importObject(importObject,appl.getRegistry());
+
+      // Alle Objekte aus dem Datenpool entfernen, die den gleichen Namen
+      // haben, wie das neuen Objekt
+      XuluObject[] presentObj = appl.getDataPool().getObjects( dynXuluObj.getDescription() );
+      if ( presentObj.length > 0 ) {
+        if ( MultipleOptionPane.showConfirmDialog(this,"Override existing data pool object(s) '"+dynXuluObj.getDescription()+"'?","Override...",MultipleOptionPane.OK_CANCEL_OPTION) == MultipleOptionPane.CANCEL_OPTION )
+          return;
+        for (XuluObject xuluObj : presentObj)
+          appl.getDataPool().removeObject(xuluObj);
+      }
+
+      // Neues Objekt dem Datenpool hinzufuegen
+      appl.getDataPool().addObject( dynXuluObj );
+      // Filter direkt in die Filter-Liste einfuegen
+      if ( MultipleOptionPane.showConfirmDialog(this,"Add loaded filters automatically to filter list?","Add filter...",MultipleOptionPane.OK_CANCEL_OPTION) == MultipleOptionPane.CANCEL_OPTION )
+        return;
+      for ( Property matrix : dynXuluObj.getProperties(MatrixProperty.class).getProperties() )
+        inputFilterTableModel.addFilterMatrix( (MatrixProperty)matrix );
+
+    } catch (Exception err) {
+      XuluGUIMessages.showError(this,err);
+    }
+  }
+
+  /**
+   * Startet die Berechnung, wenn der Start-Button betaetigt wurde.
+   */
+  private void startCalculation() {
+    // Eingaben pruefen
+    if ( !checkInputs() )
+      return;
+
+    // SwingWorker erzeugen, der die Generierung durchfuehrt
+    SwingWorker worker = new SwingWorker(
+      new SwingWorker.Work() {
+        public void execute() throws Exception {
+          // Eingabe-Raster als WritableGrid-Array
+          WritableGrid[] inGrid = inputRasterTableModel.getRasters();
+          // Eingabe-Filter als WritableGrid-Array
+          RasterFilter[] inFilter = inputFilterTableModel.getFilter();
+
+          // Ausgabe-Raster ermitteln (wenn keines angegeben, wird eines erzeugt)
+          WritableGrid outGrid = null;
+          Object       outGridValue = outputRaster.getValue();
+          if ( outGridValue == null ) {
+            // Namen fuer Raster abfragen
+            Object[] retObject = MultipleOptionPane.showMultipleInputDialog( THIS, "Create new Object...", new InputOption[] {
+                new ManualInputOption.Text("Raster name:", true, "RasterCalculator OUT")
+            });
+            if ( retObject == null )
+              return; // Dialog abgebrochen
+            String rasterName = (String)retObject[0];
+
+            SingleGrid singleGrid = null;
+            if ( inGrid.length > 0 )
+              // Ausgabe-Grid auf Basis des Eingabe-Rasters erzeugen
+              singleGrid = ((SingleGrid)appl.getRegistry().getDefaultFactory( SingleGrid.class ).newInstance(false,inGrid[0]));
+            else
+              // Dimension des Ausgabe-Grid abfragen
+              singleGrid = ((SingleGrid)appl.getRegistry().getDefaultFactory( SingleGrid.class ).newInstance(true));
+            singleGrid.setDescription( rasterName );
+            appl.getDataPool().addObject(singleGrid);
+            outGrid = singleGrid.getGrid();
+            outputRaster.setValue( outGrid );
+
+          } else
+            outGrid = ( outGridValue instanceof SingleGrid ) ? ((SingleGrid)outGridValue).getGrid() : (WritableGrid)outGridValue;
+
+          RasterCalculator.calculate(rule.getValue(), inGrid, inFilter, outGrid);
+        }
+        public void performError(Exception err) {
+          // Fehler bei der Code-Generierung verarbeiten
+          XuluGUIMessages.showError(appl.getMainFrame(),err);
+        }
+      },
+      appl.getMainFrame(),
+      XuluConstants.SWING_RES.getString("WaitMess")
+    );
+
+    // Berechnung starten
+    worker.start();
+  }
+
+  private static WritableGrid[] getWritableGridsFromObject(Object obj) {
+    if ( obj instanceof SingleGrid )
+      obj = ((SingleGrid)obj).getProperty( SingleGrid.PROP_GRID );
+    if ( obj instanceof MultiGrid )
+      obj = ((MultiGrid)obj).getProperty( MultiGrid.PROP_GRIDS );
+
+    if ( obj instanceof WritableGrid )
+      return new WritableGrid[] { (WritableGrid)obj };
+    if ( obj instanceof ScalarProperty && WritableGrid.class.isAssignableFrom( ((ScalarProperty)obj).getType() ) )
+      return new WritableGrid[] { (WritableGrid)((ScalarProperty)obj).getOneTimeReadAccess().getValue() };
+    if ( obj instanceof ListProperty && WritableGrid.class.isAssignableFrom( ((ListProperty)obj).getType() ) ) {
+      ListPropertyReadAccess a = ((ListProperty)obj).getReadAccess(obj);
+      WritableGrid[] grids = new WritableGrid[ a.getCount() ];
+      for (int i=0; i<grids.length; i++)
+        grids[i] = (WritableGrid)a.getValue(i);
+      a.release();
+      return grids;
+    }
+    return null;
+  }
+
+  private static MatrixProperty[] getMatrixPropertiesFromObject(Object obj) {
+    if ( obj instanceof MatrixProperty )
+      return new MatrixProperty[] { (MatrixProperty)obj };
+    if ( obj instanceof Properties ) {
+      Property[] props = ((Properties)obj).getProperties(MatrixProperty.class).getProperties();
+      MatrixProperty[] matrices = new MatrixProperty[props.length];
+      for (int i=0; i<props.length; i++ )
+        matrices[i] = (MatrixProperty)props[i];
+      return matrices;
+    }
+    return null;
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  /////////////////   Table fuer die DnD-Tabellen   /////////////////
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse stellt eine Tabelle fuer die Eingabe-Daten dar. Diese hat
+   * keinen Header und es wird kein Tabellen-Raster angezeigt. Ueber ein
+   * Kontextmenue koennen der Tabelle Daten hinzugefuegt oder entfernt werden.
+   * @author <a href="mailto:schmitzm at bonn.edu">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  private class InputTable extends MutableTable {
+    /**
+     * Erzeugt einen neue Tabelle
+     * @param tableModel Daten-Modell fuer die Tabelle
+     * @param toolTip Hilfe-Text der als ToolTip-Text angezeigt wird
+     */
+    public InputTable(InputTableModel tableModel, String toolTip) {
+      super( tableModel, MutableTable.ITEM_REMOVE | MutableTable.ITEM_ADD );
+      this.setToolTipText( toolTip );
+      this.setTableHeader(null);
+      this.setShowGrid(false);
+      this.getColumnModel().getColumn(0).setMaxWidth(30);
+    }
+
+    /**
+     * Erzeugt einen neue Tabelle
+     * @param tableModel Daten-Modell fuer die Tabelle
+     */
+    public InputTable(InputTableModel tableModel) {
+      this(tableModel,"");
+    }
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  //////////////   TableModels fuer die DnD-Tabellen   //////////////
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse stellt das Daten-Modell der Eingabe-Tabellen dar. Dieses
+   * stellt immer 2 Spalten zur Verfuegung. In der ersten Spalte wird die
+   * Zeilennummer (eingeleitet durch ein {@linkplain #rowIndexPrefix Praefix})
+   * dargestellt, in der zweiten Spalte ein Objekt vom Typ {@code <O>}.
+   * Durch einen Rechtsklick, koennen der Tabelle Objekte aus dem Datenpool
+   * hinzugefuegt oder entfernt werden. Dabei werden die Objekte aus dem
+   * Array {@code #fitObjects} (bzw. {@code fitObjectNames}) vorgeblendet.
+   * Diese Array passend zu fuellen muss durch die Sub-Klassen in der Methode
+   * {@link #determineFitObjectsAndNames()} implementiert werden.
+   * @author <a href="mailto:schmitzm at bonn.edu">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  private abstract class InputTableModel<O> extends MutableTableModel {
+    /** Speichert die in der Tabelle gespeicherten Raster */
+    protected Vector<O> objects = new Vector<O>();
+    /** Speichert die Namen der in der Tabelle gespeicherten Objekte */
+    protected Vector<String> objectNames = new Vector<String>();
+    /** Speichert die Instanz der Xulu-Applikation. */
+    protected XuluModellingPlatform appl = null;
+    /** Eingabe-Option fuer ein einzelnes Objekt. */
+    protected SelectionInputOption.Combo objectInputOption = null;
+
+    /** Speichert die Spaltennamen der Tabelle */
+    protected String[] COL_NAME = new String[] {"Index","Object"};
+    /** Speichert das Zeilennummer-Praefix. */
+    protected String rowIndexPrefix = null;
+
+
+    /** Flag, ob sich der Inhalt des Datenpools geaendert hat und die Arrays
+     *  {@link #fitObjects} und {@link #fitObjectNames} aktualisiert werden
+     *  muessen */
+    protected boolean  dataPoolChanged = true;
+    /** Passende Objekte im Datenpool */
+    protected Object[] fitObjects = null;
+    /** Bezeichnungen der passenden Objekte im Datenpool */
+    protected String[] fitObjectNames = null;
+
+    /**
+     * Erzeugt ein neues Tabellen-Modell.
+     * @param appl Instanz der Xulu-Applikation
+     * @param rowIndexPrefix Praefix, das den Zeilen-Indizes vorangestellt wird
+     */
+    public InputTableModel(XuluModellingPlatform appl, String rowIndexPrefix) {
+      super();
+      this.appl = appl;
+      this.rowIndexPrefix = rowIndexPrefix;
+      objectInputOption = new SelectionInputOption.Combo(getColumnName(1),true);
+      refreshInputOption();
+      // Listener auf den Datenpool setzen, damit das Auswahlfeld aktualisiert
+      // werden kann (wenn notwendig)
+      appl.getDataPool().addObjectListener( new ObjectListener() {
+        public void performObjectEvent(ObjectEvent e) {
+          if ( e instanceof DataPool.DataPoolChangeEvent ) {
+            dataPoolChanged = true;
+          }
+        }
+      });
+    }
+
+    /**
+     * Ruft {@link #determineFitObjectsAndNames()}, wenn das {@link #dataPoolChanged}-Flag
+     * auf {@code true} steht und setzt das Flag zurueck.
+     */
+    protected void refreshFitObjects() {
+      if ( dataPoolChanged )
+        determineFitObjectsAndNames();
+      dataPoolChanged = false;
+    }
+
+    /**
+     * Aktualisiert das Dialog-Auswahlfeld, in dam alle passenden Objekte
+     * aus dem Datenpool vorgeblendet werden.
+     */
+    protected void refreshInputOption() {
+      refreshFitObjects();
+      objectInputOption.setSelectionObjects(fitObjects,fitObjectNames);
+    }
+
+    /**
+     * Wird aufgerufen, wenn sich der Inhalt des Xulu-Datenpools aendert.
+     * Muss die Arrays {@link #fitObjects} und {@link #fitObjectNames} mit
+     * allen passenden Objekten des Datenpools und deren Bezeichnungen
+     * befuellen.
+     */
+    protected abstract void determineFitObjectsAndNames();
+
+
+    /**
+     * Loescht eine Tabellenzeile.
+     * @param row Zeilenindex (beginnend bei 0)
+     */
+    public void performRemoveRow(int row) {
+      objects.remove(row);
+      objectNames.remove(row);
+    }
+
+    /**
+     * Macht nichts, da in der Tabelle keine Daten veraendert werden koennen.
+     * @param row Zeilenindex (beginnend bei 0)
+     * @param col Spaltenindex (beginnend bei 0)
+     */
+    public void performChangeData(int row, int col) {
+    }
+
+    /**
+     * Liefert die Anzahl an Spalten.
+     * @return immer 2
+     */
+    public int getColumnCount() {
+      return COL_NAME.length;
+    }
+
+    /**
+     * Liefert die Spaltennamen.
+     * @param col Spaltenindex (beginnend bei 0)
+     */
+    public String getColumnName(int col) {
+      return COL_NAME[col];
+    }
+
+    /**
+     * Liefert die Anzahl an Zeilen.
+     */
+    public int getRowCount() {
+      return objects.size();
+    }
+
+    /**
+     * Liefert den Inahlt einer Tabellenzelle.
+     * @param row Zeilenindex (beginnend bei 0)
+     * @param col Spaltenindex (beginnend bei 0)
+     */
+    public Object getValueAt(int row, int col) {
+      switch ( col ) {
+        case 0: return rowIndexPrefix+row;
+        case 1: return objectNames.elementAt(row);
+      }
+      return null;
+    }
+
+  }
+
+  /**
+   * Diese Klasse stellt das Daten-Modell der Eingaberaster-Tabelle dar.
+   * Durch einen Rechtsklick, koennen der Tabelle {@link WritableGrid}-Objekte
+   * aus dem Datenpool hinzugefuegt oder entfernt werden.
+   * @author <a href="mailto:schmitzm at bonn.edu">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  private class InputRasterTableModel extends InputTableModel<WritableGrid> {
+    /** Speichert die Spaltennamen der Tabelle */
+    protected String[] COL_NAME = new String[] {"Index","Raster-Object"};
+
+    /**
+     * Erzeugt ein neues Tabellen-Modell.
+     */
+    public InputRasterTableModel(XuluModellingPlatform appl) {
+      super(appl,"#");
+    }
+
+    /**
+     * Befuellt die Arrays {@link #fitObjects} und {@link #fitObjectNames} mit
+     * allen {@link WritableGrid}- und {@link MultiGrid}-Objekten des
+     * Datenpools und deren (rekursiven) Bezeichnungen.
+     */
+    protected void determineFitObjectsAndNames() {
+      Vector fitRasterObjects = new Vector();
+      Vector fitRasterObjectNames = new Vector();
+      XuluGUIUtil.determineObjectsFromDataPool(MultiGrid.class, appl.getDataPool(), fitRasterObjects, fitRasterObjectNames);
+      XuluGUIUtil.determineObjectsFromDataPool(WritableGrid.class, appl.getDataPool(), fitRasterObjects, fitRasterObjectNames);
+      this.fitObjects     = fitRasterObjects.toArray();
+      this.fitObjectNames = (String[])fitRasterObjectNames.toArray(new String[0]);
+    }
+
+    /**
+     * Liefert die in der Tabelle angezeigten Raster als Array.
+     */
+    public WritableGrid[] getRasters() {
+      return (WritableGrid[])objects.toArray(new WritableGrid[0]);
+    }
+
+    /**
+     * Zeigt einen Dialog an, in dem alle {@link WritableGrid}- und
+     * {@link MultiGrid}-Objekte des Datenpools zur Auswahl stehen.
+     */
+    public void performAddRow() {
+      refreshFitObjects();
+      Object[] value = MultipleOptionPane.showMultipleInputDialog(getParent(),"Select raster...",objectInputOption);
+      if ( value == null )
+        return;
+
+      Object selObject = objectInputOption.getValue();
+      String selName   = (String)objectInputOption.getSelectedDisplayItem();
+      if ( selObject instanceof WritableGrid)
+        addRaster((WritableGrid)selObject,selName);
+      if ( selObject instanceof MultiGrid ) {
+        MultiGrid multiGrid = (MultiGrid)selObject;
+        for (int i=0; i<multiGrid.getGridCount(); i++)
+          addRaster(multiGrid.getGrid(i),selName+"["+i+"]");
+      }
+    }
+
+    /**
+     * Fuegt der Tabelle ein Raster hinzu.
+     * @param raster Raster
+     * @param name   Name fuer das Raster, der in der Tabelle angezeigt wird
+     */
+    public void addRaster(WritableGrid raster, String name) {
+      refreshFitObjects();
+      // Pruefen, ob Raster mit den anderen Rastern uebereinstimmt
+      if ( this.objects.size() > 0 ) {
+        WritableGrid presentGrid = this.objects.elementAt(0);
+        if ( raster.getWidth() != presentGrid.getWidth() ||
+             raster.getHeight() != presentGrid.getHeight() )
+          throw new UnsupportedOperationException("New Raster does not fit to the other rasters in the list!");
+      }
+      this.objects.add(raster);
+      this.objectNames.add(name);
+      this.fireTableDataChanged();
+    }
+
+    /**
+     * Fuegt der Tabelle ein Raster hinzu. Der Name des Objekts wird automatisch
+     * aus dem Datenpool ermittelt.
+     * @param raster Raster
+     */
+    public void addRaster(WritableGrid raster) {
+      refreshFitObjects();
+      String rasterName = "dummy";
+      for (int i=0; i<fitObjects.length; i++)
+        if ( raster == fitObjects[i] ) {
+          rasterName = fitObjectNames[i];
+          break;
+        }
+      addRaster(raster,rasterName);
+    }
+
+  }
+
+  /**
+   * Diese Klasse stellt das Daten-Modell der Eingabefilter-Tabelle dar.
+   * Durch einen Rechtsklick, koennen der Tabelle {@link MatrixProperty}-Objekte
+   * aus dem Datenpool hinzugefuegt oder entfernt werden.
+   * @author <a href="mailto:schmitzm at bonn.edu">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  private class InputFilterTableModel extends InputTableModel<MatrixProperty> {
+    /** Speichert die Spaltennamen der Tabelle */
+    protected String[] COL_NAME = new String[] {"Index","Filter-Object"};
+
+    /**
+     * Erzeugt ein neues Tabellen-Modell.
+     */
+    public InputFilterTableModel(XuluModellingPlatform appl) {
+      super(appl,"F");
+    }
+
+
+    /**
+     * Befuellt die Arrays {@link #fitObjects} und {@link #fitObjectNames} mit
+     * allen {@link MatrixProperty}-Objekten des Datenpools und deren
+     * (rekursiven) Bezeichnungen.
+     */
+    protected void determineFitObjectsAndNames() {
+      Object[][] fitMatrixObjects = XuluGUIUtil.determineObjectsFromDataPool(MatrixProperty.class, appl.getDataPool());
+      this.fitObjects     = fitMatrixObjects[0];
+      this.fitObjectNames = (String[])fitMatrixObjects[1];
+    }
+
+    /**
+     * Liefert die in der Tabelle angezeigten Matrix-Objekte Filter-Array.
+     */
+    public RasterFilter[] getFilter() {
+      RasterFilter[] filter = new RasterFilter[objects.size()];
+      for (int i=0; i<objects.size(); i++) {
+        MatrixProperty matrix = objects.elementAt(i);
+        filter[i] = new RasterFilter(matrix.getSize(0), matrix.getSize(1));
+        PropertyReadAccess access = matrix.getReadAccess(this);
+        for (int y=0; y<filter[i].getFilterSizeY(); y++)
+          for (int x=0; x<filter[i].getFilterSizeX(); x++)
+            filter[i].setFilterValue(access.getValueAsDouble(x, y), x, y);
+        access.release();
+      }
+      return filter;
+    }
+
+    /**
+     * Zeigt einen Dialog an, in dem alle {@link MatrixProperty}-Objekte
+     * des Datenpools zur Auswahl stehen.
+     */
+    public void performAddRow() {
+      Object[] value = MultipleOptionPane.showMultipleInputDialog(getParent(),"Select matrix...",objectInputOption);
+      if ( value == null )
+        return;
+
+      Object selObject = objectInputOption.getValue();
+      String selName   = (String)objectInputOption.getSelectedDisplayItem();
+      if ( selObject instanceof MatrixProperty )
+        try {
+          addFilterMatrix( (MatrixProperty) selObject, selName);
+        } catch (Exception err) {
+          XuluGUIMessages.showError(THIS,err,"Matrix '"+selName+"' not suitable for filter!");
+        }
+    }
+
+    /**
+     * Fuegt der Tabelle einen Filter hinzu.
+     * @param filterMatrix Filter
+     * @param name   Name fuer das Raster, der in der Tabelle angezeigt wird
+     */
+    public void addFilterMatrix(MatrixProperty filterMatrix, String name) {
+      refreshFitObjects();
+      // Pruefen, ob Matrix als Filter in Frage kommt
+      if ( filterMatrix.getDimension() != 2 )
+        throw new UnsupportedOperationException("Only a 2-dimensional matrix can be used as filter!");
+      if ( filterMatrix.getSize(0)%2 != 1 || filterMatrix.getSize(1)%2 != 1 )
+        throw new UnsupportedOperationException("To use a matrix as filter its size must be odd in each dimension!");
+      this.objects.add(filterMatrix);
+      this.objectNames.add(name);
+      this.fireTableDataChanged();
+    }
+
+    /**
+     * Fuegt der Tabelle einen Filter hinzu. Der Name des Objekts wird automatisch
+     * aus dem Datenpool ermittelt.
+     * @param filterMatrix Filter
+     */
+    public void addFilterMatrix(MatrixProperty filterMatrix) {
+      refreshFitObjects();
+      String filterMatrixName = "dummy";
+      for (int i=0; i<fitObjects.length; i++)
+        if ( filterMatrix == fitObjects[i] ) {
+          filterMatrixName = fitObjectNames[i];
+          break;
+        }
+      addFilterMatrix(filterMatrix,filterMatrixName);
+    }
+
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/appl/RasterCalculatorGUI.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/appl/RasterCalculatorGUI.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/appl/RasterCalculatorGUI.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,64 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.appl;
+
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.BorderLayout;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.gui.XuluInternalFrame;
+
+// nur fuer Doku
+import schmitzm.data.RasterCalculator;
+import edu.bonn.xulu.plugin.appl.RasterCalculatorPlugin;
+
+/**
+ * Diese Klasse stellt eine GUI zur Vefuegung, mit der eine einfache arithmetische
+ * (und boolsche) Berechnung auf Rasterdaten durchgefuehrt werden kann. Zudem
+ * koennen in die Formel Filter eingebunden werden.
+ * @see RasterCalculator
+ * @see RasterCalculatorPlugin
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class RasterCalculatorGUI extends XuluInternalFrame {
+  /** Referenz auf den Container des Fensters. */
+  protected Container contentPane = null;
+
+  /** Panel mit der Raster-Calculator-GUI. */
+  protected RasterCalculatorPanel rasterCalculatorPanel = null;
+
+  /**
+   * Erzeugt eine neue GUI fuer den {@link RasterCalculator}.
+   * @param appl Instanz der Xulu-Applikation, in der der Rechner
+   *             ausgefuehrt wird
+   */
+  public RasterCalculatorGUI(XuluModellingPlatform appl) {
+    super("Raster calculator");
+    this.setVisible( false );
+    this.setSize( new Dimension(500,400) );
+    this.setClosable( true );
+    this.setDefaultCloseOperation( HIDE_ON_CLOSE );
+    this.getContentPane().setLayout( new BorderLayout() );
+    contentPane  = this.getContentPane();
+    rasterCalculatorPanel = new RasterCalculatorPanel(appl);
+    contentPane.add( rasterCalculatorPanel, BorderLayout.CENTER );
+  }
+
+  /**
+   * Aktualisiert die Auswahl-Felder auf Basis des Datenpools.
+   */
+  public void refresh() {
+    rasterCalculatorPanel.refresh();
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/appl/RasterCalculatorPanel.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/appl/RasterCalculatorPanel.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/appl/RasterCalculatorPanel.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,861 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.appl;
+
+import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.Insets;
+import java.awt.dnd.DropTarget;
+import java.awt.dnd.DropTargetAdapter;
+import java.awt.dnd.DropTargetDragEvent;
+import java.awt.dnd.DropTargetDropEvent;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.Vector;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JScrollPane;
+
+import schmitzm.data.RasterCalculator;
+import schmitzm.data.RasterFilter;
+import schmitzm.data.WritableGrid;
+import schmitzm.data.event.ObjectEvent;
+import schmitzm.data.event.ObjectListener;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyReadAccess;
+import schmitzm.data.property.MatrixProperty;
+import schmitzm.data.property.Properties;
+import schmitzm.data.property.Property;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.swing.InputOption;
+import schmitzm.swing.ManualInputOption;
+import schmitzm.swing.MultipleOptionPane;
+import schmitzm.swing.SelectionInputOption;
+import schmitzm.swing.table.AbstractMutableTableModel;
+import schmitzm.swing.table.MutableTable;
+import schmitzm.swing.table.MutableTableModel;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.DataPool;
+import edu.bonn.xulu.data.DynamicXuluObject;
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.gui.XuluGUIMessages;
+import edu.bonn.xulu.gui.XuluGUIUtil;
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+import schmitzm.swing.OperationTreePanel;
+import schmitzm.swing.SwingUtil;
+
+// nur fuer Doku
+import schmitzm.data.RasterOperationTree;
+import schmitzm.data.RasterOperationTreeParser;
+import edu.bonn.xulu.plugin.appl.RasterCalculatorPlugin;
+import java.awt.event.MouseAdapter;
+import javax.swing.JTextField;
+import java.awt.event.MouseEvent;
+
+/**
+ * Diese Klasse stellt eine GUI zur Vefuegung, mit der eine einfache arithmetische
+ * (und boolsche) Berechnung auf Rasterdaten durchgefuehrt werden kann. Zudem
+ * koennen in die Formel Filter eingebunden werden.
+ * @see RasterCalculator
+ * @see RasterCalculatorPlugin
+ * @see RasterOperationTree
+ * @see RasterOperationTreeParser
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class RasterCalculatorPanel extends OperationTreePanel {
+  private final Component THIS = this;
+  /** Name der Datei, in der die Standard-Filter hinterlegt sind. */
+  public static final String DEFAULT_FILTER_FILENAME = "default_filter.inp";
+
+  /** Konstante fuer das Label zur Tabelle der Eingabe-Raster.
+  *  @see #layoutConstraints */
+  public static final String INRASTER_LABEL = "inputRasterLabel";
+  /** Konstante fuer die Tabelle der Eingabe-Raster.
+  *  @see #layoutConstraints */
+  public static final String INRASTER_TABLE = "inputRasterTable";
+  /** Konstante fuer das Label zur Tabelle der Eingabe-Filter.
+  *  @see #layoutConstraints */
+  public static final String INFILTER_LABEL = "inputFilterLabel";
+  /** Konstante fuer die Tabelle mit der Eingabe-Filter.
+  *  @see #layoutConstraints */
+  public static final String INFILTER_TABLE = "inputFilterTable";
+  /** Konstante fuer die ComboBox des Ausgabe-Rasters.
+  *  @see #layoutConstraints */
+  public static final String OUTRASTER_FIELD = "outputRasterField";
+  /** Konstante fuer den Button zum Laden der Default-Filter.
+  *  @see #layoutConstraints */
+  public static final String LOADFILTER_BUTTON = "filterButton";
+
+  /** Speichert eine Referenz auf die Xulu-Applikation, in der der Code-Generator
+   *  ausgefuehrt wird. */
+  protected XuluModellingPlatform appl = null;
+  /** Tabelle in der die Eingabe-Raster angegeben werden. */
+  protected MutableTable          inputRasterTable = null;
+  private   InputRasterTableModel inputRasterTableModel = null;
+  private   JScrollPane           inputRasterScrollPane = null;
+  /** Tabelle in der die Eingabe-Filter angegeben werden. */
+  protected MutableTable          inputFilterTable = null;
+  private   InputFilterTableModel inputFilterTableModel = null;
+  private   JScrollPane           inputFilterScrollPane = null;
+  /** Auswahlfeld fuer das Ausgabe-Raster. */
+  protected SelectionInputOption.Combo outputRaster = null;
+  /** Butten zum Laden von Standard-Filtern. */
+  protected JButton loadDefaultFilterButton = null;
+  /** Speichert die Komponente, von der eine Drag-Aktion ausgeht. */
+  private   Component dragSourceComponent = null;
+
+  /**
+   * Erzeugt eine neue GUI fuer den {@link RasterCalculator}.
+   * @param appl Instanz der Xulu-Applikation, in der der Rechner
+   *             ausgefuehrt wird
+   */
+  public RasterCalculatorPanel(XuluModellingPlatform appl) {
+    this(appl,true);
+  }
+
+  /**
+   * Erzeugt eine neue GUI fuer den {@link RasterCalculator}.
+   * @param appl Instanz der Xulu-Applikation, in der der Rechner
+   *             ausgefuehrt wird
+   * @param initGUI Flag, ob {@link #initGUI()} am Ende des Konstruktor
+   *        aufgerufen werden soll (wenn {@code false} muss die explizit
+   *        durch die Unterklasse erfolgen!)
+   */
+  protected RasterCalculatorPanel(XuluModellingPlatform appl, boolean initGUI) {
+    super(false);
+    this.appl = appl;
+
+    // Zusaetzliche Operatoren und Konstanten
+    avOperators.add("X");            avOperatorsDesc.put("X",        "Raster cell X");
+    avOperators.add("Y");            avOperatorsDesc.put("Y",        "Raster cell Y");
+    avOperators.add("NoData");       avOperatorsDesc.put("NoData",   "NoData value");
+    avOperators.add("isNoData");     avOperatorsDesc.put("isNoData", "isNoData(.)");
+
+    // Layout-Anordnung fuer GUI
+    layoutConstraints.put( INRASTER_LABEL,   new GridBagConstraints(0,0,2,1,  0,  0,GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5,10,0,10),0,0) );
+    layoutConstraints.put( INRASTER_TABLE,   new GridBagConstraints(0,1,2,1,1.0,1.0,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0,10,5,10),0,0) );
+    layoutConstraints.put( INFILTER_LABEL,   new GridBagConstraints(0,2,2,1,  0,  0,GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5,10,0,10),0,0) );
+    layoutConstraints.put( INFILTER_TABLE,   new GridBagConstraints(0,3,2,1,1.0,1.0,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0,10,5,10),0,0) );
+    layoutConstraints.put( RULE_TEXTFIELD,   new GridBagConstraints(0,4,1,1,1.0,  0,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0,10,5,10),0,0) );
+    layoutConstraints.put( OPERATOR_COMBOBOX,new GridBagConstraints(1,4,1,1,0.0,  0,GridBagConstraints.SOUTHEAST, GridBagConstraints.HORIZONTAL, new Insets(0,10,5,10),2,2) );
+    layoutConstraints.put( OUTRASTER_FIELD,  new GridBagConstraints(0,5,2,1,1.0,  0,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0,10,5,10),2,2) );
+    layoutConstraints.put( START_BUTTON,     new GridBagConstraints(0,6,1,1,0.0,  0,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,10,5,10),0,0) );
+    layoutConstraints.put( LOADFILTER_BUTTON,new GridBagConstraints(1,6,1,1,0.0,  0,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0,10,5,10),0,0) );
+
+    if ( initGUI ) {
+      initGUI();
+      refresh();
+    }
+
+    // Listener auf den Datenpool setzen, damit Auswahlfelder automatisch
+    // aktualisiert werden
+    appl.getDataPool().addObjectListener( new ObjectListener() {
+      public void performObjectEvent(ObjectEvent e) {
+        if ( e instanceof DataPool.DataPoolChangeEvent )
+          refresh();
+      }
+    });
+  }
+
+  /**
+   * Initalisiert die GUI des Fensters.
+   */
+  protected void initGUI() {
+    super.initGUI();
+    // Input-Raster-Tabelle
+    inputRasterTableModel = new InputRasterTableModel(appl);
+    inputRasterTable      = new InputTable(inputRasterTableModel,"Simply drag raster objects from xulu data pool to this table");
+    inputRasterScrollPane = inputRasterTable.createScrollPane();
+    // Input-Filter-Tabelle
+    inputFilterTableModel = new InputFilterTableModel(appl);
+    inputFilterTable      = new InputTable(inputFilterTableModel,"Simply drag matrix properties from xulu data pool to this table");
+    inputFilterScrollPane = inputFilterTable.createScrollPane();
+    // Output-Raster
+    outputRaster = new SelectionInputOption.Combo("Output raster:",false);
+    outputRaster.setToolTipText("Leave this fiels empty, to create an new raster as output");
+    // Button zum Laden der Standard-Filter
+    loadDefaultFilterButton = new JButton("Load default filter...");
+    loadDefaultFilterButton.addActionListener( new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        loadDefaultFilter();
+      }
+    });
+
+// PRUEFEN, VON WELCHER KOMPONENTE DIE DRAG-OPERATION AUSGEHT
+// LEIDER WIRD DER DragSourceListener ERST NACH DEM DropTargetListener
+// AUSGEFUEHRT
+//    // Drag & Drop vom Datenpool
+//    DragSource.getDefaultDragSource().addDragSourceListener( new DragSourceAdapter() {
+//      public void dragMouseMoved(DragSourceDragEvent e) {
+//        System.err.println("dragMoved1");
+//        dragSourceComponent = e.getDragSourceContext().getComponent();
+//        System.err.println( dragSourceComponent );
+//      }
+//      public void dragEnter(DragSourceDragEvent e) {
+//        System.err.println("dragEnter1");
+//
+//        dragSourceComponent = e.getDragSourceContext().getComponent();
+//        System.err.println( dragSourceComponent );
+//      }
+//    });
+
+    // Drag & Drop fuer Input-Raster
+    DropTarget dropTarget = new DropTarget( appl.getMainFrame(), new DropTargetAdapter() {
+      public void dragEnter(DropTargetDragEvent e) {
+//        // Drop nur Zulassen, wenn die Drag-Aktion vom Datenpool ausgeht
+//        if ( !SwingUtil.isChildComponent( dragSourceComponent, appl.getMainFrame().getDataPoolFrame() ) ) {
+//          e.rejectDrop();
+//          return;
+//        }
+
+        // Pruefen, ob mind, ein akzeptables Objekt im Datenpool selektiert ist
+        Object[] selObjects = appl.getMainFrame().getDataPoolFrame().getSelectedObjects();
+        for (Object obj : selObjects)
+          if ( getWritableGridsFromObject(obj) != null )
+            return;
+        // Drop zurueckweisen, wenn kein WritableGrid gefunden wurde
+        e.rejectDrag();
+      }
+
+      public void drop(DropTargetDropEvent e) {
+        Object[] selObjects = appl.getMainFrame().getDataPoolFrame().getSelectedObjects();
+        // Alle WritableGrid-Objekte der selektieren Datenpool-Objekte ermitteln
+        for (Object obj : selObjects) {
+          WritableGrid[] grids = getWritableGridsFromObject(obj);
+          if ( grids == null )
+            continue;
+          // WritableGrid-Objekte des Datenpool-Objekts in die Liste einfuegen
+          for ( WritableGrid grid : grids )
+            try {
+              inputRasterTableModel.addRaster(grid);
+            } catch (Exception err) {
+              XuluGUIMessages.showError(THIS,err);
+            }
+        }
+      }
+    } );
+    inputRasterTable.setDropTarget( dropTarget );
+    inputRasterScrollPane.setDropTarget( dropTarget );
+
+    // Drag & Drop fuer Input-Filter
+    dropTarget = new DropTarget( appl.getMainFrame(), new DropTargetAdapter() {
+      public void dragEnter(DropTargetDragEvent e) {
+//        // Drop nur Zulassen, wenn die Drag-Aktion vom Datenpool ausgeht
+//        if ( !SwingUtil.isChildComponent( dragSourceComponent, appl.getMainFrame().getDataPoolFrame() ) ) {
+//          e.rejectDrop();
+//          return;
+//        }
+
+        // Pruefen, ob mind, ein akzeptables Objekt im Datenpool selektiert ist
+        Object[] selObjects = appl.getMainFrame().getDataPoolFrame().getSelectedObjects();
+        for (Object obj : selObjects)
+          if ( getMatrixPropertiesFromObject(obj) != null )
+            return;
+        // Drop zurueckweisen, wenn keine Matrix gefunden wurde
+        e.rejectDrag();
+      }
+
+      public void drop(DropTargetDropEvent e) {
+        Object[] selObjects = appl.getMainFrame().getDataPoolFrame().getSelectedObjects();
+        // Alle MatrixProperty-Objekte der selektieren Datenpool-Objekte ermitteln
+        for (Object obj : selObjects) {
+          MatrixProperty[] matrices = getMatrixPropertiesFromObject(obj);
+          if ( matrices == null )
+            continue;
+          // MatrixProperty-Objekte des Datenpool-Objekts in die Liste einfuegen
+          for (MatrixProperty matrix : matrices) {
+              try {
+                inputFilterTableModel.addFilterMatrix( matrix/*, matrixName*/);
+              } catch (Exception err) {
+                XuluGUIMessages.showError(SwingUtil.getParentWindowComponent(THIS),err);//,"Matrix "+matrixName+"not suitable for filter!");
+              }
+          }
+        }
+      }
+    } );
+    inputFilterTable.setDropTarget( dropTarget );
+    inputFilterScrollPane.setDropTarget( dropTarget );
+
+    // Komponenten in Fenster anordnen
+    add( new JLabel("Input-Rasters (use context menu or simply drag rasters from xulu data pool):"),
+                                  layoutConstraints.get(INRASTER_LABEL) );
+    add( inputRasterScrollPane,   layoutConstraints.get(INRASTER_TABLE) );
+    add( new JLabel("Input-Filter (use context menu or simply drag matrixes from xulu data pool):"),
+                                  layoutConstraints.get(INFILTER_LABEL) );
+    add( inputFilterScrollPane,   layoutConstraints.get(INFILTER_TABLE) );
+    add( outputRaster,            layoutConstraints.get(OUTRASTER_FIELD) );
+    add( loadDefaultFilterButton, layoutConstraints.get(LOADFILTER_BUTTON) );
+  }
+
+  /**
+   * Aktualisiert die Auswahl-Felder auf Basis des Datenpools.
+   */
+  public void refresh() {
+    // Aktualisierung der Tabelle
+    inputRasterTableModel.refreshInputOption();
+    inputRasterTableModel.fireTableDataChanged();
+
+    // Als Ausgabe-Raster werden alle WritableGrids aus dem Datenpool angeboten
+    Object oldSelection = outputRaster.getValue();
+    Object[][] fitObjects = XuluGUIUtil.determineObjectsFromDataPool(WritableGrid.class, appl.getDataPool());
+    outputRaster.setSelectionObjects(fitObjects[0],fitObjects[1]);
+    outputRaster.setSelectedItem(oldSelection);
+  }
+
+  /**
+   * Prueft die in der Maske spezifizierten Angaben auf Korrektheit. Ist eine
+   * Angabe nicht korrekt, wird ein entsprechender Fehler-Dialog angezeigt.
+   */
+  protected void checkInputsAndError() {
+    if ( !outputRaster.isInputValid() )
+      throw new IllegalArgumentException("Ausgabe-Raster nicht zulaessig!");
+    if ( !rule.isInputValid() )
+      throw new IllegalArgumentException("Formel nicht zulaessig!");
+    RasterCalculator.checkRuleAndError(rule.getValue());
+  }
+
+
+  /**
+   * Liefert die Anzahl an geklammerten Parametern, die ein Operator hat.
+   * Erweitert die Methode der Oberklasse um den Operator {@code isNoData(.)}
+   * und die Filter-Referenz {@code F.}.
+   * @param op Operator
+   * @return 1 fuer {@code isNoData} und {@code F..}, sonst den Wert der {@code super}-Methode
+   */
+  protected int getParameterCount(String op) {
+    // Funktionen mit einem geklammerten Parameter
+    if (op.equalsIgnoreCase("isNoData") || op.charAt(0) == 'F')
+      return 1;
+    return super.getParameterCount(op);
+  }
+
+  /**
+   * Laed Standard-Filter aus der Datei {@code <Plugin-Dir>\RasterCalculator\default_filter.inp}
+   * in den Datenpool.
+   * @see #DEFAULT_FILTER_FILENAME
+   */
+  private void loadDefaultFilter() {
+    try {
+      // (eindeutige) Import-Factory fuer Dynamische Xulu-Objekte ermitteln,
+      // die aus einem File oder FileInputStream importieren kann
+      ImportFactory[] factories = appl.getRegistry().getImportFactories( DynamicXuluObject.class );
+      if ( factories.length < 1 )
+        throw new UnsupportedOperationException("No import factory for DynamicXuluObject found in registry!");
+      if ( factories.length > 1 )
+        throw new UnsupportedOperationException("More than one import factories for DynamicXuluObject found in registry!");
+      ImportFactory importFac = factories[0];
+      if ( !importFac.getImportSourceType().isAssignableFrom(File.class) &&
+           !importFac.getImportSourceType().isAssignableFrom(FileInputStream.class) )
+        throw new UnsupportedOperationException("Registrated import factories for DynamicXuluObject can neither import from File nor from FileInputStream!");
+
+      // Dynamisches Xulu-Objekt importieren
+      File   importFile = new File( appl.getPluginDirectory(), "RasterCalculator"+File.separator+DEFAULT_FILTER_FILENAME );
+      Object importObject = null;
+      if ( importFac.getImportSourceType().isAssignableFrom(File.class) )
+        importObject = importFile;
+      if ( importFac.getImportSourceType().isAssignableFrom(FileInputStream.class) )
+        importObject = new FileInputStream(importFile);
+      DynamicXuluObject dynXuluObj = (DynamicXuluObject)importFac.importObject(importObject,appl.getRegistry());
+
+      // Alle Objekte aus dem Datenpool entfernen, die den gleichen Namen
+      // haben, wie das neuen Objekt
+      XuluObject[] presentObj = appl.getDataPool().getObjects( dynXuluObj.getDescription() );
+      if ( presentObj.length > 0 ) {
+        if ( MultipleOptionPane.showConfirmDialog(this,"Override existing data pool object(s) '"+dynXuluObj.getDescription()+"'?","Override...",MultipleOptionPane.OK_CANCEL_OPTION) == MultipleOptionPane.CANCEL_OPTION )
+          return;
+        for (XuluObject xuluObj : presentObj)
+          appl.getDataPool().removeObject(xuluObj);
+      }
+
+      // Neues Objekt dem Datenpool hinzufuegen
+      appl.getDataPool().addObject( dynXuluObj );
+      // Filter direkt in die Filter-Liste einfuegen
+      if ( MultipleOptionPane.showConfirmDialog(this,"Add loaded filters automatically to filter list?","Add filter...",MultipleOptionPane.OK_CANCEL_OPTION) == MultipleOptionPane.CANCEL_OPTION )
+        return;
+      for ( Property matrix : dynXuluObj.getProperties(MatrixProperty.class).getProperties() )
+        inputFilterTableModel.addFilterMatrix( (MatrixProperty)matrix );
+
+    } catch (Exception err) {
+      XuluGUIMessages.showError(this,err);
+    }
+  }
+
+  /**
+   * Erzeugt einen {@link RasterOperationTree} aus der Formel und wertet diese
+   * aus. Das Ergebnis wird in das Ausgabe-Raster geschrieben
+   * @return das Ausgabe-Raster, als {@link WritableGrid}-Wert
+   * @see RasterOperationTreeParser
+   */
+  protected Object performCalculation() throws Exception {
+    // Eingabe-Raster als WritableGrid-Array
+    WritableGrid[] inGrid = inputRasterTableModel.getRasters();
+    // Eingabe-Filter als WritableGrid-Array
+    RasterFilter[] inFilter = inputFilterTableModel.getFilter();
+
+    // Ausgabe-Raster ermitteln (wenn keines angegeben, wird eines erzeugt)
+    WritableGrid outGrid = null;
+    Object outGridValue = outputRaster.getValue();
+    if (outGridValue == null) {
+      // Namen fuer Raster abfragen
+      Object[] retObject = MultipleOptionPane.showMultipleInputDialog( SwingUtil.getParentWindowComponent(THIS), "Create new Object...", new InputOption[] {
+          new ManualInputOption.Text("Raster name:", true, "RasterCalculator OUT")
+      });
+      if ( retObject == null )
+        return null; // Dialog abgebrochen
+      String rasterName = (String)retObject[0];
+      SingleGrid singleGrid = null;
+      if ( inGrid.length > 0 )
+        // Ausgabe-Grid auf Basis des Eingabe-Rasters erzeugen
+        singleGrid = ((SingleGrid)appl.getRegistry().getDefaultFactory( SingleGrid.class ).newInstance(false,inGrid[0]));
+      else
+        // Dimension des Ausgabe-Grid abfragen
+        singleGrid = ((SingleGrid)appl.getRegistry().getDefaultFactory( SingleGrid.class ).newInstance(true));
+      singleGrid.setDescription( rasterName );
+      appl.getDataPool().addObject(singleGrid);
+      outGrid = singleGrid.getGrid();
+      outputRaster.setValue( outGrid );
+    } else
+      outGrid = ( outGridValue instanceof SingleGrid ) ? ((SingleGrid)outGridValue).getGrid() : (WritableGrid)outGridValue;
+    RasterCalculator.calculate(rule.getValue(), inGrid, inFilter, outGrid);
+    return outGrid;
+  }
+
+  private static WritableGrid[] getWritableGridsFromObject(Object obj) {
+    if ( obj instanceof SingleGrid )
+      obj = ((SingleGrid)obj).getProperty( SingleGrid.PROP_GRID );
+    if ( obj instanceof MultiGrid )
+      obj = ((MultiGrid)obj).getProperty( MultiGrid.PROP_GRIDS );
+
+    if ( obj instanceof WritableGrid )
+      return new WritableGrid[] { (WritableGrid)obj };
+    if ( obj instanceof ScalarProperty && WritableGrid.class.isAssignableFrom( ((ScalarProperty)obj).getType() ) )
+      return new WritableGrid[] { (WritableGrid)((ScalarProperty)obj).getOneTimeReadAccess().getValue() };
+    if ( obj instanceof ListProperty && WritableGrid.class.isAssignableFrom( ((ListProperty)obj).getType() ) ) {
+      ListPropertyReadAccess a = ((ListProperty)obj).getReadAccess(obj);
+      WritableGrid[] grids = new WritableGrid[ a.getCount() ];
+      for (int i=0; i<grids.length; i++)
+        grids[i] = (WritableGrid)a.getValue(i);
+      a.release();
+      return grids;
+    }
+    return null;
+  }
+
+  private static MatrixProperty[] getMatrixPropertiesFromObject(Object obj) {
+    if ( obj instanceof MatrixProperty )
+      return new MatrixProperty[] { (MatrixProperty)obj };
+    if ( obj instanceof Properties ) {
+      Property[] props = ((Properties)obj).getProperties(MatrixProperty.class).getProperties();
+      MatrixProperty[] matrices = new MatrixProperty[props.length];
+      for (int i=0; i<props.length; i++ )
+        matrices[i] = (MatrixProperty)props[i];
+      return matrices;
+    }
+    return null;
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  /////////////////   Table fuer die DnD-Tabellen   /////////////////
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse stellt eine Tabelle fuer die Eingabe-Daten dar. Diese hat
+   * keinen Header und es wird kein Tabellen-Raster angezeigt. Ueber ein
+   * Kontextmenue koennen der Tabelle Daten hinzugefuegt oder entfernt werden.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  private class InputTable extends MutableTable {
+    /**
+     * Erzeugt einen neue Tabelle
+     * @param tableModel Daten-Modell fuer die Tabelle
+     * @param toolTip Hilfe-Text der als ToolTip-Text angezeigt wird
+     */
+    public InputTable(InputTableModel tableModel, String toolTip) {
+      super( tableModel, MutableTable.ITEM_REMOVE | MutableTable.ITEM_ADD );
+      this.setToolTipText( toolTip );
+      this.setTableHeader(null);
+      this.setShowGrid(false);
+      this.getColumnModel().getColumn(0).setMaxWidth(30);
+      // Bei Doppelklick auf Tabelle wird der Wert aus Spalte 0 in die Formel
+      // eingefuegt
+      this.addMouseListener( new MouseAdapter() {
+        public void mouseClicked(MouseEvent e) {
+          // Nur auf Doppelklick reagieren
+          if ( e.getButton() != MouseEvent.BUTTON1 ||
+               e.getClickCount() != 2 )
+            return;
+          // Selektierte Zeile ermitteln
+          String selValue = (String)getModel().getValueAt(
+              getSelectedRow(),
+              0
+          );
+          // Attribut-Namen in Formel einfuegen
+          performOperatorInsert(selValue, (JTextField)rule.getInputComponent());
+          // Fokus zurueck auf Formel-Feld
+          rule.grabFocus();
+        }
+      });
+    }
+
+    /**
+     * Erzeugt einen neue Tabelle
+     * @param tableModel Daten-Modell fuer die Tabelle
+     */
+    public InputTable(InputTableModel tableModel) {
+      this(tableModel,"");
+    }
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  //////////////   TableModels fuer die DnD-Tabellen   //////////////
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse stellt das Daten-Modell der Eingabe-Tabellen dar. Dieses
+   * stellt immer 2 Spalten zur Verfuegung. In der ersten Spalte wird die
+   * Zeilennummer (eingeleitet durch ein {@linkplain #rowIndexPrefix Praefix})
+   * dargestellt, in der zweiten Spalte ein Objekt vom Typ {@code <O>}.
+   * Durch einen Rechtsklick, koennen der Tabelle Objekte aus dem Datenpool
+   * hinzugefuegt oder entfernt werden. Dabei werden die Objekte aus dem
+   * Array {@code #fitObjects} (bzw. {@code fitObjectNames}) vorgeblendet.
+   * Diese Array passend zu fuellen muss durch die Sub-Klassen in der Methode
+   * {@link #determineFitObjectsAndNames()} implementiert werden.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  private abstract class InputTableModel<O> extends AbstractMutableTableModel {
+    /** Speichert die in der Tabelle gespeicherten Raster */
+    protected Vector<O> objects = new Vector<O>();
+    /** Speichert die Namen der in der Tabelle gespeicherten Objekte */
+    protected Vector<String> objectNames = new Vector<String>();
+    /** Speichert die Instanz der Xulu-Applikation. */
+    protected XuluModellingPlatform appl = null;
+    /** Eingabe-Option fuer ein einzelnes Objekt. */
+    protected SelectionInputOption.Combo objectInputOption = null;
+
+    /** Speichert das Zeilennummer-Praefix. */
+    protected String rowIndexPrefix = null;
+
+
+    /** Flag, ob sich der Inhalt des Datenpools geaendert hat und die Arrays
+     *  {@link #fitObjects} und {@link #fitObjectNames} aktualisiert werden
+     *  muessen */
+    protected boolean  dataPoolChanged = true;
+    /** Passende Objekte im Datenpool */
+    protected Object[] fitObjects = null;
+    /** Bezeichnungen der passenden Objekte im Datenpool */
+    protected String[] fitObjectNames = null;
+
+    /**
+     * Erzeugt ein neues Tabellen-Modell.
+     * @param appl Instanz der Xulu-Applikation
+     * @param rowIndexPrefix Praefix, das den Zeilen-Indizes vorangestellt wird
+     */
+    public InputTableModel(XuluModellingPlatform appl, String rowIndexPrefix) {
+      super();
+      this.appl = appl;
+      this.rowIndexPrefix = rowIndexPrefix;
+      objectInputOption = new SelectionInputOption.Combo(getColumnName(1),true);
+      refreshInputOption();
+      // Listener auf den Datenpool setzen, damit das Auswahlfeld aktualisiert
+      // werden kann (wenn notwendig)
+      appl.getDataPool().addObjectListener( new ObjectListener() {
+        public void performObjectEvent(ObjectEvent e) {
+          if ( e instanceof DataPool.DataPoolChangeEvent ) {
+            dataPoolChanged = true;
+          }
+        }
+      });
+    }
+
+    /**
+     * Ruft {@link #determineFitObjectsAndNames()}, wenn das {@link #dataPoolChanged}-Flag
+     * auf {@code true} steht und setzt das Flag zurueck.
+     */
+    protected void refreshFitObjects() {
+      if ( dataPoolChanged )
+        determineFitObjectsAndNames();
+      dataPoolChanged = false;
+    }
+
+    /**
+     * Aktualisiert das Dialog-Auswahlfeld, in dam alle passenden Objekte
+     * aus dem Datenpool vorgeblendet werden.
+     */
+    protected void refreshInputOption() {
+      refreshFitObjects();
+      objectInputOption.setSelectionObjects(fitObjects,fitObjectNames);
+    }
+
+    /**
+     * Wird aufgerufen, wenn sich der Inhalt des Xulu-Datenpools aendert.
+     * Muss die Arrays {@link #fitObjects} und {@link #fitObjectNames} mit
+     * allen passenden Objekten des Datenpools und deren Bezeichnungen
+     * befuellen.
+     */
+    protected abstract void determineFitObjectsAndNames();
+
+
+    /**
+     * Loescht eine Tabellenzeile.
+     * @param row Zeilenindex (beginnend bei 0)
+     */
+    public void performRemoveRow(int row) {
+      objects.remove(row);
+      objectNames.remove(row);
+    }
+
+    /**
+     * Macht nichts, da in der Tabelle keine Daten veraendert werden koennen.
+     * @param row Zeilenindex (beginnend bei 0)
+     * @param col Spaltenindex (beginnend bei 0)
+     */
+    public void performChangeData(int row, int col) {
+    }
+
+    /**
+     * Liefert die Anzahl an Zeilen.
+     */
+    public int getRowCount() {
+      return objects.size();
+    }
+
+    /**
+     * Liefert den Inahlt einer Tabellenzelle.
+     * @param row Zeilenindex (beginnend bei 0)
+     * @param col Spaltenindex (beginnend bei 0)
+     */
+    public Object getValueAt(int row, int col) {
+      switch ( col ) {
+        case 0: return rowIndexPrefix+row;
+        case 1: return objectNames.elementAt(row);
+      }
+      return null;
+    }
+
+  }
+
+  /**
+   * Diese Klasse stellt das Daten-Modell der Eingaberaster-Tabelle dar.
+   * Durch einen Rechtsklick, koennen der Tabelle {@link WritableGrid}-Objekte
+   * aus dem Datenpool hinzugefuegt oder entfernt werden.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  private class InputRasterTableModel extends InputTableModel<WritableGrid> {
+    /**
+     * Erzeugt ein neues Tabellen-Modell.
+     */
+    public InputRasterTableModel(XuluModellingPlatform appl) {
+      super(appl,"#");
+    }
+
+    /**
+     * Liefert die Spaltennamen der Tabelle.
+     */
+    @Override
+    public String[] createColumnNames() {
+      return new String[] {"Index","Raster-Object"};
+    }
+    
+    /**
+     * Befuellt die Arrays {@link #fitObjects} und {@link #fitObjectNames} mit
+     * allen {@link WritableGrid}- und {@link MultiGrid}-Objekten des
+     * Datenpools und deren (rekursiven) Bezeichnungen.
+     */
+    protected void determineFitObjectsAndNames() {
+      Vector fitRasterObjects = new Vector();
+      Vector fitRasterObjectNames = new Vector();
+      XuluGUIUtil.determineObjectsFromDataPool(MultiGrid.class, appl.getDataPool(), fitRasterObjects, fitRasterObjectNames);
+      XuluGUIUtil.determineObjectsFromDataPool(WritableGrid.class, appl.getDataPool(), fitRasterObjects, fitRasterObjectNames);
+      this.fitObjects     = fitRasterObjects.toArray();
+      this.fitObjectNames = (String[])fitRasterObjectNames.toArray(new String[0]);
+    }
+
+    /**
+     * Liefert die in der Tabelle angezeigten Raster als Array.
+     */
+    public WritableGrid[] getRasters() {
+      return (WritableGrid[])objects.toArray(new WritableGrid[0]);
+    }
+
+    /**
+     * Zeigt einen Dialog an, in dem alle {@link WritableGrid}- und
+     * {@link MultiGrid}-Objekte des Datenpools zur Auswahl stehen.
+     */
+    public void performAddRow() {
+      refreshFitObjects();
+      Object[] value = MultipleOptionPane.showMultipleInputDialog(getParent(),"Select raster...",objectInputOption);
+      if ( value == null )
+        return;
+
+      Object selObject = objectInputOption.getValue();
+      String selName   = (String)objectInputOption.getSelectedDisplayItem();
+      if ( selObject instanceof WritableGrid)
+        addRaster((WritableGrid)selObject,selName);
+      if ( selObject instanceof MultiGrid ) {
+        MultiGrid multiGrid = (MultiGrid)selObject;
+        for (int i=0; i<multiGrid.getGridCount(); i++)
+          addRaster(multiGrid.getGrid(i),selName+"["+i+"]");
+      }
+    }
+
+    /**
+     * Fuegt der Tabelle ein Raster hinzu.
+     * @param raster Raster
+     * @param name   Name fuer das Raster, der in der Tabelle angezeigt wird
+     */
+    public void addRaster(WritableGrid raster, String name) {
+      refreshFitObjects();
+      // Pruefen, ob Raster mit den anderen Rastern uebereinstimmt
+      if ( this.objects.size() > 0 ) {
+        WritableGrid presentGrid = this.objects.elementAt(0);
+        if ( raster.getWidth() != presentGrid.getWidth() ||
+             raster.getHeight() != presentGrid.getHeight() )
+          throw new UnsupportedOperationException("New Raster does not fit to the other rasters in the list!");
+      }
+      this.objects.add(raster);
+      this.objectNames.add(name);
+      this.fireTableDataChanged();
+    }
+
+    /**
+     * Fuegt der Tabelle ein Raster hinzu. Der Name des Objekts wird automatisch
+     * aus dem Datenpool ermittelt.
+     * @param raster Raster
+     */
+    public void addRaster(WritableGrid raster) {
+      refreshFitObjects();
+      String rasterName = "dummy";
+      for (int i=0; i<fitObjects.length; i++)
+        if ( raster == fitObjects[i] ) {
+          rasterName = fitObjectNames[i];
+          break;
+        }
+      addRaster(raster,rasterName);
+    }
+
+  }
+
+  /**
+   * Diese Klasse stellt das Daten-Modell der Eingabefilter-Tabelle dar.
+   * Durch einen Rechtsklick, koennen der Tabelle {@link MatrixProperty}-Objekte
+   * aus dem Datenpool hinzugefuegt oder entfernt werden.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  private class InputFilterTableModel extends InputTableModel<MatrixProperty> {
+
+    /**
+     * Erzeugt ein neues Tabellen-Modell.
+     */
+    public InputFilterTableModel(XuluModellingPlatform appl) {
+      super(appl,"F");
+    }
+
+    /**
+     * Liefert die Spaltennamen der Tabelle.
+     */
+    @Override
+    public String[] createColumnNames() {
+      return new String[] {"Index","Filter-Object"};
+    }
+
+    /**
+     * Befuellt die Arrays {@link #fitObjects} und {@link #fitObjectNames} mit
+     * allen {@link MatrixProperty}-Objekten des Datenpools und deren
+     * (rekursiven) Bezeichnungen.
+     */
+    protected void determineFitObjectsAndNames() {
+      Object[][] fitMatrixObjects = XuluGUIUtil.determineObjectsFromDataPool(MatrixProperty.class, appl.getDataPool());
+      this.fitObjects     = fitMatrixObjects[0];
+      this.fitObjectNames = (String[])fitMatrixObjects[1];
+    }
+
+    /**
+     * Liefert die in der Tabelle angezeigten Matrix-Objekte Filter-Array.
+     */
+    public RasterFilter[] getFilter() {
+      RasterFilter[] filter = new RasterFilter[objects.size()];
+      for (int i=0; i<objects.size(); i++) {
+        MatrixProperty matrix = objects.elementAt(i);
+        filter[i] = new RasterFilter(matrix.getSize(0), matrix.getSize(1));
+        PropertyReadAccess access = matrix.getReadAccess(this);
+        for (int y=0; y<filter[i].getFilterSizeY(); y++)
+          for (int x=0; x<filter[i].getFilterSizeX(); x++)
+            filter[i].setFilterValue(access.getValueAsDouble(x, y), x, y);
+        access.release();
+      }
+      return filter;
+    }
+
+    /**
+     * Zeigt einen Dialog an, in dem alle {@link MatrixProperty}-Objekte
+     * des Datenpools zur Auswahl stehen.
+     */
+    public void performAddRow() {
+      Object[] value = MultipleOptionPane.showMultipleInputDialog(getParent(),"Select matrix...",objectInputOption);
+      if ( value == null )
+        return;
+
+      Object selObject = objectInputOption.getValue();
+      String selName   = (String)objectInputOption.getSelectedDisplayItem();
+      if ( selObject instanceof MatrixProperty )
+        try {
+          addFilterMatrix( (MatrixProperty) selObject, selName);
+        } catch (Exception err) {
+          XuluGUIMessages.showError(SwingUtil.getParentWindowComponent(THIS),err,"Matrix '"+selName+"' not suitable for filter!");
+        }
+    }
+
+    /**
+     * Fuegt der Tabelle einen Filter hinzu.
+     * @param filterMatrix Filter
+     * @param name   Name fuer das Raster, der in der Tabelle angezeigt wird
+     */
+    public void addFilterMatrix(MatrixProperty filterMatrix, String name) {
+      refreshFitObjects();
+      // Pruefen, ob Matrix als Filter in Frage kommt
+      if ( filterMatrix.getDimension() != 2 )
+        throw new UnsupportedOperationException("Only a 2-dimensional matrix can be used as filter!");
+      if ( filterMatrix.getSize(0)%2 != 1 || filterMatrix.getSize(1)%2 != 1 )
+        throw new UnsupportedOperationException("To use a matrix as filter its size must be odd in each dimension!");
+      this.objects.add(filterMatrix);
+      this.objectNames.add(name);
+      this.fireTableDataChanged();
+    }
+
+    /**
+     * Fuegt der Tabelle einen Filter hinzu. Der Name des Objekts wird automatisch
+     * aus dem Datenpool ermittelt.
+     * @param filterMatrix Filter
+     */
+    public void addFilterMatrix(MatrixProperty filterMatrix) {
+      refreshFitObjects();
+      String filterMatrixName = "dummy";
+      for (int i=0; i<fitObjects.length; i++)
+        if ( filterMatrix == fitObjects[i] ) {
+          filterMatrixName = fitObjectNames[i];
+          break;
+        }
+      addFilterMatrix(filterMatrix,filterMatrixName);
+    }
+
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/appl/RasterCalculatorPlugin.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/appl/RasterCalculatorPlugin.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/appl/RasterCalculatorPlugin.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,42 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.appl;
+
+import schmitzm.lang.LangUtil;
+
+import edu.bonn.xulu.gui.XuluInternalFrame;
+
+/**
+ * Dieses Plugin integriert die {@link edu.bonn.xulu.plugin.appl.RasterCalculatorGUI}
+ * in das Xulu-Menue "Erweitert".
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class RasterCalculatorPlugin extends AbstractMenuPlugin {
+  private static final int MENU_ID = 4; // Erweitert
+  private static final String CALCULATOR_CLASSNAME = "edu.bonn.xulu.plugin.appl.RasterCalculatorGUI";
+
+  /**
+   * Erzeugt eine neue Plugin-Instanz.
+   */
+  public RasterCalculatorPlugin() {
+    super(MENU_ID,"Raster-Calculator");
+  }
+
+  /**
+   * Erzeugt eine Instanz der Plugin-Applikation {@link RasterCalculatorGUI}.
+   */
+  protected XuluInternalFrame createPluginApplication() throws Exception {
+//    return (XuluInternalFrame)LangUtil.loadPreferredObject(CALCULATOR_CLASSNAME,appl);
+    return new RasterCalculatorGUI(appl);
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/appl/VisualisationHandler.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/appl/VisualisationHandler.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/appl/VisualisationHandler.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,165 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.appl;
+
+import schmitzm.data.event.ObjectEvent;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.AbstractHandler;
+import edu.bonn.xulu.appl.VisualisationTool;
+import edu.bonn.xulu.gui.XuluGUIMessages;
+import edu.bonn.xulu.data.XuluObject;
+
+/**
+ * Diese Klasse stellt einen Handler dar, mit dem die Visualisierung eines
+ * Objekts aktualisiert wird. Instanzen dieses Handlers werden (interaktiv)
+ * ueber eine {@link VisualisationHandlerFactory} erzeugt, bzw. modifiziert.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class VisualisationHandler extends AbstractHandler {
+  /** Speichert das Objekt, das vom Handler dargestellt/aktualisiert wird. */
+  protected Object object = null;
+
+  /** Speichert das Visualisierungstool, in dem das Objekt dargestellt wird/ist. */
+  protected VisualisationTool visTool = null;
+
+  /** Speichert das Klasse des Visualisierungstool, in dem das Objekt dargestellt wird/ist. */
+  protected Class<VisualisationTool> visToolClass = null;
+
+  /** Speichert eine Referenz auf die Xulu-Applikation. */
+  protected XuluModellingPlatform appl = null;
+
+  /**
+   * Erzeugt einen neuen Handler. Dem Handler ist noch kein konkretes Objekt und
+   * auch noch kein Visualisierungstool (fuer die Darstellung) zugeordnet.
+   * @param fac Factory, die fuer den Handler zustaendig ist.
+   * @param appl Instanz der Xulu-Applikation
+   * @see #setObject(Object)
+   * @see #setVisualisationTool(VisualisationTool)
+   */
+  public VisualisationHandler(VisualisationHandlerFactory fac, XuluModellingPlatform appl) {
+    this(fac,(VisualisationTool)null,null,appl);
+  }
+
+  /**
+   * Erzeugt einen neuen Handler.
+   * @param obj zu visualisierendes Objekt
+   * @param visTool Tool, in dem das Objekt vom Handler visualisiert wird
+   * @param fac Factory, die fuer den Handler zustaendig ist.
+   * @param appl Instanz der Xulu-Applikation
+   */
+  public VisualisationHandler(Object obj, VisualisationTool visTool, VisualisationHandlerFactory fac, XuluModellingPlatform appl) {
+    this(obj,(visTool != null) ? (Class<VisualisationTool>)visTool.getClass() : null,fac,appl);
+    this.visTool = visTool;
+  }
+
+  /**
+   * Erzeugt einen neuen Handler. Beim ersten Aufruf des Handlers wird eine
+   * Instanz des Visualisierungstools erstellt.
+   * @param obj zu visualisierendes Objekt
+   * @param visToolClass Klasse des Tools, in dem das Objekt vom Handler visualisiert wird
+   * @param fac Factory, die fuer den Handler zustaendig ist.
+   * @param appl Instanz der Xulu-Applikation
+   */
+  public VisualisationHandler(Object obj, Class<VisualisationTool> visToolClass, VisualisationHandlerFactory fac, XuluModellingPlatform appl) {
+    super(fac);
+    this.object  = obj;
+    this.visTool = null;
+    this.visToolClass = visToolClass;
+    this.appl = appl;
+  }
+
+  /**
+   * Schliesst den Handler. Macht nichts.
+   */
+  public void close() {
+  }
+
+  /**
+   * Fuehrt den Handler aus. Das Objekt wird im Visualisierungstool aktualisiert,
+   * bzw. dem Visualisierungstool hinzugefuegt, falls es noch nicht dargestellt
+   * wird.
+   * @param e Ereignis fuer das der Handler ausgefuehrt wird (wird nicht verwendet!).
+   */
+  public void execute(ObjectEvent e) {
+    // Wenn das Vis-Tool noch nicht existiert, wird eine Instanz erstellt
+    // und dem Vis-Manager hinzugefuegt
+    if ( visTool == null )
+      try {
+        visTool = visToolClass.newInstance();
+        appl.getVisualisationManager().add(visTool,true);
+      } catch (Exception err) {
+          XuluGUIMessages.showError(null,err);
+      }
+
+    // Wenn Objekt noch nicht im Vis-Tool dargestellt wird, wird es
+    // hinzugefuegt
+    if ( !visTool.update(object) ) {
+      String desc = "neues Objekt";
+      if ( object instanceof XuluObject )
+        desc =  ((XuluObject)object).getDescription();
+      visTool.add(object, desc);
+    }
+  }
+
+
+  /**
+   * Liefert das Objekt, das vom Handler dargestellt/aktualisiert wird.
+   */
+  public Object getObject() {
+    return object;
+  }
+
+  /**
+   * Setzt das Objekt, das vom Handler dargestellt/aktualisiert wird.
+   * @param obj zu visualisierendes Objekt
+   */
+  public void setObject(Object obj) {
+    this.object = obj;
+  }
+
+  /**
+   * Liefert das Visualisierungstool, in dem der Handler das Objekt darstellt.
+   */
+  public VisualisationTool getVisualisationTool() {
+    return visTool;
+  }
+
+  /**
+   * Setzt das Visualisierungstool, in dem der Handler das Objekt darstellt.
+   * @param visTool Tool, in dem das Objekt vom Handler visualisiert wird
+   */
+  public void setVisualisationTool(VisualisationTool visTool) {
+    this.visTool = visTool;
+    this.visToolClass = (visTool==null) ? null : (Class<VisualisationTool>)visTool.getClass();
+  }
+
+  /**
+   * Setzt die Klasse des Visualisierungstools, in dem der Handler das Objekt darstellt.
+   * Ist dem Handler bereits ein konkretes Visualisierungstool zugeordnet und
+   * entspricht dieses <b>nicht</b> dieser Klasse, so wird das bestehende
+   * Visualisierungstool ({@link #visTool}) zurueckgesetzt.
+   * @param visToolClass Tool, in dem das Objekt vom Handler visualisiert wird
+   */
+  public void setVisualisationToolClass(Class<VisualisationTool> visToolClass) {
+    this.visToolClass = visToolClass;
+    if ( !(visToolClass.isInstance(this.visTool)) )
+      this.visTool = null;
+  }
+
+  /**
+   * Liefert die Klasse des Visualisierungstools, in dem der Handler das Objekt darstellt.
+   */
+  public Class<VisualisationTool> getVisualisationToolClass() {
+    return this.visToolClass;
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/appl/VisualisationHandlerFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/appl/VisualisationHandlerFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/appl/VisualisationHandlerFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,105 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.appl;
+
+import schmitzm.swing.MultipleOptionPane;
+import schmitzm.swing.InputOption;
+import schmitzm.swing.SelectionInputOption;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.Handler;
+import edu.bonn.xulu.appl.HandlerFactory;
+import edu.bonn.xulu.appl.VisualisationTool;
+import edu.bonn.xulu.appl.XuluConstants;
+import edu.bonn.xulu.io.Factory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.gui.DataPoolInputOption;
+
+/**
+ * Mit dieser Factory werden Instanzen des {@link VisualisationHandler}
+ * erstellt und modifiziert. Die benoetigten Informationen (darzustellendes
+ * Datenpool-Objekt und Visualisierungstool) werden interaktiv ueber Dialoge vom
+ * Anwender abgefragt.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of  Bonn/Germany)
+ * @version 1.0
+ */
+public class VisualisationHandlerFactory extends AbstractFactory implements HandlerFactory {
+  /**
+   * Erzeugt eine neue Handler-Factory.
+   */
+  public VisualisationHandlerFactory() {
+    this("");
+  }
+
+  /**
+   * Erzeugt eine neue Handler-Factory.
+   * @param name Beschreibung der Factory
+   */
+  public VisualisationHandlerFactory(String name) {
+    super(name);
+  }
+
+  /**
+   * Erzeugt einen neuen {@link VisualisationHandler}.
+   * @param appl Instanz der Xulu-Applikation
+   */
+  public VisualisationHandler createHandler(XuluModellingPlatform appl) {
+    Object[] input = showDialog(appl,null,null);
+    if ( input == null || input.length < 2 )
+      return null;
+    return input[1] instanceof VisualisationTool ? new VisualisationHandler(input[0],(VisualisationTool)input[1],this,appl) : new VisualisationHandler(input[0],(Class)input[1],this,appl);
+  }
+
+  /**
+   * Veraendert einen bestehenden {@link VisualisationHandler}.
+   * @param appl Instanz der Xulu-Applikation
+   * @param handler Handler, der veraendert werden soll
+   * @exception UnsupportedOperationException falls der uebergebene Handler
+   *            kein {@link VisualisationHandler} ist
+   */
+  public void modifyHandler(XuluModellingPlatform appl, Handler handler) {
+    if ( !(handler instanceof VisualisationHandler) )
+      throw new UnsupportedOperationException("VisualisationHandlerFactory can only modify instances of VisualisationHandler.");
+    VisualisationHandler visHandler = (VisualisationHandler)handler;
+    Object[] input = showDialog(appl,visHandler.getObject(), visHandler.getVisualisationTool() != null ? visHandler.getVisualisationTool() : visHandler.getVisualisationToolClass());
+    if ( input != null && input.length >= 2 ) {
+      visHandler.setObject(input[0]);
+      if ( input[1] instanceof Class ) {
+        // Wenn eine Klasse angewaehlt wurde, soll ein neues VisTool-Fenster
+        // erzeugt werden. Das bisher gesetzte Tool muss erst geloescht werden,
+        // da ansonsten das Setzen der Klasse keine Auswirkungen hat
+        visHandler.setVisualisationTool( null );
+        visHandler.setVisualisationToolClass( (Class) input[1]);
+      }
+      else
+        visHandler.setVisualisationTool( (VisualisationTool)input[1] );
+    }
+  }
+
+  private Object[] showDialog(XuluModellingPlatform appl, Object object, Object visTool) {
+    // existierende Visualisierungstools und Tool-Klassen
+    VisualisationTool[] visTools         = appl.getVisualisationManager().getAll();
+    Class[]             visToolClasses   = appl.getRegistry().getVisualisationTools();
+    Object[]            visToolItems     = new Object[visTools.length+visToolClasses.length];
+    String[]            visToolItemDescs = new String[visToolItems.length];
+    for (int i=0; i<visToolItemDescs.length; i++) {
+      visToolItems[i]     = (i<visTools.length) ? visTools[i] : visToolClasses[i-visTools.length];
+      visToolItemDescs[i] = (visToolItems[i] instanceof Class) ? ((Class)visToolItems[i]).getSimpleName()+" ("+XuluConstants.XULUGUI_RES.getString("new")+")" : ((VisualisationTool)visToolItems[i]).getTitle();
+    }
+
+    // Dialog erzeugen
+    return MultipleOptionPane.showMultipleInputDialog(null,XuluConstants.XULUGUI_RES.getString("Handler"), new InputOption[] {
+        new DataPoolInputOption(appl.getDataPool(),XuluConstants.XULUGUI_RES.getString("UpdateObject"),true,object),
+        new SelectionInputOption.Combo(XuluConstants.XULUGUI_RES.getString("VisTool")+":",true,visToolItems,visTool,visToolItemDescs),
+    });
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/appl/XuluRegistryReader_BasicAscii.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/appl/XuluRegistryReader_BasicAscii.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/appl/XuluRegistryReader_BasicAscii.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,380 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.appl;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.BufferedReader;
+import java.util.StringTokenizer;
+import java.util.NoSuchElementException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.net.MalformedURLException;
+
+import schmitzm.io.IOUtil;
+import schmitzm.lang.NamedObject;
+import schmitzm.lang.LangUtil;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.io.TypeMapping;
+
+import edu.bonn.xulu.appl.XuluPlugin;
+import edu.bonn.xulu.appl.ScriptInterpreter;
+import edu.bonn.xulu.appl.XuluRegistry;
+import edu.bonn.xulu.appl.XuluRegistryReader;
+
+
+// nur fuer Doku
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.appl.VisualisationTool;
+import edu.bonn.xulu.model.XuluModel;
+
+/**
+ * Diese Klasse dient dazu, die Xulu-Registry aus einem ASCII-InputStream
+ * (z.B. einer ASCII-Datei) einzulesen.<br>
+ * Dieser muss folgendes (zeilenweises) Format haben:<br>
+ * <br>
+ * <code>[Global]</code><br>
+ * <i><small>Alle Klassen in diesem Bereich werden in der Xulu-Registry fuer alles
+ *    registriert, wofuer sie geeignet sind (siehe
+ *    {@link XuluRegistry#register(Object)}).</small></i><br>
+ * <code><i>package.class</i> [<i>name</i>]<br>
+ *       <i>package.class</i> [<i>name</i>]<br>
+ *       ...<br></code>
+ * <code>[DataType]</code><br>
+ * <i><small>Alle Klassen in diesem Bereich werden in der Xulu-Registry als
+ *    Datentyp registriert. Sie muessen (Sub)Klassen von {@link XuluObject}
+ *    darstellen.</small></i><br>
+ * <code><i>package.class</i><br>
+ *       <i>package.class</i><br>
+ *       ...<br></code>
+ * <code>[DefaultFactory]</code><br>
+ * <i><small>Alle Klassen in diesem Bereich werden in der Xulu-Registry nur als
+ *    Default-Factory registriert. Sie muessen (Sub)Klassen von
+ *    {@link InstantiationFactory} darstellen und
+ *    ueber einen Standard-Konstruktor instanziierbar sein.</small></i><br>
+ * <code><i>package.class</i> [<i>name</i>]<br>
+ *       <i>package.class</i> [<i>name</i>]<br>
+ *       ...<br></code>
+ * <code>[ImportFactory]</code><br>
+ * <i><small>Alle Klassen in diesem Bereich werden in der Xulu-Registry nur als
+ *    Import-Factory registriert. Sie muessen (Sub)Klassen von
+ *    {@link ImportFactory} darstellen und
+ *    ueber einen Standard-Konstruktor instanziierbar sein.</small></i><br>
+ * <code><i>package.class</i> [<i>name</i>]<br>
+ *       <i>package.class</i> [<i>name</i>]<br>
+ *       ...<br></code>
+ * <code>[ExportFactory]</code><br>
+ * <i><small>Alle Klassen in diesem Bereich werden in der Xulu-Registry nur als
+ *    Export-Factory registriert. Sie muessen (Sub)Klassen von
+ *    {@link ExportFactory} darstellen und
+ *    ueber einen Standard-Konstruktor instanziierbar sein.</small></i><br>
+ * <code><i>package.class</i> [<i>name</i>]<br>
+ *       <i>package.class</i> [<i>name</i>]<br>
+ *       ...<br></code>
+ * <code>[TypeMapping]</code><br>
+ * <i><small>Alle Tupel in diesem Bereich werden in der Xulu-Registry nur als
+ *    TypeMapping registriert. Die Typ-Klasse muss eine (Sub)Klasse von
+ *    {@link XuluObject} sein und die Default-Factory von {@link InstantiationFactory}.
+ *    Beides sind Pflichtangaben fuer ein TypeMapping. Alle weiteren Angaben sind optional
+ *    und repraesentieren Im- und Export-Factorys. Sie muessen (Sub)Klassen von
+ *    {@link ImportFactory} bzw. {@link ExportFactory} darstellen und
+ *    ueber einen Standard-Konstruktor instanziierbar sein.</small></i><br>
+ * <code><i>package.typeClass package.defaultFacClass [package.factoryClass ...]</i><br>
+ *       <i>package.typeClass package.defaultFacClass [package.factoryClass ...]</i><br>
+ *       ...<br></code>
+ * <code>[Visualisation]</code><br>
+ * <i><small>Alle Klassen in diesem Bereich werden in der Xulu-Registry als
+ *    Visualisierungstool registriert. Sie muessen (Sub)Klassen von
+ *    {@link VisualisationTool} darstellen und
+ *    ueber einen Standard-Konstruktor instanziierbar sein.</small></i><br>
+ * <code><i>package.class</i><br>
+ *       <i>package.class</i><br>
+ *       ...<br></code>
+ * <code>[Model]</code><br>
+ * <i><small>Alle Klassen in diesem Bereich werden in der Xulu-Registry als
+ *    Modell-Klasse registriert. Sie muessen (Sub)Klassen von {@link XuluModel}
+ *    darstellen und
+ *    ueber einen Standard-Konstruktor instanziierbar sein.</small></i><br>
+ * <code><i>package.class</i><br>
+ *       <i>package.class</i><br>
+ *       ...<br></code>
+ * <code>[Script]</code><br>
+ * <i><small>Alle Klassen in diesem Bereich werden in der Xulu-Registry als
+ *    Skript-Interpreter registriert. Sie muessen (Sub)Klassen von {@link ScriptInterpreter}
+ *    darstellen und ueber einen Standard-Konstruktor instanziierbar sein.</small></i><br>
+ * <code><i>package.class</i> [<i>name</i>]<br>
+ *       <i>package.class</i> [<i>name</i>]<br>
+ *       ...<br></code>
+ * <code>[Plugin]</code><br>
+ * <i><small>Alle Klassen in diesem Bereich werden in der Xulu-Registry als
+ *    Xulu-Plugin registriert. Sie muessen (Sub)Klassen von {@link XuluPlugin}
+ *    darstellen und ueber einen Standard-Konstruktor instanziierbar sein.</small></i><br>
+ * <code><i>package.class</i> [AUTOSTART] [<i>name</i>]<br>
+ *       <i>package.class</i> [AUTOSTART] [<i>name</i>]<br>
+ *       ...<br></code>
+ * <br>
+ * Leerzeilen und Zeilen, die mit <code>//</code>, <code>|</code> oder <code>#</code>
+ * beginnen, werden als Kommentare komplett ignoriert.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class XuluRegistryReader_BasicAscii implements XuluRegistryReader {
+  public static final String TAG_GLOBAL            = "[Global]";
+  public static final String TAG_DATATYPE          = "[DataType]";
+  public static final String TAG_DEFAULTFAC        = "[DefaultFactory]";
+  public static final String TAG_IMPORTFAC         = "[ImportFactory]";
+  public static final String TAG_EXPORTFAC         = "[ExportFactory]";
+  public static final String TAG_TYPEMAPPING       = "[TypeMapping]";
+  public static final String TAG_VISUALISATION     = "[Visualisation]";
+  public static final String TAG_MODEL             = "[Model]";
+  public static final String TAG_SCRIPTINTERPRETER = "[Script]";
+  public static final String TAG_PLUGIN            = "[Plugin]";
+
+  private static final int TYPE_UNKNOWN           = -99;
+  private static final int TYPE_DATALINE          = -1;
+  private static final int TYPE_COMMENT           = 0;
+  private static final int TYPE_DATATYPE          = 1;
+  private static final int TYPE_DEFAULTFAC        = 2;
+  private static final int TYPE_IMPORTFAC         = 3;
+  private static final int TYPE_EXPORTFAC         = 4;
+  private static final int TYPE_TYPEMAPPING       = 5;
+  private static final int TYPE_VISUALISATION     = 6;
+  private static final int TYPE_GLOBAL            = 7;
+  private static final int TYPE_MODEL             = 8;
+  private static final int TYPE_SCRIPTINTERPRETER = 9;
+  private static final int TYPE_PLUGIN            = 10;
+
+  private XuluModellingPlatform appl = null;
+
+  /**
+   * Erzeugt einen neuen Reader fuer die Xulu-Registry.
+   */
+  public XuluRegistryReader_BasicAscii() {
+  }
+
+  /**
+   * Bestimmt die Art, wie die folgenden Zeilen interpretiert werden muessen.
+   */
+  private int determineLineType(String line) {
+    if ( line==null || line.trim().equals("") || IOUtil.isCommentLine(line) )
+      return TYPE_COMMENT;
+
+    if ( line.startsWith("[") ) {
+      if ( line.equals(TAG_GLOBAL) )            return TYPE_GLOBAL;
+      if ( line.equals(TAG_DATATYPE) )          return TYPE_DATATYPE;
+      if ( line.equals(TAG_DEFAULTFAC) )        return TYPE_DEFAULTFAC;
+      if ( line.equals(TAG_IMPORTFAC) )         return TYPE_IMPORTFAC;
+      if ( line.equals(TAG_EXPORTFAC) )         return TYPE_EXPORTFAC;
+      if ( line.equals(TAG_TYPEMAPPING) )       return TYPE_TYPEMAPPING;
+      if ( line.equals(TAG_VISUALISATION) )     return TYPE_VISUALISATION;
+      if ( line.equals(TAG_MODEL) )             return TYPE_MODEL;
+      if ( line.equals(TAG_SCRIPTINTERPRETER) ) return TYPE_SCRIPTINTERPRETER;
+      if ( line.equals(TAG_PLUGIN) )            return TYPE_PLUGIN;
+      return TYPE_UNKNOWN;
+    }
+
+    return TYPE_DATALINE;
+  }
+
+  /**
+   * Interpretiert eine Zeile als TypeMapping.
+   */
+  private TypeMapping readTypeMapping(String line) throws Exception {
+    StringTokenizer st = new StringTokenizer(line);
+
+    try {
+      // 1. Token: DatenTyp
+      Class dataType = loadClass(st.nextToken(),false);
+      // 2. Token: DefaultFactory
+      InstantiationFactory defaultFac = (InstantiationFactory)loadClass(st.nextToken(),false).newInstance();
+      TypeMapping mapping = new TypeMapping(dataType,defaultFac);
+      // alle weiteren Token: Im- oder ExportFactorys
+      while ( st.hasMoreTokens() ) {
+        Object fac = loadClass(st.nextToken(),false).newInstance();
+        if ( fac instanceof ImportFactory )
+          mapping.addImportFactory( (ImportFactory)fac );
+        if ( fac instanceof ExportFactory )
+          mapping.addExportFactory( (ExportFactory)fac );
+        if ( !(fac instanceof ImportFactory || fac instanceof ExportFactory) )
+          throw new Exception("Invalid TypeMapping: Import or export factory expected.");
+      }
+      return mapping;
+    } catch (NoSuchElementException err) {
+      throw new Exception("Invalid TyperMapping: First two parameters are mandatory.");
+    }
+  }
+
+  /**
+   * Schreibt eine Fehlermeldung in die Standard-Fehlerausgabe.
+   * @param lineNo Zeilennummer der Datei in der der Fehler auftrat
+   * @param line   komplette Zeile, die den Fehler verursacht hat
+   * @param mess   zusaetzliche Fehlermeldung
+   */
+  private void giveErrorMess(int lineNo, String line, String mess) {
+    System.err.println( getClass().getSimpleName().concat(" --> ").concat(mess) );
+    System.err.println( "     Line ".concat(String.valueOf(lineNo)).concat(": ").concat(line) );
+  }
+
+  /**
+   * Trennt eine Zeile am ersten Leerzeichen/Tab.
+   */
+  private String[] divideLine(String line) {
+    StringTokenizer st = new StringTokenizer(line,"\n\t ");
+    String[] ret = new String[2];
+    ret[0] = st.nextToken().trim();
+    if ( st.hasMoreTokens() )
+      ret[1] = st.nextToken("\n").trim();
+    return ret;
+  }
+
+  /**
+   * Instanziiert eine Klasse und wenn es sich dabei um eine Instanz
+   * von {@link NamedObject} handelt, wird es benannt.
+   * @param line Zeile aus dem Eingabe-File
+   * @return das instanziierte Objekt
+   */
+  private Object instantiateAndName(String line) throws Exception {
+    String[] linePart = divideLine(line);
+    Object o = loadClass(linePart[0],false).newInstance();
+    if ( o instanceof NamedObject )
+      ((NamedObject)o).setName(linePart[1]);
+    return o;
+  }
+
+  /**
+   * Erweitert eine bestehende XuluRegistry. Bestehende Eintraege werden
+   * ueberschrieben. Ist die uebergebene Registy <code>null</code> wird
+   * eine neue (leere) Instanz erstellt.
+   * Kann ein Eintrag aus dem Stream nicht richtig interpretiert oder
+   * instanziiert werden, wird die Zeile ignoriert und eine Fehlermeldung
+   * in die Standard-Fehlerausgabe geschrieben.
+   * @param appl     Instanz der Xulu-Applikation fuer die die Registry eingelesen
+   *                 werden soll
+   * @param input    Eingabe-Stream aus dem die Registry-Daten gelesen werden
+   * @param registry XuluRegistry die erweitert werden soll (kan <code>null</code> sein
+   * @return Instanz der XuluRegistry, die erstellt oder erweitert wurde
+   * @throws java.io.IOException falls ein unerwarteter Fehler beim Einlesen auftritt.
+   */
+  public XuluRegistry readRegistry(XuluModellingPlatform appl, InputStream input, XuluRegistry registry) throws IOException {
+    this.appl = appl;
+    if ( registry==null )
+      registry = new XuluRegistry();
+
+    BufferedReader in = new BufferedReader( new InputStreamReader(input) );
+
+    // Es soll nicht fuer jede eingelesene Zeile ein Event geworfen werden.
+    // Eine generelle Mitteilung an die Listener am Ende reicht.
+    registry.setEventFiringEnabled(false);
+
+    String line = "";
+    int    typeOfFollowingData = TYPE_COMMENT;
+    for (int lineNo=1; in.ready() && (line = in.readLine()) != null; lineNo++) {
+      // Typ der Zeile ermitteln
+      int type = determineLineType(line);
+
+      // unbekannte Zeile
+      if ( type == TYPE_UNKNOWN ) giveErrorMess(lineNo,line,"Unknown registry tag");
+      // Kommentarzeile ignorieren
+      if ( type == TYPE_COMMENT ) continue;
+      // Tag-Zeile
+      if ( type > 0 ) typeOfFollowingData = type;
+      // Zeile mit Registry-Data
+      Class expClass  = null;
+      try {
+        if ( type == TYPE_DATALINE )
+          switch (typeOfFollowingData) {
+            case TYPE_GLOBAL: registry.register( instantiateAndName(line) );
+                              break;
+            case TYPE_DATATYPE: registry.registerDataType( loadClass(line,false) );
+                                break;
+            case TYPE_DEFAULTFAC: expClass = InstantiationFactory.class;
+                                  registry.registerDefaultFactory( (InstantiationFactory)instantiateAndName(line) );
+                                  break;
+            case TYPE_IMPORTFAC: expClass = ImportFactory.class;
+                                 registry.registerImportFactory( (ImportFactory)instantiateAndName(line) );
+                                 break;
+            case TYPE_EXPORTFAC: expClass = ExportFactory.class;
+                                 registry.registerExportFactory( (ExportFactory)instantiateAndName(line) );
+                                 break;
+            case TYPE_TYPEMAPPING: registry.registerTypeMapping( (TypeMapping)readTypeMapping(line) );
+                                   break;
+            case TYPE_VISUALISATION: registry.registerVisualisationTool( loadClass(line,false) );
+                                     break;
+            case TYPE_MODEL: registry.registerModelClass( loadClass(line,true) );
+                             break;
+            case TYPE_SCRIPTINTERPRETER: expClass = ScriptInterpreter.class;
+                                         registry.registerScriptInterpreter( (ScriptInterpreter)instantiateAndName(line) );
+                                         break;
+            case TYPE_PLUGIN: expClass = XuluPlugin.class;
+                                         String[] linePart = divideLine(line);
+                                         XuluPlugin plugin = (XuluPlugin)loadClass(linePart[0],false).newInstance();
+                                         boolean autostart = linePart[1].startsWith("AUTOSTART");
+                                         String  name      = autostart ? linePart[1].substring(9).trim() : linePart[1];
+                                         plugin.setName( name );
+                                         if ( autostart )
+                                           registry.registerAutostartPlugin( plugin );
+                                         else
+                                           registry.registerPlugin( plugin );
+                                         break;
+          }
+      } catch (ClassCastException err) {
+        giveErrorMess(lineNo,line,"Instance of ".concat(expClass.getName()).concat(" expected"));
+      } catch (Exception err) {
+        // Datenzeile nicht korrekt
+        giveErrorMess(lineNo,line,err.toString());
+      }
+    }
+
+    // Eine generelle Mitteilung an die Listener, dass sich die Registry
+    // geaendert hat
+    registry.setEventFiringEnabled(true);
+    registry.fireGeneralEvent();
+
+    input.close();
+    return registry;
+  }
+
+  /**
+   * Erstellt eine neue XuluRegistry und befuellt diese.
+   * @param appl     Instanz der Xulu-Applikation fuer die die Registry eingelesen
+   *                 werden soll
+   * @param input    Eingabe-Stream aus dem die Registry-Daten gelesen werden
+   * @return Instanz der XuluRegistry, die erstellt wurde
+   * @throws java.io.IOException falls ein Fehler beim Einlesen auftritt
+   */
+  public XuluRegistry readRegistry(XuluModellingPlatform appl, InputStream input) throws IOException {
+    return readRegistry(appl,input,null);
+  }
+
+  /**
+   * Laed eine Klasse. Ggf. wird dazu ein eigener eigener {@link ClassLoader}
+   * erzeugt, so dass die Klasse dynamisch neu geladen werden kann.
+   * Als Suchpfad fuer diesen ClassLoader wird der fuer die Xulu-Applikation
+   * definierte Pfad fuer dynamische Klassen verwendet (siehe
+   * {@link XuluModellingPlatform#getDynamicClassRootDirectory()}).
+   * @param name  Name der zu ladenen Klasse
+   * @param newCL Flag, ob zum Laden der Klasse ein eigener {@link ClassLoader}
+   *              instanziiert werden soll.
+   */
+  private Class loadClass(String name, boolean newCL) throws ClassNotFoundException, MalformedURLException {
+//    URL searchPath = newCL ? appl.getDynamicClassRootDirectory().toURL() : null;
+//    return LangUtil.loadClass(name,searchPath);
+      if ( newCL && appl != null )
+        return LangUtil.loadPreferredClass(name,appl.getDynamicClassRootDirectory().toURL());
+      return Class.forName(name);
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/appl/package.html
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/appl/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/appl/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,9 @@
+<html>
+<body>
+	In diesem Paket können die benutzerdefinierten Skripte und Registry-Reader für die
+	Xulu-Modelling-Platform implementiert werden.
+	Damit diese in der Xulu-Anwendung verwendet werden können, müssen sie von
+	{@link edu.bonn.xulu.appl.ScriptInterpreter}, bzw.
+	{@link edu.bonn.xulu.appl.XuluRegistryReader} abgeleitet sein.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/edu/bonn/xulu/plugin/data/feature/SingleFeatureCollection.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/data/feature/SingleFeatureCollection.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/data/feature/SingleFeatureCollection.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,77 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.data.feature;
+
+import org.geotools.feature.FeatureCollection;
+
+import schmitzm.data.property.ScalarProperty;
+import edu.bonn.xulu.data.AbstractXuluObject;
+
+/**
+ * Dieser Datentyp stellt eine Sammlung von Features dar. Er baut auf der
+ * Klasse {@link FeatureCollection org.geotools.feature.FeatureCollection}
+ * auf und hat folgende Eigenschaften:<br>
+ * <ol>
+ * <li>{@linkplain #PROP_FEATURES Features}: die {@link FeatureCollection} (ScalarProperty[FeatureCollection])</li>
+ * <li>{@linkplain #PROP_STYLE Style}: Darstellungs-Style fuer die Features (ScalarProperty[Object])</li>
+ * </ol>
+ * <br>
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class SingleFeatureCollection extends AbstractXuluObject {
+  /** Name der Eigenschaft, die die {@link FeatureCollection} beinhaltet. */
+  public static final String PROP_FEATURES = "FEATURES";
+
+  /**
+   * Erzeugt eine neue <code>SingleFeatureCollection</code>.
+   * Die Eigenschaft FEATURES ist noch <b>nicht</b> mit einer konkreten
+   * {@link FeatureCollection} belegt.
+   */
+  public SingleFeatureCollection() {
+    // Beim Freigeben der Property soll auch das Grid zerstoert werden
+    propSet.addProperty(new ScalarProperty(PROP_FEATURES, FeatureCollection.class) {
+      public void dispose() {
+        if ( value != null )
+          ((FeatureCollection)value).clear();
+        super.dispose();
+      }
+    });
+    // Property fuer den Style
+    propSet.addProperty( new ScalarProperty(PROP_STYLE,Object.class) );
+  }
+
+  /**
+   * Erzeugt eine neue <code>SingleFeatureCollection</code>.
+   * @param fc Wert fuer die Eigenschaft FEATUERES
+   */
+  public SingleFeatureCollection(FeatureCollection fc) {
+    this();
+    setFeatureCollection(fc);
+  }
+
+  /**
+   * Liefert eine Referenz auf die {@link FeatureCollection}, die in der
+   * Eigenschaft FEATURES gespeichert ist.
+   */
+  public FeatureCollection getFeatureCollection() {
+    return (FeatureCollection) ((ScalarProperty)getProperty(PROP_FEATURES)).getOneTimeReadAccess().getValue();
+  }
+
+  /**
+   * Setzt die {@link FeatureCollection}, die in der Eigenschaft FEATURES
+   * gespeichert ist.
+   */
+  public void setFeatureCollection(FeatureCollection fc) {
+    ( (ScalarProperty) getProperty(PROP_FEATURES)).getOneTimeWriteAccess().setValue(fc);
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/data/grid/GridList.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/data/grid/GridList.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/data/grid/GridList.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,163 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.data.grid;
+
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ScalarProperty;
+import edu.bonn.xulu.data.AbstractXuluObject;
+
+/**
+ * Dieser Datentyp stellt eine Liste von Rastern ({@link WritableGrid} da.
+ * In der Liste koennen beliebige Raster (auch unterschiedlicher Groesse und
+ * Georeferenz) gespeichert werden. Deshalb hat das Objekt auch nur zwei
+ * Eigenschaften (Properties):<br>
+ * <ol>
+ * <li>{@linkplain #PROP_GRIDS Grids}: Die Liste der Raster (ListProperty[WritableGrid])</li>
+ * <li>{@linkplain #PROP_STYLE Style}: Darstellungs-Style fuer die Raster (ScalarProperty[Object])</li>
+ * <li>{@linkplain #PROP_COUNT Count}: Die Anzahl der Raster in der Liste (ScalarProperty[Integer])</li>
+ * </ol>
+ * Die Eigenschaft 3 ist direkt von der zu grunde liegenden Liste
+ * abhaengig (Eigenschaft 1) und kann deshalb nicht veraendert werden. Ein schreibender
+ * Zugriff auf diese Property hat keine Auswirkung.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class GridList extends AbstractXuluObject {
+  /** Name der Eigenschaft, die die Liste der {@link WritableGrid} beinhaltet. */
+  public static final String PROP_GRIDS = "Grids";
+  /** Name der Eigenschaft, die die aktuelle Listengroesse beinhaltet. */
+  public static final String PROP_COUNT = "Count";
+
+  /**
+   * Erzeugt eine neue (leere) Raster-Liste.
+   */
+  public GridList() {
+    this( new WritableGrid[0] );
+  }
+
+  /**
+   * Erzeugt eine neue Raster-Liste.
+   * @param gc erstes Raster fuer die Liste
+   */
+  public GridList(WritableGrid gc) {
+    this( new WritableGrid[] { gc } );
+  }
+
+  /**
+   * Erzeugt eine neue Raster-Liste.
+   * @param gc Raster fuer die Liste
+   */
+  public GridList(WritableGrid[] gc) {
+    // Beim Freigeben der Property sollen auch die Grids zerstoert werden
+    propSet.addProperty( new ListProperty(PROP_GRIDS,WritableGrid.class) {
+      public void dispose() {
+        for (int i=0; i<elements.size(); i++)
+          ((WritableGrid)elements.elementAt(i)).dispose();
+        // die Elements selber werden ueber die Super-Methode geloescht!
+        super.dispose();
+      }
+    } );
+    // Property fuer den Style der Grids
+    propSet.addProperty( new ScalarProperty(PROP_STYLE,Object.class) );
+    // Property fuer die Anzahl der Grids
+    propSet.addProperty( new ScalarProperty(PROP_COUNT,Integer.class) {
+      protected Object getValue(int... coords) {
+        super.getValue(coords);
+        return getGridCount();
+      }
+    });
+    // Raster hinzufuegen
+    for (WritableGrid wg : gc)
+      addGrid(wg);
+  }
+
+  /**
+   * Liefert die Anzahl an Rastern in der Liste.
+   */
+  public int getGridCount() {
+    return ((ListProperty)getProperty(PROP_GRIDS)).getOneTimeReadAccess().getCount();
+  }
+
+  /**
+   * Liefert ein Raster aus der Liste.
+   * @param idx Listen-Index
+   */
+  public WritableGrid getGrid(int idx) {
+    return (WritableGrid) ((ListProperty)getProperty(PROP_GRIDS)).getOneTimeReadAccess().getValue(idx);
+  }
+
+  /**
+   * Fuegt der Liste ein Raster hinzu.
+   */
+  public void addGrid(WritableGrid grid) {
+    ( (ListProperty)getProperty(PROP_GRIDS) ).getOneTimeWriteAccess().addValue(grid);
+  }
+
+  /**
+   * Entfernt ein Raster aus der Liste. Ist das Raster nicht in der Liste
+   * vorhanden geschieht nichts.
+   * @param grid zu entfernendes Raster
+   */
+  public void removeGrid(WritableGrid grid) {
+    ( (ListProperty)getProperty(PROP_GRIDS) ).getOneTimeWriteAccess().removeValue(grid);
+  }
+
+  /**
+   * Entfernt ein Raster aus der Liste.
+   * @param idx Listen-Index
+   */
+  public void removeGrid(int idx) {
+    ( (ListProperty)getProperty(PROP_GRIDS) ).getOneTimeWriteAccess().removeValue(idx);
+  }
+
+  /**
+   * Ersetzt ein Raster in der Liste.
+   * @param idx Listen-Index
+   * @param grid zu entfernendes Raster
+   */
+  public void replaceGrid(int idx, WritableGrid grid) {
+    ( (ListProperty)getProperty(PROP_GRIDS) ).getOneTimeWriteAccess().setValue(grid,idx);
+  }
+
+  /**
+   * Liefert das erste Grid der Liste, das nicht <code>null</code> ist.
+   * @return <code>null</code> falls es kein solches Grid gibt
+   */
+  public WritableGrid getFirstNotNullGrid() {
+    return getFirstNotNullGrid(0);
+  }
+
+  /**
+   * Liefert das erste Grid der Liste ab einem bestimmten Index, das
+   * nicht <code>null</code> ist.
+   * @return <code>null</code> falls es kein solches Grid gibt
+   */
+  public WritableGrid getFirstNotNullGrid(int firstIdx) {
+    int idx = determineFirstNotNullIndex(firstIdx);
+    if (idx >= 0)
+      return getGrid(idx);
+    return null;
+  }
+
+  /**
+   * Liefert den ersten Listen-Index, der kein null-Element enthaelt.
+   * @param firstIdx Index bei dem zu suchen begonnen wird
+   */
+  private int determineFirstNotNullIndex(int firstIdx) {
+    for (int i=firstIdx; i<getGridCount(); i++)
+      if ( getGrid(i)!=null )
+        return i;
+    return -1;
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/data/grid/MultiGrid.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/data/grid/MultiGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/data/grid/MultiGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,403 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.data.grid;
+
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.AbstractWritableGrid;
+import schmitzm.data.property.ScalarProperty;
+import edu.bonn.xulu.plugin.io.grid.WritableGridFactory;
+
+// nur fuer Doku
+import java.awt.image.DataBuffer;
+
+/**
+ * Dieser Datentyp stellt eine Liste von Rastern ({@link WritableGrid} da.
+ * In der Liste koennen nur gleichartige Raster (gleiche Groesse und gleiche
+ * Georeferenz) gespeichert werden. Deshalb hat das Objekt neben der Raster-Liste
+ * noch weitere Eigenschaften (Properties):<br>
+ * <ol>
+ * <li>{@linkplain GridList#PROP_GRIDS GridListe}: Die Liste der Raster (ListProperty[WritableGrid])</li>
+ * <li>{@linkplain XuluObject#PROP_STYLE Style}: Darstellungs-Style fuer die Raster (ScalarProperty[Object])</li>
+ * <li>{@linkplain GridList#PROP_COUNT Count}: Die Anzahl der Raster in der Liste (ScalarProperty[Integer])</li>
+ * <li>{@linkplain #PROP_COORDX X-Coordinate}: Georeferenz Longitude (ScalarProperty[Double])</li>
+ * <li>{@linkplain #PROP_COORDY Y-Coordinate}: Georeferenz Latitude (ScalarProperty[Double])</li>
+ * <li>{@linkplain #PROP_WIDTH  Width}: Reale Breite der Raster (ScalarProperty[Double])</li>
+ * <li>{@linkplain #PROP_HEIGHT Height}: Reale Hoehe der Raster (ScalarProperty[Double])</li>
+ * <li>{@linkplain #PROP_WIDTHC Width in Cells}: Breite der Raster in Zellen (ScalarProperty[Integer])</li>
+ * <li>{@linkplain #PROP_HEIGHTC Height in Cells}: Hoehe der Raster in Zellen (ScalarProperty[Integer])</li>
+ * <li>{@linkplain #PROP_CELLWIDTH Cell Width}: Breite einer Rasterzelle (ScalarProperty[Double])</li>
+ * <li>{@linkplain #PROP_CELLHEIGHT Cell Height}: Hoehe einer Rasterzelle (ScalarProperty[Double])</li>
+ * <li>{@linkplain #PROP_TYPE Data Type}: {@linkplain DataBuffer#dataType Datentyp} den eine Rasterzelle aufnehmen kann (ScalarProperty[Integer])</li>
+ * </ol>
+ * <br>
+ * Die Eigenschaften 4 bis 12 sind komplett von den zu grunde liegenden Rastern
+ * abhaengig (Eigenschaft 1) und koennen nicht veraendert werden. Ein schreibender
+ * Zugriff auf diese Properties hat keine Auswirkung.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class MultiGrid extends GridList {
+  /** Name der Eigenschaft, die die X-Koordinate des Rasters beinhaltet. */
+  public static final String PROP_COORDX     = "X-Coordinate";
+  /** Name der Eigenschaft, die die Y-Koordinate des Rasters beinhaltet. */
+  public static final String PROP_COORDY     = "Y-Coordinate";
+  /** Name der Eigenschaft, die die reale Breite des Rasters beinhaltet. */
+  public static final String PROP_WIDTH      = "Width";
+  /** Name der Eigenschaft, die die reale Hoehe des Rasters beinhaltet. */
+  public static final String PROP_HEIGHT     = "Height";
+  /** Name der Eigenschaft, die die Breite des Rasters in Zellen beinhaltet. */
+  public static final String PROP_WIDTHC     = "Width (in cells)";
+  /** Name der Eigenschaft, die die Hoehe des Rasters in Zellen beinhaltet. */
+  public static final String PROP_HEIGHTC    = "Height (in cells)";
+  /** Name der Eigenschaft, die die Zellen-Breite des Rasters beinhaltet. */
+  public static final String PROP_CELLWIDTH  = "Cell Width";
+  /** Name der Eigenschaft, die die Zellen-Hoehe des Rasters beinhaltet. */
+  public static final String PROP_CELLHEIGHT = "Cell Height";
+  /** Name der Eigenschaft, die die Zellen-Typ des Rasters beinhaltet. */
+  public static final String PROP_TYPE       = "Data Type";
+
+  /** Speichern die Vorlagen-Informationen */
+  private boolean templateExists     = false;
+  private int     templateType       = 0;
+  private double  templateX          = 0;
+  private double  templateY          = 0;
+  private int     templateMinX       = 0;
+  private int     templateMinY       = 0;
+  private int     templateWidth   	 = 0;
+  private int     templateHeight     = 0;
+  private double  templateRealWidth  = 0;
+  private double  templateRealHeight = 0;
+  private CoordinateReferenceSystem templateCRS = null;
+  /** Speichert eine Factory, mit der neue Grids erzeugt werden koennen */
+  private WritableGridFactory gridFactory = null;
+
+  /**
+   * Erzeugt eine neue (leere) Raster-Liste.
+   * @param template Vorlage fuer das Raster-Format, das in der Liste gespeichert
+   *                 werden kann
+   * @param fac      Factory mit der weitere Instanzen erzeugt werden koennen
+   */
+  public MultiGrid(WritableGrid template, WritableGridFactory fac) {
+    this( template == null ? -1   : template.getSampleType(),
+          template == null ? 0    : template.getWidth(),
+          template == null ? 0    : template.getHeight(),
+          template == null ? 0    : template.getMinX(),
+          template == null ? 0    : template.getMinY(),
+          template == null ? 0    : template.getX(),
+          template == null ? 0    : template.getY(),
+          template == null ? 0    : template.getRealWidth(),
+          template == null ? 0    : template.getRealHeight(),
+          template == null ? null : template.getCoordinateReferenceSystem(),
+          fac );
+  }
+
+  /**
+   * Erzeugt eine neue (leere) Raster-Liste. Das Format fuer die Raster
+   * wird von dem ersten Element uebernommen, welches in die Liste eingefuegt
+   * wird.
+   * @param fac      Factory mit der weitere Instanzen erzeugt werden koennen
+   */
+  public MultiGrid(WritableGridFactory fac) {
+    this( (WritableGrid)null, fac );
+  }
+  
+  /**
+   * Erzeugt eine neue Raster-Liste.
+   * @param gc  Raster fuer die Liste (das erste wird als Vorlage verwendet!)
+   * @param fac Factory mit der weitere Instanzen erzeugt werden koennen
+   * @exception ArrayIndexOutOfBoundsException falls der uebergebene Array
+   *            kein Element enthaelt
+   */
+  public MultiGrid(WritableGrid[] gc, WritableGridFactory fac) {
+    this(gc[0],fac);
+    for (int i=0; i<gc.length; i++)
+      addGrid(gc[i]);
+  }
+
+  /**
+   * Erzeugt eine neue Raster-Liste. Die uebergebenen Raster-Parameter bilden
+   * die Vorlage fuer die Raster-Art, die in der Liste gespeichert werden
+   * koennen.
+   * @param widthc  Breite in Zellen
+   * @param heightc Hoehe in Zellen
+   * @param x       Georeferenz Longitute (Suedliche/Untere Kante)
+   * @param y       Georeferenz Latitude (Westliche/Linke Kante)
+   * @param width   Breite
+   * @param height  Hoehe
+   * @param crs     Referenzsystem
+   * @param fac     Factory mit der weitere Instanzen erzeugt werden koennen
+   */
+  public MultiGrid(int type, int widthc, int heightc, int minX, int minY, double x, double y, double width, double height, CoordinateReferenceSystem crs, WritableGridFactory fac) {
+    super();
+    this.gridFactory = fac;
+    setTemplateDimension(type, widthc, heightc, minX, minY, x, y, width, height, crs);
+    
+    // Die weiteren Properties werden Wertmaessig auf die Methoden des
+    // Grids umgeleitet
+    propSet.addProperty( new ScalarProperty(PROP_COORDX,Double.class) {
+      protected Object getValue(int... coords) {
+        super.getValue(coords);
+        return templateX;
+      }
+    });
+    propSet.addProperty( new ScalarProperty(PROP_COORDY,Double.class) {
+      protected Object getValue(int... coords) {
+        super.getValue(coords);
+        return templateY;
+      }
+    });
+    propSet.addProperty( new ScalarProperty(PROP_WIDTH,Double.class) {
+      protected Object getValue(int... coords) {
+        super.getValue(coords);
+        return templateRealWidth;
+      }
+    });
+    propSet.addProperty( new ScalarProperty(PROP_HEIGHT,Double.class) {
+      protected Object getValue(int... coords) {
+        super.getValue(coords);
+        return templateRealHeight;
+      }
+    });
+    propSet.addProperty( new ScalarProperty(PROP_WIDTHC,Integer.class) {
+      protected Object getValue(int... coords) {
+        super.getValue(coords);
+        return templateWidth;
+      }
+    });
+    propSet.addProperty( new ScalarProperty(PROP_HEIGHTC,Integer.class) {
+      protected Object getValue(int... coords) {
+        super.getValue(coords);
+        return templateHeight;
+      }
+    });
+    propSet.addProperty( new ScalarProperty(PROP_CELLWIDTH,Double.class) {
+      protected Object getValue(int... coords) {
+        super.getValue(coords);
+        return templateRealWidth / templateWidth;
+      }
+    });
+    propSet.addProperty( new ScalarProperty(PROP_CELLHEIGHT,Double.class) {
+      protected Object getValue(int... coords) {
+        super.getValue(coords);
+        return templateRealHeight / templateHeight;
+      }
+    });
+    propSet.addProperty( new ScalarProperty(PROP_TYPE,Integer.class) {
+      protected Object getValue(int... coords) {
+        super.getValue(coords);
+        return templateType;
+      }
+    });
+  }
+  
+  /**
+   * Belegt die Variablen der Raster-Vorlage, welche fuer jedes Raster gelten
+   * muss, welches in die Liste ergefuegt werden soll.
+   */
+  public void setTemplateDimension(int type, int widthc, int heightc, int minX, int minY, double x, double y, double width, double height, CoordinateReferenceSystem crs) {
+    if ( getGridCount() > 0 )
+      throw new UnsupportedOperationException("Template dimension can only be changed if MultiGrid is empty!");
+    this.templateExists     = type >= 0;
+    this.templateType       = type;
+    this.templateX          = x;
+    this.templateY          = y;
+    this.templateMinX       = minX;
+    this.templateMinY       = minY;
+    this.templateWidth      = widthc;
+    this.templateHeight     = heightc;
+    this.templateRealWidth  = width;
+    this.templateRealHeight = height;
+    this.templateCRS        = crs;
+  }
+
+  /**
+   * Belegt die Variablen der Raster-Vorlage, welche fuer jedes Raster gelten
+   * muss, welches in die Liste ergefuegt werden soll.
+   */
+  public void setTemplateDimension(WritableGrid template) {
+    setTemplateDimension(
+        template == null ? -1   : template.getSampleType(),
+        template == null ? 0    : template.getWidth(),
+        template == null ? 0    : template.getHeight(),
+        template == null ? 0    : template.getMinX(),
+        template == null ? 0    : template.getMinY(),
+        template == null ? 0    : template.getX(),
+        template == null ? 0    : template.getY(),
+        template == null ? 0    : template.getRealWidth(),
+        template == null ? 0    : template.getRealHeight(),
+        template == null ? null : template.getCoordinateReferenceSystem()
+    );
+  }
+  
+  /**
+   * Prueft, ob fuer das {@code MultiGrid} eine Vorlage gesetzt ist.
+   */
+  public boolean isTemplateDimensionSet() {
+    return this.templateExists;
+  }
+
+  /**
+   * Fuegt der Liste ein leeres Raster hinzu.
+   * @param initVal initialer Wert aller Raster-Zellen
+   */
+  public void addGrid(Object initVal) {
+    addGrid();
+    WritableGrid newGrid = getGrid( getGridCount()-1 );
+    int minX = newGrid.getMinX();
+    int minY = newGrid.getMinY();
+    int maxX = minX + newGrid.getWidth();
+    int maxY = minY + newGrid.getHeight();
+    for (int y=minY; y<maxY; y++)
+      for (int x=minX; x<maxX; x++)
+        newGrid.setRasterSample(initVal, x, y);
+  }
+
+  /**
+   * Fuegt der Liste ein leeres Raster hinzu.
+   */
+  public void addGrid() {
+    if ( !templateExists )
+      throw new UnsupportedOperationException("New grid can not be added until a template grid is specified...");
+    addGrid( gridFactory.newInstance(
+                  this.templateType,
+                  this.templateWidth,
+                  this.templateHeight,
+                  this.templateMinX,
+                  this.templateMinY,
+                  this.templateX,
+                  this.templateY,
+                  this.templateRealWidth,
+                  this.templateRealHeight,
+                  this.templateCRS
+    ));
+  }
+
+  /**
+   * Fuegt der Liste ein Raster hinzu. Dieses muss von der selben Groesse und
+   * Georeferenz sein, wie die bereits in der Liste befindlichen Raster.
+   * @exception IllegalArgumentException falls das neue Raster in Groesse oder
+   *            Georeferenz nicht zum Rest der Liste passt
+   */
+  public void addGrid(WritableGrid grid) {
+    if ( !templateExists )
+      setTemplateDimension(
+          grid.getSampleType(),
+          grid.getWidth(),
+          grid.getHeight(),
+          grid.getMinX(),
+          grid.getMinY(),
+          grid.getX(),
+          grid.getY(),
+          grid.getRealWidth(),
+          grid.getRealHeight(),
+          grid.getCoordinateReferenceSystem()
+      );
+    else
+      checkStructure(grid);
+    super.addGrid(grid);
+  }
+
+  /**
+   * Ersetzt ein Raster in der Liste. Das neue Raster muss von der selben
+   * Groesse und Georeferenz sein, wie die restlichen in der Liste befindlichen Raster.
+   * @param idx Listen-Index
+   * @param grid zu entfernendes Raster
+   * @exception IllegalArgumentException falls das neue Raster in Groesse oder
+   *            Georeferenz nicht zum Rest der Liste passt
+   */
+  public void replaceGrid(int idx, WritableGrid grid) {
+    checkStructure(grid);
+    super.replaceGrid(idx,grid);
+  }
+
+  /**
+   * Prueft, ob die Struktur eines Rasters mit der des Multi-Grid vertraeglich ist.
+   * @param gc ein WritableGrid
+   * @exception IllegalArgumentException falls sich das angegebene Raster in Groesse
+   *            Aufloesung oder Geo-Referenz vom Template-Grid des Multi-Grid
+   *            unterscheidet
+   */
+  protected void checkStructure(WritableGrid gc) {
+    if ( gc == null ||
+         gc.getX()          != templateX ||
+         gc.getY()          != templateY ||
+         gc.getMinX()       != templateMinX ||
+         gc.getMinY()       != templateMinY ||
+         gc.getWidth()      != templateWidth ||
+         gc.getHeight()     != templateHeight ||
+         gc.getRealWidth()  != templateRealWidth ||
+         gc.getRealHeight() != templateRealHeight )
+      throw new IllegalArgumentException("WritableGrid does not fit to the rest of the list!");
+  }
+
+  /**
+   * Liefert ein Beispiel-Raster, das die Raster-Art repraesentiert, die in
+   * der Liste gespeichert werden koennen. Dieses liefert fuer alle Zellen
+   * den Wert 0 und kann nicht veraendert werden.
+   * @return {@code null} wenn noch kein Beispiel-Raster gesetzt ist
+   */
+  public WritableGrid getTemplateGrid() {
+    if ( !templateExists )
+      return null;
+    return new AbstractWritableGrid(templateCRS) {
+      public Object getRasterSample(int... c) { return 0; };
+      public void setRasterSample(Object o, int... c) {};
+      public void dispose() {};
+      public int getSampleType() { return templateType; }
+      public int getWidth() { return templateWidth; }
+      public int getHeight() { return templateHeight; }
+      public int getMinX() { return templateMinX; }
+      public int getMinY() { return templateMinY; }
+      public double getX() { return templateX; }
+      public double getY() { return templateY; }
+      public double getRealWidth() { return templateRealWidth; }
+      public double getRealHeight() { return templateRealHeight; }
+    };
+  }
+
+  /**
+   * Liefert die Werte aller Rasters.
+   * @param coords Georeferenz
+   */
+  public Object[] getGridSample(double... coords) {
+    Object[] sample = new Object[getGridCount()];
+    for (int i=0; i<sample.length; i++)
+      sample[i] = getGrid(i).getGridSample(coords);
+    return sample;
+  }
+
+  /**
+   * Liefert die Werte aller Rasters.
+   * @param coords Raster-Position
+   */
+  public Object[] getRasterSample(int... coords) {
+    Object[] sample = new Object[getGridCount()];
+    for (int i=0; i<sample.length; i++)
+      sample[i] = getGrid(i).getRasterSample(coords);
+    return sample;
+  }
+
+  /**
+   * @return an array of all grids in the {@link MultiGrid}
+   * @author Dominik Appl
+   */
+public WritableGrid[] toArray(){
+	  WritableGrid[] array = new WritableGrid[this.getGridCount()];
+	  for (int i = 0; i < array.length; i++) {
+		array[i] = this.getGrid(i);
+	}
+	  return array;
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/data/grid/SingleGrid.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/data/grid/SingleGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/data/grid/SingleGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,173 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.data.grid;
+
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.data.property.ValuePropertyAccessParameters;
+import edu.bonn.xulu.data.AbstractXuluObject;
+
+/**
+ * Dieser Datentyp stellt ein einzelnes Raster dar. Dieses baut auf
+ * der Klasse {@link WritableGrid schmitzm.data.WritableGrid} auf und
+ * hat folgende Eigenschaften:<br>
+ * <ol>
+ * <li>{@linkplain #PROP_GRID Grid}: Das gesamte Raster (ScalarProperty[WritableGrid])</li>
+ * <li>{@linkplain #PROP_STYLE Style}: Darstellungs-Style fuer das Raster (ScalarProperty[Object])</li>
+ * <li>{@linkplain #PROP_COORDX X-Coordinate}: Georeferenz Longitude der S�dwestlichen Ecke (ScalarProperty[Double])</li>
+ * <li>{@linkplain #PROP_COORDY Y-Coordinate}: Georeferenz Latitude der S�dwestlichen Ecke (ScalarProperty[Double])</li>
+ * <li>{@linkplain #PROP_WIDTH  Width}: Reale Breite des Rasters (ScalarProperty[Double])</li>
+ * <li>{@linkplain #PROP_HEIGHT Height}: Reale Hoehe des Rasters (ScalarProperty[Double])</li>
+ * <li>{@linkplain #PROP_WIDTHC Width in Cells}: Breite des Rasters in Zellen (ScalarProperty[Integer])</li>
+ * <li>{@linkplain #PROP_HEIGHTC Height in Cells}: Hoehe des Rasters in Zellen (ScalarProperty[Integer])</li>
+ * <li>{@linkplain #PROP_CELLWIDTH Cell Width}: Breite einer Rasterzelle (ScalarProperty[Double])</li>
+ * <li>{@linkplain #PROP_CELLHEIGHT Cell Height}: Hoehe einer Rasterzelle (ScalarProperty[Double])</li>
+ * </ol>
+ * <br>
+ * Die Eigenschaften 3 bis 10 sind komplett von dem zu grunde liegenden Raster
+ * abhaengig (Eigenschaft 1) und koennen nicht veraendert werden. Ein schreibender
+ * Zugriff auf diese Properties hat keine Auswirkung.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class SingleGrid extends AbstractXuluObject {
+  /** Name der Eigenschaft, die die {@link WritableGrid} beinhaltet. */
+  public static final String PROP_GRID       = "Grid";
+  /** Name der Eigenschaft, die die X-Koordinate des Rasters beinhaltet. */
+  public static final String PROP_COORDX     = "X-Coordinate";
+  /** Name der Eigenschaft, die die Y-Koordinate des Rasters beinhaltet. */
+  public static final String PROP_COORDY     = "Y-Coordinate";
+  /** Name der Eigenschaft, die die reale Breite des Rasters beinhaltet. */
+  public static final String PROP_WIDTH      = "Width";
+  /** Name der Eigenschaft, die die reale Hoehe des Rasters beinhaltet. */
+  public static final String PROP_HEIGHT     = "Height";
+  /** Name der Eigenschaft, die die Breite des Rasters in Zellen beinhaltet. */
+  public static final String PROP_WIDTHC     = "Width (in cells)";
+  /** Name der Eigenschaft, die die Hoehe des Rasters in Zellen beinhaltet. */
+  public static final String PROP_HEIGHTC    = "Height (in cells)";
+  /** Name der Eigenschaft, die die Zellen-Breite des Rasters beinhaltet. */
+  public static final String PROP_CELLWIDTH  = "Cell Width";
+  /** Name der Eigenschaft, die die Zellen-Hoehe des Rasters beinhaltet. */
+  public static final String PROP_CELLHEIGHT = "Cell Height";
+
+  /**
+   * Erzeugt ein neues Raster. Saemtliche Properties sind noch unbelegt.
+   */
+  public SingleGrid() {
+    // Beim Freigeben der Property soll auch das Grid zerstoert werden
+//    propSet.addProperty( new ScalarProperty(PROP_GRID,WritableGrid.class,new ValuePropertyAccessParameters(1,1)) {
+    propSet.addProperty( new ScalarProperty(PROP_GRID,WritableGrid.class ) {
+      public void dispose() {
+        if ( value != null )
+          ((WritableGrid)value).dispose();
+        super.dispose();
+      }
+    });
+    // Property fuer den Style
+    propSet.addProperty( new ScalarProperty(PROP_STYLE,Object.class) );
+    // Die weiteren Properties werden Wertmaessig auf die Methoden des
+    // Grids umgeleitet
+    propSet.addProperty( new ScalarProperty(PROP_COORDX,Double.class) {
+      protected Object getValue(int... coords) {
+        super.getValue(coords);
+        return getGrid().getX();
+      }
+    });
+    propSet.addProperty( new ScalarProperty(PROP_COORDY,Double.class) {
+      protected Object getValue(int... coords) {
+        super.getValue(coords);
+        return getGrid().getY();
+      }
+    });
+    propSet.addProperty( new ScalarProperty(PROP_WIDTH,Double.class) {
+      protected Object getValue(int... coords) {
+        super.getValue(coords);
+        return getGrid().getRealWidth();
+      }
+    });
+    propSet.addProperty( new ScalarProperty(PROP_HEIGHT,Double.class) {
+      protected Object getValue(int... coords) {
+        super.getValue(coords);
+        return getGrid().getRealHeight();
+      }
+    });
+    propSet.addProperty( new ScalarProperty(PROP_WIDTHC,Integer.class) {
+      protected Object getValue(int... coords) {
+        super.getValue(coords);
+        return getGrid().getWidth();
+      }
+    });
+    propSet.addProperty( new ScalarProperty(PROP_HEIGHTC,Integer.class) {
+      protected Object getValue(int... coords) {
+        super.getValue(coords);
+        return getGrid().getHeight();
+      }
+    });
+    propSet.addProperty( new ScalarProperty(PROP_CELLWIDTH,Double.class) {
+      protected Object getValue(int... coords) {
+        super.getValue(coords);
+        WritableGrid g = getGrid();
+        return g.getRealWidth() / g.getWidth();
+      }
+    });
+    propSet.addProperty( new ScalarProperty(PROP_CELLHEIGHT,Double.class) {
+      protected Object getValue(int... coords) {
+        super.getValue(coords);
+        WritableGrid g = getGrid();
+        return g.getRealHeight() / g.getHeight();
+      }
+    });
+  }
+
+  /**
+   * Erzeugt ein neues Raster.
+   * @param gc zugrunde liegendes Raster
+   */
+  public SingleGrid(WritableGrid gc) {
+    this();
+    setGrid(gc);
+  }
+
+  /**
+   * Liefert das zugrunde liegende Raster. Aenderungen an diesem Raster
+   * wirken sich automatisch auf die anderen Properties aus!
+   */
+  public WritableGrid getGrid() {
+    return (WritableGrid) ((ScalarProperty)getProperty(PROP_GRID)).getOneTimeReadAccess().getValue();
+  }
+
+  /**
+   * Setzt das zugrunde liegende Raster. Hierdurch werden automatisch auch
+   * die anderen Properties beeinflusst.
+   */
+  public void setGrid(WritableGrid grid) {
+    ( (ScalarProperty)getProperty(PROP_GRID) ).getOneTimeWriteAccess().setValue(grid);
+  }
+
+  /**
+   * Liefert einen Wert des Rasters.
+   * @param coords Georeferenz
+   */
+  public Object getGridSample(double... coords) {
+    return getGrid().getGridSample(coords);
+  }
+
+  /**
+   * Liefert einen Wert des Rasters.
+   * @param coords Raster-Position
+   */
+  public Object getRasterSample(int... coords) {
+    return getGrid().getRasterSample(coords);
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/data/misc/CAArea.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/data/misc/CAArea.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/data/misc/CAArea.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,162 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.data.misc;
+
+import java.awt.Point;
+import java.awt.geom.Point2D;
+import java.util.Vector;
+
+/**
+ * Dieser Datentyp stellt eine Region (z.B. Siedlung) in einem
+ * {@linkplain edu.bonn.xulu.plugin.model.ca.MultiCellularAutomaton multiplen zellularen Automaten}
+ * dar. Eine <code>CAArea</code> hat folgende Eigenschaften:
+ * <ul>
+ *   <li>ein Name</li>
+ *   <li>ein Start-Position (lat/lon-Georeferenz)</li>
+ *   <li>eine aktuelle Bedeckung, wie viele qm der Region zugewiesen wurden</li>
+ *   <li>eine Liste an Randpunkten die fuer die Expansion im naechsten Schritt in Frage kommen</li>
+ *   <li>eine Flag, das signalisiert, ob der Bedarf fuer einen Zeitschritt gedeckt ist</li>
+ *   <li>eine Flag, das signalisiert, ob sich die Region in einem Deadlock befindet</li>
+ * </ul>
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class CAArea {
+  /** Speichert den Namen der Area. */
+  protected String          name         = "";
+  /** Speichert die Start-Position der Area. */
+  protected Point2D         startLoc     = null;
+  /** Speichert die aktuelle Flaeche (in qm), die der CA der Area zugewiesen hat. */
+  protected double          cover        = 0.0;
+  /** Speichert die Randzellen der Region. */
+  protected Vector<Point>   border       = null;
+  /** Flag, ob sich die Area in einem Deadlock befindet. */
+  protected boolean         deadlock     = false;
+
+  /**
+   * Erzeugt eine neue Area.
+   */
+  public CAArea() {
+    this("",0,0);
+  }
+
+  /**
+   * Erzeugt eine neue Area.
+   * @param name Name der Area
+   * @param x    X-Koodinate (Longitude)
+   * @param y    Y-Koodinate (Latitude)
+   */
+  public CAArea(String name, double x, double y) {
+    setName(name);
+    this.startLoc       = new Point2D.Double(x,y);
+    this.border         = new Vector<Point>();
+    this.deadlock       = false;
+  }
+
+
+  /**
+   * Initialisiert die Area, in dem die aktuelle Flaeche und die Liste der
+   * Randzellen zurueckgesetzt werden.
+   */
+  public void init() {
+    this.cover = 0.0;
+    this.border.clear();
+    this.deadlock = false;
+  }
+
+  /**
+   * Liefert den Namen der Area.
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Setzt den Namen der Area.
+   * @param name neuer Name
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  /**
+   * Liefert die Startkoordinaten der Area.
+   * @return loc Lat/Lon-Georeferenz
+   */
+  public Point2D getStartLocation() {
+    return startLoc;
+  }
+
+  /**
+   * Setzt die Startkoordinaten der Area.
+   * @param loc Lat/Lon-Georeferenz
+   */
+  public void setStartLocation(Point2D loc) {
+    this.startLoc = loc;
+  }
+
+  /**
+   * Liefert die aktuelle qm-Flaeche, die der Area zugeordnet ist.
+   */
+  public double getCurrentCover() {
+    return this.cover;
+  }
+
+  /**
+   * Erhoeht die Flaeche, die der Area aktuell zugeordnet ist. Wird vom
+   * CA verwendet.
+   * @param value Wert um den Gesamt-Flaeche erhoeht wird (in qm)
+   */
+  public void incCurrentCover(double value) {
+    this.cover += value;
+  }
+
+  /**
+   * Reduziert die Flaeche, die der Area aktuell zugeordnet ist. Wird vom
+   * CA verwendet.
+   * @param value Wert um den Gesamt-Flaeche reduziert wird (in qm)
+   */
+  public void decCurrentCover(double value) {
+    this.cover -= value;
+  }
+
+  /**
+   * Liefert die Liste der Randpunkte der Area. Wird vom CA verwaltet und
+   * durch {@link #init()} initialisiert.
+   */
+  public Vector<Point> getBorder() {
+    return this.border;
+  }
+
+  /**
+   * Checkt, ob sich der CA fuer diese Area in einem Deadlock befindet.
+   */
+  public boolean isDeadlock() {
+    return this.deadlock;
+  }
+
+  /**
+   * Setzt ein Flag, dass sich diese Area in einem Deadlock befindet.
+   * @param deadlock <code>true</code> wenn der CA fuer diese Area nicht mehr
+   *                 weiter expandieren kann
+   */
+  public void setDeadlock(boolean deadlock) {
+    this.deadlock = deadlock;
+  }
+
+  /**
+   * Prueft, ob die aktuell belegte Flaeche den Bedarf deckt.
+   * @param step Schrittnummer (beginnend bei 0!)
+   */
+  public abstract boolean isDemandSatisfied(int step);
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/data/misc/CASettlementArea.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/data/misc/CASettlementArea.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/data/misc/CASettlementArea.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,151 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.data.misc;
+
+import java.awt.Point;
+import java.awt.geom.Point2D;
+import java.util.Vector;
+
+/**
+ * Dieser Datentyp erweitert die allgemeine {@linkplain CAArea CA-Region} um
+ * folgende Eigenschaften:
+ * <ul>
+ *   <li>Einwohnerzahl (zum Zeitpunkt 0)</li>
+ *   <li>Wachstumsrate der Einwohnerzahl pro Zeitschritt</li>
+ *   <li>Bedarf pro Einwohner (in qm)</li>
+ * </ul>
+ * @see edu.bonn.xulu.plugin.model.ca.MultiCellularAutomaton
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class CASettlementArea extends CAArea {
+  /** Speichert die Einwohnerzahlen zum Start-Zeitpunkt. */
+  protected double          inhabitants  = 0.0;
+  /** Speichert die Wachstumsrate fuer die Einwohnerzahl. */
+  protected double          growthRate   = 0.0;
+  /** Speichert den Flaechenbedarf in qm pro Einwohner. */
+  protected double          demandPerInh = 0.0;
+
+  /** Umrechnungsfaktor, falls der Bedarf (pro Einwohner) nicht in qm angegeben
+   *  ist (Standard: 1.0). */
+  protected double          demandConvFact = 1.0;
+
+  /**
+   * Erzeugt eine neue Area.
+   */
+  public CASettlementArea() {
+    this("",0,0,0.0,0.0,1);
+  }
+
+  /**
+   * Erzeugt eine neue Area.
+   * @param name Name der Area
+   * @param x    X-Koodinate (Longitude)
+   * @param y    Y-Koodinate (Latitude)
+   * @param inhabitants Einwohner-Zahl zum Start-Zeitpunkt
+   * @param growthRate  Wachstumsrate der Einwohner pro Zeitschritt
+   * @param dpi  qm-Bedarf pro Einwohner
+   */
+  public CASettlementArea(String name, double x, double y, double inhabitants, double growthRate, double dpi) {
+    super(name,x,y);
+    this.inhabitants    = inhabitants;
+    this.growthRate     = growthRate;
+    this.demandPerInh   = dpi;
+    this.demandConvFact = 1.0;
+  }
+
+  /**
+   * Liefert den Bedarf pro Einwohner in qm.
+   */
+  public double getDemandPerInhabitant() {
+    return this.demandPerInh;
+  }
+
+  /**
+   * Setzt den Bedarf pro Einwohner.
+   * @param dpi Bedarf in qm
+   */
+  public void setDemandPerInhabitant(double dpi) {
+    this.demandPerInh = dpi;
+  }
+
+  /**
+   * Liefert den Umrechnungsfaktor, um den Bedarf pro Einwohner in qm
+   * zu transformieren.
+   */
+  public double getDemandToQMFactor() {
+    return this.demandConvFact;
+  }
+
+  /**
+   * Setzt einen Umrechnungsfaktor, falls der Bedarf pro Einwohner nicht in
+   * qm angegeben ist. Mit diesem Wert wird der {@link #demandPerInh} multipliziert
+   * um festzustellen, ob der Bedarf gedeckt ist.
+   * @param dcf Faktor
+   * @see #isDemandSatisfied(int)
+   */
+  public void setDemandToQMFactor(double dcf) {
+    this.demandConvFact = dcf;
+  }
+
+  /**
+   * Liefert die Wachstumsrate der Bevoelkerung (z.B. <code>0.3</code> bei
+   * 30%igem Wachstum).
+   */
+  public double getGrowthRate() {
+    return this.growthRate;
+  }
+
+  /**
+   * Setzt die Wachstumsrate der Bevoelkerung (z.B. <code>0.3</code> bei
+   * 30%igem Wachstum).
+   * @param rate Wachstumsrate
+   */
+  public void setGrowthRate(double rate) {
+    this.growthRate = rate;
+  }
+
+  /**
+   * Liefert die Einwohnerzahl fuer einen bestimmten Zeitschritt. Diese
+   * berechnet sich ueber folgende Formel:<br>
+   * <code>inhabitants(i) = inhabitants(0) * growthRate^step</code>
+   * @param step Schrittnummer (beginnend bei 0)
+   * @return 0, falls <code>step < 0</code>
+   */
+  public double getInhabitants(int step) {
+    if ( step < 0 )
+      return 0;
+    return this.inhabitants * Math.pow(1+growthRate,step);
+  }
+
+  /**
+   * Liefert die Einwohnerzahl zum Start-Zeitpunkt (0).
+   */
+  public double getInhabitants() {
+    return this.inhabitants;
+  }
+
+  /**
+   * Setzt die Einwohnerzahl zum Start-Zeitpunkt (0).
+   */
+  public void setInhabitants(double inhabitants) {
+    this.inhabitants = inhabitants;
+  }
+
+  /**
+   * Prueft, ob die aktuell belegte Flaeche den Bedarf deckt.
+   * @param step Schrittnummer (beginnend bei 0!)
+   */
+  public boolean isDemandSatisfied(int step) {
+    return getCurrentCover() >= getInhabitants(step) * getDemandPerInhabitant() * getDemandToQMFactor();
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/data/package.html
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/data/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/data/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,9 @@
+<html>
+<body>
+	In diesem Paket können sämtliche benutzerdefinierten Datentypen für die
+	Xulu-Modelling-Platform implementiert werden. Damit diese im
+	{@linkplain edu.bonn.xulu.appl.DataPool Xulu-Datenpool} verwendet werden
+	können, müssen sie von {@link edu.bonn.xulu.data.XuluObject} oder
+	{@link edu.bonn.xulu.data.DynamicXuluObject} abgeleitet sein.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/edu/bonn/xulu/plugin/gui/AbstractManagerFrame_BasicTable.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/gui/AbstractManagerFrame_BasicTable.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/gui/AbstractManagerFrame_BasicTable.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,278 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.gui;
+
+import java.awt.Dimension;
+import java.awt.BorderLayout;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import javax.swing.JScrollPane;
+import javax.swing.JButton;
+//import javax.swing.JTable;
+//import javax.swing.table.AbstractTableModel;
+
+import schmitzm.swing.table.AbstractMutableTableModel;
+import schmitzm.swing.table.ComponentRenderer;
+import schmitzm.swing.table.TableComponentMouseListener;
+import schmitzm.swing.table.MutableTable;
+import schmitzm.swing.table.MutableTableModel;
+import schmitzm.data.event.ObjectListener;
+import schmitzm.data.event.ObjectEvent;
+
+import edu.bonn.xulu.appl.XuluConstants;
+import edu.bonn.xulu.appl.AbstractManager;
+import edu.bonn.xulu.appl.AbstractManager.ChangeEvent;
+import edu.bonn.xulu.gui.AbstractManagerFrame;
+import edu.bonn.xulu.gui.XuluGUIMessages;
+
+/**
+ * Diese Klasse stellt eine GUI-Komponente fuer den {@link AbstractManager}
+ * dar. In dieser werden die darin registrierten Komponenten tabellarisch
+ * aufgelistet:
+ * <ul>
+ * <li>Spalte 1: Titel der Komponente</li>
+ * <li>Spalte 2: Klassenname der Komponente</li>
+ * <li>Spalte 3: Button zum Anzeigen der Komponente</li>
+ * </ul>
+ * Mit einem Doppelklick auf einen Eintrag wird das jeweilige Fenster angezeigt.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class AbstractManagerFrame_BasicTable extends AbstractManagerFrame {
+  private MutableTable compTable = null;
+
+  /**
+   * Erzeugt einen neue Instanz des grafischen Manager-Fensters.
+   * Die Groesse ist auf 300x350 Pixel voreingestellt.
+   * @param title   Bezeichnung fuer das Fenster
+   * @param manager Manager der im Fenster dargestellt wird
+   */
+  public AbstractManagerFrame_BasicTable(String title, AbstractManager manager) {
+    this(title, new AbstractManagerTableModel(manager));
+  }
+
+  /**
+   * Erzeugt einen neue Instanz des grafischen Manager-Fensters.
+   * @param title   Bezeichnung fuer das Fenster
+   * @param manager Manager der im Fenster dargestellt wird
+   * @param size    Groesse des Fensters.
+   */
+  public AbstractManagerFrame_BasicTable(String title, AbstractManager manager, Dimension size) {
+    this(title,new AbstractManagerTableModel(manager),size);
+  }
+
+  /**
+   * Erzeugt einen neue Instanz des grafischen Manager-Fensters.
+   * Die Groesse ist auf 300x350 Pixel voreingestellt.
+   * @param title             Bezeichnung fuer das Fenster
+   * @param managerTableModel Datenmodell fuer den Manager der im Fenster dargestellt wird
+   */
+  public AbstractManagerFrame_BasicTable(String title, AbstractManagerTableModel managerTableModel) {
+    this(title, managerTableModel, new Dimension(300,350));
+  }
+
+  /**
+   * Erzeugt einen neue Instanz des grafischen Manager-Fensters.
+   * @param title             Bezeichnung fuer das Fenster
+   * @param managerTableModel Datenmodell fuer den Manager der im Fenster dargestellt wird
+   * @param size              Groesse des Fensters.
+   */
+  public AbstractManagerFrame_BasicTable(String title, AbstractManagerTableModel managerTableModel, Dimension size) {
+    this(title,managerTableModel,size,MutableTable.ITEM_REMOVE);
+  }
+
+  /**
+   * Erzeugt einen neue Instanz des grafischen Manager-Fensters.
+   * @param title             Bezeichnung fuer das Fenster
+   * @param managerTableModel Datenmodell fuer den Manager der im Fenster dargestellt wird
+   * @param size              Groesse des Fensters.
+   * @param tableMask         Kontextmenue-Optionen, die zur manuellen Modifikation der Tabelle zur
+   *                          Verfuegung stehen (vgl. {@link MutableTable})
+   */
+  protected AbstractManagerFrame_BasicTable(String title, AbstractManagerTableModel managerTableModel, Dimension size, int tableMask) {
+    super(title,managerTableModel.manager);
+    this.setSize(size);
+    this.setLayout( new BorderLayout() );
+    // MutableTable implementiert "Aendern" fuer einen Doppelklick.
+    // Fuer den AbstractManager soll jedoch das jeweilige Fenster
+    // geoeffnet werden -> performDoubleClick(..) ueberschreiben
+    this.compTable = new MutableTable( managerTableModel, tableMask ) {
+      public void performDoubleClick() {
+        AbstractManager.ContentType[] selComp = getSelectedObjects();
+        if ( selComp != null ) selComp[0].setVisible(true);
+      }
+    };
+    this.compTable.addMouseListener( new TableComponentMouseListener(compTable) );
+    this.compTable.setDefaultRenderer(compTable.getModel().getColumnClass(2),new ComponentRenderer());
+    this.compTable.getColumnModel().getColumn(2).setPreferredWidth(70);
+    this.compTable.getColumnModel().getColumn(2).setMaxWidth(70);
+    this.getContentPane().add( compTable.createScrollPane() );
+  }
+
+  /**
+   * Aktualisiert die Darstellung des Managers, indem ein
+   * <code>fireTableDataChanged()</code>-Event auf das TableModel der
+   * Manager-Tabelle ausgeloest wird.
+   */
+  public void refresh() {
+    ((MutableTableModel)compTable.getModel()).fireTableDataChanged();
+  }
+
+  /**
+   * Liefert die aktuell in der Tabelle selektierte Komponente.
+   * In der Tabelle kann immer nur ein Eintrag selektiert werden. Diese
+   * Methode liefert also immer einen Array, der nur ein Element enthaelt.
+   * @return <code>null</code> falls kein Eintrag selektiert ist
+   */
+  public AbstractManager.ContentType[] getSelectedObjects() {
+    int selCompIdx = compTable.getSelectedRow();
+    return selCompIdx >=0 ? new AbstractManager.ContentType[] { manager.get( selCompIdx ) } : null;
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // TableModel fuer die Manager-Tabelle
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse stellt ein TableModel fuer den {@link AbstractManager} dar.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class AbstractManagerTableModel extends AbstractMutableTableModel implements ObjectListener {
+    /** Speichert die Spaltentypen der Tabelle */
+    protected Class[] COLUMN_TYPE = {
+        String.class,
+        String.class,
+        JButton.class
+    };
+    /** Speichert die Datenbasis fuer die Tabelle */
+    protected AbstractManager manager = null;
+
+    /**
+     * Erzeugt ein neues Daten-Modell fuer einen <code>AbstractManager</code>.
+     * @param manager Instanz eines <code>AbstractManager</code>
+     */
+    public AbstractManagerTableModel(AbstractManager manager) {
+      super();
+      this.manager = manager;
+      manager.addObjectListener( this );
+    }
+
+    /**
+     * Wird aufgerufen, wenn sich der Inhalt des Managers aendert.
+     * Handelt es sich um ein {@link AbstractManager.ChangeEvent}
+     * wird ein <code>fireTableDataChanged()</code> ausgeloest, damit der
+     * Tabelleninhalt aktualisiert wird.
+     */
+    public void performObjectEvent(ObjectEvent e) {
+      if ( e instanceof AbstractManager.ChangeEvent )
+        fireTableDataChanged();
+    }
+
+    /**
+     * Liefert die Spaltennamen der Tabelle.
+     */
+    @Override
+    public String[] createColumnNames() {
+      return new String[] {
+          XuluConstants.XULUGUI_RES.getString("Name"),
+          XuluConstants.XULUGUI_RES.getString("Type"),
+          ""
+      };      
+    }
+    
+    /**
+     * Liefert die Anzahl an Tabellenzeilen. Entspricht der Anzahl der
+     * Komponenten, die im Manager registriert sind.
+     */
+    public int getRowCount() {
+      return manager.getCount();
+    }
+
+    /**
+     * Liefert einen Wert der Tabelle. Fuer Spalte 0 wird der jeweilige Titel
+     * der Komponente geliefert, fuer Spalte 1 der Klassenname.
+     * @param row Tabellen-Zeile
+     * @param col Tabellen-Spalte
+     */
+    public Object getValueAt(int row, int col) {
+      switch( col ) {
+        case 0: // erste Spalte: Titel der Komponente
+                return manager.get(row).getTitle();
+        case 1: // zweite Spalte: Typ der Komponente
+                return manager.get(row).getClass().getName();
+        case 2: // dritte Spalte: Oeffnen-Button
+                JButton openButton = new JButton( XuluConstants.SWING_RES.getString("Open") );
+                final int r = row;
+                openButton.addMouseListener( new MouseAdapter() {
+                  public void mouseClicked(MouseEvent e) {
+                    manager.get(r).setVisible(true);
+                  }
+                });
+                return openButton;
+      }
+      return null;
+    }
+
+    /**
+     * Prueft, ob eine Tabellen-Zelle editierbar ist. Dies ist fuer alle
+     * Zellen der Spalte 0 ("Titel") der Fall.
+     * @param row Tabellen-Zeile
+     * @param col Tabellen-Spalte
+     */
+    public boolean isCellEditable(int row, int col) {
+      return col == 0;
+    }
+
+    /**
+     * Setzt den Titel der jeweiligen Komponente neu,
+     * wenn als Spaltennummer 0 angegeben wird. Ansonsten macht diese Methode nichts.
+     * @param obj neuer Titel (<code>String</code>)
+     * @param row Tabellen-Zeile
+     * @param col Tabellen-Spalte
+     */
+    public void setValueAt(Object obj, int row, int col) {
+      // nur die Spalte mit der Objekt-Beschreibung ist editierbar
+      if ( isCellEditable(row,col) )
+        manager.get(row).setTitle(obj.toString());
+    }
+
+
+    /**
+     * Entfernt einen Eintrag aus dem <code>AbstractManager</code> und
+     * somit aus der Tabelle. Wird aufgerufen, wenn der Menuepunkt
+     * "Entfernen" aus dem Kontextmenue gewaehlt wird.
+     * @param row Tabellenzeile
+     * @see AbstractManager#remove(int)
+     */
+    public void performRemoveRow(int row) {
+      manager.remove(row);
+    }
+
+    /**
+     * Macht nichts, da das Menu fuer den <code>AbstractManager</code>
+     * den Aendern-Menuepunkt nicht enthaelt.
+     * @param row Tabellenzeile
+     * @param col Tabellenspalte
+     */
+    public void performChangeData(int row, int col) {
+    }
+
+    /**
+     * Macht nichts, da das Menu fuer den <code>AbstractManager</code>
+     * den Hinzufuegen-Menuepunkt nicht enthaelt.
+     */
+    public void performAddRow() {}
+
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/gui/DataPoolFrame_BasicTable.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/gui/DataPoolFrame_BasicTable.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/gui/DataPoolFrame_BasicTable.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,285 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.gui;
+
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.BorderLayout;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import javax.swing.JFileChooser;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.table.AbstractTableModel;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.io.File;
+//import java.io.FileInputStream;
+//import java.io.FileOutputStream;
+
+import adagios.swing.MultiSplitPane;
+
+import schmitzm.swing.event.PopupMenuListener;
+
+import schmitzm.data.event.ObjectListener;
+import schmitzm.data.event.ObjectEvent;
+import schmitzm.data.property.Property;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.DataPool;
+
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.gui.DataPoolFrame;
+import edu.bonn.xulu.gui.DataPoolMenu;
+import edu.bonn.xulu.plugin.gui.DisplayContainer_Properties;
+
+/**
+ * Dieses Fenster stellt die grafische Implementierung des Xulu-Datenpools
+ * dar. Es visualiert den Datenpool tabellarisch durch zwei Komponenten:
+ * <ul>
+ * <li>Tabelle mit den Objekten des Datenpools (oberer Bereich)</li>
+ * <li>Tabelle mit den Properties des aktuell selektieren Objekts (unterer Bereich)</li>
+ * </ul>
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class DataPoolFrame_BasicTable extends DataPoolFrame {
+  private XuluModellingPlatform       appl              = null;
+  private MultiSplitPane              dataPoolSplitPane = new MultiSplitPane(2,javax.swing.JSplitPane.VERTICAL_SPLIT);
+  private Container                   contentPane       = null;
+  private JTable                      dataPoolTable     = null;
+  private DisplayContainer_Properties propCont          = null;
+  private Object[]                    selectedObjects   = new Object[0];
+  private DataPoolMenu                dataPoolMenu      = null;
+
+  /**
+   * Erzeugt einen neue Instanz des grafischen Datenpools. Die Groesse ist
+   * auf 300x350 Pixel voreingestellt.
+   * @param appl Xulu-Applikation fuer die der Datenpool-Frame instanziiert wird
+   */
+  public DataPoolFrame_BasicTable(XuluModellingPlatform appl) {
+    this(appl, new Dimension(300,350));
+  }
+
+  /**
+   * Erzeugt einen neue Instanz des grafischen Datenpools.
+   * @param appl   Xulu-Applikation fuer die der Datenpool-Frame instanziiert wird
+   * @param size   Groesse des Fensters.
+   */
+  public DataPoolFrame_BasicTable(XuluModellingPlatform appl, Dimension size) {
+    super();
+    this.appl = appl;
+    this.setSize(size);
+    this.contentPane = this.getContentPane();
+    contentPane.setLayout( new BorderLayout() );
+
+    // Tabelle mit Properties
+    this.propCont = new DisplayContainer_Properties();
+    // Tabelle mit Xulu-Objekten
+    this.dataPoolTable = new JTable( new DataPoolTableModel(appl.getDataPool()) );
+    this.dataPoolTable.addMouseListener( new MouseAdapter() {
+      public void mouseClicked(MouseEvent e) {
+        int index = dataPoolTable.getSelectedRow();
+        XuluObject xuluObject  = index < 0 ? null : ((DataPoolTableModel)dataPoolTable.getModel()).getXuluData(index);
+        if ( propCont.canDisplay(xuluObject) )
+          propCont.setObject(xuluObject);
+      }
+    });
+
+    // SplitPane organisieren
+    dataPoolSplitPane.setResizeWeigth( new double[] {0.5,0.5} );
+    dataPoolSplitPane.setDividerSize(2);
+    dataPoolSplitPane.setContainer(0,new JScrollPane(dataPoolTable));
+    dataPoolSplitPane.setContainer(1,propCont);
+    contentPane.add(dataPoolSplitPane);
+
+    // Popup-Menu anbinden
+    dataPoolMenu = new DataPoolMenu(appl, this);
+    PopupMenuListener listener = new PopupMenuListener(dataPoolMenu.getPopupMenu()) {
+      public void mouseReleased(MouseEvent e) {
+        // Wenn noch keine Zeile in Tabelle selektiert war, wird automatisch
+        // die Zeile selektiert, auf die geklickt wurde
+        if ( dataPoolTable.getSelectedRowCount() <= 1 ) {
+          int clickIdx = dataPoolTable.rowAtPoint( e.getPoint() );
+          dataPoolTable.getSelectionModel().addSelectionInterval(
+              clickIdx,
+              clickIdx
+          );
+        }
+        super.mouseReleased(e);
+      }
+    };
+    dataPoolTable.addMouseListener( listener );
+    dataPoolSplitPane.getContainer(0).addMouseListener( listener );
+  }
+
+  /**
+   * Liefert alle in der Datentabelle <b>und</b> in der Eigenschaftstabelle
+   * selektierten Objekte. Dies koennen sowohl <code>XuluObject</code>s sein,
+   * als auch einzelne <code>Property</code>s.<br>
+   * <b>Bemerke:</b><br>
+   * Zur Zeit werden nur die Xulu-Objekte zurueckgegeben!!
+   * @return einen leeren Array wenn keine Zeilen selektiert sein.
+   */
+  public Object[] getSelectedObjects() {
+    int[]      selXuluData = dataPoolTable.getSelectedRows();
+    Property[] selProperty = propCont.getSelectedElements();
+
+    Object[] selectedObjects = new Object[ selXuluData.length + selProperty.length ];
+    for (int i=0; i<selXuluData.length; i++)
+      selectedObjects[i] = ((DataPoolTableModel)dataPoolTable.getModel()).getXuluData(selXuluData[i]);
+    for (int i=0; i<selProperty.length; i++)
+      selectedObjects[i+selXuluData.length] = selProperty[i];
+    return selectedObjects;
+  }
+
+  /**
+   * Liefert das in der Datentabelle selektierte XuluObjekt.
+   * @return <code>null</code> wenn keine Zeile selektiert ist
+   */
+  public XuluObject getSelectedObject() {
+    int selXuluData = dataPoolTable.getSelectedRow();
+    if ( selXuluData < 0 )
+      return null;
+    return ((DataPoolTableModel)dataPoolTable.getModel()).getXuluData(selXuluData);
+  }
+
+  /**
+   * Aktualisiert die Visualisierung des Datenpools, indem ein
+   * <code>fireTableDataChanged()</code>-Event auf das TableModel der
+   * Datenpool-Tabelle ausgeloest wird.
+   */
+  public void refresh() {
+    ((AbstractTableModel)dataPoolTable.getModel()).fireTableDataChanged();
+  };
+
+
+  ///////////////////////////////////////////////////////////////////
+  // TableModel fuer die Datenpool-Tabelle
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse stellt ein TableModel fuer den {@link schmitzm.data.DataPool} dar.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  private class DataPoolTableModel extends AbstractTableModel {
+    /** Speichert die Spaltennamen der Tabelle */
+    protected final String[] COLUMN_NAME = {"Xulu-Objekt","Datentyp"};
+
+    /** Fuer wahlfreien Zugriff, wird der DataPool-Inhalt protokolliert. */
+    private Vector content = new Vector();
+
+    /**
+     * Erzeugt ein neues Daten-Modell fuer einen Datenpool.
+     * @param dp Instanz eines Xulu-Datenpools
+     */
+    public DataPoolTableModel(DataPool dp) {
+      // Inhalt des Datenpools aufnehmen
+      for (Enumeration e=dp.asEnumeration(); e.hasMoreElements(); )
+        content.add( e.nextElement() );
+
+      // Listener, der neue DP-Inhalte protokolliert
+      dp.addObjectListener( new ObjectListener() {
+        public void performObjectEvent(ObjectEvent e) {
+          DataPool.DataPoolChangeEvent dpEvent = (DataPool.DataPoolChangeEvent)e;
+          switch (dpEvent.getType()) {
+            // Objekt wurde hinzugefuegt
+            case DataPool.DataPoolChangeEvent.OBJECT_ADDED:
+              content.add(dpEvent.getSource().getRoot());
+              break;
+            // Objekt wurde entfernt
+            case DataPool.DataPoolChangeEvent.OBJECT_REMOVED:
+              content.remove(dpEvent.getSource().getRoot());
+              break;
+          }
+          // Aenderungen an Table(s) weitergeben
+          fireTableDataChanged();
+        }
+      });
+
+    }
+
+    /**
+     * Liefert ein Xulu-Objekt.
+     * @param row Zeile des Datenmodells
+     */
+    public XuluObject getXuluData(int row) {
+      return (XuluObject)content.elementAt(row);
+    }
+
+    /**
+     * Liefert einen Eintrag der Tabelle. Fuer Spalte 0 wird die Objekt-Beschreibung
+     * zurueckgegeben, fuer Spalte 1 der Datentyp des jeweiligen (durch <code>row</code>
+     * spezifizierten) Objekts.
+     * @param row Tabellenzeile
+     * @param col Tabellenspalte
+     */
+    public Object getValueAt(int row, int col) {
+      switch( col ) {
+        case 0: // Objekt-Beschreibung
+                return ((XuluObject)content.elementAt(row)).getDescription();
+        case 1: // Objekt-Typ
+                return ((XuluObject)content.elementAt(row)).getClass();
+      }
+      return null;
+    }
+
+    /**
+     * Liefert die Anzahl an Tabellen-Zeilen. Diese entspricht der Anzahl an
+     * Daten-Objekten im Datenpool.
+     */
+    public int getRowCount() {
+      return this.content.size();
+    }
+
+    /**
+     * Liefert die Anzahl an Tabellen-Spalten. Diese ist konstant 2 (eine
+     * Spalte fuer die Objekt-Bezeichnung und eine fuer den Datentyp).
+     */
+    public int getColumnCount() {
+      return COLUMN_NAME.length;
+    }
+
+    /**
+     * Liefert die Spaltennamen.
+     * @see #COLUMN_NAME
+     */
+    public String getColumnName(int col) {
+      return COLUMN_NAME[col];
+    }
+
+    /**
+     * Prueft, ob eine Tabellen-Zelle editierbar ist. Dies ist fuer alle
+     * Zellen der Spalte 0 ("Objekt-Bezeichnung") der Fall.
+     * @param row Tabellen-Zeile
+     * @param col Tabellen-Spalte
+     */
+    public boolean isCellEditable(int row, int col) {
+      return col == 0;
+    }
+
+    /**
+     * Setzt die jeweilige Objekt-Beschreibung neu, wenn als Spaltennummer 0
+     * angegeben wird. Ansonsten macht diese Methode nichts.
+     * @param obj neue Objektbeschreibung (<code>String</code>)
+     * @param row Tabellen-Zeile
+     * @param col Tabellen-Spalte
+     */
+    public void setValueAt(Object obj, int row, int col) {
+      // nur die Spalte mit der Objekt-Beschreibung ist editierbar
+      if ( isCellEditable(row,col) )
+        ((XuluObject)content.elementAt(row)).setDescription(obj.toString());
+    }
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/gui/DataPoolFrame_Tree.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/gui/DataPoolFrame_Tree.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/gui/DataPoolFrame_Tree.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,471 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.gui;
+
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.BorderLayout;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import javax.swing.JFileChooser;
+import javax.swing.JScrollPane;
+import javax.swing.JTree;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreePath;
+import javax.swing.JTable;
+import javax.swing.table.AbstractTableModel;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.io.File;
+
+import adagios.swing.MultiSplitPane;
+
+import schmitzm.io.FileInputStream;
+import schmitzm.io.FileOutputStream;
+import schmitzm.lang.AlreadyHandledException;
+import schmitzm.swing.ObjectDisplayContainer;
+import schmitzm.swing.event.PopupMenuListener;
+import schmitzm.swing.menu.ObjectMenuItem;
+import schmitzm.swing.tree.EmptyNode;
+import schmitzm.swing.tree.ContentNode;
+import schmitzm.swing.tree.EditableNode;
+
+import schmitzm.data.ObjectStructure;
+import schmitzm.data.event.ObjectListener;
+import schmitzm.data.event.ObjectEvent;
+import schmitzm.data.property.Property;
+import schmitzm.data.property.PropertyType;
+import schmitzm.data.property.Properties;
+import schmitzm.data.property.ValueProperty;
+import schmitzm.data.property.ValuePropertyType;
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.MatrixProperty;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.PropertyWriteAccess;
+import schmitzm.data.property.AccessViolationException;
+
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.DataPool;
+import edu.bonn.xulu.appl.VisualisationTool;
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.data.XuluDataException;
+import edu.bonn.xulu.gui.XuluGUIMessages;
+import edu.bonn.xulu.gui.XuluMainFrame;
+import edu.bonn.xulu.gui.DataPoolMenu;
+import edu.bonn.xulu.gui.DataPoolFrame;
+import edu.bonn.xulu.gui.DataPoolTreeModel;
+
+import schmitzm.temp.BaseTypeUtil;
+
+import javax.swing.tree.DefaultTreeCellRenderer;
+import javax.swing.tree.DefaultTreeCellEditor;
+import javax.swing.event.TreeSelectionEvent;
+import java.util.EventObject;
+
+/**
+ * Diese Klasse stellt den Xulu-Datenpool als Baum dar, in der die Datenstrukturen
+ * der einzelnen Objekte aufgeschluesselt werden.<br>
+ * Die eigentlichen Werte der Eigenschaften werden im Baum nicht dargestellt.
+ * Statt befindet sich im unteren Fensterbereich ein Detail-Fenster, in dem
+ * zur Zeit{@link Properties}-, {@link ListProperty} und
+ * {@link MatrixProperty}-Instanzen tabellarisch dargestellt werden, sowie
+ * Raster/Geometrie-Daten grafisch.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class DataPoolFrame_Tree extends DataPoolFrame {
+  private final Container                       DC_EMPTY          = new Container();
+  private final DisplayContainer_Properties     DC_PROPERTIES     = new DisplayContainer_Properties();
+  private final DisplayContainer_ListProperty   DC_LISTPROPERTY   = new DisplayContainer_ListProperty();
+  private final DisplayContainer_MatrixProperty DC_MATRIXPROPERTY = new DisplayContainer_MatrixProperty();
+  private final DisplayContainer_GeomAndGrid    DC_GEOMGRID       = new DisplayContainer_GeomAndGrid();
+
+  private XuluModellingPlatform  appl              = null;
+  private MultiSplitPane         dataPoolSplitPane = new MultiSplitPane(2,javax.swing.JSplitPane.VERTICAL_SPLIT);
+  private Container              contentPane       = null;
+  private JTree                  dataPoolTree      = null;
+  private ObjectDisplayContainer displayCont       = null;
+  private Object[]               selectedObjects   = new Object[0];
+  private DataPoolMenu           dataPoolMenu      = null;
+
+  /**
+   * Erzeugt einen neue Instanz des grafischen Datenpools. Die Groesse ist
+   * auf 300x350 Pixel voreingestellt.
+   * @param appl Xulu-Applikation fuer die der Datenpool-Frame instanziiert wird
+   */
+  public DataPoolFrame_Tree(XuluModellingPlatform appl) {
+    this(appl, new Dimension(300,350));
+  }
+
+  /**
+   * Erzeugt einen neue Instanz des grafischen Datenpools.
+   * @param appl   Xulu-Applikation fuer die der Datenpool-Frame instanziiert wird
+   * @param size   Groesse des Fensters.
+   */
+  public DataPoolFrame_Tree(XuluModellingPlatform appl, Dimension size) {
+    super();
+    this.appl = appl;
+    this.setSize(size);
+    this.contentPane = this.getContentPane();
+    contentPane.setLayout( new BorderLayout() );
+
+    // Tabelle mit Xulu-Objekten
+    this.dataPoolTree = new JTree( new DataPoolTreeModel(appl.getDataPool(),true,"ROOT") );
+    this.dataPoolTree.setRootVisible(false);
+    this.dataPoolTree.setEditable(true);
+    this.dataPoolTree.setDragEnabled(true);
+    this.dataPoolTree.setCellEditor( new DefaultTreeCellEditor(dataPoolTree, (DefaultTreeCellRenderer)dataPoolTree.getCellRenderer()) {
+      private Object lastSelected = null;
+      // Diese Methode wird aufgerufen, um zu entscheiden, ob ein
+      // Knoten editierbar ist
+      public boolean isCellEditable(EventObject event) {
+        return super.isCellEditable(event) &&
+               lastSelected != null &&
+               lastSelected instanceof EditableNode &&
+               ((EditableNode)lastSelected).isEditable();
+      }
+      // Diese Methode wird aufgerufen, sobald ein neuer Knoten im Baum
+      // selektiert wurde --> merken, welcher das ist
+      public void valueChanged(TreeSelectionEvent e) {
+        if ( e.getNewLeadSelectionPath() != null )
+          lastSelected = e.getNewLeadSelectionPath().getLastPathComponent();
+        else
+          lastSelected = null;
+        super.valueChanged(e);
+      }
+    });
+
+    this.dataPoolTree.addMouseListener(new MouseAdapter() {
+      public void mouseClicked(MouseEvent e) {
+        TreePath selPath = dataPoolTree.getSelectionPath();
+        Object selObj = (selPath!=null && selPath.getLastPathComponent() instanceof ContentNode) ? ((ContentNode)selPath.getLastPathComponent()).getUserObject() : null;
+
+        Object selVal = selObj; // darzustellender Wert
+        try {
+          // Handelt es sich um eine skalare Property, wird deren Wert
+          // dargestellt
+          if (selObj instanceof ScalarProperty)
+            selVal = ( (ScalarProperty) selObj).getOneTimeReadAccess().getValue();
+          // ggf. neuen DisplayContainer setzen
+          setDisplayContainerForObject(selVal);
+          // falls es fuer den Wert keinen Container gibt, es sich aber um
+          // Property handelt, diese selbst darstellen
+          if (displayCont == null && selObj instanceof Property) {
+            setDisplayContainerForObject(selObj);
+            selVal = selObj;
+          }
+          // falls es einen passenden Container gibt, Objekt setzen
+          if (displayCont != null)
+            displayCont.setObject(selVal);
+        } catch ( AccessViolationException err ) {
+          XuluGUIMessages.showAccessError(contentPane,err);
+        } catch ( Exception err ) {
+          XuluGUIMessages.showError(contentPane,err,"Unerwarteter Fehler:");
+        }
+      }
+    });
+
+    // SplitPane organisieren
+    dataPoolSplitPane.setResizeWeigth( new double[] {0.5,0.5} );
+    dataPoolSplitPane.setDividerSize(2);
+    dataPoolSplitPane.setContainer(0,new JScrollPane(dataPoolTree));
+    dataPoolSplitPane.setContainer(1,DC_EMPTY);
+    contentPane.add(dataPoolSplitPane);
+
+    // Popup-Menu anbinden
+    dataPoolMenu = new DataPoolMenu(appl,this);
+    PopupMenuListener listener = new PopupMenuListener(dataPoolMenu.getPopupMenu()) {
+      public void mouseReleased(MouseEvent e) {
+        // Wenn noch keine Baum-Element selektiert war, wird automatisch
+        // das Element selektiert, das die geklickt wurde
+        if ( e.isPopupTrigger() && dataPoolTree.getSelectionCount() <= 1 ) {
+          TreePath path = dataPoolTree.getPathForLocation(e.getX(),e.getY());
+          dataPoolTree.setSelectionPath(path);
+        }
+        super.mouseReleased(e);
+      }
+    };
+    dataPoolTree.addMouseListener( listener );
+    dataPoolSplitPane.getContainer(0).addMouseListener( listener );
+
+  }
+
+  /**
+   * Liefert alle in der Datentabelle <b>und</b> in der Eigenschaftstabelle
+   * selektierten Objekte. Dies koennen sowohl <code>XuluObject</code>s sein,
+   * als auch einzelne <code>Property</code>s.<br>
+   * <b>Bemerke:</b><br>
+   * Zur Zeit werden nur die Xulu-Objekte zurueckgegeben!!
+   * @return einen leeren Array wenn keine Zeilen selektiert sind
+   */
+  public Object[] getSelectedObjects() {
+    // selektierte Objekte im Datenpool und DisplayContainer
+    TreePath[] selXuluDataPath = dataPoolTree.getSelectionPaths();
+    if ( selXuluDataPath == null )
+      selXuluDataPath = new TreePath[0];
+    Object[] selDisplayObjects = getSelectedObjectsFromDisplayContainer();
+
+    // alle selektierten Objekte zusammen
+    Object[]   selectedObjects = new Object[ selXuluDataPath.length + selDisplayObjects.length ];
+    for (int i=0; i<selXuluDataPath.length; i++)
+      selectedObjects[i] = ((ContentNode)selXuluDataPath[i].getLastPathComponent()).getUserObject();
+    for (int i=0; i<selDisplayObjects.length; i++)
+      selectedObjects[i+selXuluDataPath.length] = selDisplayObjects[i];
+    return selectedObjects;
+  }
+
+  /**
+   * Liefert das letzte in der Datentabelle selektierte Objekt.
+   * @return <code>null</code> wenn keine Zeile selektiert ist
+   */
+  public Object getSelectedObject() {
+    // selektierte Objekte im Datenpool und DisplayContainer
+    TreePath selXuluDataPath = dataPoolTree.getSelectionPath();
+    if ( selXuluDataPath == null )
+      return null;
+    return ((ContentNode)selXuluDataPath.getLastPathComponent()).getUserObject();
+  }
+
+  /**
+   * Aktualisiert die Visualisierung des Datenpools, indem ein
+   * <code>reload()</code>-Event auf das TreeModel des Datenpools
+   * ausgeloest wird.
+   */
+  public void refresh() {
+    ((DataPoolTreeModel)dataPoolTree.getModel()).reload();
+    setDisplayContainerForObject(null);
+  };
+
+
+  /**
+   * Setzt den passenden Display-Container fuer ein Objekt.
+   */
+  private void setDisplayContainerForObject(Object obj) {
+    // wenn noch kein DisplayContainer besteht oder der bestehende
+    // das Objekt nicht darstellen kann, wird ein neuer gewaehlt
+    if ( displayCont == null || !displayCont.canDisplay(obj) ||
+         // Da ListProperty und MatrixProperty auch Property implementieren,
+         // koennen sie von DC_PROPERTIES dargestellt werden, dieser soll
+         // jedoch nicht fuer Liste/Matrix verwendet werden!
+         displayCont == DC_PROPERTIES && (obj instanceof ListProperty || obj instanceof MatrixProperty) ) {
+      if ( DC_LISTPROPERTY.canDisplay(obj) )
+        displayCont = DC_LISTPROPERTY;
+      else if ( DC_MATRIXPROPERTY.canDisplay(obj) )
+        displayCont = DC_MATRIXPROPERTY;
+      else if ( DC_PROPERTIES.canDisplay(obj) )
+        displayCont = DC_PROPERTIES;
+      else if ( DC_GEOMGRID.canDisplay(obj) )
+        displayCont = DC_GEOMGRID;
+      else
+        // fuer das Object gibt es keinen Container
+        displayCont = null;
+      // SplitPane aktualisieren
+      dataPoolSplitPane.setContainer(1,displayCont!=null ? displayCont : DC_EMPTY);
+    }
+  }
+
+  /**
+   * Liefert alle im Display-Container selektierten Objekte.
+   */
+  private Object[] getSelectedObjectsFromDisplayContainer() {
+    Object[] selDisplayObjects = new Object[0];
+    if ( displayCont instanceof DisplayContainer_Table )
+      selDisplayObjects = ((DisplayContainer_Table)displayCont).getSelectedElements();
+    return selDisplayObjects;
+  }
+
+// Es gibt nun eine eigene Klasse fuer
+//  ///////////////////////////////////////////////////////////////////
+//  // TreeModel fuer die Datenpool-Tabelle
+//  ///////////////////////////////////////////////////////////////////
+//  /**
+//   * Diese Klasse stellt ein TreeModel fuer den {@link schmitzm.data.DataPool} dar.
+//   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+//   * @version 1.0
+//   */
+//  private class DataPoolTreeModel extends DefaultTreeModel {
+//    private DataPool dataPool = null;
+//
+//    /**
+//     * Erzeugt ein neues Daten-Modell fuer einen Datenpool.
+//     * @param dp Instanz eines Xulu-Datenpools
+//     */
+//    public DataPoolTreeModel(DataPool dp) {
+//      super( new EmptyNode("ROOT") );
+//      this.dataPool = dp;
+//
+//      dp.addObjectListener( new ObjectListener() {
+//        public void performObjectEvent(ObjectEvent e) {
+//          DataPool.DataPoolChangeEvent dpEvent = (DataPool.DataPoolChangeEvent)e;
+//          switch (dpEvent.getType()) {
+//            // Objekt wurde hinzugefuegt
+//            case DataPool.DataPoolChangeEvent.OBJECT_ADDED:
+//              add( (XuluObject)dpEvent.getSource().getRoot() );
+//              break;
+//            // Objekt wurde entfernt
+//            case DataPool.DataPoolChangeEvent.OBJECT_REMOVED:
+//              remove( (XuluObject)dpEvent.getSource().getRoot() );
+//              break;
+//          }
+//          reload();
+//        }
+//      });
+//    }
+//
+//    public void reorganize() {
+//      ((EmptyNode)getRoot()).removeAllChildren();
+//      // Fuer alle Xulu-Objekte einen Knoten einfuegen
+//      for ( Enumeration e = dataPool.asEnumeration(); e.hasMoreElements(); )
+//        add( (XuluObject)e.nextElement() );
+////      this.nodeStructureChanged( (TreeNode)getRoot() );
+//      reload();
+//    }
+//
+//    public void add(XuluObject obj) {
+//      ObjectStructureNode node = new ObjectStructureNode(obj,true) {
+//        // bei Aenderung aendert sich der Name des Objekts
+//        public void setUserObject(Object newValue) {
+//          if ( newValue instanceof String && getUserObject() instanceof XuluObject )
+//            ((XuluObject)getUserObject()).setDescription( (String)newValue );
+//        }
+//      };
+//      ((EmptyNode)getRoot()).add(node);
+//    }
+//
+//    public void remove(XuluObject obj) {
+//      // Knoten des Objekts suchen und entfernen
+//      for (int i=0; i<((TreeNode)getRoot()).getChildCount();i++) {
+//        ContentNode child = (ContentNode) ((EmptyNode)getRoot()).getChildAt(i);
+//        if ( child.getUserObject() == obj )
+//          ((EmptyNode)getRoot()).remove( i-- );
+//      }
+//    }
+//
+//    private class ObjectStructureNode extends ContentNode {
+//      public ObjectStructureNode(Object obj) {
+//        this(obj,false);
+//      }
+//
+//      public ObjectStructureNode(Object obj, boolean editable) {
+//        super(obj,editable);
+//        reorganize();
+//      }
+//
+//      public void reorganize() {
+//        // Wenn kein strukturiertes Objekt, dann auch keine Kindknoten
+//        if ( !(getUserObject() instanceof ObjectStructure) )
+//          return;
+//
+//        ObjectStructure struct = (ObjectStructure)getUserObject();
+//        removeAllChildren();
+//
+//        // Zwischenknoten?
+//        DefaultMutableTreeNode node = this;
+//        if ( struct.containsMultipleValues() )
+//          node = new EmptyNode(struct.getClass().getSimpleName());
+//
+//        // Kindknoten
+//        for (Enumeration attr = struct.getAttrTypes(); attr.hasMoreElements();)
+//          node.add( new ObjectStructureNode(attr.nextElement()) );
+//
+//        // wenn Zwischenknoten, dann diesen einfuegen
+//        if ( node != this )
+//          add( node );
+//      }
+//
+//      public String toString() {
+//        if ( getUserObject() instanceof ObjectStructure &&
+//             ((ObjectStructure)getUserObject()).isStructureNamed() )
+//          return ((ObjectStructure)getUserObject()).getStructureName();
+//        if ( getUserObject() instanceof Class )
+//          return ((Class)getUserObject()).getSimpleName();
+//
+//        return getUserObject().getClass().getSimpleName();
+//      }
+//    }
+//
+////    private class ObjectStructureNode extends ContentNode {
+////      public ObjectStructureNode(Object obj, String desc) {
+////        super(obj,desc,false);
+////        reorganize();
+////      }
+////
+////      public void reorganize() {
+////        removeAllChildren();
+////
+////        // Xulu-Objekte >> Jede Property erhaelt einen Knoten
+////        if ( getUserObject() instanceof XuluObject ) {
+////          Property[] prop = ((Properties)getUserObject()).getProperties();
+////          for (int i=0; i<prop.length; i++) {
+////            PropertyType type = prop[i].getPropertyType();
+////            add(new ObjectStructureNode(prop[i],prop[i].getName()));
+////          }
+////        }
+////        // andere Property-Mengen >> erst eigener "Menge"-Knoten, darunter
+////        //                           ein Unterkoten fuer Property
+////        else if ( getUserObject() instanceof Properties ) {
+////          Property[] prop = ((Properties)getUserObject()).getProperties();
+////          ContentNode inNode = new ContentNode(getUserObject(),"PropertySet",false);
+////          for (int i=0; i<prop.length; i++) {
+////            PropertyType type = prop[i].getPropertyType();
+////            inNode.add(new ObjectStructureNode(prop[i],prop[i].getName()));
+////          }
+////          add(inNode);
+////        }
+//// /*
+////        // ListProperty >> erst eigener "Liste"-Knoten, darunter
+////        //                 ein Unterkoten den Elementtyp
+////        else if ( getUserObject() instanceof ListProperty ) {
+////          ContentNode inNode = new ContentNode(getUserObject(),"List",false);
+////          Object sample = ((ListProperty)getUserObject()).getPropertyType().getSampleValue();
+////          if ( sample == null )
+////            inNode.add( new EmptyNode( ((ListProperty)getUserObject()).getType().getName() ) );
+////          else
+////            inNode.add(new ObjectStructureNode( ((ListProperty)getUserObject()).getPropertyType().getSampleValue(),"??" ));
+////          add(inNode);
+////        }
+////        // ScalarProperty >> erst eigener "Liste"-Knoten, darunter
+////        //                   ein Unterkoten den Elementtyp
+////        else if ( getUserObject() instanceof ScalarProperty ) {
+////          Object sample = ((ScalarProperty)getUserObject()).getPropertyType().getSampleValue();
+////          if ( sample == null )
+////            add( new EmptyNode( ((ScalarProperty)getUserObject()).getType().getName() ) );
+////          else if ( sample instanceof Property )
+////            add( new ObjectStructureNode( sample, ((Property)sample).getName() ) );
+////          else
+////            add( new EmptyNode(sample.getClass().getName()) );
+////        }
+////*/
+////        else if ( getUserObject() instanceof ValueProperty ) {
+////          Object sample = ((ValueProperty)getUserObject()).getPropertyType().getSampleValue();
+////          if ( sample == null )
+////            add( new EmptyNode( ((ValueProperty)getUserObject()).getType().getName() ) );
+////          else
+////            add(new ObjectStructureNode( ((ValueProperty)getUserObject()).getPropertyType().getSampleValue(),getUserObject().getClass().getSimpleName() ));
+////        }
+////
+////        else {
+////          add( new EmptyNode(getUserObject().getClass().getName()) );
+////        }
+////      }
+////    }
+//  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/gui/DisplayContainer_GeomAndGrid.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/gui/DisplayContainer_GeomAndGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/gui/DisplayContainer_GeomAndGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,151 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.gui;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.geom.Rectangle2D;
+import java.awt.event.MouseEvent;
+import javax.swing.JScrollPane;
+
+import org.opengis.geometry.Envelope; // gt2-2.4.2
+//import org.opengis.spatialschema.geometry.Envelope; // gt2-2.3.4
+
+import org.geotools.coverage.grid.GridCoverage2D;
+import org.geotools.feature.FeatureCollection;
+
+import org.geotools.map.DefaultMapContext;
+import org.geotools.renderer.lite.StreamingRenderer;
+import org.geotools.styling.Style;
+import org.geotools.styling.Symbolizer;
+import org.geotools.styling.Rule;
+import org.geotools.styling.ColorMap;
+import org.geotools.styling.RasterSymbolizer;
+import org.geotools.styling.StyleBuilder;
+import org.geotools.styling.BasicPolygonStyle;
+import org.geotools.styling.BasicLineStyle;
+import schmitzm.geotools.feature.FeatureUtil;
+import schmitzm.geotools.gui.JMapPane;
+import edu.bonn.xulu.gui.XuluGUIMessages;
+
+import schmitzm.swing.ObjectDisplayContainer;
+
+/**
+ * Diese Klasse stellt eine GUI-Komponente dar, in der immer eine der folgenden
+ * Instanzen grafisch angezeigt werden kann:
+ * <ul>
+ * <li>{@link GridCoverage2D}</li>
+ * <li>{@link FeatureCollection}</li>
+ * </ul>
+ * @see JMapPane
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class DisplayContainer_GeomAndGrid extends ObjectDisplayContainer {
+  private JMapPane map = null;
+
+  /**
+   * Erzeugt eine neue Darstellungskomponente.
+   */
+  public DisplayContainer_GeomAndGrid() {
+    this(null);
+  }
+
+  /**
+   * Erzeugt eine neue Darstellungskomponente und zeigt sofort ein
+   * Objekt an.
+   * @param data anzuzeigendes Objekt
+   */
+  public DisplayContainer_GeomAndGrid(Object data) {
+    super();
+    this.setLayout(new BorderLayout());
+    this.map = new JMapPane();
+    this.map.setSize(100,100);
+    this.add(map, BorderLayout.CENTER);
+    this.doLayout();
+    setObject(data);
+  }
+
+  /**
+   * Prueft, ob ein Objekt darstellbar ist.
+   * @return <code>true</code> gdw. das angegebene Objekt eine Instanz von
+   *         {@link GridCoverage2D} oder {@link FeatureCollection} ist.
+   */
+  public boolean canDisplay(Object data) {
+    return data instanceof GridCoverage2D
+        || data instanceof FeatureCollection
+    ;
+  }
+
+  /**
+   * Aktualisiert die Darstellung des aktuell angezeigten Objekts.
+   */
+  public void refresh() {
+    if (map != null) {
+      // aktuelle Darstellung (Position/Zoom) merken, um nachher den
+      // das neue Layer in diesen Einstellungen anzuzeigen
+      com.vividsolutions.jts.geom.Envelope oldArea = ( map.getContext().getLayerCount() > 0 ) ? map.getMapArea() : null;
+      com.vividsolutions.jts.geom.Envelope newArea = null;
+      // alte Layer entfernen
+      map.getContext().clearLayerList();
+
+      // neues Layer einfuegen
+      if ( data instanceof GridCoverage2D ) {
+        // ###### RASTER ######
+        StyleBuilder builder = new StyleBuilder();
+        ColorMap     colMap  = builder.createColorMap(
+            new String[]  {    "Blue",     "Green",     "Yellow",    "Red"},
+            new double[]  {         0,           1,          2,          3},
+            new Color[]   {Color.BLUE, Color.GREEN, Color.YELLOW, Color.RED},
+            ColorMap.TYPE_VALUES
+        );
+        RasterSymbolizer rasterSymb = builder.createRasterSymbolizer();
+        rasterSymb.setColorMap( colMap );
+
+        Style rasterStyle = builder.createStyle( rasterSymb );
+        map.getContext().addLayer( (GridCoverage2D) data, rasterStyle );
+
+// Versuch, die Farbe nachtraeglich zu aktualisieren:
+//        colMap  = builder.createColorMap(
+//            new String[]  {    "Blue",     "Green",     "Yellow",    "Red"},
+//            new double[]  {         0,           1,          2,          3},
+//            new Color[]   {Color.BLUE, Color.GREEN, Color.YELLOW, Color.RED},
+//            ColorMap.TYPE_VALUES
+//        );
+//        rasterSymb = builder.createRasterSymbolizer(colMap,1.0);
+//        rasterSymb.setColorMap( colMap );
+//        map.getContext().getLayer(0).setStyle(rasterStyle);
+
+        // neuer Anzeigebereich: Das komplette Raster
+        Envelope e = ((GridCoverage2D) data).getEnvelope();
+        newArea = new com.vividsolutions.jts.geom.Envelope(
+              e.getUpperCorner().getOrdinate(0),  // X1
+              e.getLowerCorner().getOrdinate(0),  // X2
+              e.getUpperCorner().getOrdinate(1),  // Y1
+              e.getLowerCorner().getOrdinate(1)); // Y2
+      } else
+      if ( data instanceof FeatureCollection ) {
+        // ###### FEATURECOLLECTION ######
+        FeatureCollection fc      = (FeatureCollection) data;
+        Style             fcStyle = FeatureUtil.createDefaultStyle(fc);
+        map.getContext().addLayer( fc, fcStyle );
+        // neuer Anzeigebereich: Die komplette FeatureCollection
+        newArea = (fc.getBounds());
+      }
+
+      map.setMapArea( newArea );
+      map.setReset(true);
+      map.repaint();
+
+    }
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/gui/DisplayContainer_ListProperty.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/gui/DisplayContainer_ListProperty.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/gui/DisplayContainer_ListProperty.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,235 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.gui;
+
+import java.awt.BorderLayout;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+
+import schmitzm.swing.ObjectDisplayContainer;
+import schmitzm.data.property.Properties;
+import schmitzm.data.property.Property;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyWriteAccess;
+import schmitzm.data.property.AccessViolationException;
+
+import edu.bonn.xulu.gui.XuluGUIMessages;
+
+import schmitzm.temp.BaseTypeUtil;
+
+/**
+ * Diese Klasse stellt eine GUI-Komponente dar, in der eine
+ * {@link ListProperty}-Instanz angezeigt werden kann. Die einzelnen Listen-Elemente
+ * werden tabellarisch in 3 Spalten aufgelistet:
+ * <ol>
+ * <li>Listenindex</li>
+ * <li>Typ des Listenelements</li>
+ * <li>Typ des Listenelements (sofern darstellbar)</li>
+ * </ol>
+ * Darstellbar sind Elemente, die einen Basis-Datentyps (z.B. Integer) repraesentieren.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class DisplayContainer_ListProperty extends DisplayContainer_Table {
+  /**
+   * Erzeugt eine neue Darstellungskomponente.
+   */
+  public DisplayContainer_ListProperty() {
+    this(null);
+  }
+
+  /**
+   * Erzeugt eine neue Darstellungskomponente und zeigt sofort ein
+   * Objekt an.
+   * @param data anzuzeigendes Objekt
+   */
+  public DisplayContainer_ListProperty(Object data) {
+    super(data);
+  }
+
+  /**
+   * Erzeugt das TableModel fuer die Tabelle
+   * @param o darzustellendes <code>ListProperty</code>-Objekt (kann <code>null</code> sein!)
+   */
+  protected ListPropertyTableModel createTableModel(Object o) {
+    return new ListPropertyTableModel((ListProperty)o);
+  }
+
+  /**
+   * Liefert die aktuell dargestellte {@link ListProperty}-Instanz.
+   * @return <code>null</code> falls aktuell kein Objekt dargestellt wird
+   */
+  public ListProperty getObject() {
+    return (ListProperty)super.getObject();
+  }
+
+  /**
+   * Prueft, ob ein Objekt darstellbar ist.
+   * @return <code>true</code> gdw. das angegebene Objekt eine Instanz von
+   *         {@link ListProperty} ist.
+   */
+  public boolean canDisplay(Object data) {
+    return data instanceof ListProperty;
+  }
+
+  /**
+   * Liefert alle in der Tabelle selektierten Listenelemente.
+   */
+  public Object[] getSelectedElements() {
+    int[] selIdx = table.getSelectedRows();
+    Object[] selElements = new Object[selIdx.length];
+    for (int i=0; i<selElements.length; i++)
+      selElements[i] = ((ListPropertyTableModel)tableModel).getListElement( selIdx[i] );
+    return selElements;
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // TableModel fuer die ListProperty-Tabelle
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse stellt ein TableModel fuer ListProperty-Instanzen dar.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  private class ListPropertyTableModel extends DisplayContainerTableModel {
+    protected final String[] COLUMN_NAME = {"Index","Type","Value"};
+    private ListProperty listProp = null;
+
+    /**
+     * Erzeugt ein neues Daten-Modell fuer ein <code>ListProperty</code>-Objekt.
+     * @param data listProp Listen-Eigenschaft
+     * @see schmitzm.data.property.ListProperty
+     */
+    public ListPropertyTableModel(ListProperty listProp) {
+      setData(listProp);
+    }
+
+    /**
+     * Erzeugt ein leeres Daten-Modell fuer ein <code>ListProperty</code>-Objekt.
+     * @see schmitzm.data.property.ListProperty
+     */
+    public ListPropertyTableModel() {
+      this(null);
+    }
+
+    /**
+     * Setzt die Liste, deren Elemente dargestellt werden sollen.
+     * @param listProp Listen-Eigenschaft (kann <code>null</code> sein!)
+     */
+    public void setData(Object listProp) {
+      this.listProp = (ListProperty)listProp;
+      fireTableDataChanged();
+    }
+
+    /**
+     * Liefert ein Listen-Element.
+     * @param row Zeile des Datenmodells
+     */
+    public Object getListElement(int row) {
+      return this.listProp.getOneTimeReadAccess().getValue(row);
+    }
+
+    /**
+     * Liefert einen Eintrag der Tabelle. Fuer Spalte 0 wird der Listenindex
+     * zurueckgegeben, fuer Spalte 1 der Datentyp und fuer Spalte 2
+     * der aktuelle Wert des Listenelements. Letzter wird nur angezeigt, wenn es
+     * sich bei dem Listenelement um einen Basisdatentyp handelt.
+     * @param row Tabellenzeile
+     * @param col Tabellenspalte
+     */
+    public Object getValueAt(int row, int col) {
+      switch( col ) {
+        case 0: // Name der Property
+                return row;
+        case 1: // Typ des Listenelements
+                String typeStr = getListElement(row).getClass().getSimpleName();
+                if ( getListElement(row) instanceof Property )
+                  typeStr += "["+((Property)getListElement(row)).getType().getSimpleName()+"]";
+                return typeStr;
+        case 2: // aktueller Wert des Listen-Elements
+                try {
+                  return getListElement(row);
+                } catch( AccessViolationException err ) {
+                  return "<no access!!>";
+                }
+      }
+      return null;
+    }
+
+    /**
+     * Liefert die Anzahl an Tabellen-Zeilen. Diese entspricht der Anzahl an
+     * Elementen in der ListProperty.
+     */
+    public int getRowCount() {
+      return (listProp!=null) ? listProp.getOneTimeReadAccess().getCount() :0;
+    }
+
+    /**
+     * Liefert die Anzahl an Tabellen-Spalten. Diese ist konstant 3 (je eine
+     * Spalte fuer Listenindex, Elementtyp und Elementwert).
+     */
+    public int getColumnCount() {
+      return COLUMN_NAME.length;
+    }
+
+    /**
+     * Liefert die Spaltennamen.
+     * @see #COLUMN_NAME
+     */
+    public String getColumnName(int col) {
+      return COLUMN_NAME[col];
+    }
+
+    /**
+     * Prueft, ob eine Tabellen-Zelle editierbar ist. Dies ist nur fuer die
+     * Spalte mit dem Element-Wert der Fall und nur wenn es sich um einen
+     * Build-In-Type beinhaltet.
+     * @param row Tabellen-Zeile
+     * @param col Tabellen-Spalte
+     * @see schmitzm.temp.BaseTypeUtil#isBaseType(Class)
+     */
+    public boolean isCellEditable(int row, int col) {
+      return col == 2 &&
+             BaseTypeUtil.isBaseType( getListElement(row) );
+    }
+
+    /**
+     * Setzt den jeweiligen Property-Wert neu.
+     * @param obj neue Objektbeschreibung (<code>String</code>)
+     * @param row Tabellen-Zeile
+     * @param col Tabellen-Spalte
+     * @see #isCellEditable(int,int)
+     * @see schmitzm.temp.BaseTypeUtil#convertFromString(String,Class)
+     */
+    public void setValueAt(Object obj, int row, int col) {
+      if ( isCellEditable(row,col) ) {
+        ListPropertyWriteAccess w = null;
+        try {
+          w = listProp.getWriteAccess(this);
+          w.setValue(BaseTypeUtil.convertFromString((String)obj, listProp.getType()),row);
+        } catch (AccessViolationException err) {
+          XuluGUIMessages.showAccessError(GUI_COMPONENT,err);
+        } catch (NumberFormatException err) {
+          XuluGUIMessages.showBaseTypeError(GUI_COMPONENT,err);
+        } catch (Exception err) {
+          XuluGUIMessages.showError(GUI_COMPONENT,err);
+        } finally {
+          // Schreibrecht muss unbedingt wieder freigegeben werden!!
+          if ( w!=null ) w.release();
+        }
+
+      }
+    }
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/gui/DisplayContainer_MatrixProperty.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/gui/DisplayContainer_MatrixProperty.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/gui/DisplayContainer_MatrixProperty.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,248 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.gui;
+
+import java.util.Vector;
+import java.awt.Component;
+import javax.swing.JTable;
+import javax.swing.JLabel;
+import javax.swing.ListSelectionModel;
+import javax.swing.table.DefaultTableCellRenderer;
+
+import schmitzm.data.property.MatrixProperty;
+import schmitzm.data.property.PropertyWriteAccess;
+import schmitzm.data.property.AccessViolationException;
+
+import edu.bonn.xulu.gui.XuluGUIMessages;
+
+import schmitzm.temp.BaseTypeUtil;
+
+/**
+ * Diese Klasse stellt eine GUI-Komponente dar, in der eine
+ * 2-dimensionale (m,n)-{@link MatrixProperty} angezeigt werden kann.
+ * Die einzelnen Matrix-Werte werden tabellarisch in m Spalten und n Zeilen
+ * aufgelistet.<br>
+ * Darstellbar (und editierbar) sind Elemente, die einen Basis-Datentyps
+ * (z.B. Integer) repraesentieren.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class DisplayContainer_MatrixProperty extends DisplayContainer_Table {
+  /**
+   * Erzeugt eine neue Darstellungskomponente.
+   */
+  public DisplayContainer_MatrixProperty() {
+    this(null);
+  }
+
+  /**
+   * Erzeugt eine neue Darstellungskomponente und zeigt sofort ein
+   * Objekt an.
+   * @param data anzuzeigendes Objekt
+   */
+  public DisplayContainer_MatrixProperty(Object data) {
+    super(data);
+    this.table.getTableHeader().setReorderingAllowed(false);
+    this.table.setCellSelectionEnabled(true);
+    this.table.setSelectionMode( ListSelectionModel.MULTIPLE_INTERVAL_SELECTION );
+    // Die erste Spalte, in der die Zeilennummern ausgegeben werden, soll
+    // wie der Header aussehen
+    this.table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
+      public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+        if ( column == 0 )
+          return table.getTableHeader().getDefaultRenderer().getTableCellRendererComponent(table,value,false,false,row,column);
+        JLabel comp = (JLabel)super.getTableCellRendererComponent(table,value,isSelected,hasFocus,row,column);
+        comp.setHorizontalAlignment(JLabel.CENTER);
+        return comp;
+      }
+    });
+  }
+
+  /**
+   * Erzeugt das TableModel fuer die Tabelle
+   * @param o darzustellendes <code>MatrixProperty</code>-Objekt (kann <code>null</code> sein!)
+   */
+  protected MatrixPropertyTableModel createTableModel(Object o) {
+    return new MatrixPropertyTableModel((MatrixProperty)o);
+  }
+
+  /**
+   * Liefert die aktuell dargestellte {@link MatrixProperty}-Instanz.
+   * @return <code>null</code> falls aktuell kein Objekt dargestellt wird
+   */
+  public MatrixProperty getObject() {
+    return (MatrixProperty)super.getObject();
+  }
+
+  /**
+   * Prueft, ob ein Objekt darstellbar ist.
+   * @return <code>true</code> gdw. das angegebene Objekt eine Instanz von
+   *         {@link MatrixProperty} ist, dessen Dimension 2 ist.
+   */
+  public boolean canDisplay(Object data) {
+    return data instanceof MatrixProperty &&
+           ((MatrixProperty)data).getDimension() == 2;
+  }
+
+  /**
+   * Liefert alle in der Tabelle selektierten Matrixelemente.
+   */
+  public Object[] getSelectedElements() {
+    Vector selElem = new Vector();
+    int[] selRowIdx = table.getSelectedRows();
+    int[] selColIdx = table.getSelectedRows();
+    for (int c=0; c<selColIdx.length; c++)
+      if (selColIdx[c] > 0 ) // erste Spalte sind die Zeilennummern! Nicht selektierbar!
+        for (int r=0; r<selRowIdx.length; r++)
+          if ( table.isCellSelected(r,c) )
+            selElem.add( ((MatrixPropertyTableModel)tableModel).getMatrixElement(selRowIdx[r],selColIdx[c]) );
+    return selElem.toArray(new Object[0]);
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // TableModel fuer die MatrixProperty-Tabelle
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse stellt ein TableModel fuer MatrixProperty-Instanzen dar.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  private class MatrixPropertyTableModel extends DisplayContainerTableModel {
+    private MatrixProperty matrixProp = null;
+
+    /**
+     * Erzeugt ein neues Daten-Modell fuer ein <code>MatrixProperty</code>-Objekt.
+     * @param data matrixProp Matrix-Eigenschaft
+     * @see schmitzm.data.property.MatrixProperty
+     */
+    public MatrixPropertyTableModel(MatrixProperty matrixProp) {
+      setData(matrixProp);
+    }
+
+    /**
+     * Erzeugt ein leeres Daten-Modell fuer ein <code>MatrixProperty</code>-Objekt.
+     * @see schmitzm.data.property.MatrixProperty
+     */
+    public MatrixPropertyTableModel() {
+      this(null);
+    }
+
+    /**
+     * Setzt die Matrix, deren Elemente dargestellt werden sollen.
+     * @param matrixProp Matrix-Eigenschaft (kann <code>null</code> sein!)
+     */
+    public void setData(Object matrixProp) {
+      this.matrixProp = (MatrixProperty)matrixProp;
+      fireTableDataChanged();
+    }
+
+    /**
+     * Liefert ein Matrix-Element.
+     * @param row Zeile des Datenmodells
+     * @param col Spalte des Datenmodells
+     */
+    public Object getMatrixElement(int row, int col) {
+      if ( col == 0 )
+        return null;
+      return this.matrixProp.getOneTimeReadAccess().getValue(col-1,row);
+    }
+
+    /**
+     * Liefert einen Eintrag der Tabelle. Es wird das entsprechende Matrix-Element
+     * geliefert
+     * @param row Tabellenzeile
+     * @param col Tabellenspalte
+     */
+    public Object getValueAt(int row, int col) {
+      try {
+        // in der ersten Spalte stehen die Zeilennummern
+        if ( col == 0 )
+          return row;
+        // in den weiteren Spalten die Matrix-Spalten
+        return getMatrixElement(row,col);
+      } catch( AccessViolationException err ) {
+        return "<no access!!>";
+      }
+    }
+
+    /**
+     * Liefert die Anzahl an Tabellen-Zeilen. Diese entspricht der
+     * Matrix-Groesse in Dimension 1.
+     */
+    public int getRowCount() {
+      return (matrixProp!=null) ? matrixProp.getSize(1) :0;
+    }
+
+    /**
+     * Liefert die Anzahl an Tabellen-Spalten. Diese entspricht der
+     * Matrix-Groesse in Dimension 0 plus 1 fuer die erste Spalte, die die
+     * Zeilennummern enthaelt.
+     */
+    public int getColumnCount() {
+      // Matrix-Spalten plus eine Spalte fuer die Zeilennummern
+      return (matrixProp!=null) ? matrixProp.getSize(0)+1 :0;
+    }
+
+    /**
+     * Liefert die Spaltennamen. Dieser entspricht der Spaltennummer minus 1,
+     * da in der allerersten Spalte die Zeilennummern stehen.
+     */
+    public String getColumnName(int col) {
+      // in der ersten Spalte stehen die Zeilennummern
+      if ( col == 0 )
+        return matrixProp.getSize(0)+"x"+matrixProp.getSize(1);
+      // in den restlichen Spalten die Matrix-Spalten
+      return String.valueOf(col-1);
+    }
+
+    /**
+     * Prueft, ob eine Tabellen-Zelle editierbar ist. Dies ist nur fuer Zellen
+     * der Fall bei denen es sich um einen Build-In-Type beinhaltet.
+     * @param row Tabellen-Zeile
+     * @param col Tabellen-Spalte
+     * @see schmitzm.temp.BaseTypeUtil#isBaseType(Class)
+     */
+    public boolean isCellEditable(int row, int col) {
+      // in der ersten Spalte stehen die Zeilennummern
+      return col > 0 && BaseTypeUtil.isBaseType( getMatrixElement(row,col) );
+    }
+
+    /**
+     * Setzt den jeweiligen Property-Wert neu.
+     * @param obj neue Objektbeschreibung (<code>String</code>)
+     * @param row Tabellen-Zeile
+     * @param col Tabellen-Spalte
+     * @see #isCellEditable(int,int)
+     * @see schmitzm.temp.BaseTypeUtil#convertFromString(String,Class)
+     */
+    public void setValueAt(Object obj, int row, int col) {
+      if ( isCellEditable(row,col) ) {
+        PropertyWriteAccess w = null;
+        try {
+          w = matrixProp.getWriteAccess(this);
+          w.setValue(BaseTypeUtil.convertFromString((String)obj, matrixProp.getType()),col-1,row);
+        } catch (AccessViolationException err) {
+          XuluGUIMessages.showAccessError(GUI_COMPONENT,err);
+        } catch (NumberFormatException err) {
+          XuluGUIMessages.showBaseTypeError(GUI_COMPONENT,err);
+        } catch (Exception err) {
+          XuluGUIMessages.showError(GUI_COMPONENT,err);
+        } finally {
+          // Schreibrecht muss unbedingt wieder freigegeben werden!!
+          if ( w!=null ) w.release();
+        }
+
+      }
+    }
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/gui/DisplayContainer_Properties.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/gui/DisplayContainer_Properties.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/gui/DisplayContainer_Properties.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,273 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.gui;
+
+import java.awt.BorderLayout;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+
+import schmitzm.swing.ObjectDisplayContainer;
+import schmitzm.data.property.Properties;
+import schmitzm.data.property.Property;
+import schmitzm.data.property.PropertySet;
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.data.property.PropertyWriteAccess;
+import schmitzm.data.property.AccessViolationException;
+
+import edu.bonn.xulu.gui.XuluGUIMessages;
+
+import schmitzm.temp.BaseTypeUtil;
+
+/**
+ * Diese Klasse stellt eine GUI-Komponente dar, in der eine
+ * {@link Properties}-Instanz angezeigt werden kann. Die einzelnen Eigenschaften
+ * werden tabellarisch in 3 Spalten aufgelistet:
+ * <ol>
+ * <li>Name der Property</li>
+ * <li>Typ der Property</li>
+ * <li>Wert der Property (sofern darstellbar)</li>
+ * </ol>
+ * Darstellbar (und aenderbar) sind skalare Propertys, die einen Basis-Datentyps
+ * (z.B. Integer) repraesentieren.<br>
+ * Dieser Container kann auch fuer die darstellung einer einzelnen {@link Property}
+ * genutzt werden. Die Methode {@link #setObject(Object)} legt hierzu ein
+ * {@link PropertySet} an, in dem nur die eine Property enthalten ist.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class DisplayContainer_Properties extends DisplayContainer_Table {
+  /**
+   * Erzeugt eine neue Darstellungskomponente.
+   */
+  public DisplayContainer_Properties() {
+    this(null);
+  }
+
+  /**
+   * Erzeugt eine neue Darstellungskomponente und zeigt sofort ein
+   * Objekt an.
+   * @param data anzuzeigendes Objekt
+   */
+  public DisplayContainer_Properties(Object data) {
+    super(data);
+  }
+
+  /**
+   * Erzeugt das TableModel fuer die Tabelle
+   * @param o darzustellendes <code>Properties</code>-Objekt (kann <code>null</code> sein!)
+   */
+  protected PropertiesTableModel createTableModel(Object o) {
+    return new PropertiesTableModel((Properties)o);
+  }
+
+  /**
+   * Liefert die aktuell dargestellte {@link Properties}-Instanz.
+   * @return <code>null</code> falls aktuell kein Objekt dargestellt wird
+   */
+  public Properties getObject() {
+    return (Properties)super.getObject();
+  }
+
+  /**
+   * Setzt das darzustellende Objekt. Wird eine einzelne {@link Property}
+   * uebergeben, wird zur Darstellung ein {@link PropertySet} angelegt, in dem
+   * sich nur die eine Property befindet.
+   * @exception UnsupportedOperationException falls das angegebene Objekt
+   *            nicht dargestellt werden kann.
+   * @see #canDisplay(Object)
+   */
+  public void setObject(Object data) {
+    if ( data instanceof Property )
+      data = createPropertySet((Property)data);
+    super.setObject(data);
+  }
+
+  /**
+   * Erzeugt ein PropertySet fuer eine einzelne Property.
+   */
+  private static PropertySet createPropertySet(Property p) {
+    PropertySet ps = new PropertySet();
+    ps.addProperty(p);
+    return ps;
+  }
+
+  /**
+   * Prueft, ob ein Objekt darstellbar ist.
+   * @return <code>true</code> gdw. das angegebene Objekt eine Instanz von
+   *         {@link Properties} oder {@link Property} ist.
+   */
+  public boolean canDisplay(Object data) {
+    return data instanceof Properties || data instanceof Property;
+  }
+
+  /**
+   * Liefert alle in der Tabelle selektierten Propertys.
+   */
+  public Property[] getSelectedElements() {
+    int[] selIdx = table.getSelectedRows();
+    Property[] selProp = new Property[selIdx.length];
+    for (int i=0; i<selProp.length; i++)
+      selProp[i] = ((PropertiesTableModel)tableModel).getProperty( selIdx[i] );
+    return selProp;
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // TableModel fuer die Properties-Tabelle
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse stellt ein TableModel fuer Properties (z.B. eines
+   * {@link schmitzm.data.XuluObject}) dar.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  private class PropertiesTableModel extends DisplayContainerTableModel {
+    protected final String[] COLUMN_NAME = {"Property","Type","Value"};
+    private Properties propObj = null;
+    private Property[] prop    = null;
+
+    /**
+     * Erzeugt ein neues Daten-Modell fuer ein <code>Properties</code>-Objekt.
+     * @param data propObj Objekt das aus Eigenschaften zusammengesetzt ist
+     * @see schmitzm.data.property.Properties
+     */
+    public PropertiesTableModel(Properties propObj) {
+      setData(propObj);
+    }
+
+    /**
+     * Erzeugt ein leeres Daten-Modell fuer ein <code>Properties</code>-Objekt.
+     * @see schmitzm.data.property.Properties
+     */
+    public PropertiesTableModel() {
+      this((Properties)null);
+    }
+
+    /**
+     * Setzt das Objekt, dessen Properties dargestellt werden sollen.
+     * @param propObj Objekt das aus Eigenschaften zusammengesetzt ist (kann
+     *                <code>null</code> sein!)
+     */
+    public void setData(Object propObj) {
+      this.propObj = (Properties)propObj;
+      this.prop    = (propObj != null) ? this.propObj.getProperties() : new Property[0];
+      fireTableDataChanged();
+    }
+
+    /**
+     * Liefert eine angezeigte Property.
+     * @param row Zeile des Datenmodells
+     */
+    public Property getProperty(int row) {
+      return this.prop[row];
+    }
+
+    /**
+     * Liefert einen Eintrag der Tabelle. Fuer Spalte 0 wird die Property-Bezeichnung
+     * zurueckgegeben, fuer Spalte 1 der Property-Datentyp und fuer Spalte 2
+     * der aktuelle Wert der Property. Letzter wird nur angezeigt, wenn es
+     * sich um eine {@link schmitzm.data.property.ScalarProperty} handelt.
+     * @param row Tabellenzeile
+     * @param col Tabellenspalte
+     */
+    public Object getValueAt(int row, int col) {
+      switch( col ) {
+        case 0: // Name der Property
+                return prop[row].getName();
+        case 1: // Typ der Property
+                //  fuer Skalare: "Typ-Name"
+                //  fuer Listen/Matrizen: "Klassenname [Typ-Name]"
+                String typeStr = prop[row].getType().getSimpleName();
+                if ( !(prop[row] instanceof ScalarProperty) )
+                  typeStr = prop[row].getClass().getSimpleName().concat(" [").concat(typeStr).concat("]");
+                return typeStr;
+        case 2: // aktueller Wert der Property
+                if ( prop[row] instanceof ScalarProperty &&
+                     BaseTypeUtil.isBaseType(prop[row].getType())) {
+                  try {
+                    return ((ScalarProperty)prop[row]).getOneTimeReadAccess().getValue();
+                  } catch( AccessViolationException err ) {
+                    return "<no access!!>";
+                  }
+                }
+                return "<can not be displayed>";
+      }
+      return null;
+    }
+
+    /**
+     * Liefert die Anzahl an Tabellen-Zeilen. Diese entspricht der Anzahl an
+     * Eigenschaften (Properties) des Objekts.
+     */
+    public int getRowCount() {
+      return prop.length;
+    }
+
+    /**
+     * Liefert die Anzahl an Tabellen-Spalten. Diese ist konstant 3 (je eine
+     * Spalte fuer Property-Bezeichnung Property-Typ und Property-Wert).
+     */
+    public int getColumnCount() {
+      return COLUMN_NAME.length;
+    }
+
+    /**
+     * Liefert die Spaltennamen.
+     * @see #COLUMN_NAME
+     */
+    public String getColumnName(int col) {
+      return COLUMN_NAME[col];
+    }
+
+    /**
+     * Prueft, ob eine Tabellen-Zelle editierbar ist. Dies ist nur fuer die
+     * Spalte mit dem Property-Wert der Fall und nur wenn es sich um eine
+     * {@link schmitzm.data.property.ScalarProperty} handelt, welche
+     * einen Build-In-Type beinhaltet.
+     * @param row Tabellen-Zeile
+     * @param col Tabellen-Spalte
+     * @see schmitzm.temp.BaseTypeUtil#isBaseType(Class)
+     */
+    public boolean isCellEditable(int row, int col) {
+      return col == 2 &&
+             prop[row] instanceof ScalarProperty &&
+             BaseTypeUtil.isBaseType( prop[row].getType() );
+    }
+
+    /**
+     * Setzt den jeweiligen Property-Wert neu.
+     * @param obj neue Objektbeschreibung (<code>String</code>)
+     * @param row Tabellen-Zeile
+     * @param col Tabellen-Spalte
+     * @see #isCellEditable(int,int)
+     * @see schmitzm.temp.BaseTypeUtil#convertFromString(String,Class)
+     */
+    public void setValueAt(Object obj, int row, int col) {
+      if ( isCellEditable(row,col) ) {
+        PropertyWriteAccess w = null;
+        try {
+          w = ((ScalarProperty)prop[row]).getWriteAccess(this);
+          w.setValue(BaseTypeUtil.convertFromString( (String) obj, prop[row].getType()));
+        } catch (AccessViolationException err) {
+          XuluGUIMessages.showAccessError(GUI_COMPONENT,err);
+        } catch (NumberFormatException err) {
+          XuluGUIMessages.showBaseTypeError(GUI_COMPONENT,err);
+        } catch (Exception err) {
+          XuluGUIMessages.showError(GUI_COMPONENT,err);
+        } finally {
+          // Schreibrecht muss unbedingt wieder freigegeben werden!!
+          if ( w!=null ) w.release();
+        }
+      }
+    }
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/gui/DisplayContainer_Table.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/gui/DisplayContainer_Table.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/gui/DisplayContainer_Table.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,106 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.gui;
+
+import java.awt.BorderLayout;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.table.TableModel;
+import javax.swing.ListSelectionModel;
+
+import schmitzm.swing.ObjectDisplayContainer;
+import schmitzm.data.property.Property;
+import schmitzm.data.property.MatrixProperty;
+import schmitzm.data.property.PropertyWriteAccess;
+import schmitzm.data.property.AccessViolationException;
+
+import edu.bonn.xulu.gui.XuluGUIMessages;
+
+import schmitzm.temp.BaseTypeUtil;
+
+/**
+ * Diese Klasse stellt eine abstrakte Oberklasse fuer die Darstellung
+ * von tabellarischen <code>ObjectDisplayContainer</code> dar.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class DisplayContainer_Table extends ObjectDisplayContainer {
+  protected JTable                        table      = null;
+  protected JScrollPane                   scrollPane = null;
+  protected DisplayContainerTableModel    tableModel = null;
+
+  /**
+   * Erzeugt eine neue Darstellungskomponente.
+   */
+  public DisplayContainer_Table() {
+    this(null);
+  }
+
+  /**
+   * Erzeugt eine neue Darstellungskomponente und zeigt sofort ein
+   * Objekt an.
+   * @param data anzuzeigendes Objekt
+   */
+  public DisplayContainer_Table(Object data) {
+    super();
+    this.setLayout( new BorderLayout() );
+    this.tableModel = createTableModel(null); // Objekt wird erst gesetzt, wenn Tabelle erzeugt ist!
+    this.table      = new JTable(tableModel);
+    this.scrollPane = new JScrollPane( table );
+    this.add( scrollPane );
+    setObject(data);
+  }
+
+  /**
+   * Erzeugt das TableModel fuer die Tabelle
+   * @param o darzustellendes Objekt (kann <code>null</code> sein!)
+   */
+  protected abstract DisplayContainerTableModel createTableModel(Object o);
+
+  /**
+   * Aktualisiert die Darstellung des aktuell angezeigten Objekts.
+   */
+  public void refresh() {
+    if (tableModel != null) {
+      tableModel.setData(getObject());
+      tableModel.fireTableStructureChanged();
+      scrollPane.getVerticalScrollBar().setValue(0);
+      scrollPane.getHorizontalScrollBar().setValue(0);
+    }
+  }
+
+  /**
+   * Liefert alle in der Tabelle selektierten Tabellenelemente.
+   * @return immer leerer <code>Object</code>-Array
+   */
+  public Object[] getSelectedElements() {
+    return new Object[0];
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // TableModel fuer die MatrixProperty-Tabelle
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse stellt ein TableModel fuer MatrixProperty-Instanzen dar.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  protected abstract class DisplayContainerTableModel extends AbstractTableModel {
+    /**
+     * Setzt das Datenobjekt, das in der Tabelle dargestellt wird.
+     * @param obj Objekt (kann <code>null</code> sein!)
+     */
+    public abstract void setData(Object obj);
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/gui/EventManagerFrame_BasicTable.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/gui/EventManagerFrame_BasicTable.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/gui/EventManagerFrame_BasicTable.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,250 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.gui;
+
+import java.awt.Dimension;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.MutableTreeNode;
+
+import schmitzm.swing.TreeSelectionDialog;
+import schmitzm.swing.MultipleOptionPane;
+import schmitzm.swing.InputOption;
+import schmitzm.swing.SelectionInputOption;
+import schmitzm.swing.event.InputOptionAdapter;
+import schmitzm.swing.table.MutableTable;
+import schmitzm.swing.tree.EmptyNode;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.DataPool;
+import edu.bonn.xulu.appl.ModelControlManager;
+import edu.bonn.xulu.appl.Handler;
+import edu.bonn.xulu.appl.HandlerFactory;
+import edu.bonn.xulu.appl.EventHandler;
+import edu.bonn.xulu.appl.EventManager;
+
+import edu.bonn.xulu.appl.XuluConstants;
+import edu.bonn.xulu.gui.DataPoolTreeModel;
+import edu.bonn.xulu.gui.DataPoolInputOption;
+import edu.bonn.xulu.gui.ObjectOrModelInputOption;
+import edu.bonn.xulu.gui.ModelManagerTreeModel;
+import edu.bonn.xulu.gui.XuluGUIMessages;
+
+import edu.bonn.xulu.plugin.gui.AbstractManagerFrame_BasicTable;
+
+// nur fuer Doku
+import javax.swing.JInternalFrame;
+
+
+/**
+ * Diese Klasse stellt eine GUI fuer den {@linkplain EventManager Xulu-EventManager}
+ * dar. Diese stellt (in einem {@link JInternalFrame}) tabellarisch alle {@link EventHandler}
+ * in 3 Spalten dar:
+ * <ol>
+ *   <li>Objekt, das beobachtet wird</li>
+ *   <li>Ereignistyp, auf den reagiert wird</li>
+ *   <li>Handler, der ausgefuehrt wird, wenn das Objekt das Ereignis ausgeloest hat</li>
+ * </ol>
+ * Ueber ein Popup-Menue koennen dem Event-Manager Event-Handler hinzugefuegt oder
+ * entfernt werden. Durch einen Doppelklick auf eine Tabellenzeile wird der
+ * jeweilige Event-Handler editiert.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class EventManagerFrame_BasicTable extends AbstractManagerFrame_BasicTable {
+  private XuluModellingPlatform appl = null;
+
+  /**
+   * Erzeugt ein neues EventManager-Fenster.
+   * @param appl  Instanz der XuluModellingPlatform
+   * @param title Titel fuer das Fenster
+   */
+  public EventManagerFrame_BasicTable(XuluModellingPlatform appl, String title) {
+    this(appl,title, new EventManagerTableModel(appl));
+  }
+
+  /**
+   * Erzeugt ein neues EventManager-Fenster.
+   * @param appl  Instanz der XuluModellingPlatform
+   * @param title Titel fuer das Fenster
+   * @param size  Groesse des Fensters
+   */
+  public EventManagerFrame_BasicTable(XuluModellingPlatform appl, String title, Dimension size) {
+    this(appl,title, new EventManagerTableModel(appl), size);
+  }
+
+  /**
+   * Erzeugt ein neues EventManager-Fenster.
+   * @param appl  Instanz der XuluModellingPlatform
+   * @param title Titel fuer das Fenster
+   * @param managerTableModel TableModel fuer den Event-Manager
+   */
+  private EventManagerFrame_BasicTable(XuluModellingPlatform appl, String title, EventManagerTableModel managerTableModel) {
+    this(appl,title, managerTableModel, new Dimension(300,350));
+  }
+
+  /**
+   * Erzeugt ein neues EventManager-Fenster.
+   * @param appl  Instanz der XuluModellingPlatform
+   * @param title Titel fuer das Fenster
+   * @param managerTableModel TableModel fuer den Event-Manager
+   * @param size  Groesse des Fensters
+   */
+  private EventManagerFrame_BasicTable(XuluModellingPlatform appl, String title, EventManagerTableModel managerTableModel, Dimension size) {
+    super(title, managerTableModel, size,MutableTable.ITEM_ADD | MutableTable.ITEM_REMOVE);
+    this.appl = appl;
+  }
+
+  /**
+   * Diese Klasse stellt ein tabellarisches Daten-Modell fuer den Xulu-EventManager dar.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  private static class EventManagerTableModel extends AbstractManagerFrame_BasicTable.AbstractManagerTableModel {
+    private XuluModellingPlatform appl = null;
+
+    /**
+     * Erzeugt ein neues Daten-Modell fuer einen <code>EventManager</code>.
+     * @param appl Instanz der Xulu-Anwendung
+     */
+    public EventManagerTableModel(XuluModellingPlatform appl) {
+      super(appl.getEventManager());
+      this.appl = appl;
+    }
+
+    /**
+     * Liefert die Spaltennamen der Tabelle.
+     */
+    @Override
+    public String[] createColumnNames() {
+      return new String[] {
+          XULUGUI_RES.getString("Object"),
+          XULUGUI_RES.getString("Event"),
+          XULUGUI_RES.getString("Handler")
+      };
+    }
+    
+    /**
+     * Liefert einen Wert der Tabelle. Fuer Spalte 0 wird der jeweilige Titel
+     * der Komponente geliefert, fuer Spalte 1 der Klassenname des Ereignisses
+     * und fuer Spalte 3 eine Beschreibung des Handlers.
+     * @param row Tabellen-Zeile
+     * @param col Tabellen-Spalte
+     */
+    public Object getValueAt(int row, int col) {
+      switch (col) {
+        case 0: // erste Spalte: Objekt
+          return manager.get(row).getTitle();
+        case 1: // zweite Spalte: Event
+          return ( (EventHandler) manager.get(row)).getEventType().getSimpleName();
+        case 2: // dritte Spalte: Handler
+          Handler handler = ( (EventHandler) manager.get(row)).getHandler();
+          return handler.getFactory() == null ? handler.getClass().getSimpleName() : handler.getFactory().getName();
+      }
+      return null;
+    }
+
+    /**
+     * Prueft, ob eine Tabellen-Zelle editierbar ist. Dies ist fuer <b>keine</b>
+     * @param row Tabellen-Zeile
+     * @param col Tabellen-Spalte
+     */
+    public boolean isCellEditable(int row, int col) {
+      return false;
+    }
+
+    /**
+     * Entfernt einen Eintrag aus dem <code>AbstractManager</code> und
+     * somit aus der Tabelle. Wird aufgerufen, wenn der Menuepunkt
+     * "Entfernen" aus dem Kontextmenue gewaehlt wird.
+     * @param row Tabellenzeile
+     * @see AbstractManager#remove(int)
+     */
+    public void performRemoveRow(int row) {
+      manager.remove(row);
+    }
+
+    /**
+     * Fragt ueber Anwender-Dialoge ein Objekt, ein Ereignis und einen
+     * Handler ab und fuegt dem Event-Manager einen entsprechenden
+     * Event-Handler hinzu.
+     */
+    public void performAddRow() {
+      try {
+        EventHandler eh = createEventHandler(appl);
+        if (eh != null)
+          manager.add(eh);
+      } catch(Exception err) {
+        XuluGUIMessages.showError(null,err);
+      }
+    }
+
+    /**
+     * Fragt ein Objekt, einen moeglichen Ereignis-Typ, sowie einen Handler
+     * ab und erzeugt daraus einen Event-Handler.
+     * @return <code>null</code> falls einer der Anwender-Dialoge abgebrochen wurde
+     */
+    private EventHandler createEventHandler(XuluModellingPlatform appl) {
+      Object object = null;
+      Class eventType = null;
+      Handler handler = null;
+
+      final XuluModellingPlatform    xulu            = appl;
+      final ObjectOrModelInputOption objectOption    = new ObjectOrModelInputOption(appl,XULUGUI_RES.getString("EventObject"),true,null);
+      final SelectionInputOption     eventTypeOption = new SelectionInputOption.Combo(XULUGUI_RES.getString("Event")+":",true);
+      final SelectionInputOption     handlerOption   = new SelectionInputOption.Combo(XULUGUI_RES.getString("Handler")+":",true);
+
+      // wenn sich das zu beobachtende Objekt aendert, muss die Auswahl der
+      // moeglichen Ereignis-Typen und Handler entsprechend aktualisiert werden
+      objectOption.addInputOptionListener( new InputOptionAdapter() {
+        public void optionChanged(InputOption option, Object oldValue, Object newValue) {
+          // moegliche Ereignis-Typen fuer Objekt setzen
+          Class[]  eventTypesForObject = xulu.getEventManager().getEventTypes(objectOption.getValue());
+          if ( eventTypesForObject.length < 1 )
+            XuluGUIMessages.showError(null,XuluConstants.XULUERR_RES.getString("NoEvents"));
+          String[] eventTypeNamesForObject = new String[eventTypesForObject.length];
+          for (int i=0; i<eventTypeNamesForObject.length; i++)
+            eventTypeNamesForObject[i] = eventTypesForObject[i].getSimpleName();
+          eventTypeOption.setSelectionObjects(eventTypesForObject,eventTypeNamesForObject);
+
+          // moegliche Handler fuer Objekt setzen
+          HandlerFactory[] handlerFac = xulu.getEventManager().getHandlerFactories();
+          if (handlerFac.length < 1)
+            XuluGUIMessages.showError(null,XuluConstants.XULUERR_RES.getString("NoHandler"));
+          String[] handlerFacDesc = new String[handlerFac.length];
+          for (int i = 0; i < handlerFacDesc.length; i++)
+            handlerFacDesc[i] = handlerFac[i].getName();
+          handlerOption.setSelectionObjects(handlerFac,handlerFacDesc);
+        }
+      });
+
+      while( handler == null ) {
+        // Dialog erzeugen
+        Object[] input = MultipleOptionPane.showMultipleInputDialog(null,
+            XULUGUI_RES.getString("Event"), new InputOption[] {
+            objectOption,
+            eventTypeOption,
+            handlerOption
+        });
+        if (input == null || input.length < 1)
+          return null; // Dialog abgebrochen
+
+        object = input[0];
+        eventType = (Class) input[1];
+        handler = ( (HandlerFactory) input[2]).createHandler(xulu);
+      }
+
+      // Event-Handler erzeugen
+      return new EventHandler(object,eventType,handler,appl);
+    }
+  }
+}
+

Added: trunk/src/edu/bonn/xulu/plugin/gui/ModelControlContainer.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/gui/ModelControlContainer.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/gui/ModelControlContainer.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,345 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.gui;
+
+import java.awt.Container;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import java.util.Vector;
+
+import schmitzm.lang.WorkingThread;
+import schmitzm.lang.WorkingThreadListener;
+import schmitzm.lang.WorkingThreadAdapter;
+import edu.bonn.xulu.model.XuluModel;
+import edu.bonn.xulu.model.StepModel;
+import edu.bonn.xulu.model.event.ModelAdapter;
+import edu.bonn.xulu.model.XuluModelThread;
+import edu.bonn.xulu.model.StepModelThread;
+
+import edu.bonn.xulu.gui.XuluGUIMessages;
+
+// fuer doku
+import appl.plugin.multimodelcontrol.MultiModelControlPlugin;
+
+/**
+ * Diese Klasse stellt einen Container dar, ueber den der Modellablauf gesteuert
+ * werden kann. Hierzu enthaelt er 5 Buttons
+ * <ul>
+ * <li><b>Init</b><br>
+ *     erzeugt einen neuen Thread fuer das Modell (entweder {@link StepModelThread}
+ *     falls das Modell {@link StepModel} implementiert, sonst {@link XuluModelThread})
+ *     und fuehrt {@link XuluModel#initModel()} aus</li>
+ * <li><b>Start/Resume</b><br>
+ *     fuehrt {@link XuluModelThread#start()} aus</li>
+ * <li><b>Pause</b><br>
+ *     fuehrt {@link XuluModelThread#pause()} aus</li>
+ * <li><b>Step</b><br>
+ *     fuehrt {@link StepModelThread#step()} aus</li>
+ * <li><b>Stop</b><br>
+ *     fuehrt {@link XuluModelThread#terminate()} aus</li>
+ * </ul>
+ * Je nach Modell-Status sind die Button aktivier oder deaktiviert.
+ * Uber die Methode {@link #addButtonActionListener(int,ActionListener)} koennen den
+ * Button zusaetzliche Aktionen zugewiesen werden.
+ *
+ * <br><b>29.04.07, Dominik Appl</b><br>
+ *  it is now possible to access start, stop, init, step and pause from outside (e.g. for controlling the
+ *  model execution from the {@link MultiModelControlPlugin})
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class ModelControlContainer extends Container {
+  /** Identifiziert den Init-Button. */
+  public static final int BUTTON_INIT  = 1;
+  /** Identifiziert den Start/Resume-Button. */
+  public static final int BUTTON_START = 2;
+  /** Identifiziert den Pause-Button. */
+  public static final int BUTTON_PAUSE = 3;
+  /** Identifiziert den Step-Button. */
+  public static final int BUTTON_STEP  = 4;
+  /** Identifiziert den Stop-Button. */
+  public static final int BUTTON_STOP  = 5;
+
+  protected XuluModel model        = null;
+  private JButton   initButton   = new JButton("Init");
+  private JButton   startButton  = new JButton("Start/Resume");
+  private JButton   pauseButton  = new JButton("Pause");
+  private JButton   stepButton   = new JButton("Step");
+  private JButton   stopButton   = new JButton("Stop");
+
+  private XuluModelThread modelThread     = null;
+  private Vector          threadListeners = new Vector<WorkingThreadListener>();
+  private ModelAdapter    modelListener   = null;
+
+
+  /**
+   * Erzeugt eine neue Modell-Steuerungs-Komponente.
+   * @param model zu steuerndes XuluModel
+   */
+  public ModelControlContainer(XuluModel model) {
+    super();
+    this.setLayout( new BoxLayout( this,BoxLayout.X_AXIS ) );
+    this.add(initButton);
+    this.add(startButton);
+    //Pause funktioniert zur Zeit noch nicht richtig
+    //this.add(pauseButton);
+    this.add(stepButton);
+    this.add(stopButton);
+    setButtonsEnabled(true,false,false,false,false);
+    initActions();
+    // Auf Thread-Aktionen lauschen, um Button zu (de)aktivieren
+    addThreadListener( new WorkingThreadAdapter() {
+      public void threadStarted(WorkingThread thread) {
+        setButtonsEnabled(false,false,true,true,true);
+      }
+      public void threadResumed(WorkingThread thread) {
+        setButtonsEnabled(false,false,true,true,true);
+      }
+      public void threadPaused(WorkingThread thread) {
+        setButtonsEnabled(false,true,true,false,true);
+      }
+      public void threadStopped(WorkingThread thread) {
+        setButtonsEnabled(true,false,false,false,false);
+      }
+    });
+    // Auf Model-Aktionen lauschen, um Button zu (de)aktivieren
+    // Bemerke: Kann nicht ueber ThreadListener erfolgen, da Thread
+    //          erst beim Start initialisiert wird!
+    this.modelListener = new ModelAdapter() {
+      public void modelInitialised(XuluModel model) {
+        setButtonsEnabled(true, true, true, false, false);
+      }
+    };
+    // Model setzen
+    setModel(model);
+  }
+
+  /**
+   * Setzt das Modell, das durch den Container kontrolliert wird.
+   * @param model ein Modell
+   */
+  public void setModel(XuluModel model) {
+    if ( model != null ) {
+      if ( modelThread != null && modelThread.getMode() != modelThread.MODE_TERMINATE )
+        perfomModelAction( BUTTON_STOP );
+      model.removeModelListener( modelListener );
+    }
+
+    this.model = model;
+    model.addModelListener( modelListener );
+  }
+
+  /**
+   * Liefert das Modell, das durch den Container kontrolliert wird.
+   */
+  public XuluModel getModel() {
+    return this.model;
+  }
+
+  /**
+   * Belegt die Button mit Modell-Aktionen.
+   */
+  private void initActions() {
+    addButtonActionListener( BUTTON_INIT, new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        perfomModelAction(BUTTON_INIT);
+      }
+    });
+    addButtonActionListener( BUTTON_START, new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        perfomModelAction(BUTTON_START);
+      }
+    });
+    addButtonActionListener( BUTTON_PAUSE, new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        perfomModelAction(BUTTON_PAUSE);
+      }
+    });
+    addButtonActionListener( BUTTON_STEP, new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        perfomModelAction(BUTTON_STEP);
+      }
+    });
+    addButtonActionListener( BUTTON_STOP, new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        perfomModelAction(BUTTON_STOP);
+      }
+    });
+  }
+
+//  /**
+//   * Liefert den Thread, der durch die Komponente kontrolliert wird.
+//   */
+//  public XuluModelThread getModelThread() {
+//    return modelThread;
+//  }
+
+  /**
+   * Liefert einen Button des Containers.
+   */
+  private JButton getButton(int button) {
+    switch( button ) {
+      case BUTTON_INIT:  return initButton;
+      case BUTTON_START: return startButton;
+      case BUTTON_PAUSE: return pauseButton;
+      case BUTTON_STEP:  return stepButton;
+      case BUTTON_STOP:  return stopButton;
+    }
+    return null;
+  }
+
+  /**
+   * Belegt einen Button mit einer Aktion.
+   * @param button   Code fuer den Button
+   * @param listener Aktion
+   * @see #BUTTON_INIT
+   * @see #BUTTON_START
+   * @see #BUTTON_PAUSE
+   * @see #BUTTON_STEP
+   * @see #BUTTON_STOP
+   */
+  public void addButtonActionListener(int button, ActionListener listener) {
+    JButton b = getButton(button);
+    if (b != null) b.addActionListener(listener);
+  }
+
+//  /**
+//   * Liefert alle bisher einem Button zugewiesenen Aktionen.
+//   * @param button Code fuer den Button
+//   * @see #BUTTON_INIT
+//   * @see #BUTTON_START
+//   * @see #BUTTON_PAUSE
+//   * @see #BUTTON_STEP
+//   * @see #BUTTON_STOP
+//   */
+//  public ActionListener[] getButtonActionListeners(int button) {
+//    JButton b = getButton(button);
+//    if (b != null) return b.getActionListeners().clone();
+//    return new ActionListener[0];
+//  }
+
+  /**
+   * Fuegt dem Modell-Thread einen Listener hinzu.
+   * @param listener Modell-Listener
+   */
+  public void addThreadListener(WorkingThreadListener listener) {
+    threadListeners.add(listener);
+    if ( modelThread != null )
+      modelThread.addThreadListener(listener);
+  }
+
+  /**
+   * (De)Aktiviert die Steuerungsbutton.
+   */
+  private void setButtonsEnabled(boolean initEn, boolean startEn, boolean stepEn, boolean pauseEn, boolean stopEn) {
+    initButton.setEnabled(initEn);
+    startButton.setEnabled(startEn);
+    stepButton.setEnabled( (model instanceof StepModel) && stepEn);
+    pauseButton.setEnabled(pauseEn);
+    stopButton.setEnabled(stopEn);
+  }
+
+  /**
+   * Fuehrt eine Modell-Aktion aus. Diese koennten auch einzeln direkt in die
+   * ActionListener programmiert werden. So kann jedoch das Error-Handling
+   * einheitlich erfolgen.
+   */
+  private void perfomModelAction(int action) {
+    try {
+      switch( action ) {
+        case BUTTON_INIT:  init(); break;
+        case BUTTON_START: start(); break;
+        case BUTTON_PAUSE: pause(); break;
+        case BUTTON_STEP:  step();break;
+        case BUTTON_STOP:  stop(); break;
+      }
+    } catch( Exception err ) {
+      XuluGUIMessages.showError(this,err);
+    }
+  }
+
+  /**
+	 * starts the model
+	 */
+	public void start() {
+		modelThread.start();
+	}
+
+	/**
+	 * inits the model
+	 */
+	public void init() {
+		createNewThread();
+	}
+
+	/**
+	 * stops the model
+	 */
+	public void stop() {
+		modelThread.terminate();
+	}
+
+	/**
+	 * makes one model step
+	 */
+	public void step() {
+		if (modelThread instanceof StepModelThread)
+			((StepModelThread) modelThread).step();
+	}
+
+	/**
+	 * pauses the model
+	 */
+	public void pause() {
+		modelThread.pause();
+	}
+
+	public XuluModelThread getModelThread(){
+		return modelThread;
+	}
+
+
+  /**
+   * Erzeugt einen neuen Thread fuer das Modell. Handelt es sich um eine
+   * StepModel-Modell, wird ein StepModelThread erzeugt, ansonsten ein
+   * XuluModelThread.
+   */
+  protected void createNewThread() {
+    // Wenn die Ressourcen noch nicht richtig zugeordnet sind, wird auch kein
+    // Thread erzeugt.
+    // Bemerke: Meldungen zu fehlerhaften Ressourcen sollten bereits bei
+    //          beim Befuellen des ResourceManagers mit den GUI-Komponenten
+    //          gemeldet werden (z.B. ModelControlFrame_Basic.setResources())
+    if ( !model.getContentManager().check() )
+      return;
+
+    // noch aktiven Thread anhalten
+    if ( modelThread != null && modelThread.isAlive() )
+      modelThread.terminate();
+
+    // neuen Thread erzeugen
+    if ( model instanceof StepModel )
+      modelThread = new StepModelThread((StepModel)model);
+    else
+      modelThread = new XuluModelThread(model);
+
+    // dem neuen Thread die Listener hinzufuegen
+    for (int i=0; i<threadListeners.size(); i++)
+      modelThread.addThreadListener( (WorkingThreadListener)threadListeners.get(i) );
+
+    // Modell initialisieren
+    model.initModel();
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/gui/ModelControlFrame_Basic.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/gui/ModelControlFrame_Basic.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/gui/ModelControlFrame_Basic.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,368 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.gui;
+
+import java.awt.BorderLayout;
+
+import java.awt.GridBagLayout;
+import java.awt.GridBagConstraints;
+import java.awt.Insets;
+import java.awt.Container;
+import java.awt.Component;
+import java.awt.Point;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.util.Vector;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JLabel;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JMenuItem;
+import javax.swing.JMenu;
+
+import schmitzm.lang.WorkingThread;
+import schmitzm.lang.WorkingThreadAdapter;
+import schmitzm.lang.LangUtil;
+import schmitzm.swing.SwingUtil;
+import schmitzm.swing.TextAreaPrintStream;
+import schmitzm.swing.event.PopupMenuListener;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.XuluConstants;
+import edu.bonn.xulu.appl.EventHandler;
+import edu.bonn.xulu.appl.AbstractManager;
+import edu.bonn.xulu.appl.EventManager;
+
+import edu.bonn.xulu.gui.ModelControlFrame;
+import edu.bonn.xulu.gui.XuluGUIMessages;
+import edu.bonn.xulu.model.XuluModel;
+import edu.bonn.xulu.plugin.gui.ModelControlContainer;
+import edu.bonn.xulu.gui.ModelContentManagerContainer;
+import edu.bonn.xulu.data.XuluDataException;
+
+// nur fuer Doku
+import edu.bonn.xulu.model.ModelContentManager;
+import appl.plugin.multimodelcontrol.MultiModelControlPlugin;
+
+/**
+ * Diese Klasse stellt ein Fenster, ueber welches ein Modell gesteuert werden
+ * kann. Es besteht im wesentlichen aus 3 Bereichen:
+ * <ol>
+ * <li><b>Kontroll-Bereich ({@link ModelControlContainer})</b><br>
+ *     Dient der Steuerung des Modellablaufs (Start/Stop/Init/...)</li>
+ * <li><b>Daten-Bereich ({@link ModelContentManagerContainer})</b><br>
+ *     Dient der Zuordnung von Datenpool-Objekten zu den benoetigten
+ *     Modell-Ressourcen</li>
+ * <li><b>Status-Bereich ({@link JTextArea})</b><br>
+ *     Auf diesen Text-Bereich werden saemtlich Status-Ausgaben des Modells
+ *     umgelenkt (siehe {@link XuluModel#setStatusOut(PrintStream)} und
+ *     {@link TextAreaPrintStream})</li>
+ * <li><b>Reload-Button</b><br>
+ *     Dient dazu die dem Fenster zugrunde liegende Modell-Klasse neu von der
+ *     Festplatte zu laden. Wurde die Klasse seit dem Instanziieren des Modells
+ *     veraendert und neu kompiliert, werden diese Aenderungen uebernommen.</li>
+ * </ol>
+ *
+ * <hr>
+ *<br><b>1.04.07, Dominik Appl</b><br>
+ *  reorganzied, so that subclasses can reuse more code
+ *<br><b>29.04.07, Dominik Appl</b><br>
+ *  it is now possible to access the underlying control container and the setResources() method
+ *  from outside (for controlling the model execution from the {@link MultiModelControlPlugin})
+ *
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.1
+ */
+public class ModelControlFrame_Basic extends ModelControlFrame implements XuluConstants {
+	protected ModelContentManagerContainer contentContainer     = null;
+	protected ModelControlContainer        controlContainer     = null;
+	protected JButton                      reloadButton         = new JButton("Modell neu laden");
+	private   JTextArea                    statusArea           = null;
+	private   TextAreaPrintStream          statusStream         = null;
+	protected Container                    contentPane          = null;
+	private   JFrame                       modelSpecificFrame   = null;
+	private   JMenu                        statusMenu           = new JMenu("Bearbeiten");
+	private   JMenuItem                    statusMenuItem_clear = new JMenuItem("Löschen");
+	protected XuluModellingPlatform        appl                 = null;
+  /**
+   * Erzeugt ein neues Kontrollfenster
+   * @param appl  Applikation in der das Modell laeuft
+   * @param model Modell, das durch das Fenster kontrolliert werden soll
+   */
+  public ModelControlFrame_Basic(XuluModellingPlatform appl, XuluModel model) {
+    super(model);
+    this.appl = appl;
+
+    contentPane = this.getContentPane();
+    contentPane.setLayout( new GridBagLayout() );
+
+    initControlContainer();
+    initReloadButton();
+    initContentPane();
+    initStatusArea();
+
+    // Fenster auf optimale Breite bringen
+    this.pack();
+
+    // ####### optionale Modell-GUI #######
+    createModelSpecificFrame(model);
+  }
+
+  	/**
+	 * inits the status Area
+	 */
+	protected void initStatusArea() {
+		// ####### Status-Komponente #######
+		statusArea = new JTextArea();
+		statusArea.setEditable(false);
+		statusArea.setRows(10); // initiale Groesse 10 Zeilen
+		contentPane.add(new JLabel("Status-Ausgaben:"), new GridBagConstraints(
+				0, 2, 2, 1, 0.0, 0.0, GridBagConstraints.SOUTHWEST,
+				GridBagConstraints.BOTH, new Insets(5, 5, 0, 5), 0, 0));
+		contentPane.add(new JScrollPane(statusArea), new GridBagConstraints(0,
+				3, 2, 1, 1.0, 1.0, GridBagConstraints.CENTER,
+				GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));
+		// Model-Ausgabe auf Status-Komponente umleiten
+		statusStream = new TextAreaPrintStream(statusArea);
+		model.setStatusOut(statusStream);
+		// PopupMenue um Feld zu loeschen
+		statusMenuItem_clear.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				statusArea.setText("");
+			}
+		});
+		statusMenu.add(statusMenuItem_clear);
+		statusArea.addMouseListener(new PopupMenuListener(this.statusMenu
+				.getPopupMenu()));
+
+	}
+
+	/**
+	 * inits the content pane
+	 */
+	protected void initContentPane() { // ####### Daten-Komponente #######
+		contentContainer = new ModelContentManagerContainer(model
+				.getContentManager(), appl.getDataPool());
+		contentPane.add(contentContainer, new GridBagConstraints(0, 1, 2, 1,
+				1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+				new Insets(5, 5, 5, 5), 0, 0));
+	}
+
+	/**
+	 * inits the reload button
+	 */
+	protected void initReloadButton() {
+		// ####### Reload-Button ######
+		reloadButton.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				reloadModel();
+			}
+		});
+		contentPane.add(reloadButton, new GridBagConstraints(1, 0, 1, 1, 1.0,
+				0.0, GridBagConstraints.EAST, GridBagConstraints.NONE,
+				new Insets(5, 5, 5, 5), 0, 0));
+
+	}
+
+	/**
+	 * inits the control container
+	 */
+	protected void initControlContainer() {
+		// ####### Kontroll-Komponente #######
+		controlContainer = new ModelControlContainer(model);
+		// Bei Init-Aktion muessen zunaechst die Modell-Ressourcen mit den
+		// ausgewaehlten
+		// Datenpool-Objekten verknuepft werden; bevor das Modell initialisiert
+		// wird
+		controlContainer.addButtonActionListener(
+				ModelControlContainer.BUTTON_INIT, new ActionListener() {
+					public void actionPerformed(ActionEvent e) {
+						setModelResources();
+					}
+				});
+		// Waehrend das Modell laeuft, soll nichts an den Ressourcen veraendet
+		// werden
+		controlContainer.addThreadListener(new WorkingThreadAdapter() {
+			public void threadStarted(WorkingThread thread) {
+				contentContainer.setEnabled(false);
+				reloadButton.setEnabled(false);
+			}
+
+			public void threadStopped(WorkingThread thread) {
+				contentContainer.setEnabled(true);
+				reloadButton.setEnabled(true);
+			}
+		});
+		contentPane.add(controlContainer, new GridBagConstraints(0, 0, 1, 1,
+				1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+				new Insets(5, 5, 5, 5), 0, 0));
+	}
+
+
+/**
+ * Erzeugt das Fenster fuer die modellspezifische GUI, falls eine solche vom
+ * Modell angeboten wird
+ */
+  private void createModelSpecificFrame(XuluModel model) {
+    if ( modelSpecificFrame != null )
+      modelSpecificFrame.dispose();
+
+    Component modelGUI = model.getModelSpecificGUI();
+    if ( modelGUI == null )
+      this.modelSpecificFrame = null;
+    else {
+      this.modelSpecificFrame = new JFrame();
+      this.modelSpecificFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+      this.modelSpecificFrame.getContentPane().setLayout(new BorderLayout());
+      this.modelSpecificFrame.getContentPane().add(modelGUI, BorderLayout.CENTER);
+      this.modelSpecificFrame.pack();
+      SwingUtil.setRelativeFramePosition(modelSpecificFrame,this,SwingUtil.BOUNDS_OUTER,SwingUtil.NORTHEAST);
+    }
+  }
+
+  /**
+   * Zeigt das Kontroll-Fenster an oder verbirgt es. Zudem wird (falls
+   * vorhanden) das modellspezifische Fenster angezeigt/verborgen.
+   */
+  public void setVisible(boolean visible) {
+    super.setVisible(visible);
+    if ( modelSpecificFrame != null)
+      modelSpecificFrame.setVisible(visible);
+  }
+
+  /**
+   * Setzt die Bezeichnung fuer das Kontroll-Fenster. Zudem wird (falls
+   * vorhanden) die entsprechende Bezeichnung fuer das modellspezifische Fenster
+   * gesetzt.
+   */
+  public void setTitle(String title) {
+    super.setTitle(title);
+    model.setName(title);
+    if ( modelSpecificFrame != null)
+      modelSpecificFrame.setTitle(getTitle()+" [Modellspezifisch]");
+  }
+
+  /**
+   * Belegt die Ressourcen des Modells mit den ausgewaehlten Objekten des
+   * Datenpools. Hierbei wird durch den {@link ModelContentManager} die
+   * Korrektheit geprueft.
+   * @exception XuluDataException falls eine Ressource nicht korrekt belegt wurde
+   */
+  public void setModelResources() {
+    Object[] data = contentContainer.getSelection();
+
+    if ( model.isInitialised() )
+      model.disposeModel();
+
+    try {
+      // erst die Ressoucen zuordnen (ohne Check, da sie aufeinander
+      // aufbauen koennen!)
+      for (int i = 0; i < data.length; i++)
+        model.getContentManager().getResource(i).setData(data[i],false);
+      // wenn alle Ressourcen zugeordnet sind, checken
+      model.getContentManager().checkAndError();
+    } catch (XuluDataException err) {
+      XuluGUIMessages.showDataError(this,err);
+    } catch (Exception err) {
+      XuluGUIMessages.showError(this,err,"Fehler bei Ressourcenzuteilung");
+    }
+  }
+
+  /**
+   * Schliesst die Komponente komplett. Das Modell wird angehalten und
+   * alle Ressourcen freigegeben.
+   */
+  public void close() {
+    model.disposeModel();
+    setVisible(false);
+    contentContainer.dispose();
+    if ( modelSpecificFrame != null)
+      modelSpecificFrame.dispose();
+    super.dispose();
+  }
+
+  /**
+   * Aktualisiert die grafische Darstellung des internen Fensters, in dem
+   * die Auswahlfelder des ModelContentManagers neu organisiert werden.
+   * Die aktuelle Auswahl geht dabei verloren!
+   */
+  public void refresh() {
+    this.contentContainer.reorganize();
+  }
+
+  public ModelContentManagerContainer getModelContentManagerContainer(){
+	  return contentContainer;
+  }
+  public ModelControlContainer getControlContainer(){
+	  return controlContainer;
+  }
+
+  protected ModelControlFrame_Basic newInstance(XuluModel newModel){
+	  return new ModelControlFrame_Basic(appl,newModel);
+  }
+
+  private void reloadModel() {
+    try {
+      // Klasse neu laden
+      Class newModelClass = LangUtil.loadPreferredClass(model.getClass().getName(), appl.getDynamicClassRootDirectory().toURL() );
+      // Alte Klasse in Registry durch neue ersetzen
+      appl.getRegistry().replaceModelClass( model.getClass(), newModelClass );
+      // Modell neu erzeugen
+      XuluModel newModel = (XuluModel)newModelClass.newInstance();
+      // Modell-Fenste neu erzeugen (und Groesse/Position des alten uebernehmen)
+      ModelControlFrame_Basic newModelFrame = newInstance(newModel);
+      newModelFrame.setTitle( getTitle() );
+      newModelFrame.setExtendedState( getExtendedState() );
+      // Groesse und Position nur setzen, wenn Fenster nicht minimiert ist.
+      // Ansonsten wird "normale" Groesse/Position auf maximierte Groesse gesetzt!
+      if ( (getExtendedState() & JFrame.MAXIMIZED_BOTH) == 0 ) {
+        newModelFrame.setSize(getSize());
+        newModelFrame.setLocation(getLocation());
+      }
+      // Position des Modell-spezifischen Fensters setzen
+      if ( modelSpecificFrame != null && newModelFrame.modelSpecificFrame != null )
+        newModelFrame.modelSpecificFrame.setLocation( modelSpecificFrame.getLocation() );
+
+      // Ressourcen-Zurordnung von altem Fenster uebernehmen
+      Object[] selection = contentContainer.getSelection();
+      for (int i=0; i<selection.length && i<newModel.getContentManager().getResourceCount(); i++)
+        newModelFrame.contentContainer.setResourceByObject(i,selection[i]);
+
+      // alle Events vom alten Modell merken
+      Vector<EventHandler> events = new Vector<EventHandler>();
+      EventManager em = appl.getEventManager();
+      for (int i=0; i<em.getCount(); i++) {
+        EventHandler eh = (EventHandler)em.get(i);
+        if ( eh.getObject() == model )
+          events.add( new EventHandler(newModel,eh.getEventType(),eh.getHandler(),appl) );
+      }
+
+      // Altes Modell-Fenster loeschen (EventHandler vom geloeschten Modell werden
+      // automatisch auch geloescht!!)
+      appl.getModelControlManager().remove(this);
+      // Neues Modell-Fenster hinzufuegen
+      appl.getModelControlManager().add(newModelFrame,true);
+      for (int i=0; i<events.size(); i++)
+        em.add( events.elementAt(i) );
+
+      // Meldung geben, dass Aktualisierung erfolgreich
+      XuluGUIMessages.showInfoMessage(newModelFrame,XULUGUI_RES.getString("ModelReloadSuccessMess"));
+
+    } catch (ClassNotFoundException err) {
+      XuluGUIMessages.showClassNotFoundError(this,err,model.getClass().getName());
+    } catch (Exception err) {
+      XuluGUIMessages.showError(this,err);
+    }
+
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/gui/PluginManagerFrame_BasicTable.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/gui/PluginManagerFrame_BasicTable.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/gui/PluginManagerFrame_BasicTable.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,242 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.gui;
+
+import java.awt.Dimension;
+import java.awt.BorderLayout;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import javax.swing.JScrollPane;
+import javax.swing.ListSelectionModel;
+import javax.swing.JButton;
+
+import schmitzm.swing.StoplightContainer;
+import schmitzm.swing.table.AbstractMutableTableModel;
+import schmitzm.swing.table.MutableTable;
+import schmitzm.swing.table.MutableTableModel;
+import schmitzm.swing.table.ComponentRenderer;
+import schmitzm.swing.table.TableComponentMouseListener;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.XuluRegistry;
+import edu.bonn.xulu.appl.XuluPlugin;
+import edu.bonn.xulu.gui.XuluInternalFrame;
+import schmitzm.data.event.ObjectListener;
+import schmitzm.data.event.ObjectEvent;
+import schmitzm.data.event.GeneralObjectChangeEvent;
+
+/**
+ * Diese Klasse stellt das Xulu-internes Fenster dar, in dem alle aktiven
+ * (in der Xulu-Registry registrierten) {@linkplain XuluPlugin Xulu-Plugins}
+ * tabellarisch aufgelistet werden.
+ * Bei einem Doppelklick auf eine Tabellenzeile wird (sofern vorhanden) die
+ * Konfigurations-GUI des Plugins angezeigt.<br>
+ * Fuer jedes Plugin wird eine {@linkplain StoplightContainer "Ampel"} dargestellt,
+ * die anzeigt, ob das Plugin gestartet ist (GRUEN) oder nicht (ROT). Bei einem
+ * Doppelklick auf die Ampel wird das Plugin gestartet, bzw. gestoppt.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class PluginManagerFrame_BasicTable extends XuluInternalFrame {
+  private XuluModellingPlatform appl        = null;
+  private MutableTable          pluginTable = null;
+
+  /**
+   * Erzeugt ein neues Xulu-internes Fenster.
+   * @param name Titel des Fensters
+   * @param appl Instanz der Xulu-Applikation
+   */
+  public PluginManagerFrame_BasicTable(String name, XuluModellingPlatform appl) {
+    this(name, new Dimension(300,350), appl);
+  }
+
+  /**
+   * Erzeugt ein neues Xulu-internes Fenster.
+   * @param name Titel des Fensters
+   * @param size initiale Groesse des Fensters
+   * @param appl Instanz der Xulu-Applikation
+   */
+  public PluginManagerFrame_BasicTable(String name, Dimension size, XuluModellingPlatform appl) {
+    super(name);
+    this.appl = appl;
+    this.pluginTable = new MutableTable( new PluginTableModel(appl.getRegistry()), MutableTable.ITEM_CHANGE );
+    this.pluginTable.addMouseListener( new TableComponentMouseListener(pluginTable) );
+    this.pluginTable.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
+    this.pluginTable.setDefaultRenderer(pluginTable.getModel().getColumnClass(2),new ComponentRenderer());
+    this.pluginTable.getColumnModel().getColumn(2).setPreferredWidth(40);
+    this.pluginTable.getColumnModel().getColumn(2).setMaxWidth(40);
+    this.setSize(size);
+    this.setLayout( new BorderLayout() );
+    this.getContentPane().add( new JScrollPane(pluginTable) );
+  }
+
+  /**
+   * Aktualisiert die grafische Darstellung des Plugin-Fensters.
+   */
+  public void refresh() {
+    if ( pluginTable != null && pluginTable.getModel() != null )
+      ((PluginTableModel)this.pluginTable.getModel()).fireTableDataChanged();
+  }
+
+  /**
+   * Diese Klasse bildet die Datenbasis der Plugin-Tabelle.
+   */
+  private class PluginTableModel extends AbstractMutableTableModel {
+    private final Class[]  colClass = {String.class, String.class, StoplightContainer.class};
+
+    private XuluRegistry registry = null;
+
+    /**
+     * Erzeugt ein neues Tabellen-Modell. Die dargestellten Plugins bezieht
+     * es aus der Xulu-Registry.
+     * @param registry Instanz der Xulu-Registry
+     */
+    public PluginTableModel(XuluRegistry registry) {
+      this.registry = registry;
+      registry.addObjectListener( new ObjectListener() {
+        public void performObjectEvent(ObjectEvent e) {
+          if ( e instanceof XuluRegistry.ChangeEvent ) {
+            XuluRegistry.ChangeEvent regEvent = (XuluRegistry.ChangeEvent)e;
+            if ( regEvent.getOldValue() instanceof XuluPlugin || // Plugin geloescht
+                 regEvent.getNewValue() instanceof XuluPlugin || // Plugin hinzugefuegt
+                 regEvent.getOldValue() == null && regEvent.getNewValue() == null ) // Generelles Aenderungs-Ereignis
+              fireTableDataChanged();
+          }
+        }
+      });
+    }
+
+    /**
+     * Liefert die Spaltennamen der Tabelle.
+     */
+    @Override
+    public String[] createColumnNames() {
+      return new String[] {"Plugin", "Beschreibung", ""};
+    }
+    
+    /**
+     * Liefert einen Wert fuer die Tabelle. Fuer Spalte 0 wird der Klassenname
+     * des Plugins geliefert (String), fuer Spalte 1 die Plugin-Beschreibung (String)
+     * und fuer Spalte 3 die "Ampel", welche den Plugin-Status anzeigt ({@link StoplightContainer}).
+     * @param row Zeilennummer
+     * @param col Spaltennummer
+     */
+    public Object getValueAt(int row, int col) {
+      XuluPlugin plugin = registry.getPlugins()[row];
+      switch ( col ) {
+          case 0: // Plugin-Name
+                  return plugin.getClass().getSimpleName();
+          case 1: // Plugin-Bezeichnung
+                  return plugin.getName();
+          case 2: // Button zum Starten/Stoppen des Plugins
+                  return new PluginControlButton(plugin,
+                                                 appl,
+                                                 pluginTable.getColumnModel().getColumn(2).getWidth(),
+                                                 15
+                  );
+      }
+      return "";
+    }
+
+    /**
+     * Liefert den Typ einer Tabellen-Spalte.
+     * @param col Spaltennummer (beginnend bei 0)
+     */
+    public Class getColumnClass(int col) {
+      return colClass[col];
+    }
+
+    /**
+     * Liefert die Anzahl an Tabellen-Zeilen. Entspricht der Anzahl der in der
+     * Xulu-Registry registrierten Plugins.
+     */
+    public int getRowCount() {
+      return registry.getPlugins().length;
+    }
+
+    /**
+     * Macht nichts, da die Plugin-Tabelle die Option "Loeschen" nicht
+     * unterstuetzt.
+     * @param row Zeilennummer
+     */
+    public void performRemoveRow(int row) {
+    }
+
+    /**
+     * Macht nichts, da die Plugin-Tabelle die Option "Hinzufuegen" nicht
+     * unterstuetzt.
+     */
+    public void performAddRow() {
+    }
+
+    /**
+     * Wird bei einem Doppelklick auf die Tabellenzeile ausgefuehrt.
+     * Dabei wird die GUI zur Konfiguration des jeweilige Plugins geoeffnet.
+     * @param row Zeilennummer
+     * @param col Spalzennummer (nicht relevant)
+     */
+    public void performChangeData(int row, int col) {
+      XuluPlugin plugin = registry.getPlugins()[row];
+      // nicht beim Doppelklick auf die Start/Stop-Button
+      if ( col != 2 )
+        plugin.setVisible(true);
+    }
+  }
+
+  /**
+   * Diese Klasse stellt den Ampel-Button dar, der den Status eines Plugins anzeigt.
+   * Bei einem Doppelklick auf die "Ampel" wird das Plugin gestartet, bzw.
+   * gestoppt.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  private class PluginControlButton extends StoplightContainer {
+    private XuluPlugin            plugin;
+
+    /**
+     * Erzeugt eine neue Ampel.
+     * @param plugin Plugin, das durch den Button gesteuert wird
+     * @param appl   Instanz der Xulu-Applikation
+     * @param width  Breite des Buttons
+     * @param height Hoehe des Buttons
+     */
+    public PluginControlButton(final XuluPlugin plugin, final XuluModellingPlatform appl, int width, int height) {
+      super(StoplightContainer.RED,width,height,false);
+      this.plugin = plugin;
+      actualiseCaption();
+      this.addMouseListener( new MouseAdapter() {
+        public void mouseClicked(MouseEvent e) {
+          if ( e.getClickCount() != 2 )
+            return;
+
+          if ( plugin.isStarted() )
+            plugin.stop();
+          else
+            plugin.execute(appl);
+          actualiseCaption();
+        }
+      });
+    }
+
+    /**
+     * Aktualisiert die Darstellung der Ampel entsprechend des Plugin-Status.
+     */
+    public void actualiseCaption() {
+      if ( plugin.isStarted() )
+        this.setMode(GREEN);
+      else
+        this.setMode(RED);
+    }
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/gui/RegistryFrame_Tree.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/gui/RegistryFrame_Tree.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/gui/RegistryFrame_Tree.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,557 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.gui;
+
+import java.awt.BorderLayout;
+import javax.swing.JScrollPane;
+import javax.swing.JTree;
+import javax.swing.tree.MutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.DefaultTreeCellEditor;
+import javax.swing.tree.DefaultTreeCellRenderer;
+import javax.swing.tree.TreeSelectionModel;
+import javax.swing.event.TreeSelectionEvent;
+import java.util.EventObject;
+
+import schmitzm.data.event.ObjectListener;
+import schmitzm.data.event.ObjectEvent;
+import schmitzm.lang.NamedObject;
+import schmitzm.lang.AlreadyHandledException;
+import schmitzm.swing.tree.EditableNode;
+import schmitzm.swing.tree.EmptyNode;
+import schmitzm.swing.tree.EmptyInnerNode;
+import schmitzm.swing.tree.ContentNode;
+
+import edu.bonn.xulu.io.Factory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.io.TypeMapping;
+import edu.bonn.xulu.appl.XuluRegistry;
+import edu.bonn.xulu.appl.ScriptInterpreter;
+import edu.bonn.xulu.appl.XuluPlugin;
+import edu.bonn.xulu.appl.VisualisationTool;
+import edu.bonn.xulu.gui.XuluGUIMessages;
+import edu.bonn.xulu.gui.RegistryFrame;
+
+/**
+ * Dieses Fenster stellt die Visualisierung der {@link edu.bonn.xulu.appl.XuluRegistry}
+ * dar. Es stellt deren gesamten Inhalt in einer Baumstruktur dar.
+ * @todo Veraenderungen an Registry mittels PopupMenu
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class RegistryFrame_Tree extends RegistryFrame {
+  private XuluRegistry registry     = null;
+  private JTree        registryTree = null;
+
+  /**
+   * Erzeugt ein neues Registry-Fenster.
+   * @param registry Datenbasis
+   */
+  public RegistryFrame_Tree(XuluRegistry registry) {
+    super();
+    this.registry = registry;
+    this.setLayout( new BorderLayout() );
+    this.registryTree = new JTree();
+    registryTree.setModel( new RegistryTreeModel(registry) );
+    registryTree.setRootVisible(false);
+    registryTree.setEditable(true);
+    registryTree.getSelectionModel().setSelectionMode( TreeSelectionModel.SINGLE_TREE_SELECTION );
+    // nicht alle Zellen im Baum duerfen veraendet werden
+    registryTree.setCellEditor( new DefaultTreeCellEditor(registryTree, (DefaultTreeCellRenderer)registryTree.getCellRenderer()) {
+      private Object lastSelected = null;
+      // Diese Methode wird aufgerufen, um zu entscheiden, ob ein
+      // Knoten editierbar ist
+      public boolean isCellEditable(EventObject event) {
+        return super.isCellEditable(event) &&
+               lastSelected != null &&
+               lastSelected instanceof EditableNode &&
+               ((EditableNode)lastSelected).isEditable();
+      }
+      // Diese Methode wird aufgerufen, sobald ein neuer Knoten im Baum
+      // selektiert wurde --> merken, welcher das ist
+      public void valueChanged(TreeSelectionEvent e) {
+        if ( e.getNewLeadSelectionPath() != null )
+          lastSelected = e.getNewLeadSelectionPath().getLastPathComponent();
+        else
+          lastSelected = null;
+        super.valueChanged(e);
+      }
+    });
+    // UpdateListener auf Registry
+    registry.addObjectListener( new ObjectListener() {
+      public void performObjectEvent(ObjectEvent e) {
+        if ( e instanceof XuluRegistry.ChangeEvent ) {
+          XuluRegistry.ChangeEvent regEvent = (XuluRegistry.ChangeEvent)e;
+          // Wenn der alte oder neue Wert null ist, wurde ein Eintrag
+          // hinzugefuegt oder entfernt --> Update noetig
+          // Bei blosser Aenderung muss der Baum nicht reorganisiert werden!
+          if (regEvent.getOldValue() == null || regEvent.getNewValue() == null)
+            refresh();
+        }
+      }
+    });
+    this.getContentPane().add( new JScrollPane( registryTree ) );
+  }
+
+  /**
+   * Baut den Baum der Registry komplett neu auf.
+   */
+  public void refresh() {
+    ((RegistryTreeModel)registryTree.getModel()).reorganize();
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Datenmodell fuer den Registry-Baum
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Diese klasse stellt das Datenmodell fuer den Regstry-Baum dar.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  private class RegistryTreeModel extends DefaultTreeModel {
+    /**
+     * Erzeugt ein neues Datenmodell
+     * @param registry darzustellende XuluRegistry
+     */
+    public RegistryTreeModel(XuluRegistry registry) {
+      super(new RegistryRootNode(registry));
+    }
+
+    /**
+     * Regorganisiert das Datenmodell der Registry komplett.
+     */
+    public void reorganize() {
+      ((RegistryRootNode)this.getRoot()).reorganize();
+      nodeStructureChanged((RegistryRootNode)this.getRoot());
+    }
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  // Knoten des Registry-Baums
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse stellt Knoten dar, der den Klassennamen des UserObjects
+   * anzeigt. Handelt es sich beim UserObject bereits um eine
+   * <code>Class</code>-Instanz, wird deren Name angezeigt.
+   */
+  private abstract class ClassDisplayNode extends ContentNode {
+    /**
+     * Ereugt einen neuen Knoten.
+     */
+    public ClassDisplayNode(Object userObject, boolean editable) {
+      super(userObject,editable);
+    }
+
+    /**
+     * Liefert den Klassennamen des UserObject (oder falls es sich dabei
+     * bereits um eine <code>Class</code>-Instanz handelt, deren Namen).
+     */
+    public String toString() {
+      Object o = getUserObject();
+
+// UEBERDENKEN: Aenderung eines Objekts problematisch, wenn Name angezeigt wird!
+//              --> Klasse soll aus String erzeugt werden!!
+//      // benannte Objekte
+//      if ( o instanceof NamedObject ) {
+//        NamedObject n = (NamedObject)o;
+//        if ( n.getName() != null && !n.getName().equals("") )
+//          return n.getName().concat(" (").concat(n.getClass().getName()).concat(")");
+//      }
+
+      // Klassen
+      if ( o instanceof Class )
+        return ((Class)o).getName();
+
+      // alle anderen Objekte
+      return o.getClass().getName();
+    }
+
+    /**
+     * Wird aufgerufen, wenn der angezeigte Klassenname veraendert wird und
+     * daraus eine neue Klasse instanziiert werden konnte.
+     * Die Implementierung muss dann entscheiden, wie weiter mit dieser
+     * Klasse verfahren wird (ob daraus eine neue Instanz erzeugt wird,
+     * oder die Klasse selbst gespeichert wird, ...).
+     * @see #setUserObject(Object)
+     * @return aus der Klasse generiertes Object, welches als UserObject
+     *         gespeichert wird
+     */
+    public abstract Object createUserObjectFromClass(Class newClass) throws Exception;
+
+    /**
+     * Wird aufgerufen, wenn der angezeigte Klassenname veraendert wird.
+     * Es wird versucht, daraus ein neues <code>Class</code>-Objekt zu
+     * instanziieren.
+     * Nachdem die Implementierung daraus erfolgreich ein neues UserObject
+     * erzeugt hat, wird diese gespeichert.
+     * @see #createUserObjectFromClass(Class)
+     */
+    public void setUserObject(Object object) {
+      try {
+        Class newValue = Class.forName( (String) object);
+        // Registry entsprechend updaten
+        createUserObjectFromClass(newValue);
+        // nachdem Registry erfolgreich aktualisiert wurde
+        // kann auch der Baum aktualisiert werden
+        super.setUserObject(newValue);
+      }
+      catch (AlreadyHandledException err) {
+        // Fehler wurde bereits verarbeitet
+      }
+      catch (ClassNotFoundException err) {
+        XuluGUIMessages.showClassNotFoundError(GUI_COMPONENT, err, (String)object);
+//        throw new AlreadyHandledException();
+      }
+      catch (Exception err) {
+        XuluGUIMessages.showError(GUI_COMPONENT, err);
+//        throw new AlreadyHandledException();
+      }
+    }
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse stellt den Wurzelknoten des Registry-Baums dar. Er wird
+   * mit "ROOT" benannt und enthaelt Kind-Knoten fuer:
+   * <ul>
+   * <li>die registrierten Datentypen</li>
+   * <li>die registrierten Default-Factorys</li>
+   * <li>die registrierten Import-Factorys</li>
+   * <li>die registrierten Export-Factorys</li>
+   * <li>die registrierten TypeMappings</li>
+   * <li>die registrierten Modell-Klassen</li>
+   * <li>die registrierten Script-Interpreter</li>
+   * <li>die registrierten Plugins</li>
+   * <li>die registrierten Autostart-Plugins</li>
+   * </ul>
+   */
+  private class RegistryRootNode extends EmptyNode {
+    private XuluRegistry registry = null;
+
+    /**
+     * Erzeugt einen neuen Wurzel-Knoten.
+     * @param registry Datenbasis-XuluRegistry
+     */
+    public RegistryRootNode(XuluRegistry registry) {
+      super("ROOT");
+      this.registry = registry;
+      reorganize();
+    }
+    /**
+     * Reorganisiert den (Unter)Baum der Registry, in dem der komplette
+     * Baum neu aufgebaut wird.
+     */
+    public void reorganize() {
+      this.removeAllChildren();
+      // Kind fuer Datentypen
+      this.add(new ClassesRoot("Daten-Typen", registry.getDataTypes()) {
+        public void replaceClass(Class oldType, Class newType) {
+          registry.replaceDataType(oldType, newType);
+        }
+      });
+      // Kind fuer Default-Factories
+      this.add(new ToolsRoot("Default-Factorys", registry.getDefaultFactories()) {
+        public void replaceTool(Object oldFac, Object newFac) {
+          registry.replaceDefaultFactory((InstantiationFactory)oldFac, (InstantiationFactory)newFac);
+        }
+      });
+      // Kind fuer Import-Factories
+      this.add(new ToolsRoot("Import-Factorys", registry.getImportFactories()) {
+        public void replaceTool(Object oldFac, Object newFac) {
+          registry.replaceImportFactory((ImportFactory)oldFac, (ImportFactory)newFac);
+        }
+      });
+      // Kind fuer Export-Factories
+      this.add(new ToolsRoot("Export-Factorys", registry.getExportFactories()) {
+        public void replaceTool(Object oldFac, Object newFac) {
+          registry.replaceExportFactory((ExportFactory)oldFac, (ExportFactory)newFac);
+        }
+      });
+      // Kind fuer TypeMappings
+      this.add(new TypeMappingRoot("Type-Mappings", registry));
+      // Kind fuer Visualisationtools
+      this.add(new ClassesRoot("Visualisierungstools", registry.getVisualisationTools()) {
+        public void replaceClass(Class oldVis, Class newVis) {
+          registry.replaceVisualisationTool(oldVis, newVis);
+        }
+      });
+      // Kind fuer Modellklassen
+      this.add(new ClassesRoot("Modellklassen", registry.getModelClasses()) {
+        public void replaceClass(Class oldVis, Class newVis) {
+          registry.replaceModelClass(oldVis, newVis);
+        }
+      });
+      // Kind fuer Skript-Interpreter
+      this.add(new ToolsRoot("Script-Interpreter", registry.getScriptInterpreter()) {
+        public void replaceTool(Object oldInt, Object newInt) {
+          registry.replaceScriptInterpreter((ScriptInterpreter)oldInt, (ScriptInterpreter)newInt);
+        }
+      });
+      // Kind fuer Plugins
+      this.add(new ToolsRoot("Xulu-Plugins", registry.getPlugins()) {
+        public void replaceTool(Object oldPlugin, Object newPlugin) {
+          registry.replacePlugin((XuluPlugin)oldPlugin, (XuluPlugin)newPlugin);
+        }
+      });
+      // Kind fuer Autostart-Plugins
+      this.add(new ToolsRoot("Autostart-Plugins", registry.getAutostartPlugins()) {
+        public void replaceTool(Object oldPlugin, Object newPlugin) {
+          registry.replaceAutostartPlugin((XuluPlugin)oldPlugin, (XuluPlugin)newPlugin);
+        }
+      });
+    }
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse bildet die Wurzel fuer Registry-Unterbaeume, die
+   * Klassen (z.B. Datentypen oder Visualisationtools) darstellen.
+   */
+  private abstract class ClassesRoot extends EmptyInnerNode {
+    /**
+     * Erzeugt einen neuen Knoten.
+     * @param desc    Beschreibung
+     * @param classes Klassen fuer den Teilbaum
+     */
+    public ClassesRoot(String desc, final Class[] classes) {
+      super(desc);
+      for (int i = 0; classes != null && i < classes.length; i++)
+        add(classes[i]);
+    }
+
+    /**
+     * Fuegt einen neuen Datentyp-Kindknoten ein.
+     * @param aChild muss eine Instanz von <code>ClassDisplayNode</code> sein
+     */
+    public void add(MutableTreeNode aChild) {
+      if ( !(aChild instanceof ClassDisplayNode) )
+        throw new RuntimeException("Only instances of ClassDisplayNode are allowed as childs for ClassesRoot");
+      super.add(aChild);
+    }
+
+    /**
+     * Fuegt einen neuen Datentyp-Kindknoten ein.
+     * @param type ein Datentyp
+     */
+    public void add(Class type) {
+      add( new ClassDisplayNode(type, true) {
+        public Object createUserObjectFromClass(Class newClass) throws Exception {
+          try {
+            replaceClass( (Class)getUserObject(), newClass);
+          }
+          catch (Exception err) {
+            XuluGUIMessages.showError(GUI_COMPONENT, err);
+            throw new AlreadyHandledException();
+          }
+          return newClass;
+        }
+      });
+    }
+
+    /**
+     * Ersetzt in der Datenbasis eine Klasse durch ein anderes.
+     * An welcher Stelle in der Registry dies geschiet, wird durch die Implementierung
+     * bestimmt.
+     * @param oldClass zu ersetzende Klasse
+     * @param newClass neue Klasse
+     */
+    public abstract void replaceClass(Class oldClass, Class newClass) throws Exception;
+
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse bildet eine allgemeine Wurzel fuer alle Registry-Unterbaeume,
+   * die "Tools" (z.B. Factorys) darstellen.
+   * Mit "Tools" sind quasi-statische Klassen gemeint, die durch ihren
+   * Klassenamen repraesentiert werden und durch einen Standard-Konstruktor
+   * instanziiert werden.<br>
+   * Die Implementierung dieser abstrakten Klasse bestimmt lediglich an welcher
+   * Stelle die Registry zu aktualisieren ist, wenn sich ein Eintrag im Baum
+   * aendert.
+   * @see #replaceTool(Object,Object)
+   */
+  private abstract class ToolsRoot extends EmptyInnerNode {
+    /**
+     * Erzeugt einen neuen Knoten. Dieser enthaelt noch keine Kinder
+     * (ausser dem Pseudo-Nachfolger des {@link schmitzm.swing.tree.EmptyInnerNode}).
+     * @param desc Beschreibung fuer den Knoten, welche angezeigt wird
+     */
+    public ToolsRoot(String desc) {
+      this(desc, new Object[0]);
+    }
+
+    /**
+     * Erzeugt einen neuen Knoten.
+     * @param desc Beschreibung fuer den Knoten, welche angezeigt wird
+     * @param tool Tools, deren Klassennamen aufgelistet werden.
+     */
+    public ToolsRoot(String desc, Object[] tool) {
+      super(desc);
+      for (int i = 0; tool != null && i < tool.length; i++)
+        add(tool[i]);
+    }
+
+    /**
+     * Fuegt einen neuen Tool-Kindknoten ein.
+     * @param aChild muss eine Instanz von <code>ClassDisplayNode</code> sein
+     */
+    public void add(MutableTreeNode aChild) {
+      if ( !(aChild instanceof ClassDisplayNode) )
+        throw new RuntimeException("Only instances of ClassDisplayNode are allowed as childs for ToolsRoot");
+      super.add(aChild);
+    }
+
+    /**
+     * Fuegt einen neuen Tool-Kindknoten ein.
+     * @param tool eine "Tool"-Instanz (z.B. Factory)
+     */
+    public void add(Object tool) {
+      add( new ClassDisplayNode(tool,true) {
+        public Object createUserObjectFromClass(Class newToolType) throws Exception {
+          try {
+            Object newTool = newToolType.newInstance();
+            replaceTool( getUserObject(), newTool );
+            return newTool;
+          }
+          catch (InstantiationException err) {
+            XuluGUIMessages.showInstantiationError(GUI_COMPONENT, err);
+            throw new AlreadyHandledException();
+          }
+          catch (ClassCastException err) {
+            XuluGUIMessages.showClassCastError(GUI_COMPONENT, err, getUserObject().getClass());
+            throw new AlreadyHandledException();
+          }
+          catch (Exception err) {
+            XuluGUIMessages.showError(GUI_COMPONENT, err);
+            throw new AlreadyHandledException();
+          }
+        }
+      });
+    }
+
+    /**
+     * Ersetzt in der Datenbasis ein Tool durch ein anderes.
+     * An welcher Stelle in der Registry dies geschiet, wird durch die Implementierung
+     * bestimmt.
+     * @param oldTool zu ersetzende Tool-Instanz
+     * @param newTool neue Tool-Instanz
+     */
+    public abstract void replaceTool(Object oldTool, Object newTool) throws Exception;
+  }
+
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse bildet die Wurzel fuer den Registry-Unterbaum, der die
+   * Type-Mappings darstellt.
+   */
+  private class TypeMappingRoot extends EmptyInnerNode {
+    private XuluRegistry registry = null;
+
+    /**
+     * Erzeugt einen neuen Knoten.
+     * @param desc     Beschreibung fuer den Knoten
+     * @param registry Datenbasis fuer die TypeMappings
+     */
+    public TypeMappingRoot(String desc, XuluRegistry registry) {
+      super(desc);
+      this.registry = registry;
+      TypeMapping[] mapping = registry.getTypeMappings();
+      for (int i = 0; mapping != null && i < mapping.length; i++)
+        add(mapping[i]);
+    }
+
+    /**
+     * Fuegt einen neuen TypeMapping-Kindknoten ein.
+     * @param aChild muss eine Instanz von <code>ClassDisplayNode</code> sein
+     */
+    public void add(MutableTreeNode aChild) {
+      if ( !(aChild instanceof TypeMappingNode) )
+        throw new RuntimeException("Only instances of TypeMappingNode are allowed as childs for TypeMappingRoot");
+      super.add(aChild);
+    }
+
+    /**
+     * Fuegt einen neuen TypeMapping-Kindknoten ein.
+     * @param mapping ein TypeMapping
+     */
+    public void add(TypeMapping mapping) {
+      add(new TypeMappingNode(mapping));
+    }
+  }
+
+
+  ///////////////////////////////////////////////////////////////////
+  /**
+   * Diese Klasse bildet die Wurzel fuer den Registry-Unterbaum, der ein
+   * Type-Mapping darstellt. Dieser selbst ist nicht editierbar, da der
+   * Datentyp eines TypeMappings nicht veraenderbar ist.
+   */
+  private class TypeMappingNode extends ClassDisplayNode {
+    public TypeMappingNode(final TypeMapping mapping) {
+      super(mapping.getType(), false);
+
+      // Kind fuer die Default-Factorys
+      add(new ToolsRoot("Default-Factory", new Factory[] {mapping.getDefaultFactory()}) {
+        // ersetzt die DefaultFactory des Mappings durch eine andere
+        public void replaceTool(Object oldFac, Object newFac) throws Exception {
+          try {
+            mapping.setDefaultFactory( (InstantiationFactory) newFac);
+          }
+          catch (ClassCastException err) {
+            XuluGUIMessages.showClassCastError(GUI_COMPONENT, err,InstantiationFactory.class);
+            throw new AlreadyHandledException();
+          }
+        }
+      });
+
+      // Kind fuer die Import-Factorys
+      add(new ToolsRoot("Import-Factorys", mapping.getImportFactories()) {
+        // ersetzt eine ImportFactory des Mappings durch eine andere
+        public void replaceTool(Object oldFac, Object newFac) throws Exception {
+          try {
+            mapping.replaceImportFactory( (ImportFactory)oldFac, (ImportFactory)newFac );
+          }
+          catch (ClassCastException err) {
+            XuluGUIMessages.showClassCastError(GUI_COMPONENT, err,ImportFactory.class);
+            throw new AlreadyHandledException();
+          }
+        }
+      });
+
+      // Kind fuer die Export-Factorys
+      add(new ToolsRoot("Export-Factorys", mapping.getExportFactories()) {
+        // ersetzt eine ExportFactory des Mappings durch eine andere
+        public void replaceTool(Object oldFac, Object newFac) throws Exception {
+          try {
+            mapping.replaceExportFactory( (ExportFactory)oldFac, (ExportFactory)newFac );
+          }
+          catch (ClassCastException err) {
+            XuluGUIMessages.showClassCastError(GUI_COMPONENT, err,ExportFactory.class);
+            throw new AlreadyHandledException();
+          }
+        }
+      });
+    }
+
+    /**
+     * Macht nichts, da der Knoten nicht editierbar ist.
+     * @return <code>newClass</code>
+     */
+    public Object createUserObjectFromClass(Class newClass) {
+      // macht nichts, da der Knoten nicht editierbar ist
+      return newClass;
+    }
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/gui/StatusFrame_BasicTextArea.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/gui/StatusFrame_BasicTextArea.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/gui/StatusFrame_BasicTextArea.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,94 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.gui;
+
+import javax.swing.JTextArea;
+import javax.swing.JScrollPane;
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+import schmitzm.swing.event.PopupMenuListener;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.gui.StatusFrame;
+
+/**
+ * Diese Klasse stellt ein Fenster fuer die Xulu-Modelling-Platform dar, in
+ * dem beliebige Statusmeldungen ausgegeben werden koennen. Dies kann ueber
+ * einzelne Zeilen geschehen ({@link #print(String)}, {@link #println(String)})
+ * oder ueber einen <code>PrintStream</code>. So ist es z.B. auch moeglich
+ * mittels {@link System#setErr(PrintStream)} die Standard-Fehlerausgabe auf
+ * dieses Fenster umzulenken.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class StatusFrame_BasicTextArea extends StatusFrame {
+
+  private XuluModellingPlatform appl = null;
+  private JTextArea             textArea = null;
+  private JMenu                 menu           = new JMenu("Bearbeiten");
+  private JMenuItem             menuItem_clear = new JMenuItem("Löschen");
+
+  /**
+   * Erzeugt einen neue Instanz des grafischen Statusfenster. Die Groesse ist
+   * auf 300x350 Pixel voreingestellt.
+   * @param appl Xulu-Applikation fuer die das Status-Fenster instanziiert wird
+   */
+  public StatusFrame_BasicTextArea(XuluModellingPlatform appl) {
+    this(appl, new Dimension(300,350));
+  }
+
+  /**
+   * Erzeugt einen neue Instanz des grafischen Statusfenster. Die Groesse ist
+   * auf 300x350 Pixel voreingestellt.
+   * @param appl Xulu-Applikation fuer die das Status-Fenster instanziiert wird
+   * @param size initiale Groesse des Fensters
+   */
+  public StatusFrame_BasicTextArea(XuluModellingPlatform appl, Dimension size) {
+    super();
+    this.appl = appl;
+    this.setSize(size);
+    this.getContentPane().setLayout( new BorderLayout() );
+    this.textArea = new JTextArea();
+    this.textArea.setEditable(false);
+    this.getContentPane().add( new JScrollPane( textArea ) );
+    // PopupMenue
+    this.menuItem_clear.addActionListener( new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        textArea.setText("");
+      }
+    });
+    this.menu.add(menuItem_clear);
+    this.textArea.addMouseListener( new PopupMenuListener(this.menu.getPopupMenu()) );
+  }
+
+  /**
+   * Macht nichts, da die Ausgaben im Statusfenster nicht von einer bestimmten
+   * anderen Komponente abhaengt, welche sich geaendert haben koennte.
+   */
+  public void refresh() {
+  }
+
+  /**
+   * Schreibt einen Text in das Statusfenster (ohne anschliessenden Zeilenumbruch!).
+   */
+  public void print(String text) {
+    textArea.append(text);
+    // Position ans Ende des Textes setzen
+    textArea.setCaretPosition( textArea.getText().lastIndexOf("\n")+1 );
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/gui/package.html
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/gui/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/gui/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,11 @@
+<html>
+<body>
+	In diesem Paket sind die Implementierungen der grafischen Xulu-Komponenten zu finden, welche
+	als Fenster im Xulu-Hauptfenster eingebettet sind. Diese sind von den entsprechenden
+	abstrakten Oberklassen im Paket {@link edu.bonn.xulu.gui} abgeleitet.
+	Zur Zeit sind sie noch explizit in der Klasse {@link edu.bonn.xulu.gui.XuluMainFrame}
+	eingebunden. Es ist jedoch geplant, diese in der Xulu-Registry dynamisch einzubinden, so
+	dass die GUI-Komponenten auch ausgewechselt werden koennen, ohne die Hauptfenster-Klasse
+	anzupassen.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/edu/bonn/xulu/plugin/io/IOUtil.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/IOUtil.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/IOUtil.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,126 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io;
+
+import java.io.File;
+
+import java.net.URL;
+
+import schmitzm.data.property.Property;
+import schmitzm.data.property.ScalarProperty;
+
+import edu.bonn.xulu.data.XuluObject;
+
+import skrueger.geotools.StyledMapStyle;
+import skrueger.geotools.StyledMapUtil;
+
+// fuer Doku
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+
+/**
+ * Diese Klasse enthaelt statische Hilfs-Methoden fuer das Importieren und
+ * Exportieren von {@linkplain XuluObject Xulu-Objekten}.
+ * @see ImportFactory
+ * @see ExportFactory
+ * @author <a href="mailto:schmitzm at bonn.edu">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class IOUtil {
+
+  /**
+   * Hinterlegt einen Style fuer ein {@link XuluObject} in der Property
+   * {@linkplain XuluObject#PROP_STYLE "Style"}.
+   * Macht nichts, wenn das {@link XuluObject} keine entsprechende Property besitzt.
+   * @param object ein {@link XuluObject}
+   * @param style  Style
+   */
+  public static void setStyleToXuluObject(XuluObject object, Object style) {
+    // Style-Property ermitteln
+    Property styleProp = object.getProperty(object.PROP_STYLE);
+    if ( styleProp != null && styleProp instanceof ScalarProperty )
+      ((ScalarProperty)styleProp).getOneTimeWriteAccess().setValue(style);
+  }
+
+  /**
+   * Liefert den eines {@link XuluObject} aus der Property
+   * {@linkplain XuluObject#PROP_STYLE "Style"}.
+   * @param object ein {@link XuluObject}
+   * @return {@code null}, wenn das {@link XuluObject} keine entsprechende Property besitzt.
+   */
+  public static Object getStyleFromXuluObject(XuluObject object) {
+    if ( object == null )
+      return null;
+    // Style-Property ermitteln
+    Property styleProp = object.getProperty(XuluObject.PROP_STYLE);
+    if ( styleProp != null && styleProp instanceof ScalarProperty )
+      return ((ScalarProperty)styleProp).getOneTimeReadAccess().getValue();
+
+    return null;
+  }
+
+  /**
+   * Importiert einen {@linkplain StyledMapStyle Raster-Style} fuer ein
+   * {@link XuluObject} und hinterlegt diesen in der Property
+   * {@linkplain XuluObject#PROP_STYLE "Style"}.
+   * Macht nichts, wenn das {@link XuluObject} keine entsprechende Property besitzt.
+   * @param object ein {@link XuluObject}
+   * @param objectURL URL unter der das XuluObject hinterlegt ist (bestimmt
+   *                  Pfad und Dateiname fuer die Style-Dateien)
+   * @see StyledMapUtil#loadStyledRasterStyle(URL)
+   */
+  public static void importRasterStyle(XuluObject object, URL objectURL) {
+    Object style = StyledMapUtil.loadStyledRasterStyle( objectURL );
+    setStyleToXuluObject(object, style);
+  }
+
+  /**
+   * Importiert einen {@linkplain StyledMapStyle Feature-Style} fuer ein
+   * {@link XuluObject} und hinterlegt diesen in der Property
+   * {@linkplain XuluObject#PROP_STYLE "Style"}.
+   * Macht nichts, wenn das {@link XuluObject} keine entsprechende Property besitzt.
+   * @param object ein {@link XuluObject}
+   * @param objectURL URL unter der das XuluObject hinterlegt ist (bestimmt
+   *                  Pfad und Dateiname fuer die Style-Dateien)
+   * @see StyledMapUtil#loadStyledFeatureStyle(URL)
+   */
+  public static void importFeatureStyle(XuluObject object, URL objectURL) {
+    Object style = StyledMapUtil.loadStyledFeatureStyle( objectURL );
+    setStyleToXuluObject(object, style);
+  }
+
+  /**
+   * Exportiert den Style eines {@link XuluObject}, der in der Property
+   * {@linkplain XuluObject#PROP_STYLE "Style"} hinterlegt ist. Macht nichts,
+   * wenn das {@link XuluObject} keine entsprechende Property besitzt, oder
+   * in der Property nichts hinterlegt ist.
+   * @param object ein {@link XuluObject}
+   * @param objectURL URL unter der das XuluObject hinterlegt ist (bestimmt
+   *                  Pfad und Dateiname fuer die Style-Dateien)
+   * @throws Exception wenn ein Fehler auftritt
+   */
+  public static void exportStyle(XuluObject object, URL objectURL) throws Exception {
+    // Style-Property ermitteln
+    Property styleProp = object.getProperty(object.PROP_STYLE);
+    if ( styleProp != null && styleProp instanceof ScalarProperty ) {
+      Object style = ((ScalarProperty)styleProp).getOneTimeWriteAccess().getValue();
+      if ( style != null ) {
+        if ( style instanceof StyledMapStyle )
+          StyledMapUtil.saveStyledMapStyle( (StyledMapStyle)style, objectURL );
+        else
+          throw new UnsupportedOperationException("Export of style not supported: "+style.getClass().getSimpleName());
+      }
+    }
+
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/feature/gt/SingleFeatureCollectionFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/feature/gt/SingleFeatureCollectionFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/feature/gt/SingleFeatureCollectionFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,71 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.feature.gt;
+
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.plugin.data.feature.SingleFeatureCollection;
+import org.geotools.feature.FeatureCollections;
+// nur fuer Doku
+import org.geotools.feature.FeatureCollection;
+
+/**
+ * Diese Factory erzeugt Standard-Instanzen von {@link SingleFeatureCollection}.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class SingleFeatureCollectionFactory extends AbstractFactory implements InstantiationFactory {
+  /**
+   * Liefert den Datentyp, der von der Factory erzeugt wird.
+   * @return immer {@link SingleFeatureCollection SingleFeatureCollection.class}
+   */
+  public Class getInstanceType() {
+    return SingleFeatureCollection.class;
+  }
+
+  /**
+   * Erzeugt eine {@link SingleFeatureCollection}, die eine leerer
+   * {@link FeatureCollection} beinhaltet. Diese wird ueber die Methode
+   * {@link FeatureCollections#newCollection()} erzeugt.
+   * @param dialog wird nicht benoetigt, da kein Anwenderdialog benoetigt wird
+   *               um eine leere FeatureCollection zu erzeugen
+   */
+  public SingleFeatureCollection newInstance(boolean dialog) {
+    return new SingleFeatureCollection( FeatureCollections.newCollection() );
+  }
+
+  /**
+   * <b>Noch nicht implementiert!!</b><br>
+   * Erzeugt eine (strukturelle) Kopie einer {@link SingleFeatureCollection}.
+   * @todo newInstance(Object sample) implementieren
+   * @param dialog bestimmt, ob die Vorlagen-Daten sofort uebernommen werden, oder
+   *               ueber einen Anwender-Dialog abgeaendert werden koennen
+   * @param sample Vorlage
+   * @exception IllegalArgumentException falls es sich bei der Vorlage nicht
+   *            um eine <code>SingleFeatureCollection</code> handelt
+   */
+  public SingleFeatureCollection newInstance(boolean dialog, Object sample) {
+    if ( sample == null )
+      throw new IllegalArgumentException(this.getClass().getSimpleName().concat(" can not create an instance of ").concat(getInstanceType().getSimpleName()).concat(" from null") );
+    if ( !getInstanceType().isAssignableFrom(sample.getClass()) )
+      throw new IllegalArgumentException(this.getClass().getSimpleName().concat(" can not create an instance of ").concat(getInstanceType().getSimpleName()).concat(" from ").concat(sample.getClass().getName()) );
+    throw new UnsupportedOperationException("newInstance(Object) not yet implemented!");
+//    SingleFeatureCollection sfc = ...
+//    // Style von der Vorlage uebernehmen
+//      edu.bonn.xulu.plugin.io.IOUtil.setStyleToXuluObject(
+//        sfc,
+//        edu.bonn.xulu.plugin.io.IOUtil.getStyleFromXuluObject( (SingleFeatureCollection) sample )
+//      );
+//    return sfc;
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/feature/gt/SingleFeatureCollectionFactory_ShapeFile.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/feature/gt/SingleFeatureCollectionFactory_ShapeFile.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/feature/gt/SingleFeatureCollectionFactory_ShapeFile.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,129 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.feature.gt;
+
+import java.io.File;
+
+import schmitzm.geotools.io.GeoImportUtil;
+import schmitzm.geotools.io.GeoExportUtil;
+
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.plugin.io.IOUtil;
+import edu.bonn.xulu.plugin.data.feature.SingleFeatureCollection;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link SingleFeatureCollection} aus/in Shape-Files.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class SingleFeatureCollectionFactory_ShapeFile extends AbstractFactory implements ImportFactory, ExportFactory {
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link SingleFeatureCollection SingleFeatureCollection.class}
+   */
+  public Class getImportType() {
+    return SingleFeatureCollection.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getImportSourceType() {
+    return File.class;
+  }
+
+  /**
+   * Importiert eine Instanz von {@link SingleFeatureCollection} aus einer Datei im
+   * ShapeFile-Format (.shp).
+   * @param input Eingabe-Quelle (muss ein {@link File} sein!)
+   * @param reg   Instanz der Xulu-Registry, ueber die eine Factory ermittelt
+   *              wird, die eine Standard-Instanz von {@link SingleFeatureCollection}
+   *              erzeugt, in die das Objekt importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Datei angegeben wird
+   * @see GeoImportUtil#readFeaturesFromShapeFile(File)
+   */
+  public SingleFeatureCollection importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+    // Eine SingleFeatureCollection instanziieren und ShapeFile importieren
+    InstantiationFactory instFac = AbstractFactory.getInstantiationFactoryFromRegistry(reg,getImportType(),true);
+    SingleFeatureCollection sfc = (SingleFeatureCollection)instFac.newInstance(false);
+    sfc.setFeatureCollection( GeoImportUtil.readFeaturesFromShapeFile((File)input) );
+
+    // Style importieren und falls vorhanden in Property einfuegen
+    IOUtil.importFeatureStyle( sfc, ((File)input).toURI().toURL() );
+
+    // Dateinamen in die Bezeichnung aufnehmen
+    sfc.setDescription(sfc.getDescription().concat(" [").concat(((File)input).getName()).concat("]"));
+    return sfc;
+
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um ein {@link SingleFeatureCollection} handelt.
+   * @param object zu pruefendes Objekt
+   */
+  public boolean isExportable(Object object) {
+    return object!=null && object instanceof SingleFeatureCollection;
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link SingleFeatureCollection} (oder eine Unterklasse)
+   * handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return SingleFeatureCollection.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getExportDestinationType() {
+    return File.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link SingleFeatureCollection} in das
+   * ShapeFile-Format.
+   * @param fc     zu exportiertendes Objekt (muss ein {@link SingleFeatureCollection} sein
+   * @param output Export-Ziel (muss ein {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel keine
+   *            Datei angegeben wird
+   * @exception IllegalArgumentException falls es sich bei <code>fc</code>
+   *            nicht um ein {@link SingleFeatureCollection} handelt
+   */
+  public void exportObject(Object fc, Object output) throws Exception {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(fc) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(fc.getClass().getName()));
+    SingleFeatureCollection sfc = (SingleFeatureCollection)fc;
+    GeoExportUtil.writeFeaturesToShapeFile(sfc.getFeatureCollection(),(File)output);
+    IOUtil.exportStyle( sfc, ((File)output).toURI().toURL() );
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/feature/gt/package.html
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/feature/gt/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/feature/gt/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,6 @@
+<html>
+<body>
+	Die Instanziierungs- und Im/Export-Factorys in diesem Paket basieren auf der
+	<a href="http://www.geotools.org" target=_blank>GeoTools</a>-Bibliothek.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/edu/bonn/xulu/plugin/io/feature/package.html
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/feature/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/feature/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,6 @@
+<html>
+<body>
+	In diesem Paket können die Instanziierungs- und Im/Export-Factorys für die
+	benutzerdefinierten Feature-Datentypen der Xulu-Modelling-Platform implementiert werden.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/WritableGridFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/WritableGridFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/WritableGridFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,173 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid;
+
+import java.awt.image.DataBuffer;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.swing.InputOption;
+import schmitzm.swing.SelectionInputOption;
+import schmitzm.swing.ManualInputOption;
+import schmitzm.swing.MultipleOptionPane;
+import schmitzm.geotools.io.GeoImportUtil;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.io.FactoryCanceledException;
+import edu.bonn.xulu.appl.XuluConstants;
+
+// nur fuer Doku
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+
+/**
+ * Diese Klasse bildet eine Oberklasse fuer alle Factorys, die Standard-Instanzen
+ * des Datentyps {@link WritableGrid} erzeugen.<br>
+ * <b>Bemerke:</b><br>
+ * Dieser Datentyp stellt <b>kein</b> {@linkplain XuluObject Xulu-Objekt} dar,
+ * kann also nicht direkt im Xulu-Datenpool gespeichert werden. Hierzu ist der Datentyp
+ * {@link SingleGrid} (bzw. eine entsprechende Factory) zu verwenden!
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class WritableGridFactory extends AbstractFactory implements InstantiationFactory {
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link WritableGrid WritableGrid.class}
+   */
+  public Class getInstanceType() {
+    return WritableGrid.class;
+  }
+
+  /**
+   * Erzeugt ein neues Raster. Die dazu benoetigten Angaben werden von einem
+   * Vorlagen-Raster uebernommen, koennen aber ueber einen Anwender-Dialog
+   * abgeaendert werden.
+   * @param sample Vorlage
+   * @param dialog gibt an, ob die Factory einen Dialog mit dem Anwender
+   *               fuehren darf, um die Instanz zu initialisieren (bei
+   *               <code>false</code> wird die Vorlage ohne Dialog kopiert)
+   * @exception IllegalArgumentException falls es sich bei der Vorlage nicht
+   *            um ein <code>WritableGridCoverage</code> handelt
+   * @exception FactoryCanceledException falls der Anwender-Dialog ueber
+   *            "Abbrechen" verlassen wird
+   */
+  public WritableGrid newInstance(boolean dialog, Object sample) {
+    if ( sample == null )
+      throw new IllegalArgumentException(this.getClass().getSimpleName().concat(" can not create an instance of ").concat(getInstanceType().getSimpleName()).concat(" from null") );
+    if ( !getInstanceType().isInstance(sample) )
+      throw new IllegalArgumentException(this.getClass().getSimpleName().concat(" can not create an instance of ").concat(getInstanceType().getSimpleName()).concat(" from ").concat(sample.getClass().getName()) );
+
+    WritableGrid wg = (WritableGrid)sample;
+    return newInstance( dialog,
+                        wg.getSampleType(),
+                        wg.getWidth(),
+                        wg.getHeight(),
+                        wg.getX(),
+                        wg.getY(),
+                        wg.getRealWidth(),
+                        wg.getRealHeight(),
+                        wg.getCoordinateReferenceSystem()
+    );
+  }
+
+  /**
+   * Erzeugt ein neues Raster. Die dazu benoetigten Angaben
+   * <ul>
+   * <li>Datentyp</li>
+   * <li>Rasterbreite (in Zellen)</li>
+   * <li>Rasterhoehe (in Zellen)</li>
+   * <li>GeoReferenz-Koordinaten (lat/lon)</li>
+   * <li>Reale Groesse des Rasters</li>
+   * </ul>
+   * werden durch einen Anwender-Dialog abgefragt.
+   * @param dialog gibt an, ob die Factory einen Dialog mit dem Anwender
+   *               fuehren darf, um die Instanz zu initialisieren (bei
+   *               <code>false</code> wird eine Standard-Instanz erzeugt)
+   * @exception FactoryCanceledException falls der Anwender-Dialog ueber
+   *            "Abbrechen" verlassen wird
+   */
+  public WritableGrid newInstance(boolean dialog) {
+    return newInstance(dialog, DataBuffer.TYPE_FLOAT, 500, 500, 0.0, 0.0, 500.0, 500.0, null);
+  }
+
+  /**
+   * Erzeugt ein neues Raster aus einer Vorlage. Trotzdem wird ein Dialog
+   * angezeigt, in dem die Vorlagen-Daten nacheditiert werden koennen.
+   * Falls die Vorlage <code>null</code> ist, werden Default-Angaben vorgeblendet.
+   * @param dialog bestimmt, ob die Vorlagen-Daten sofort uebernommen werden, oder
+   *               ueber einen Anwender-Dialog abgeaendert werden koennen
+   * @param type Datentyp der gespeicherten Objekte
+   * @param wCells Breite in Zellen
+   * @param hCells Hoehe in Zellen
+   * @param xCoord Georeferenz Longitute (Westliche/Linke Kante)
+   * @param yCoord Georeferenz Latitude (Suedliche/Untere Kante)
+   * @param wReal  Breite
+   * @param hReal  Hoehe
+   * @param crs Referenzsystem fuer das Raster (wenn {@code null}, wird
+   *            {@link GeoImportUtil#DEFAULT_CRS} verwendet
+   */
+  public WritableGrid newInstance(boolean dialog, int type, int wCells, int hCells, double xCoord, double yCoord, double wReal, double hReal, CoordinateReferenceSystem crs) {
+    if ( crs == null )
+      crs = GeoImportUtil.DEFAULT_CRS;
+
+    // Sample-Angaben ohne Dialog uebernehmen
+    if ( !dialog )
+      return newInstance(type,wCells,hCells,0,0,xCoord,yCoord,wReal,hReal,crs);
+
+    InputOption[] inpOpt = new InputOption[] {
+        new SelectionInputOption.Combo("Typ", true,
+                        new Integer[] {/*DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT,*/ DataBuffer.TYPE_FLOAT},
+                        (Object)type,
+                        new String[] {/*"Byte", "Unsigned Short", "Integer",*/"Float"}),
+        new ManualInputOption.Integer("Breite in Zellen", true, wCells),
+        new ManualInputOption.Integer("Hoehe in Zellen", true, hCells),
+        new ManualInputOption.Double("Geo-Referenz Lon/X (Südwestliche Ecke)", true, xCoord),
+        new ManualInputOption.Double("Geo-Referenz Lat/Y (Südwestliche Ecke)", true, yCoord),
+        new ManualInputOption.Double("Geo-Referenz Breite", true, wReal),
+        new ManualInputOption.Double("Geo-Referenz Hoehe", true, hReal)
+    };
+
+    Object[] inpValue = MultipleOptionPane.showMultipleInputDialog(
+      null,"Grid erzeugen", inpOpt);
+    if (inpValue == null)
+      throw new FactoryCanceledException(this);
+
+    return newInstance(
+      (Integer)inpValue[0], // Datentyp
+      (Integer)inpValue[1], // Breite in Zellen
+      (Integer)inpValue[2], // Hoehe in Zellen
+      0,
+      0,
+      (Double)inpValue[3],  // Lat
+      (Double)inpValue[4],  // Lon
+      (Double)inpValue[5],  // Breite
+      (Double)inpValue[6],  // Hoehe
+      crs
+    );
+  }
+
+  /**
+   * Erzeugt ein neues Grid.
+   * @param type Datentyp der gespeicherten Objekte
+   * @param widthc Breite in Zellen
+   * @param heightc Hoehe in Zellen
+   * @param minX    Index der ersten Zelle in X-Richtung
+   * @param minY    Index der ersten Zelle in Y-Richtung
+   * @param x Georeferenz Longitute (Westliche/Linke Kante)
+   * @param y Georeferenz Latitude (Suedliche/Untere Kante)
+   * @param width Breite
+   * @param height Hoehe
+   * @param crs Referenzsystem fuer das Raster
+   */
+  public abstract WritableGrid newInstance(int type, int widthc, int heightc, int minX, int minY, double x, double y, double width, double height, CoordinateReferenceSystem crs);
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/array/GridListFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/array/GridListFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/array/GridListFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,36 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.array;
+
+import edu.bonn.xulu.io.InstantiationFactory;
+
+// nur fuer Doku
+import schmitzm.data.WritableGrid;
+import edu.bonn.xulu.plugin.data.grid.GridList;
+
+/**
+ * Diese Factory erzeugt Standard-Instanzen von {@link GridList} mit
+ * durch die Factory {@link WritableGridArrayFactory} erzeugten (auf Standard-Arrays
+ * basierenden) {@link WritableGrid}-Instanzen als Inhalt.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class GridListFactory extends edu.bonn.xulu.plugin.io.grid.awt.GridListFactory {
+  /**
+   * Liefert eine Instanz von {@link WritableGridArrayFactory}, die auf
+   * Standard-Arrays basierende Instanzen von {@link WritableGrid} erzeugt. Mit diesen
+   * Instanzen wird die GridList gefuellt.
+   */
+  protected InstantiationFactory getWritableGridFactory() {
+    return new WritableGridArrayFactory();
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/array/GridListFactory_ArcInfoAsciiGrid.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/array/GridListFactory_ArcInfoAsciiGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/array/GridListFactory_ArcInfoAsciiGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,166 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.array;
+
+import java.io.File;
+
+import schmitzm.io.IOUtil;
+import schmitzm.data.WritableGridArray;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyReadAccess;
+
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+import edu.bonn.xulu.plugin.data.grid.GridList;
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link GridList} aus/in Dateien im ArcInfo-ASCII-Grid-Format.
+ * Beim Import liefert die Factory eine Standard-Arrays basierendes Raster-Liste
+ * ({@link WritableGridArray}).
+ * Entsprechend koennen beim Export nur {@link GridList GridLists}
+ * verarbeitet werden, die {@link WritableGridArray}-Instanzen in ihrer
+ * Raster-Property besitzen.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class GridListFactory_ArcInfoAsciiGrid extends AbstractFactory implements ImportFactory, ExportFactory {
+  private static final WritableGridArrayFactory_ArcInfoAsciiGrid GRID_FAC = new WritableGridArrayFactory_ArcInfoAsciiGrid();
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link GridList GridList.class}
+   */
+  public Class getImportType() {
+    return GridList.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File[].class}
+   */
+  public Class getImportSourceType() {
+    return File[].class;
+  }
+
+  /**
+   * Importiert Raster aus Dateien im ArcInfoAsciiGrid-Format
+   * und fuegt diese in einer {@link GridList} zusammen.
+   * @param input Eingabe-Quelle (muss ein {@link File File[]} sein!)
+   * @param reg   Instanz der Xulu-Registry, ueber die eine Factory ermittelt
+   *              wird, die eine Standard-Instanz von {@link GridList} erzeugt, in
+   *              die das Objekt importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Dateien angegeben werden
+   */
+  public GridList importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+    InstantiationFactory instFac = AbstractFactory.getInstantiationFactoryFromRegistry(reg,getImportType(),true);
+    GridList gl = (GridList)instFac.newInstance(false);
+    // Raster importieren und in GridList einfuegen
+    for (int i=0; i<((Object[])input).length; i++) {
+      gl.addGrid(
+        GRID_FAC.importObject( ((File[])input)[i], reg )
+      );
+      // Style vom ersten Raster uebernehmen
+      if ( edu.bonn.xulu.plugin.io.IOUtil.getStyleFromXuluObject( gl ) == null )
+        edu.bonn.xulu.plugin.io.IOUtil.importRasterStyle( gl, ((File[])input)[i].toURI().toURL() );
+    }
+
+//    // Dateinamen in die Bezeichnung aufnehmen
+//    sg.setDescription(sg.getDescription().concat(" [").concat(((File)input).getName()).concat("]"));
+    return gl;
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um eine {@link GridList} handelt, die nur Instanzen
+   * von {@link WritableGridArray} als Elemente enthaelt.
+   * @param obj zu pruefendes Objekt
+   */
+  public boolean isExportable(Object obj) {
+    if ( obj==null || !(obj instanceof GridList) )
+      return false;
+    GridList list = (GridList)obj;
+    for (int i=0; i<list.getGridCount(); i++)
+      if ( !(list.getGrid(i) instanceof WritableGridArray) )
+        return false;
+    return true;
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link GridList} (oder eine Unterklasse)
+   * handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return GridList.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt. Dabei handelt es sich um eine <b>einzelne Datei</b>, da
+   * die die letztendlichen Export-Dateien automatisch durchnummeriert werden!!
+   * @return immer {@link File File.class}
+   */
+  public Class getExportDestinationType() {
+    return File.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link GridList} in Dateien des
+   * ArcInfoAsciiGrid-Formats.<br>
+   * <b>Beachte:</b><br>
+   * Als Ausgabe-Objekt ist eine <b>einzelne</b> Datei anzugeben, kein
+   * Array! Die Dateien werden ausgehend von dem angegebenen Dateinamen
+   * durchnummeriert!!
+   * @param object zu exportiertende Raster (muss eine {@link GridList} sein
+   * @param output Export-Ziel (muss ein einzelner {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel keine
+   *            einzelne Datei angegeben wird
+   * @exception IllegalArgumentException falls es sich bei dem angegeben Objekt
+   *            nicht um eine {@link GridList} handelt
+   */
+  public void exportObject(Object object, Object output) throws Exception {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(object) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(object.getClass().getName()));
+
+    // Dateinamen-Teile ermitteln
+    String fileName = IOUtil.getBaseFileName((File)output);
+    String fileExt  = IOUtil.getFileExt((File)output);
+
+    // Grids in der Liste einzeln exportieren
+    GridList               gl         = (GridList)object;
+    ListPropertyReadAccess listAccess = ((ListProperty) (gl.getProperty(GridList.PROP_GRIDS))).getReadAccess(this);
+    for (int i=0; i<listAccess.getCount(); i++) {
+      File outFile = new File( fileName.concat("_"+i).concat(fileExt) );
+      GRID_FAC.exportObject( listAccess.getValue(i), outFile );
+      // Style exportieren
+      edu.bonn.xulu.plugin.io.IOUtil.exportStyle(gl, outFile.toURI().toURL() );
+    }
+    listAccess.release();
+
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/array/MultiGridFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/array/MultiGridFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/array/MultiGridFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,36 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.array;
+
+import edu.bonn.xulu.plugin.io.grid.WritableGridFactory;
+// nur fuer Doku
+import schmitzm.data.WritableGrid;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+
+/**
+ * Diese Factory erzeugt Standard-Instanzen von {@link MultiGrid} mit
+ * durch die Factory {@link WritableGridArrayFactory} erzeugten (auf Standard-Arrays
+ * basierenden) {@link WritableGrid}-Instanzen als Inhalt.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class MultiGridFactory extends edu.bonn.xulu.plugin.io.grid.awt.MultiGridFactory {
+  /**
+   * Liefert eine Instanz von {@link WritableGridArrayFactory}, die auf Standard-Arrays
+   * basierende Instanzen von {@link WritableGrid} erzeugt. Mit diesen
+   * Instanzen wird die GridList gefuellt.
+   */
+  protected WritableGridFactory getWritableGridFactory() {
+    return new WritableGridArrayFactory();
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/array/MultiGridFactory_ArcInfoAsciiGrid.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/array/MultiGridFactory_ArcInfoAsciiGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/array/MultiGridFactory_ArcInfoAsciiGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,94 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.array;
+
+import java.io.File;
+
+import schmitzm.data.WritableGrid;
+
+import edu.bonn.xulu.appl.XuluRegistry;
+import edu.bonn.xulu.io.AbstractFactory;
+
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+import edu.bonn.xulu.plugin.data.grid.GridList;
+import edu.bonn.xulu.plugin.io.grid.WritableGridFactory;
+import edu.bonn.xulu.plugin.io.grid.array.GridListFactory_ArcInfoAsciiGrid;
+
+// nur fuer Doku
+import schmitzm.data.WritableGridArray;
+import edu.bonn.xulu.io.InstantiationFactory;
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link MultiGrid} aus/in Dateien im ArcInfo-ASCII-Grid-Format.
+ * Beim Import liefert die Factory eine Standard-Arrays basierendes Raster-Liste
+ * ({@link WritableGridArray}).
+ * Entsprechend koennen beim Export nur {@link MultiGrid MultiGrids}
+ * verarbeitet werden, die {@link WritableGridArray}-Instanzen in ihrer
+ * Raster-Property besitzen.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class MultiGridFactory_ArcInfoAsciiGrid extends GridListFactory_ArcInfoAsciiGrid {
+  private static final WritableGridArrayFactory_ArcInfoAsciiGrid GRID_FAC = new WritableGridArrayFactory_ArcInfoAsciiGrid();
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link MultiGrid MultiGrid.class}
+   */
+  public Class getImportType() {
+    return MultiGrid.class;
+  }
+
+  /**
+   * Importiert Raster aus Dateien im ArcInfoAsciiGrid-Format
+   * und fuegt diese in einem {@link MultiGrid} zusammen.
+   * @param input Eingabe-Quelle (muss ein {@link File File[]} sein!)
+   * @param reg   Instanz der Xulu-Registry, ueber die eine Factory ermittelt
+   *              wird, die eine Standard-Instanz von {@link MultiGrid} erzeugt, in
+   *              die das Objekt importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Dateien angegeben werden
+   */
+  public MultiGrid importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+
+    // MultiGrid erst erzeugen, wenn ein Beispiel-Raster vorliegt
+    MultiGrid mg = null;
+    // Raster importieren und in GridList einfuegen
+    for (int i=0; i<((Object[])input).length; i++) {
+      WritableGrid grid = GRID_FAC.importObject( ((File[])input)[i], reg );
+      // das erste Grid dient dem MultiGrid als Vorlage
+      if ( mg == null )
+        mg = new MultiGrid(grid,getWritableGridFactory());
+      mg.addGrid(grid);
+      // Style vom ersten Raster uebernehmen
+      if ( edu.bonn.xulu.plugin.io.IOUtil.getStyleFromXuluObject( mg ) == null )
+        edu.bonn.xulu.plugin.io.IOUtil.importRasterStyle( mg, ((File[])input)[i].toURI().toURL() );
+    }
+
+    return mg;
+  }
+
+  /**
+   * Liefert eine Instanz von {@link WritableGridArrayFactory}, die auf Standard-Arrays
+   * basierende Instanzen von {@link WritableGrid} erzeugt. Mit diesen
+   * Instanzen wird das SingleGrid gefuellt.
+   */
+  protected WritableGridFactory getWritableGridFactory() {
+    return new WritableGridArrayFactory();
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/array/SingleGridFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/array/SingleGridFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/array/SingleGridFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,37 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.array;
+
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.plugin.io.grid.array.WritableGridArrayFactory;
+// nur fuer Doku
+import schmitzm.data.WritableGrid;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+
+/**
+ * Diese Factory erzeugt Standard-Instanzen von {@link SingleGrid} mit einem
+ * durch die Factory {@link WritableGridArrayFactory} erzeugten (auf Standard-Arrays basierenden)
+ * {@link WritableGrid}.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class SingleGridFactory extends edu.bonn.xulu.plugin.io.grid.awt.SingleGridFactory {
+
+  /**
+   * Liefert eine Instanz von {@link WritableGridArrayFactory}, die auf Standard-Arrays
+   * basierende Instanzen von {@link WritableGrid} erzeugt. Mit diesen
+   * Instanzen wird das SingleGrid gefuellt.
+   */
+  protected InstantiationFactory getWritableGridFactory() {
+    return new WritableGridArrayFactory();
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/array/SingleGridFactory_ArcInfoAsciiGrid.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/array/SingleGridFactory_ArcInfoAsciiGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/array/SingleGridFactory_ArcInfoAsciiGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,140 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.array;
+
+import java.io.File;
+
+import schmitzm.data.WritableGridArray;
+
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+
+import edu.bonn.xulu.plugin.io.IOUtil;
+
+// nur fuer Doku
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link SingleGrid} aus/in das ArcInfo-ASCII-Grid-Format.
+ * Beim Import liefert die Factory ein auf Standard-Arrays basierendes Raster
+ * ({@link WritableGridArray}).
+ * Entsprechend koennen beim Export nur {@link SingleGrid SingleGrids}
+ * verarbeitet werden, die eine {@link WritableGridArray}-Instanz in ihrere
+ * Raster-Property besitzen.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class SingleGridFactory_ArcInfoAsciiGrid extends AbstractFactory implements ImportFactory, ExportFactory {
+  private static final WritableGridArrayFactory_ArcInfoAsciiGrid GRID_FAC = new WritableGridArrayFactory_ArcInfoAsciiGrid();
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link SingleGrid SingleGrid.class}
+   */
+  public Class getImportType() {
+    return SingleGrid.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getImportSourceType() {
+    return File.class;
+  }
+
+  /**
+   * Importiert eine Instanz von {@link SingleGrid} aus einer Datei im
+   * ArcInfoAsciiGrid-Format.
+   * @param input Eingabe-Quelle (muss ein {@link File} sein!)
+   * @param reg   Instanz der Xulu-Registry, ueber die eine Factory ermittelt
+   *              wird, die eine Standard-Instanz von {@link SingleGrid} erzeugt, in
+   *              die das Raster importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Datei angegeben wird
+   */
+  public SingleGrid importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+    // Aus Registry die passende Factory fuer SingleGrid suchen
+    InstantiationFactory instFac = AbstractFactory.getInstantiationFactoryFromRegistry(reg,getImportType(),true);
+    // Raster importieren und in ein SingleGrid einfuegen
+    SingleGrid sg = (SingleGrid)instFac.newInstance(false);
+    sg.setGrid( GRID_FAC.importObject( (File)input,reg) );
+    // Style importieren und falls vorhanden in Property einfuegen
+    IOUtil.importRasterStyle( sg, ((File)input).toURI().toURL() );
+    // Dateinamen in die Bezeichnung aufnehmen
+    sg.setDescription(sg.getDescription().concat(" [").concat(((File)input).getName()).concat("]"));
+    return sg;
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um ein {@link SingleGrid} handelt, das ein
+   * {@link WritableGridArray} in seiner Raster-Eigenschaft besitzt.
+   * @param obj zu pruefendes Objekt
+   */
+  public boolean isExportable(Object obj) {
+    return obj!=null &&
+           obj instanceof SingleGrid &&
+           ((SingleGrid)obj).getGrid() instanceof WritableGridArray;
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link SingleGrid} (oder eine Unterklasse)
+   * handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return SingleGrid.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getExportDestinationType() {
+    return File.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link SingleGrid} in eine ArcInfoAsciiGrid-Datei.
+   * @param grid zu exportiertendes Raster (muss ein {@link SingleGrid} sein
+   * @param output Export-Ziel (muss ein {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel keine
+   *            Datei angegeben wird
+   * @exception IllegalArgumentException falls es sich bei dem angegeben Raster
+   *            nicht um ein {@link SingleGrid} handelt
+   */
+  public void exportObject(Object grid, Object output) throws Exception {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(grid) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(grid.getClass().getName()));
+    SingleGrid sg = (SingleGrid)grid;
+    // Raster exportieren
+    GRID_FAC.exportObject( sg.getGrid(), (File)output );
+    IOUtil.exportStyle( sg, ((File)output).toURI().toURL() );
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/array/SingleGridFactory_GeoTiff.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/array/SingleGridFactory_GeoTiff.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/array/SingleGridFactory_GeoTiff.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,139 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.array;
+
+import java.io.File;
+
+import schmitzm.data.WritableGridArray;
+
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+import edu.bonn.xulu.plugin.io.IOUtil;
+
+// nur fuer Doku
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link SingleGrid} aus/in das GeoTiff-Format.
+ * Beim Import liefert die Factory ein auf Standard-Arrays basierendes Raster
+ * ({@link WritableGridArray}).
+ * Entsprechend koennen beim Export nur {@link SingleGrid SingleGrids}
+ * verarbeitet werden, die eine {@link WritableGridArray}-Instanz in ihrere
+ * Raster-Property besitzen.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class SingleGridFactory_GeoTiff extends AbstractFactory implements ImportFactory, ExportFactory {
+  private static final WritableGridArrayFactory_GeoTiff GRID_FAC = new WritableGridArrayFactory_GeoTiff();
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link SingleGrid SingleGrid.class}
+   */
+  public Class getImportType() {
+    return SingleGrid.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getImportSourceType() {
+    return File.class;
+  }
+
+  /**
+   * Importiert eine Instanz von {@link SingleGrid} aus einer Datei im
+   * GeoTiff-Format.
+   * @param input Eingabe-Quelle (muss ein {@link File} sein!)
+   * @param reg   Instanz der Xulu-Registry, ueber die eine Factory ermittelt
+   *              wird, die eine Standard-Instanz von {@link SingleGrid} erzeugt, in
+   *              die das Raster importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Datei angegeben wird
+   */
+  public SingleGrid importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+    // Aus Registry die passende Factory fuer SingleGrid suchen
+    InstantiationFactory instFac = AbstractFactory.getInstantiationFactoryFromRegistry(reg,getImportType(),true);
+    // Raster importieren und in ein SingleGrid einfuegen
+    SingleGrid sg = (SingleGrid)instFac.newInstance(false);
+    sg.setGrid( GRID_FAC.importObject( (File)input,reg) );
+    // Style importieren und falls vorhanden in Property einfuegen
+    IOUtil.importRasterStyle( sg, ((File)input).toURI().toURL() );
+    // Dateinamen in die Bezeichnung aufnehmen
+    sg.setDescription(sg.getDescription().concat(" [").concat(((File)input).getName()).concat("]"));
+    return sg;
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um ein {@link SingleGrid} handelt, das ein
+   * {@link WritableGridArray} in seiner Raster-Eigenschaft besitzt.
+   * @param obj zu pruefendes Objekt
+   */
+  public boolean isExportable(Object obj) {
+    return obj!=null &&
+           obj instanceof SingleGrid &&
+           ((SingleGrid)obj).getGrid() instanceof WritableGridArray;
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link SingleGrid} (oder eine Unterklasse)
+   * handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return SingleGrid.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getExportDestinationType() {
+    return File.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link SingleGrid} in eine GeoTiff-Datei.
+   * @param grid zu exportiertendes Raster (muss ein {@link SingleGrid} sein
+   * @param output Export-Ziel (muss ein {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel keine
+   *            Datei angegeben wird
+   * @exception IllegalArgumentException falls es sich bei dem angegeben Raster
+   *            nicht um ein {@link SingleGrid} handelt
+   */
+  public void exportObject(Object grid, Object output) throws Exception {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(grid) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(grid.getClass().getName()));
+    SingleGrid sg = (SingleGrid)grid;
+    GRID_FAC.exportObject( sg.getGrid(),(File)output );
+    IOUtil.exportStyle( sg, ((File)output).toURI().toURL() );
+
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/array/WritableGridArrayFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/array/WritableGridArrayFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/array/WritableGridArrayFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,73 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.array;
+
+import java.awt.geom.Rectangle2D;
+import java.awt.image.DataBuffer;
+
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.WritableGridArray;
+import edu.bonn.xulu.plugin.io.grid.WritableGridFactory;
+import edu.bonn.xulu.appl.XuluConstants;
+// nur fuer Doku
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+
+/**
+ * Diese Factory erzeugt Standard-Instanzen des Datentyps {@link WritableGridArray}.<br>
+ * <b>Bemerke:</b><br>
+ * Dieser stellt <b>kein</b> {@linkplain XuluObject Xulu-Objekt} dar, kann also
+ * nicht direkt im Xulu-Datenpool gespeichert werden. Hierzu ist der Datentyp
+ * {@link SingleGrid} (bzw. eine entsprechende Factory) zu verwenden!
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class WritableGridArrayFactory extends WritableGridFactory {
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link WritableGridArray WritableGridArray.class}
+   */
+  public Class getInstanceType() {
+    return WritableGridArray.class;
+  }
+
+  /**
+   * Erzeugt ein neues Grid.
+   * @param type    Datentyp der gespeicherten Objekte
+   * @param widthc  Breite in Zellen
+   * @param heightc Hoehe in Zellen
+   * @param minX    Index der ersten Zelle in X-Richtung (<b>wird nicht verwendet! immer 0!</b>)
+   * @param minY    Index der ersten Zelle in Y-Richtung (<b>wird nicht verwendet! immer 0!</b>).
+   * @param x       Georeferenz Longitute (Westliche/Linke Kante)
+   * @param y       Georeferenz Latitude (Suedliche/Untere Kante)
+   * @param crs     Referenzsystem fuer das Raster
+   * @param width   Breite
+   * @param height  Hoehe
+   */
+  public WritableGridArray newInstance(int type, int widthc, int heightc, int minX, int minY, double x, double y, double width, double height, CoordinateReferenceSystem crs) {
+    // Envelope erzeugen
+    Rectangle2D e = new Rectangle2D.Double(x,y,width,height);
+    // Grid erzeugen
+    switch( type ) {
+//      case DataBuffer.TYPE_BYTE:
+      case DataBuffer.TYPE_INT: return new WritableGridArray.Integer(minX,minY,widthc,heightc,e,crs,null);
+//      case DataBuffer.TYPE_SHORT:
+//      case DataBuffer.TYPE_USHORT:
+      case DataBuffer.TYPE_DOUBLE: return new WritableGridArray.Double(minX,minY,widthc,heightc,e,crs,null);
+      case DataBuffer.TYPE_FLOAT:  return new WritableGridArray.Float(minX,minY,widthc,heightc,e,crs,null);
+    }
+    throw new UnsupportedOperationException("WritableGridArray-Instances of this data type not yet implemented!");
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/array/WritableGridArrayFactory_ArcInfoAsciiGrid.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/array/WritableGridArrayFactory_ArcInfoAsciiGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/array/WritableGridArrayFactory_ArcInfoAsciiGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,155 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.array;
+
+import java.io.File;
+
+import java.lang.reflect.Array;
+import java.util.Arrays;
+
+import org.geotools.coverage.grid.GridCoverageFactory;
+import org.geotools.coverage.grid.GridCoverage2D;
+
+import schmitzm.data.WritableGridArray;
+import schmitzm.data.WritableGridArray.Float;
+import schmitzm.data.WritableGridArray.Double;
+import schmitzm.data.WritableGridArray.Integer;
+import schmitzm.geotools.GTUtil;
+import schmitzm.geotools.io.GeoImportUtil;
+import schmitzm.geotools.io.GeoExportUtil;
+
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+// nur fuer Doku
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+import org.geotools.geometry.Envelope2D;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link WritableGridArray} aus/in das ArcInfo-ASCII-Grid-Format.<br>
+ * <b>Bemerke:</b><br>
+ * Die erzeugten Instanzen stellen <b>kein</b> {@linkplain XuluObject Xulu-Objekte} dar,
+ * koennen also nicht direkt im Xulu-Datenpool gespeichert werden. Hierzu ist der Datentyp
+ * {@link SingleGrid} (bzw. eine entsprechende Factory) zu verwenden!
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class WritableGridArrayFactory_ArcInfoAsciiGrid extends AbstractFactory implements ImportFactory, ExportFactory {
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link WritableGridArray WritableGridArray.class}
+   */
+  public Class getImportType() {
+    return WritableGridArray.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getImportSourceType() {
+    return File.class;
+  }
+
+  /**
+   * Importiert eine Instanz von {@link WritableGridArray} aus einer
+   * Datei.
+   * @param input Eingabe-Quelle (muss ein {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle kein
+   *            {@link File} angegeben wird
+   * @param reg wird nicht beruecksichtigt, da immer Instanzen von
+   *            {@link WritableGridArray} verwendet werden!
+   * @see GeoImportUtil#readGridFromArcInfoASCII(File,CoordinateReferenceSystem)
+   */
+  public WritableGridArray importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+    GridCoverage2D grid = (GridCoverage2D)GeoImportUtil.readGridFromArcInfoASCII(((File)input));
+    return WritableGridArray.create(grid.getRenderedImage(),grid.getEnvelope2D(),grid.getCoordinateReferenceSystem());
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um ein {@link WritableGridArray.Integer},
+   * {@link WritableGridArray.Float} oder {@link WritableGridArray.Double}
+   * handelt.
+   * @param obj zu pruefendes Objekt
+   */
+  public boolean isExportable(Object obj) {
+    return obj!=null &&
+         ( obj instanceof WritableGridArray.Integer ||
+           obj instanceof WritableGridArray.Float ||
+           obj instanceof WritableGridArray.Double );
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link WritableGridArray.Integer},
+   * {@link WritableGridArray.Float}, {@link WritableGridArray.Double} oder
+   * eine Unterklasse handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return WritableGridArray.Integer.class.isAssignableFrom(c) ||
+           WritableGridArray.Float.class.isAssignableFrom(c) ||
+           WritableGridArray.Double.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getExportDestinationType() {
+    return File.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link WritableGridArray} in eine Datei.
+   * @param grid zu exportiertendes Raster (muss ein {@link WritableGridArray.Float} sein
+   * @param output Export-Ziel (muss ein {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel kein
+   *            File angegeben wird
+   * @exception IllegalArgumentException falls es sich bei dem angegeben Raster
+   *            nicht um ein {@link WritableGridArray} handelt
+   * @see GeoExportUtil#writeGridToArcInfoASCII(GridCoverage2D,File)
+   */
+  public void exportObject(Object grid, Object output) throws Exception {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(grid) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(grid.getClass().getName()));
+    WritableGridArray wga = (WritableGridArray)grid;
+    float[][] floatData = new float[wga.getHeight()][wga.getWidth()];
+    if ( wga instanceof WritableGridArray.Float )
+      ((WritableGridArray.Float)wga).getData(floatData);
+    else if ( wga instanceof WritableGridArray.Integer )
+      ((WritableGridArray.Integer)wga).getData(floatData);
+    else  if ( wga instanceof WritableGridArray.Double )
+      ((WritableGridArray.Double)wga).getData(floatData);
+
+    GeoExportUtil.writeGridToArcInfoASCII(
+      new GridCoverageFactory().create("",floatData,GTUtil.createEnvelope2D(wga.getEnvelope(),wga.getCoordinateReferenceSystem())),
+      (File)output
+    );
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/array/WritableGridArrayFactory_GeoTiff.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/array/WritableGridArrayFactory_GeoTiff.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/array/WritableGridArrayFactory_GeoTiff.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,150 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.array;
+
+import java.io.File;
+
+import org.geotools.coverage.grid.GridCoverageFactory;
+
+import schmitzm.data.WritableGridArray;
+import schmitzm.data.WritableGridArray.Float;
+import schmitzm.data.WritableGridArray.Double;
+import schmitzm.data.WritableGridArray.Integer;
+import schmitzm.geotools.GTUtil;
+import schmitzm.geotools.io.GeoImportUtil;
+import schmitzm.geotools.io.GeoExportUtil;
+import schmitzm.geotools.grid.WritableGridCoverage;
+
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+// nur fuer Doku
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+import org.geotools.coverage.grid.GridCoverage2D;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link WritableGridArray} aus/in das GeoTiff-Format.<br>
+ * <b>Bemerke:</b><br>
+ * Die erzeugten Instanzen stellen <b>keine</b> {@linkplain XuluObject Xulu-Objekte} dar,
+ * koenn also nicht direkt im Xulu-Datenpool gespeichert werden. Hierzu ist der Datentyp
+ * {@link SingleGrid} (bzw. eine entsprechende Factory) zu verwenden!
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class WritableGridArrayFactory_GeoTiff extends AbstractFactory implements ImportFactory, ExportFactory {
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link WritableGridArray WritableGridArray.class}
+   */
+  public Class getImportType() {
+    return WritableGridArray.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getImportSourceType() {
+    return File.class;
+  }
+
+  /**
+   * Importiert eine Instanz von {@link WritableGridArray} aus einer
+   * Datei.
+   * @param input Eingabe-Quelle (muss ein {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Datei angegeben wird
+   * @param reg wird nicht beruecksichtigt, da immer Instanzen von
+   *            {@link WritableGridArray} verwendet werden!
+   * @see GeoImportUtil#readGridFromGeoTiff(File,CoordinateReferenceSystem)
+   */
+  public WritableGridArray importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+    GridCoverage2D grid = GeoImportUtil.readGridFromGeoTiff((File)input);
+    return WritableGridArray.create(grid.getRenderedImage(),grid.getEnvelope2D(),grid.getCoordinateReferenceSystem());
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um ein {@link WritableGridArray.Integer},
+   * {@link WritableGridArray.Float} oder {@link WritableGridArray.Double}
+   * handelt.
+   * @param obj zu pruefendes Objekt
+   */
+  public boolean isExportable(Object obj) {
+    return obj!=null &&
+         ( obj instanceof WritableGridArray.Integer ||
+           obj instanceof WritableGridArray.Float ||
+           obj instanceof WritableGridArray.Double );
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link WritableGridArray.Integer},
+   * {@link WritableGridArray.Float}, {@link WritableGridArray.Double} oder
+   * eine Unterklasse handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return WritableGridArray.Integer.class.isAssignableFrom(c) ||
+           WritableGridArray.Float.class.isAssignableFrom(c) ||
+           WritableGridArray.Double.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getExportDestinationType() {
+    return File.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link WritableGridArray} in eine Datei.
+   * @param grid zu exportiertendes Raster (muss ein {@link WritableGridArray.Float} sein
+   * @param output Export-Ziel (muss ein {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel keine
+   *            Datei angegeben wird
+   * @exception IllegalArgumentException falls es sich bei dem angegeben Raster
+   *            nicht um ein {@link WritableGridArray} handelt
+   * @see GeoExportUtil#writeGridToGeoTiff(GridCoverage2D,File)
+   */
+  public void exportObject(Object grid, Object output) throws Exception {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(grid) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(grid.getClass().getName()));
+    WritableGridArray wga = (WritableGridArray)grid;
+    float[][] floatData = new float[wga.getHeight()][wga.getWidth()];
+    if ( wga instanceof WritableGridArray.Float )
+      ((WritableGridArray.Float)wga).getData(floatData);
+    else if ( wga instanceof WritableGridArray.Integer )
+      ((WritableGridArray.Integer)wga).getData(floatData);
+    else  if ( wga instanceof WritableGridArray.Double )
+      ((WritableGridArray.Double)wga).getData(floatData);
+    GeoExportUtil.writeGridToGeoTiff(
+      new GridCoverageFactory().create("",floatData,GTUtil.createEnvelope2D(wga.getEnvelope(),wga.getCoordinateReferenceSystem())),
+      (File)output
+    );
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/awt/GridListFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/awt/GridListFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/awt/GridListFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,135 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.awt;
+
+import schmitzm.data.WritableGrid;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.FactoryCanceledException;
+import edu.bonn.xulu.plugin.data.grid.GridList;
+import schmitzm.swing.MultipleOptionPane;
+import schmitzm.swing.InputOption;
+import schmitzm.swing.ManualInputOption;
+
+/**
+ * Diese Factory erzeugt Standard-Instanzen von {@link GridList} mit
+ * durch die Factory {@link WritableGridRasterFactory} erzeugten (auf Standard-AWT
+ * basierenden) {@link WritableGrid}-Instanzen als Inhalt.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class GridListFactory extends AbstractFactory implements InstantiationFactory {
+  /**
+   * Liefert den Datentyp, der von der Factory erzeugt wird.
+   * @return immer {@link GridList GridList.class}
+   */
+  public Class getInstanceType() {
+    return GridList.class;
+  }
+
+  /**
+   * Erzeugt eine neue Instanz von {@link GridList}. Hierzu wird ueber einen
+   * Anwenderdialog abgefragt wie viele Raster die Liste enthalten soll und
+   * die von {@link #getWritableGridFactory()} gelieferte Factory herangezogen,
+   * um die Raster zu erzeugen.
+   * @param sample Vorlage
+   * @param dialog gibt an, ob die Factory einen Dialog mit dem Anwender
+   *               fuehren darf, um die Instanz zu initialisieren (bei
+   *               <code>false</code> wird die Vorlage ohne Dialog kopiert)
+   * @exception IllegalArgumentException falls es sich bei der Vorlage nicht
+   *            um eine <code>GridList</code> handelt
+   * @exception FactoryCanceledException falls der Anwender-Dialog ueber
+  *            "Abbrechen" verlassen wird
+  */
+  public GridList newInstance(boolean dialog, Object sample) throws Exception {
+    if ( sample == null )
+      throw new IllegalArgumentException(this.getClass().getSimpleName().concat(" can not create an instance of ").concat(getInstanceType().getSimpleName()).concat(" from null") );
+    if ( !getInstanceType().isInstance(sample) )
+      throw new IllegalArgumentException(this.getClass().getSimpleName().concat(" can not create an instance of ").concat(getInstanceType().getSimpleName()).concat(" from ").concat(sample.getClass().getName()) );
+
+    return createFromSample(dialog,(GridList)sample);
+  }
+
+  /**
+   * Erzeugt eine neue Instanz von {@link GridList}. Hierzu wird ueber einen
+   * Anwenderdialog abgefragt wie viele Raster die Liste enthalten soll und
+   * die von {@link #getWritableGridFactory()} gelieferte Factory herangezogen,
+   * um die Raster zu erzeugen.
+   * @param dialog gibt an, ob die Factory einen Dialog mit dem Anwender
+   *               fuehren darf, um die Instanz zu initialisieren (bei
+   *               <code>false</code> wird eine Standard-Instanz erzeugt)
+   * @exception FactoryCanceledException falls der Anwender-Dialog ueber
+   *            "Abbrechen" verlassen wird
+   */
+  public GridList newInstance(boolean dialog) throws Exception {
+    return createFromSample(dialog, null);
+  }
+
+  /**
+   * Erzeugt eine neue GridList aus einer Vorlage. Trotzdem wird ein Dialog
+   * angezeigt, in dem die Vorlagen-Daten nacheditiert werden koennen.
+   * Falls die Vorlage <code>null</code> ist, werden Default-Angaben vorgeblendet.
+   * @param sample Vorlage
+   * @param dialog bestimmt, ob die Vorlagen-Daten sofort uebernommen werden, oder
+   *               ueber einen Anwender-Dialog abgeaendert werden koennen
+   */
+  public GridList createFromSample(boolean dialog, GridList sample) throws Exception {
+    // Anzahl an Grids aus dem Sample uebernehmen
+    int count = (sample == null) ? 0 : sample.getGridCount();
+    // Anzahl zu erzeugender Grids abfragen
+    if (dialog) {
+      Object[] inpValue = MultipleOptionPane.showMultipleInputDialog(
+                               null,
+                               this.getInstanceType().getSimpleName().concat(" erzeugen"),
+                               new InputOption[] { new ManualInputOption.Integer("Anzahl an Grids in der Liste",true,count) }
+      );
+      if ( inpValue == null )
+        throw new FactoryCanceledException(this);
+      count = (Integer)inpValue[0];
+    }
+
+    // nacheinander die Grids erzeugen
+    InstantiationFactory fac = getWritableGridFactory();
+    if ( !WritableGrid.class.isAssignableFrom(fac.getInstanceType()) )
+      throw new UnsupportedOperationException(getClass().getSimpleName().concat(".getWritableGridFactory() must provide a factory that creates a WritableGrid!"));
+
+    WritableGrid[] grid = new WritableGrid[count];
+    for (int i=0; i<grid.length; i++) {
+      // falls vorhanden, die Werte der Grids aus der Vorlage vorblenden
+      WritableGrid sampleGrid = (sample!=null && i<sample.getGridCount()) ? sample.getGrid(i) : null;
+      if ( sampleGrid == null )
+        grid[i] = (WritableGrid)fac.newInstance(dialog);
+      else
+        grid[i] = (WritableGrid)fac.newInstance(dialog,sampleGrid);
+    }
+    GridList gl = new GridList(grid);
+
+    // Style von der Vorlage uebernehmen
+    edu.bonn.xulu.plugin.io.IOUtil.setStyleToXuluObject(
+      gl,
+      edu.bonn.xulu.plugin.io.IOUtil.getStyleFromXuluObject( sample )
+    );
+
+    return gl;
+  }
+
+  /**
+   * Liefert eine {@link InstantiationFactory}, die Instanzen von {@link WritableGrid}
+   * erzeugt. Mit diesen Instanzen wird die Liste gefuellt.<br>
+   * Standardmaessig wird eine Instanz von {@link WritableGridRasterFactory}
+   * zurueckgegeben. Sub-Klassen koennen diese Methode ueberschreiben, um
+   * andere Arten von WritableGrid zu erzeugen.
+   */
+  protected InstantiationFactory getWritableGridFactory() {
+    return new WritableGridRasterFactory();
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/awt/GridListFactory_ArcInfoAsciiGrid.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/awt/GridListFactory_ArcInfoAsciiGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/awt/GridListFactory_ArcInfoAsciiGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,172 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.awt;
+
+import java.io.File;
+
+import schmitzm.geotools.io.GeoImportUtil;
+import schmitzm.geotools.io.GeoExportUtil;
+import schmitzm.io.IOUtil;
+import schmitzm.data.WritableGridRaster;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyReadAccess;
+
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.appl.XuluRegistry;
+import edu.bonn.xulu.plugin.data.grid.GridList;
+
+// fuer Doku
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link GridList} aus/in Dateien im ArcInfo-ASCII-Grid-Format.
+ * Beim Import liefert die Factory eine Liste von auf Java-AWT basierenden
+ * Rastern ({@link WritableGridRaster}).
+ * Entsprechend koennen beim Export nur {@link GridList GridLists}
+ * verarbeitet werden, die {@link WritableGridRaster}-Instanzen als
+ * Listen-Elemente besitzen.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class GridListFactory_ArcInfoAsciiGrid extends AbstractFactory implements ImportFactory, ExportFactory {
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link GridList GridList.class}
+   */
+  public Class getImportType() {
+    return GridList.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File[].class}
+   */
+  public Class getImportSourceType() {
+    return File[].class;
+  }
+
+  /**
+   * Importiert Raster aus Dateien im ArcInfoAsciiGrid-Format
+   * und fuegt diese in einer {@link GridList} zusammen.
+   * @param input Eingabe-Quelle (muss ein {@link File File[]} sein!)
+   * @param reg   Instanz der Xulu-Registry, ueber die eine Factory ermittelt
+   *              wird, die eine Standard-Instanz von {@link GridList} erzeugt, in
+   *              die das Objekt importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Dateien angegeben werden
+   * @see GeoImportUtil#readGridRasterFromArcInfoASCII(File,CoordinateReferenceSystem)
+   */
+  public GridList importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+    InstantiationFactory instFac = AbstractFactory.getInstantiationFactoryFromRegistry(reg,getImportType(),true);
+    GridList gl    = (GridList)instFac.newInstance(false);
+    Object   style = null;
+    // Raster importieren und in GridList einfuegen
+    for (int i=0; i<((Object[])input).length; i++) {
+      gl.addGrid(
+        GeoImportUtil.readGridRasterFromArcInfoASCII(((File[])input)[i])
+      );
+      // Style vom ersten Raster uebernehmen
+      if ( edu.bonn.xulu.plugin.io.IOUtil.getStyleFromXuluObject( gl ) == null )
+        edu.bonn.xulu.plugin.io.IOUtil.importRasterStyle( gl, ((File[])input)[i].toURI().toURL() );
+    }
+
+//    // Dateinamen in die Bezeichnung aufnehmen
+//    gl.setDescription(sg.getDescription().concat(" [").concat(((File)input).getName()).concat("]"));
+    return gl;
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um eine {@link GridList} handelt, die nur Instanzen
+   * von {@link WritableGridRaster} als Elemente enthaelt.
+   * @param obj zu pruefendes Objekt
+   */
+  public boolean isExportable(Object obj) {
+    if ( obj==null || !(obj instanceof GridList) )
+      return false;
+    GridList list = (GridList)obj;
+    for (int i=0; i<list.getGridCount(); i++)
+      if ( !(list.getGrid(i) instanceof WritableGridRaster) )
+        return false;
+    return true;
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link GridList} (oder eine Unterklasse)
+   * handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return GridList.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt. Dabei handelt es sich um eine <b>einzelne Datei</b>, da
+   * die die letztendlichen Export-Dateien automatisch durchnummeriert werden!!
+   * @return immer {@link File File.class}
+   */
+  public Class getExportDestinationType() {
+    return File.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link GridList} in Dateien des
+   * ArcInfoAsciiGrid-Formats.<br>
+   * <b>Beachte:</b><br>
+   * Als Ausgabe-Objekt ist eine <b>einzelne</b> Datei anzugeben, kein
+   * Array! Die Dateien werden ausgehend von dem angegebenen Dateinamen
+   * durchnummeriert!!
+   * @param object zu exportiertende Raster (muss eine {@link GridList} sein
+   * @param output Export-Ziel (muss ein einzelner {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel keine
+   *            einzelne Datei angegeben wird
+   * @exception IllegalArgumentException falls es sich bei dem angegeben Objekt
+   *            nicht um eine {@link GridList} handelt
+   * @see GeoExportUtil#writeGridRasterToArcInfoASCII(WritableGridRaster,File)
+   */
+  public void exportObject(Object object, Object output) throws Exception {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(object) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(object.getClass().getName()));
+
+    // Dateinamen-Teile ermitteln
+    String fileName = IOUtil.getBaseFileName((File)output);
+    String fileExt  = IOUtil.getFileExt((File)output);
+
+    // Grids in der Liste einzeln exportieren
+    GridList               gl         = (GridList)object;
+    ListPropertyReadAccess listAccess = ((ListProperty)gl.getProperty(GridList.PROP_GRIDS)).getReadAccess(this);
+    for (int i=0; i<listAccess.getCount(); i++) {
+      File outFile = new File( fileName.concat("_"+i).concat(fileExt) );
+      GeoExportUtil.writeGridRasterToArcInfoASCII( (WritableGridRaster)listAccess.getValue(i),outFile );
+      // Style  exportieren
+      edu.bonn.xulu.plugin.io.IOUtil.exportStyle(gl, outFile.toURI().toURL() );
+    }
+    listAccess.release();
+
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/awt/MultiGridFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/awt/MultiGridFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/awt/MultiGridFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,154 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.awt;
+
+import schmitzm.data.WritableGrid;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.FactoryCanceledException;
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+import edu.bonn.xulu.plugin.io.grid.WritableGridFactory;
+import schmitzm.swing.MultipleOptionPane;
+import schmitzm.swing.InputOption;
+import schmitzm.swing.ManualInputOption;
+
+/**
+ * Diese Factory erzeugt Standard-Instanzen von {@link MultiGrid} mit
+ * durch die Factory {@link WritableGridRasterFactory} erzeugten (auf Standard-AWT
+ * basierenden) {@link WritableGrid}-Instanzen als Inhalt.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class MultiGridFactory extends AbstractFactory implements InstantiationFactory {
+  /**
+   * Liefert den Datentyp, der von der Factory erzeugt wird.
+   * @return immer {@link MultiGrid MultiGrid.class}
+   */
+  public Class getInstanceType() {
+    return MultiGrid.class;
+  }
+
+  /**
+   * Erzeugt eine neue Instanz von {@link MultiGrid}. Hierzu wird ueber einen
+   * Anwenderdialog abgefragt, wie viele Raster die Liste enthalten soll und
+   * die Factory {@link WritableGridRasterFactory} herangezogen, um die Raster zu
+   * erzeugen.
+   * @param dialog gibt an, ob die Factory einen Dialog mit dem Anwender
+   *               fuehren darf, um die Instanz zu initialisieren (bei
+   *               <code>false</code> wird die Vorlage ohne Dialog kopiert)
+   * @param sample Vorlage
+   * @exception IllegalArgumentException falls es sich bei der Vorlage nicht
+   *            um eine {@link MultiGrid}, {@link SingleGrid} oder {@link WritableGrid}
+   *            handelt
+   * @exception FactoryCanceledException falls der Anwender-Dialog ueber
+   *            "Abbrechen" verlassen wird
+   */
+  public MultiGrid newInstance(boolean dialog, Object sample) throws Exception {
+//    if ( sample == null )
+//      throw new IllegalArgumentException(this.getClass().getSimpleName().concat(" can not create an instance of ").concat(getInstanceType().getSimpleName()).concat(" from null") );
+// wird nun in createFromSample(..) geprueft
+//    if ( !getInstanceType().isInstance(sample) )
+//      throw new IllegalArgumentException(this.getClass().getSimpleName().concat(" can not create an instance of ").concat(getInstanceType().getSimpleName()).concat(" from ").concat(sample.getClass().getName()) );
+
+    return createFromSample(dialog,sample);
+  }
+
+  /**
+   * Erzeugt eine neue Instanz von {@link MultiGrid}. Hierzu wird ueber einen
+   * Anwenderdialog abgefragt wie viele Raster die Liste enthalten soll und
+   * die Factory {@link WritableGridRasterFactory} herangezogen, um die Raster zu
+   * erzeugen.
+   * @param dialog gibt an, ob die Factory einen Dialog mit dem Anwender
+   *               fuehren darf, um die Instanz zu initialisieren (bei
+   *               <code>false</code> wird eine Standard-Instanz erzeugt)
+   * @exception FactoryCanceledException falls der Anwender-Dialog ueber
+   *            "Abbrechen" verlassen wird
+   */
+  public MultiGrid newInstance(boolean dialog) throws Exception {
+    return createFromSample(dialog,null);
+  }
+
+  /**
+   * Erzeugt ein neues {@link MultiGrid} aus einer Vorlage. Trotzdem wird ein Dialog
+   * angezeigt, in dem die Vorlagen-Daten nacheditiert werden koennen.
+   * Falls die Vorlage <code>null</code> ist, werden Default-Angaben vorgeblendet.
+   * @param sample Vorlage ({@link WritableGrid}, {@link SingleGrid} oder {@link MultiGrid})
+   * @param dialog bestimmt, ob die Vorlagen-Daten sofort uebernommen werden, oder
+   *               ueber einen Anwender-Dialog abgeaendert werden koennen
+   */
+  private MultiGrid createFromSample(boolean dialog, Object sample) throws Exception {
+    if ( sample != null && !(sample instanceof WritableGrid) &&
+                           !(sample instanceof SingleGrid) &&
+                           !(sample instanceof MultiGrid) )
+      throw new IllegalArgumentException(this.getClass().getSimpleName().concat(" can not create an instance of ").concat(getInstanceType().getSimpleName()).concat(" from ").concat(sample.getClass().getSimpleName()) );
+
+    // Anzahl an Grids aus dem Sample uebernehmen
+    int count = 0;
+    if ( sample != null && dialog && sample instanceof MultiGrid )
+      count = ((MultiGrid)sample).getGridCount();
+
+    // Anzahl zu erzeugender Grids abfragen
+    if (dialog) {
+      Object[] inpValue = MultipleOptionPane.showMultipleInputDialog(
+                               null,
+                               this.getInstanceType().getSimpleName().concat(" erzeugen"),
+                               new InputOption[] { new ManualInputOption.Integer("Anzahl an Grids in der Liste",true,count) }
+      );
+      if ( inpValue == null )
+        throw new FactoryCanceledException(this);
+      count = (Integer)inpValue[0];
+    }
+
+    // nacheinander die Grids erzeugen
+    WritableGridFactory fac = getWritableGridFactory();
+    if ( !WritableGrid.class.isAssignableFrom(fac.getInstanceType()) )
+      throw new UnsupportedOperationException(getClass().getSimpleName().concat(".getWritableGridFactory() must provide a factory that creates a WritableGrid!"));
+
+    // Vorlage erstellen
+    WritableGrid sampleGrid = null;
+    if ( sample instanceof MultiGrid )
+      sampleGrid = ((MultiGrid)sample).getTemplateGrid();
+    else if ( sample instanceof SingleGrid )
+      sampleGrid = ((SingleGrid)sample).getGrid();
+    else if ( sample instanceof WritableGrid )
+      sampleGrid = (WritableGrid)sample;
+    else if ( dialog )
+      sampleGrid = fac.newInstance(dialog);
+
+    // MultiGrid erstellen
+    MultiGrid multiGrid = new MultiGrid(sampleGrid,fac);
+    for (int i=0; i<count; i++)
+      multiGrid.addGrid();
+    // Style von der Vorlage uebernehmen
+    if ( sample instanceof XuluObject )
+      edu.bonn.xulu.plugin.io.IOUtil.setStyleToXuluObject(
+        multiGrid,
+        edu.bonn.xulu.plugin.io.IOUtil.getStyleFromXuluObject( (XuluObject)sample )
+      );
+
+    return multiGrid;
+  }
+
+  /**
+   * Liefert eine {@link InstantiationFactory}, die Instanzen von {@link WritableGrid}
+   * erzeugt. Mit diesen Instanzen wird die Liste gefuellt.<br>
+   * Standardmaessig wird eine Instanz von {@link WritableGridRasterFactory}
+   * zurueckgegeben. Sub-Klassen koennen diese Methode ueberschreiben, um
+   * andere Arten von WritableGrid zu erzeugen.
+   */
+  protected WritableGridFactory getWritableGridFactory() {
+    return new WritableGridRasterFactory();
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/awt/MultiGridFactory_ArcInfoAsciiGrid.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/awt/MultiGridFactory_ArcInfoAsciiGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/awt/MultiGridFactory_ArcInfoAsciiGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,98 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.awt;
+
+import java.io.File;
+
+import schmitzm.geotools.io.GeoImportUtil;
+import schmitzm.data.WritableGrid;
+
+import edu.bonn.xulu.appl.XuluRegistry;
+import edu.bonn.xulu.io.AbstractFactory;
+
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+import edu.bonn.xulu.plugin.data.grid.GridList;
+import edu.bonn.xulu.plugin.io.grid.WritableGridFactory;
+import edu.bonn.xulu.plugin.io.grid.awt.GridListFactory_ArcInfoAsciiGrid;
+
+// nur fuer Doku
+import schmitzm.data.WritableGridRaster;
+import edu.bonn.xulu.io.InstantiationFactory;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link MultiGrid} aus/in Dateien im ArcInfo-ASCII-Grid-Format.
+ * Beim Import liefert die Factory eine Liste von auf Java-AWT basierenden
+ * Rastern ({@link WritableGridRaster}).
+ * Entsprechend koennen beim Export nur {@link MultiGrid MultiGrids}
+ * verarbeitet werden, die {@link WritableGridRaster}-Instanzen als
+ * Listen-Elemente besitzen.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class MultiGridFactory_ArcInfoAsciiGrid extends GridListFactory_ArcInfoAsciiGrid {
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link MultiGrid MultiGrid.class}
+   */
+  public Class getImportType() {
+    return MultiGrid.class;
+  }
+
+  /**
+   * Importiert Raster aus Dateien im ArcInfoAsciiGrid-Format
+   * und fuegt diese in einem {@link MultiGrid} zusammen.
+   * @param input Eingabe-Quelle (muss ein {@link File File[]} sein!)
+   * @param reg   Instanz der Xulu-Registry, ueber die eine Factory ermittelt
+   *              wird, die eine Standard-Instanz von {@link MultiGrid} erzeugt, in
+   *              die das Objekt importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Dateien angegeben werden
+   * @see GeoImportUtil#readGridRasterFromArcInfoASCII(File,CoordinateReferenceSystem)
+   */
+  public MultiGrid importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+
+    // MultiGrid erst erzeugen, wenn ein Beispiel-Raster vorliegt
+    MultiGrid mg    = null;
+    Object    style = null;
+    // Raster importieren und in GridList einfuegen
+    for (int i=0; i<((Object[])input).length; i++) {
+      WritableGrid grid = GeoImportUtil.readGridRasterFromArcInfoASCII(((File[])input)[i]);
+      // das erste Grid dient dem MultiGrid als Vorlage
+      if ( mg == null )
+        mg = new MultiGrid(grid,getWritableGridFactory());
+      mg.addGrid(grid);
+      // Style vom ersten Raster uebernehmen
+      if ( edu.bonn.xulu.plugin.io.IOUtil.getStyleFromXuluObject( mg ) == null )
+        edu.bonn.xulu.plugin.io.IOUtil.importRasterStyle( mg, ((File[])input)[i].toURI().toURL() );
+    }
+
+    return mg;
+  }
+
+  /**
+   * Liefert eine {@link InstantiationFactory}, die Instanzen von {@link WritableGrid}
+   * erzeugt. Mit diesen Instanzen wird die Liste gefuellt.<br>
+   * Standardmaessig wird eine Instanz von {@link WritableGridRasterFactory}
+   * zurueckgegeben. Sub-Klassen koennen diese Methode ueberschreiben, um
+   * andere Arten von WritableGrid zu erzeugen.
+   */
+  protected WritableGridFactory getWritableGridFactory() {
+    return new WritableGridRasterFactory();
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/awt/SingleGridFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/awt/SingleGridFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/awt/SingleGridFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,95 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.awt;
+
+import schmitzm.data.WritableGrid;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+import edu.bonn.xulu.plugin.io.grid.awt.WritableGridRasterFactory;
+import schmitzm.data.property.ScalarProperty;
+
+/**
+ * Diese Factory erzeugt Standard-Instanzen von {@link SingleGrid} mit einem
+ * durch die Factory {@link WritableGridRasterFactory} erzeugten (auf Standard-AWT
+ * basierenden) {@link WritableGrid}.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class SingleGridFactory extends AbstractFactory implements InstantiationFactory {
+  /**
+   * Liefert den Datentyp, der von der Factory erzeugt wird.
+   * @return immer {@link SingleGrid SingleGrid.class}
+   */
+  public Class getInstanceType() {
+    return SingleGrid.class;
+  }
+
+  /**
+   * Erzeugt eine neue Instanz von {@link SingleGrid}. Hierzu wird die
+   * Factory {@link WritableGridRasterFactory} herangezogen.
+   * @param dialog gibt an, ob die Factory einen Dialog mit dem Anwender
+   *               fuehren darf, um die Instanz zu initialisieren (bei
+   *               <code>false</code> wird die Vorlage ohne Dialog kopiert)
+   * @param sample Vorlage
+   * @exception IllegalArgumentException falls es sich bei der Vorlage nicht
+   *            um ein <code>SingleGrid</code> oder um ein <code>WritableGrid</code>
+   *            handelt
+   */
+  public SingleGrid newInstance(boolean dialog, Object sample) throws Exception {
+    if ( sample == null )
+      throw new IllegalArgumentException(this.getClass().getSimpleName().concat(" can not create an instance of ").concat(getInstanceType().getSimpleName()).concat(" from null") );
+    if ( !getInstanceType().isInstance(sample) && !WritableGrid.class.isInstance(sample) )
+      throw new IllegalArgumentException(this.getClass().getSimpleName().concat(" can not create an instance of ").concat(getInstanceType().getSimpleName()).concat(" from ").concat(sample.getClass().getName()) );
+
+    InstantiationFactory fac = getWritableGridFactory();
+    if ( !WritableGrid.class.isAssignableFrom(fac.getInstanceType()) )
+      throw new UnsupportedOperationException(getClass().getSimpleName().concat(".getWritableGridFactory() must provide a factory that creates a WritableGrid!"));
+
+    WritableGrid sampleGrid = ( sample instanceof WritableGrid ) ? (WritableGrid)sample : ((SingleGrid)sample).getGrid();
+    SingleGrid sg = new SingleGrid( (WritableGrid)fac.newInstance( dialog, sampleGrid ) );
+    // Style von der Vorlage uebernehmen
+    if ( sample instanceof SingleGrid )
+      edu.bonn.xulu.plugin.io.IOUtil.setStyleToXuluObject(
+        sg,
+        edu.bonn.xulu.plugin.io.IOUtil.getStyleFromXuluObject( (SingleGrid) sample )
+      );
+    return sg;
+  }
+
+  /**
+   * Erzeugt eine neue Instanz von {@link SingleGrid}. Fuer den Inhalt des
+   * Grids wird die von der Methode {@link #getWritableGridFactory()} gelieferte
+   * Factory herangezogen.
+   * @param dialog gibt an, ob die Factory einen Dialog mit dem Anwender
+   *               fuehren darf, um die Instanz zu initialisieren (bei
+   *               <code>false</code> wird eine Standard-Instanz erzeugt)
+   */
+  public SingleGrid newInstance(boolean dialog) throws Exception {
+    InstantiationFactory fac = getWritableGridFactory();
+    if ( !WritableGrid.class.isAssignableFrom(fac.getInstanceType()) )
+      throw new UnsupportedOperationException(getClass().getSimpleName().concat(".getWritableGridFactory() must provide a factory that creates a WritableGrid!"));
+
+    return new SingleGrid( (WritableGrid)fac.newInstance(dialog) );
+  }
+
+  /**
+   * Liefert eine {@link InstantiationFactory}, die Instanzen von {@link WritableGrid}
+   * erzeugt. Mit diesen Instanzen wird das SingleGrid gefuellt.<br>
+   * Standardmaessig wird eine Instanz von {@link WritableGridRasterFactory}
+   * zurueckgegeben. Sub-Klassen koennen diese Methode ueberschreiben, um
+   * andere Arten von WritableGrid zu erzeugen.
+   */
+  protected InstantiationFactory getWritableGridFactory() {
+    return new WritableGridRasterFactory();
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/awt/SingleGridFactory_ArcInfoAsciiGrid.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/awt/SingleGridFactory_ArcInfoAsciiGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/awt/SingleGridFactory_ArcInfoAsciiGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,148 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.awt;
+
+import java.io.File;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.WritableGridRaster;
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.geotools.io.GeoImportUtil;
+import schmitzm.geotools.io.GeoExportUtil;
+
+import skrueger.geotools.StyledMapUtil;
+
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+import edu.bonn.xulu.plugin.io.IOUtil;
+
+// fuer Doku
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link SingleGrid} aus/in das ArcInfo-ASCII-Grid-Format.
+ * Beim Import liefert die Factory ein auf Java-AWT basierendes Raster
+ * ({@link WritableGridRaster}).
+ * Entsprechend koennen beim Export nur {@link SingleGrid SingleGrids}
+ * verarbeitet werden, die eine {@link WritableGridRaster}-Instanz in ihrere
+ * Raster-Property besitzen.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class SingleGridFactory_ArcInfoAsciiGrid extends AbstractFactory implements ImportFactory, ExportFactory {
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link SingleGrid SingleGrid.class}
+   */
+  public Class getImportType() {
+    return SingleGrid.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getImportSourceType() {
+    return File.class;
+  }
+
+  /**
+   * Importiert eine Instanz von {@link SingleGrid} aus einer Datei im
+   * ArcInfoAsciiGrid-Format.
+   * @param input Eingabe-Quelle (muss ein {@link File} sein!)
+   * @param reg   Instanz der Xulu-Registry, ueber die eine Factory ermittelt
+   *              wird, die eine Standard-Instanz von {@link SingleGrid} erzeugt, in
+   *              die das Raster importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Datei angegeben wird
+   * @see GeoImportUtil#readGridRasterFromArcInfoASCII(File,CoordinateReferenceSystem)
+   */
+  public SingleGrid importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+    // Aus Registry die passende Factory fuer SingleGrid suchen
+    InstantiationFactory instFac = AbstractFactory.getInstantiationFactoryFromRegistry(reg,getImportType(),true);
+    // Raster importieren
+    WritableGrid gc = GeoImportUtil.readGridRasterFromArcInfoASCII((File)input);
+    // Raster in ein SingleGrid einfuegen
+    SingleGrid sg = (SingleGrid)instFac.newInstance(false);
+    sg.setGrid(gc);
+
+    // Style importieren und falls vorhanden in Property einfuegen
+    edu.bonn.xulu.plugin.io.IOUtil.importRasterStyle( sg, ((File)input).toURI().toURL() );
+
+    // Dateinamen in die Bezeichnung aufnehmen
+    sg.setDescription(sg.getDescription().concat(" [").concat(((File)input).getName()).concat("]"));
+    return sg;
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um ein {@link SingleGrid} handelt, das ein
+   * {@link WritableGridRaster} in seiner Raster-Eigenschaft besitzt.
+   */
+  public boolean isExportable(Object obj) {
+    return obj!=null &&
+           obj instanceof SingleGrid &&
+           ((SingleGrid)obj).getGrid() instanceof WritableGridRaster;
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link SingleGrid} (oder eine Unterklasse)
+   * handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return SingleGrid.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getExportDestinationType() {
+    return File.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link SingleGrid} in eine ArcInfoAsciiGrid-Datei.
+   * @param grid zu exportiertendes Raster (muss ein {@link SingleGrid} sein
+   * @param output Export-Ziel (muss ein {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel keine
+   *            Datei angegeben wird
+   * @exception IllegalArgumentException falls es sich bei dem angegeben Raster
+   *            nicht um ein {@link SingleGrid} handelt
+   * @see GeoExportUtil#writeGridRasterToArcInfoASCII(WritableGridRaster,File)
+   */
+  public void exportObject(Object grid, Object output) throws Exception {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(grid) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(grid.getClass().getName()));
+    SingleGrid sg = (SingleGrid)grid;
+    GeoExportUtil.writeGridRasterToArcInfoASCII( (WritableGridRaster)sg.getGrid(),(File)output );
+    IOUtil.exportStyle( sg, ((File)output).toURI().toURL() );
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/awt/SingleGridFactory_GeoTiff.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/awt/SingleGridFactory_GeoTiff.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/awt/SingleGridFactory_GeoTiff.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,148 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.awt;
+
+import java.io.File;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.WritableGridRaster;
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.geotools.io.GeoImportUtil;
+import schmitzm.geotools.io.GeoExportUtil;
+
+import skrueger.geotools.StyledMapUtil;
+
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+import edu.bonn.xulu.plugin.io.IOUtil;
+
+
+// fuer Doku
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link SingleGrid} aus/in das GeoTiff-Format.
+ * Beim Import liefert die Factory ein auf Java-AWT basierendes Raster
+ * ({@link WritableGridRaster}).
+ * Entsprechend koennen beim Export nur {@link SingleGrid SingleGrids}
+ * verarbeitet werden, die eine {@link WritableGridRaster}-Instanz in ihrere
+ * Raster-Property besitzen.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class SingleGridFactory_GeoTiff extends AbstractFactory implements ImportFactory, ExportFactory {
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link SingleGrid SingleGrid.class}
+   */
+  public Class getImportType() {
+    return SingleGrid.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getImportSourceType() {
+    return File.class;
+  }
+
+  /**
+   * Importiert eine Instanz von {@link SingleGrid} aus einer Datei im
+   * GeoTiff-Format.
+   * @param input Eingabe-Quelle (muss ein {@link File} sein!)
+   * @param reg   Instanz der Xulu-Registry, ueber die eine Factory ermittelt
+   *              wird, die eine Standard-Instanz von {@link SingleGrid} erzeugt, in
+   *              die das Raster importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Datei angegeben wird
+   * @see GeoImportUtil#readGridRasterFromGeoTiff(File,CoordinateReferenceSystem)
+   */
+  public SingleGrid importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+    // Aus Registry die passende Factory fuer SingleGrid suchen
+    InstantiationFactory instFac = AbstractFactory.getInstantiationFactoryFromRegistry(reg,getImportType(),true);
+    // Raster importieren
+//    WritableGridCoverage gc = (WritableGridCoverage)GeoImportUtil.readGridFromGeoTiff((File)input);
+    WritableGrid gc = GeoImportUtil.readGridRasterFromGeoTiff((File)input);
+    // Raster in ein SingleGrid einfuegen
+    SingleGrid sg = (SingleGrid)instFac.newInstance(false);
+    sg.setGrid(gc);
+    // Style importieren und falls vorhanden in Property einfuegen
+    edu.bonn.xulu.plugin.io.IOUtil.importRasterStyle( sg, ((File)input).toURI().toURL() );
+    // Dateinamen in die Bezeichnung aufnehmen
+    sg.setDescription(sg.getDescription().concat(" [").concat(((File)input).getName()).concat("]"));
+    return sg;
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um ein {@link SingleGrid} handelt, das ein
+   * {@link WritableGridRaster} in seiner Raster-Eigenschaft besitzt.
+   */
+  public boolean isExportable(Object obj) {
+    return obj!=null &&
+           obj instanceof SingleGrid &&
+           ((SingleGrid)obj).getGrid() instanceof WritableGridRaster;
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link SingleGrid} (oder eine Unterklasse)
+   * handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return SingleGrid.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getExportDestinationType() {
+    return File.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link SingleGrid} in eine GeoTiff-Datei.
+   * @param grid zu exportiertendes Raster (muss ein {@link SingleGrid} sein
+   * @param output Export-Ziel (muss ein {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel keine
+   *            Datei angegeben wird
+   * @exception IllegalArgumentException falls es sich bei dem angegeben Raster
+   *            nicht um ein {@link SingleGrid} handelt
+   * @see GeoExportUtil#writeGridRasterToGeoTiff(WritableGridRaster,File)
+   */
+  public void exportObject(Object grid, Object output) throws Exception {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(grid) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(grid.getClass().getName()));
+    SingleGrid sg = (SingleGrid)grid;
+    GeoExportUtil.writeGridRasterToGeoTiff( (WritableGridRaster)sg.getGrid(),(File)output );
+    IOUtil.exportStyle( sg, ((File)output).toURI().toURL() );
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/awt/WritableGridRasterFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/awt/WritableGridRasterFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/awt/WritableGridRasterFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,63 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.awt;
+
+import java.awt.geom.Rectangle2D;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.WritableGridRaster;
+import edu.bonn.xulu.plugin.io.grid.WritableGridFactory;
+
+// nur fuer Doku
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+
+/**
+ * Diese Factory erzeugt Standard-Instanzen des Datentyps {@link WritableGridRaster}.<br>
+ * <b>Bemerke:</b><br>
+ * Diese stellen <b>keine</b> {@linkplain XuluObject Xulu-Objekte} dar, koennen also
+ * nicht direkt im Xulu-Datenpool gespeichert werden. Hierzu ist der Datentyp
+ * {@link SingleGrid} (bzw. eine entsprechende Factory) zu verwenden!
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class WritableGridRasterFactory extends WritableGridFactory {
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link WritableGridRaster WritableGridRaster.class}
+   */
+  public Class getInstanceType() {
+    return WritableGridRaster.class;
+  }
+
+  /**
+   * Erzeugt ein neues Grid.
+   * @param type    Datentyp der gespeicherten Objekte
+   * @param widthc  Breite in Zellen
+   * @param heightc Hoehe in Zellen
+   * @param minX    Index der ersten Zelle in X-Richtung (<b>wird nicht verwendet! immer 0!</b>)
+   * @param minY    Index der ersten Zelle in Y-Richtung (<b>wird nicht verwendet! immer 0!</b>).
+   * @param x       Georeferenz Longitute (Westliche/Linke Kante)
+   * @param y       Georeferenz Latitude (Suedliche/Untere Kante)
+   * @param width   Breite
+   * @param height  Hoehe
+   * @param crs     Referenzsystem fuer das Raster
+   */
+  public WritableGridRaster newInstance(int type, int widthc, int heightc, int minX, int minY, double x, double y, double width, double height, CoordinateReferenceSystem crs) {
+    // Envelope erzeugen
+    Rectangle2D e = new Rectangle2D.Double(x,y,width,height);
+    // Grid erzeugen
+    return new WritableGridRaster(type,0,0,widthc,heightc,e,crs);
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/awt/WritableGridRasterFactory_ArcInfoAsciiGrid.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/awt/WritableGridRasterFactory_ArcInfoAsciiGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/awt/WritableGridRasterFactory_ArcInfoAsciiGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,122 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.awt;
+
+import java.io.File;
+
+import schmitzm.data.WritableGridRaster;
+
+import schmitzm.geotools.io.GeoImportUtil;
+import schmitzm.geotools.io.GeoExportUtil;
+
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+// nur fuer Doku
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link WritableGridRaster} aus/in das ArcInfo-ASCII-Grid-Format.<br>
+ * <b>Bemerke:</b><br>
+ * Die erzeugten Instanzen stellen <b>keine</b> {@linkplain XuluObject Xulu-Objekte} dar,
+ * koennen also nicht direkt im Xulu-Datenpool gespeichert werden. Hierzu ist der Datentyp
+ * {@link SingleGrid} (bzw. eine entsprechende Factory) zu verwenden!
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class WritableGridRasterFactory_ArcInfoAsciiGrid extends AbstractFactory implements ImportFactory, ExportFactory {
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link WritableGridRaster WritableGridRaster.class}
+   */
+  public Class getImportType() {
+    return WritableGridRaster.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getImportSourceType() {
+    return File.class;
+  }
+
+  /**
+   * Importiert eine Instanz von {@link WritableGridRaster} aus einer Datei.
+   * @param input Eingabe-Quelle (muss ein {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle kein
+   *            File angegeben wird
+   * @param reg wird nicht beruecksichtigt, da immer Instanzen von
+   *            {@link WritableGridRaster} verwendet werden!
+   * @see GeoImportUtil#readGridRasterFromArcInfoASCII(File,CoordinateReferenceSystem)
+   */
+  public WritableGridRaster importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+    return GeoImportUtil.readGridRasterFromArcInfoASCII((File)input);
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um ein {@link WritableGridRaster} handelt.
+   * @param obj zu pruefendes Objekt
+   */
+  public boolean isExportable(Object obj) {
+    return obj!=null & obj instanceof WritableGridRaster;
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link WritableGridRaster} (oder eine Unterklasse)
+   * handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return WritableGridRaster.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getExportDestinationType() {
+    return File.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link WritableGridRaster} in eine Datei.
+   * @param grid zu exportiertendes Raster (muss ein {@link WritableGridRaster} sein
+   * @param output Export-Ziel (muss ein {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel kein
+   *            File angegeben wird
+   * @exception IllegalArgumentException falls es sich bei dem angegeben Raster
+   *            nicht um ein {@link WritableGridRaster} handelt
+   * @see GeoExportUtil#writeGridRasterToArcInfoASCII(WritableGridRaster,File)
+   */
+  public void exportObject(Object grid, Object output) throws Exception {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(grid) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(grid.getClass().getName()));
+    GeoExportUtil.writeGridRasterToArcInfoASCII((WritableGridRaster)grid,(File)output);
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/awt/WritableGridRasterFactory_GeoTiff.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/awt/WritableGridRasterFactory_GeoTiff.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/awt/WritableGridRasterFactory_GeoTiff.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,123 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.awt;
+
+import java.io.File;
+
+import schmitzm.data.WritableGridRaster;
+
+import schmitzm.geotools.io.GeoImportUtil;
+import schmitzm.geotools.io.GeoExportUtil;
+
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+// nur fuer Doku
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link WritableGridRaster} aus/in das GeoTiff-Format.<br>
+ * <b>Bemerke:</b><br>
+ * Die erzeugten Instanzen stellen <b>keine</b> {@linkplain XuluObject Xulu-Objekte} dar,
+ * koennen also nicht direkt im Xulu-Datenpool gespeichert werden. Hierzu ist der Datentyp
+ * {@link SingleGrid} (bzw. eine entsprechende Factory) zu verwenden!
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class WritableGridRasterFactory_GeoTiff extends AbstractFactory implements ImportFactory, ExportFactory {
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link WritableGridRaster WritableGridRaster.class}
+   */
+  public Class getImportType() {
+    return WritableGridRaster.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getImportSourceType() {
+    return File.class;
+  }
+
+  /**
+   * Importiert eine Instanz von {@link WritableGridRaster} aus einer
+   * Datei.
+   * @param input Eingabe-Quelle (muss ein {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Datei angegeben wird
+   * @param reg wird nicht beruecksichtigt, da immer Instanzen von
+   *            {@link WritableGridRaster} verwendet werden!
+   * @see GeoImportUtil#readGridRasterFromGeoTiff(File,CoordinateReferenceSystem)
+   */
+  public WritableGridRaster importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+    return (WritableGridRaster)GeoImportUtil.readGridRasterFromGeoTiff((File)input);
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um ein {@link WritableGridRaster} handelt.
+   * @param obj zu pruefendes Objekt
+   */
+  public boolean isExportable(Object obj) {
+    return obj!=null & obj instanceof WritableGridRaster;
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link WritableGridRaster} (oder eine Unterklasse)
+   * handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return WritableGridRaster.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getExportDestinationType() {
+    return File.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link WritableGridRaster} in eine Datei.
+   * @param grid zu exportiertendes Raster (muss ein {@link WritableGridRaster} sein
+   * @param output Export-Ziel (muss ein {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel keine
+   *            Datei angegeben wird
+   * @exception IllegalArgumentException falls es sich bei dem angegeben Raster
+   *            nicht um ein {@link WritableGridRaster} handelt
+   * @see GeoExportUtil#writeGridRasterToGeoTiff(WritableGridRaster,File)
+   */
+  public void exportObject(Object grid, Object output) throws Exception {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(grid) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(grid.getClass().getName()));
+    GeoExportUtil.writeGridRasterToGeoTiff((WritableGridRaster)grid,(File)output);
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/awt/package.html
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/awt/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/awt/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,6 @@
+<html>
+<body>
+	Die Instanziierungs- und Im/Export-Factorys in diesem Paket basieren auf reinem
+	<a href="http://java.sun.com" target=_blank>Standard-Java</a>.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/gt/GridCoverageFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/gt/GridCoverageFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/gt/GridCoverageFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,63 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.gt;
+
+import java.awt.geom.Rectangle2D;
+import org.geotools.geometry.Envelope2D;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.geotools.grid.WritableGridCoverage;
+import edu.bonn.xulu.plugin.io.grid.WritableGridFactory;
+// nur fuer Doku
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+
+/**
+ * Diese Factory erzeugt Standard-Instanzen des Datentyps {@link WritableGridCoverage}.<br>
+ * <b>Bemerke:</b><br>
+ * Diese stellen <b>keine</b> {@linkplain XuluObject Xulu-Objekte} dar, koennen also
+ * nicht direkt im Xulu-Datenpool gespeichert werden. Hierzu ist der Datentyp
+ * {@link SingleGrid} (bzw. eine entsprechende Factory) zu verwenden!
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class GridCoverageFactory extends WritableGridFactory {
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link WritableGridCoverage WritableGridCoverage.class}
+   */
+  public Class getInstanceType() {
+    return WritableGridCoverage.class;
+  }
+
+  /**
+   * Erzeugt ein neues Grid.
+   * @param type    Datentyp der gespeicherten Objekte
+   * @param widthc  Breite in Zellen
+   * @param heightc Hoehe in Zellen
+   * @param minX    Index der ersten Zelle in X-Richtung (<b>wird nicht verwendet! immer 0!</b>)
+   * @param minY    Index der ersten Zelle in Y-Richtung (<b>wird nicht verwendet! immer 0!</b>).
+   * @param x       Georeferenz Longitute (Westliche/Linke Kante)
+   * @param y       Georeferenz Latitude (Suedliche/Untere Kante)
+   * @param width   Breite
+   * @param height  Hoehe
+   * @param crs     Referenzsystem fuer das Raster
+   */
+  public WritableGridCoverage newInstance(int type, int widthc, int heightc, int minX, int minY, double x, double y, double width, double height, CoordinateReferenceSystem crs) {
+    // Envelope erzeugen
+    Envelope2D e = new Envelope2D(crs,new Rectangle2D.Double(x,y,width,height));
+    // Grid erzeugen
+    return WritableGridCoverage.create("",type,widthc,heightc,e);
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/gt/GridCoverageFactory_ArcInfoAsciiGrid.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/gt/GridCoverageFactory_ArcInfoAsciiGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/gt/GridCoverageFactory_ArcInfoAsciiGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,123 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.gt;
+
+import java.io.File;
+
+import org.geotools.coverage.grid.GridCoverage2D;
+
+import schmitzm.geotools.grid.WritableGridCoverage;
+import schmitzm.geotools.io.GeoImportUtil;
+import schmitzm.geotools.io.GeoExportUtil;
+
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+// nur fuer Doku
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link WritableGridCoverage} aus/in das ArcInfo-ASCII-Grid-Format.<br>
+ * <b>Bemerke:</b><br>
+ * Die erzeugten Instanzen stellen <b>keine</b> {@linkplain XuluObject Xulu-Objekte} dar,
+ * koennen also nicht direkt im Xulu-Datenpool gespeichert werden. Hierzu ist der Datentyp
+ * {@link SingleGrid} (bzw. eine entsprechende Factory) zu verwenden!
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class GridCoverageFactory_ArcInfoAsciiGrid extends AbstractFactory implements ImportFactory, ExportFactory {
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link WritableGridCoverage WritableGridCoverage.class}
+   */
+  public Class getImportType() {
+    return WritableGridCoverage.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getImportSourceType() {
+    return File.class;
+  }
+
+  /**
+   * Importiert eine Instanz von {@link WritableGridCoverage} aus einer Datei.
+   * @param input Eingabe-Quelle (muss ein {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle kein
+   *            File angegeben wird
+   * @param reg wird nicht beruecksichtigt, da immer Instanzen von
+   *            {@link WritableGridCoverage} verwendet werden!
+   * @see GeoImportUtil#readGridFromArcInfoASCII(File,CoordinateReferenceSystem)
+   */
+  public WritableGridCoverage importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+    return WritableGridCoverage.create( GeoImportUtil.readGridFromArcInfoASCII((File)input), 0 );
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um ein {@link GridCoverage2D} handelt.
+   * @param obj zu pruefendes Objekt
+   */
+  public boolean isExportable(Object obj) {
+    return obj!=null & obj instanceof GridCoverage2D;
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link GridCoverage2D} (oder eine Unterklasse)
+   * handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return GridCoverage2D.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getExportDestinationType() {
+    return File.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link GridCoverage2D} in eine Datei.
+   * @param grid zu exportiertendes Raster (muss ein {@link GridCoverage2D} sein
+   * @param output Export-Ziel (muss ein {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel kein
+   *            File angegeben wird
+   * @exception IllegalArgumentException falls es sich bei dem angegeben Raster
+   *            nicht um ein {@link GridCoverage2D} handelt
+   * @see GeoExportUtil#writeGridToArcInfoASCII(GridCoverage2D,File)
+   */
+  public void exportObject(Object grid, Object output) throws Exception {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(grid) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(grid.getClass().getName()));
+    GeoExportUtil.writeGridToArcInfoASCII((GridCoverage2D)grid,(File)output);
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/gt/GridCoverageFactory_GeoTiff.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/gt/GridCoverageFactory_GeoTiff.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/gt/GridCoverageFactory_GeoTiff.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,124 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.gt;
+
+import java.io.File;
+
+import org.geotools.coverage.grid.GridCoverage2D;
+
+import schmitzm.geotools.grid.WritableGridCoverage;
+import schmitzm.geotools.io.GeoImportUtil;
+import schmitzm.geotools.io.GeoExportUtil;
+
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+// nur fuer Doku
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link WritableGridCoverage} aus/in das GeoTiff-Format.<br>
+ * <b>Bemerke:</b><br>
+ * Die erzeugten Instanzen stellen <b>keine</b> {@linkplain XuluObject Xulu-Objekte} dar,
+ * koennen also nicht direkt im Xulu-Datenpool gespeichert werden. Hierzu ist der Datentyp
+ * {@link SingleGrid} (bzw. eine entsprechende Factory) zu verwenden!
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class GridCoverageFactory_GeoTiff extends AbstractFactory implements ImportFactory, ExportFactory {
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link WritableGridCoverage WritableGridCoverage.class}
+   */
+  public Class getImportType() {
+    return WritableGridCoverage.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getImportSourceType() {
+    return File.class;
+  }
+
+  /**
+   * Importiert eine Instanz von {@link WritableGridCoverage} aus einer
+   * Datei.
+   * @param input Eingabe-Quelle (muss ein {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Datei angegeben wird
+   * @param reg wird nicht beruecksichtigt, da immer Instanzen von
+   *            {@link WritableGridCoverage} verwendet werden!
+   * @see GeoImportUtil#readGridFromGeoTiff(File,CoordinateReferenceSystem)
+   */
+  public WritableGridCoverage importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+    return (WritableGridCoverage)GeoImportUtil.readGridFromGeoTiff((File)input);
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um ein {@link GridCoverage2D} handelt.
+   * @param obj zu pruefendes Objekt
+   */
+  public boolean isExportable(Object obj) {
+    return obj!=null & obj instanceof GridCoverage2D;
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link GridCoverage2D} (oder eine Unterklasse)
+   * handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return GridCoverage2D.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getExportDestinationType() {
+    return File.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link GridCoverage2D} in eine Datei.
+   * @param grid zu exportiertendes Raster (muss ein {@link GridCoverage2D} sein
+   * @param output Export-Ziel (muss ein {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel keine
+   *            Datei angegeben wird
+   * @exception IllegalArgumentException falls es sich bei dem angegeben Raster
+   *            nicht um ein {@link GridCoverage2D} handelt
+   * @see GeoExportUtil#writeGridToGeoTiff(GridCoverage2D,File)
+   */
+  public void exportObject(Object grid, Object output) throws Exception {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(grid) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(grid.getClass().getName()));
+    GeoExportUtil.writeGridToGeoTiff((GridCoverage2D)grid,(File)output);
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/gt/GridListFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/gt/GridListFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/gt/GridListFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,36 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.gt;
+
+import edu.bonn.xulu.io.InstantiationFactory;
+
+// nur fuer Doku
+import schmitzm.data.WritableGrid;
+import edu.bonn.xulu.plugin.data.grid.GridList;
+
+/**
+ * Diese Factory erzeugt Standard-Instanzen von {@link GridList} mit
+ * durch die Factory {@link GridCoverageFactory} erzeugten (auf GeoTools
+ * basierenden) {@link WritableGrid}-Instanzen als Inhalt.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class GridListFactory extends edu.bonn.xulu.plugin.io.grid.awt.GridListFactory {
+  /**
+   * Liefert eine Instanz von {@link GridCoverageFactory}, die auf GeoTools
+   * basierende Instanzen von {@link WritableGrid} erzeugt. Mit diesen
+   * Instanzen wird die GridList gefuellt.
+   */
+  protected InstantiationFactory getWritableGridFactory() {
+    return new GridCoverageFactory();
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/gt/GridListFactory_ArcInfoAsciiGrid.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/gt/GridListFactory_ArcInfoAsciiGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/gt/GridListFactory_ArcInfoAsciiGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,173 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.gt;
+
+import java.io.File;
+
+import org.geotools.coverage.grid.GridCoverage2D;
+
+import schmitzm.geotools.io.GeoImportUtil;
+import schmitzm.geotools.io.GeoExportUtil;
+import schmitzm.geotools.grid.WritableGridCoverage;
+
+import schmitzm.io.IOUtil;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyReadAccess;
+
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+import edu.bonn.xulu.plugin.data.grid.GridList;
+
+// fuer Doku
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import skrueger.geotools.StyledMapUtil;
+import schmitzm.data.property.ScalarProperty;
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link GridList} aus/in Dateien im ArcInfo-ASCII-Grid-Format.
+ * Beim Import liefert die Factory eine auf GeoTools basierendes Raster-Liste
+ * ({@link GridCoverage2D}).
+ * Entsprechend koennen beim Export nur {@link GridList GridLists}
+ * verarbeitet werden, die {@link GridCoverage2D}-Instanzen in ihrer
+ * Raster-Property besitzen.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class GridListFactory_ArcInfoAsciiGrid extends AbstractFactory implements ImportFactory, ExportFactory {
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link GridList GridList.class}
+   */
+  public Class getImportType() {
+    return GridList.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File[].class}
+   */
+  public Class getImportSourceType() {
+    return File[].class;
+  }
+
+  /**
+   * Importiert Raster aus Dateien im ArcInfoAsciiGrid-Format
+   * und fuegt diese in einer {@link GridList} zusammen.
+   * @param input Eingabe-Quelle (muss ein {@link File File[]} sein!)
+   * @param reg   Instanz der Xulu-Registry, ueber die eine Factory ermittelt
+   *              wird, die eine Standard-Instanz von {@link GridList} erzeugt, in
+   *              die das Objekt importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Dateien angegeben werden
+   * @see GeoImportUtil#readGridFromArcInfoASCII(File,CoordinateReferenceSystem)
+   */
+  public GridList importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+    InstantiationFactory instFac = AbstractFactory.getInstantiationFactoryFromRegistry(reg,getImportType(),true);
+    GridList gl    = (GridList)instFac.newInstance(false);
+    // Raster importieren und in GridList einfuegen
+    for (int i=0; i<((Object[])input).length; i++) {
+      gl.addGrid(
+        WritableGridCoverage.create( GeoImportUtil.readGridFromArcInfoASCII(((File[])input)[i]), 0 )
+      );
+      // Style vom ersten Raster uebernehmen
+      if ( edu.bonn.xulu.plugin.io.IOUtil.getStyleFromXuluObject( gl ) == null )
+        edu.bonn.xulu.plugin.io.IOUtil.importRasterStyle( gl, ((File[])input)[i].toURI().toURL() );
+    }
+    return gl;
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um eine {@link GridList} handelt, die nur Instanzen
+   * von {@link GridCoverage2D} als Elemente enthaelt.
+   * @param obj zu pruefendes Objekt
+   */
+  public boolean isExportable(Object obj) {
+    if ( obj==null || !(obj instanceof GridList) )
+      return false;
+    GridList list = (GridList)obj;
+    for (int i=0; i<list.getGridCount(); i++)
+      if ( !(list.getGrid(i) instanceof GridCoverage2D) )
+        return false;
+    return true;
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link GridList} (oder eine Unterklasse)
+   * handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return GridList.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt. Dabei handelt es sich um eine <b>einzelne Datei</b>, da
+   * die die letztendlichen Export-Dateien automatisch durchnummeriert werden!!
+   * @return immer {@link File File.class}
+   */
+  public Class getExportDestinationType() {
+    return File.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link GridList} in Dateien des
+   * ArcInfoAsciiGrid-Formats.<br>
+   * <b>Beachte:</b><br>
+   * Als Ausgabe-Objekt ist eine <b>einzelne</b> Datei anzugeben, kein
+   * Array! Die Dateien werden ausgehend von dem angegebenen Dateinamen
+   * durchnummeriert!!
+   * @param object zu exportiertende Raster (muss eine {@link GridList} sein
+   * @param output Export-Ziel (muss ein einzelner {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel keine
+   *            einzelne Datei angegeben wird
+   * @exception IllegalArgumentException falls es sich bei dem angegeben Objekt
+   *            nicht um eine {@link GridList} handelt
+   * @see GeoExportUtil#writeGridToArcInfoASCII(GridCoverage2D,File)
+   */
+  public void exportObject(Object object, Object output) throws Exception {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(object) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(object.getClass().getName()));
+
+    // Dateinamen-Teile ermitteln
+    String fileName = IOUtil.getBaseFileName((File)output);
+    String fileExt  = IOUtil.getFileExt((File)output);
+
+    // Grids in der Liste einzeln exportieren
+    GridList               gl         = (GridList)object;
+    ListPropertyReadAccess listAccess = ((ListProperty)gl.getProperty(GridList.PROP_GRIDS)).getReadAccess(this);
+    for (int i=0; i<listAccess.getCount(); i++) {
+      File outFile = new File( fileName.concat("_"+i).concat(fileExt) );
+      GeoExportUtil.writeGridToArcInfoASCII( (GridCoverage2D)listAccess.getValue(i),outFile );
+      // Style exportieren
+      edu.bonn.xulu.plugin.io.IOUtil.exportStyle(gl, outFile.toURI().toURL() );
+    }
+    listAccess.release();
+
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/gt/MultiGridFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/gt/MultiGridFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/gt/MultiGridFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,36 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.gt;
+
+import edu.bonn.xulu.plugin.io.grid.WritableGridFactory;
+// nur fuer Doku
+import schmitzm.data.WritableGrid;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+
+/**
+ * Diese Factory erzeugt Standard-Instanzen von {@link MultiGrid} mit
+ * durch die Factory {@link GridCoverageFactory} erzeugten (auf GeoTools
+ * basierenden) {@link WritableGrid}-Instanzen als Inhalt.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class MultiGridFactory extends edu.bonn.xulu.plugin.io.grid.awt.MultiGridFactory {
+  /**
+   * Liefert eine Instanz von {@link GridCoverageFactory}, die auf GeoTools
+   * basierende Instanzen von {@link WritableGrid} erzeugt. Mit diesen
+   * Instanzen wird die GridList gefuellt.
+   */
+  protected WritableGridFactory getWritableGridFactory() {
+    return new GridCoverageFactory();
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/gt/MultiGridFactory_ArcInfoAsciiGrid.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/gt/MultiGridFactory_ArcInfoAsciiGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/gt/MultiGridFactory_ArcInfoAsciiGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,96 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.gt;
+
+import java.io.File;
+
+import schmitzm.geotools.io.GeoImportUtil;
+import schmitzm.geotools.grid.WritableGridCoverage;
+import schmitzm.data.WritableGrid;
+
+import edu.bonn.xulu.appl.XuluRegistry;
+import edu.bonn.xulu.io.AbstractFactory;
+
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+import edu.bonn.xulu.plugin.data.grid.GridList;
+import edu.bonn.xulu.plugin.io.grid.WritableGridFactory;
+import edu.bonn.xulu.plugin.io.grid.gt.GridListFactory_ArcInfoAsciiGrid;
+
+// nur fuer Doku
+import org.geotools.coverage.grid.GridCoverage2D;
+import edu.bonn.xulu.io.InstantiationFactory;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link MultiGrid} aus/in Dateien im ArcInfo-ASCII-Grid-Format.
+ * Beim Import liefert die Factory eine auf GeoTools basierendes Raster-Liste
+ * ({@link GridCoverage2D}).
+ * Entsprechend koennen beim Export nur {@link MultiGrid MultiGrids}
+ * verarbeitet werden, die {@link GridCoverage2D}-Instanzen in ihrer
+ * Raster-Property besitzen.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class MultiGridFactory_ArcInfoAsciiGrid extends GridListFactory_ArcInfoAsciiGrid {
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link MultiGrid MultiGrid.class}
+   */
+  public Class getImportType() {
+    return MultiGrid.class;
+  }
+
+  /**
+   * Importiert Raster aus Dateien im ArcInfoAsciiGrid-Format
+   * und fuegt diese in einem {@link MultiGrid} zusammen.
+   * @param input Eingabe-Quelle (muss ein {@link File File[]} sein!)
+   * @param reg   Instanz der Xulu-Registry, ueber die eine Factory ermittelt
+   *              wird, die eine Standard-Instanz von {@link MultiGrid} erzeugt, in
+   *              die das Objekt importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Dateien angegeben werden
+   * @see GeoImportUtil#readGridFromArcInfoASCII(File,CoordinateReferenceSystem)
+   */
+  public MultiGrid importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+
+    // MultiGrid erst erzeugen, wenn ein Beispiel-Raster vorliegt
+    MultiGrid mg    = null;
+    // Raster importieren und in GridList einfuegen
+    for (int i=0; i<((Object[])input).length; i++) {
+      WritableGrid grid = WritableGridCoverage.create( GeoImportUtil.readGridFromArcInfoASCII(((File[])input)[i]), 0);
+      // das erste Grid dient dem MultiGrid als Vorlage
+      if ( mg == null )
+        mg = new MultiGrid(grid,getWritableGridFactory());
+      mg.addGrid(grid);
+      // Style vom ersten Raster uebernehmen
+      if ( edu.bonn.xulu.plugin.io.IOUtil.getStyleFromXuluObject( mg ) == null )
+        edu.bonn.xulu.plugin.io.IOUtil.importRasterStyle( mg, ((File[])input)[i].toURI().toURL() );
+    }
+
+   return mg;
+  }
+
+  /**
+   * Liefert eine Instanz von {@link GridCoverageFactory}, die auf GeoTools
+   * basierende Instanzen von {@link WritableGrid} erzeugt. Mit diesen
+   * Instanzen wird das SingleGrid gefuellt.
+   */
+  protected WritableGridFactory getWritableGridFactory() {
+    return new GridCoverageFactory();
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/gt/SingleGridFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/gt/SingleGridFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/gt/SingleGridFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,37 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.gt;
+
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.plugin.io.grid.gt.GridCoverageFactory;
+// nur fuer Doku
+import schmitzm.data.WritableGrid;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+
+/**
+ * Diese Factory erzeugt Standard-Instanzen von {@link SingleGrid} mit einem
+ * durch die Factory {@link GridCoverageFactory} erzeugten (auf GeoTools basierenden)
+ * {@link WritableGrid}.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class SingleGridFactory extends edu.bonn.xulu.plugin.io.grid.awt.SingleGridFactory {
+
+  /**
+   * Liefert eine Instanz von {@link GridCoverageFactory}, die auf GeoTools
+   * basierende Instanzen von {@link WritableGrid} erzeugt. Mit diesen
+   * Instanzen wird das SingleGrid gefuellt.
+   */
+  protected InstantiationFactory getWritableGridFactory() {
+    return new GridCoverageFactory();
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/gt/SingleGridFactory_ArcInfoAsciiGrid.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/gt/SingleGridFactory_ArcInfoAsciiGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/gt/SingleGridFactory_ArcInfoAsciiGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,147 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.gt;
+
+import java.io.File;
+
+import org.geotools.coverage.grid.GridCoverage2D;
+
+import schmitzm.geotools.grid.WritableGridCoverage;
+import schmitzm.geotools.io.GeoImportUtil;
+import schmitzm.geotools.io.GeoExportUtil;
+import schmitzm.data.property.ScalarProperty;
+
+import skrueger.geotools.StyledMapUtil;
+
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.appl.XuluRegistry;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+import edu.bonn.xulu.plugin.io.IOUtil;
+
+// fuer Doku
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link SingleGrid} aus/in das ArcInfo-ASCII-Grid-Format.
+ * Beim Import liefert die Factory ein auf GeoTools basierendes Raster
+ * ({@link GridCoverage2D}).
+ * Entsprechend koennen beim Export nur {@link SingleGrid SingleGrids}
+ * verarbeitet werden, die eine {@link GridCoverage2D}-Instanz in ihrere
+ * Raster-Property besitzen.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class SingleGridFactory_ArcInfoAsciiGrid extends AbstractFactory implements ImportFactory, ExportFactory {
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link SingleGrid SingleGrid.class}
+   */
+  public Class getImportType() {
+    return SingleGrid.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getImportSourceType() {
+    return File.class;
+  }
+
+  /**
+   * Importiert eine Instanz von {@link SingleGrid} aus einer Datei im
+   * ArcInfoAsciiGrid-Format.
+   * @param input Eingabe-Quelle (muss ein {@link File} sein!)
+   * @param reg   Instanz der Xulu-Registry, ueber die eine Factory ermittelt
+   *              wird, die eine Standard-Instanz von {@link SingleGrid} erzeugt, in
+   *              die das Raster importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Datei angegeben wird
+   * @see GeoImportUtil#readGridFromArcInfoASCII(File,CoordinateReferenceSystem)
+   */
+  public SingleGrid importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+    // Aus Registry die passende Factory fuer SingleGrid suchen
+    InstantiationFactory instFac = AbstractFactory.getInstantiationFactoryFromRegistry(reg,getImportType(),true);
+    // Raster importieren
+    WritableGridCoverage gc = WritableGridCoverage.create( GeoImportUtil.readGridFromArcInfoASCII((File)input), 0 );
+    // Raster in ein SingleGrid einfuegen
+    SingleGrid sg = (SingleGrid)instFac.newInstance(false);
+    sg.setGrid(gc);
+    // Style importieren und falls vorhanden in Property einfuegen
+    edu.bonn.xulu.plugin.io.IOUtil.importRasterStyle( sg, ((File)input).toURI().toURL() );
+    // Dateinamen in die Bezeichnung aufnehmen
+    sg.setDescription(sg.getDescription().concat(" [").concat(((File)input).getName()).concat("]"));
+    return sg;
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um ein {@link SingleGrid} handelt, das ein
+   * {@link GridCoverage2D} in seiner Raster-Eigenschaft besitzt.
+   * @param obj zu pruefendes Objekt
+   */
+  public boolean isExportable(Object obj) {
+    return obj!=null &&
+           obj instanceof SingleGrid &&
+           ((SingleGrid)obj).getGrid() instanceof GridCoverage2D;
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link SingleGrid} (oder eine Unterklasse)
+   * handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return SingleGrid.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getExportDestinationType() {
+    return File.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link SingleGrid} in eine ArcInfoAsciiGrid-Datei.
+   * @param grid zu exportiertendes Raster (muss ein {@link SingleGrid} sein
+   * @param output Export-Ziel (muss ein {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel keine
+   *            Datei angegeben wird
+   * @exception IllegalArgumentException falls es sich bei dem angegeben Raster
+   *            nicht um ein {@link SingleGrid} handelt
+   * @see GeoExportUtil#writeGridToArcInfoASCII(GridCoverage2D,File)
+   */
+  public void exportObject(Object grid, Object output) throws Exception {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(grid) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(grid.getClass().getName()));
+    SingleGrid sg = (SingleGrid)grid;
+    GeoExportUtil.writeGridToArcInfoASCII( (GridCoverage2D)sg.getGrid(), (File)output );
+    IOUtil.exportStyle( sg, ((File)output).toURI().toURL() );
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/gt/SingleGridFactory_GeoTiff.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/gt/SingleGridFactory_GeoTiff.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/gt/SingleGridFactory_GeoTiff.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,148 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.gt;
+
+import java.io.File;
+
+import org.geotools.coverage.grid.GridCoverage2D;
+
+import schmitzm.geotools.grid.WritableGridCoverage;
+import schmitzm.geotools.io.GeoImportUtil;
+import schmitzm.geotools.io.GeoExportUtil;
+import schmitzm.data.property.ScalarProperty;
+
+import skrueger.geotools.StyledMapUtil;
+
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+import edu.bonn.xulu.plugin.io.IOUtil;
+
+// fuer Doku
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link SingleGrid} aus/in das GeoTiff-Format.
+ * Beim Import liefert die Factory ein auf GeoTools basierendes Raster
+ * ({@link GridCoverage2D}).
+ * Entsprechend koennen beim Export nur {@link SingleGrid SingleGrids}
+ * verarbeitet werden, die eine {@link GridCoverage2D}-Instanz in ihrere
+ * Raster-Property besitzen.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class SingleGridFactory_GeoTiff extends AbstractFactory implements ImportFactory, ExportFactory {
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link SingleGrid SingleGrid.class}
+   */
+  public Class getImportType() {
+    return SingleGrid.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getImportSourceType() {
+    return File.class;
+  }
+
+  /**
+   * Importiert eine Instanz von {@link SingleGrid} aus einer Datei im
+   * GeoTiff-Format.
+   * @param input Eingabe-Quelle (muss ein {@link File} sein!)
+   * @param reg   Instanz der Xulu-Registry, ueber die eine Factory ermittelt
+   *              wird, die eine Standard-Instanz von {@link SingleGrid} erzeugt, in
+   *              die das Raster importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Datei angegeben wird
+   * @see GeoImportUtil#readGridFromGeoTiff(File,CoordinateReferenceSystem)
+   */
+  public SingleGrid importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+    // Aus Registry die passende Factory fuer SingleGrid suchen
+    InstantiationFactory instFac = AbstractFactory.getInstantiationFactoryFromRegistry(reg,getImportType(),true);
+    // Raster importieren
+    WritableGridCoverage gc = WritableGridCoverage.create( GeoImportUtil.readGridFromGeoTiff((File)input), 0);
+    // Raster in ein SingleGrid einfuegen
+    SingleGrid sg = (SingleGrid)instFac.newInstance(false);
+    sg.setGrid(gc);
+    // Style importieren und falls vorhanden in Property einfuegen
+    edu.bonn.xulu.plugin.io.IOUtil.importRasterStyle( sg, ((File)input).toURI().toURL() );
+    // Dateinamen in die Bezeichnung aufnehmen
+    sg.setDescription(sg.getDescription().concat(" [").concat(((File)input).getName()).concat("]"));
+    return sg;
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um ein {@link SingleGrid} handelt, das ein
+   * {@link GridCoverage2D} in seiner Raster-Eigenschaft besitzt.
+   * @param obj zu pruefendes Objekt
+   */
+  public boolean isExportable(Object obj) {
+    return obj!=null &&
+           obj instanceof SingleGrid &&
+           ((SingleGrid)obj).getGrid() instanceof GridCoverage2D;
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link SingleGrid} (oder eine Unterklasse)
+   * handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return SingleGrid.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getExportDestinationType() {
+    return File.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link SingleGrid} in eine GeoTiff-Datei.
+   * @param grid zu exportiertendes Raster (muss ein {@link SingleGrid} sein
+   * @param output Export-Ziel (muss ein {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel keine
+   *            Datei angegeben wird
+   * @exception IllegalArgumentException falls es sich bei dem angegeben Raster
+   *            nicht um ein {@link SingleGrid} handelt
+   * @see GeoExportUtil#writeGridToGeoTiff(GridCoverage2D,File)
+   */
+  public void exportObject(Object grid, Object output) throws Exception {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(grid) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(grid.getClass().getName()));
+    SingleGrid sg = (SingleGrid)grid;
+    GeoExportUtil.writeGridToGeoTiff( (GridCoverage2D)sg.getGrid(),(File)output );
+    IOUtil.exportStyle( sg, ((File)output).toURI().toURL() );
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/gt/package.html
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/gt/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/gt/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,6 @@
+<html>
+<body>
+	Die Instanziierungs- und Im/Export-Factorys in diesem Paket basieren auf der
+	<a href="http://www.geotools.org" target=_blank>GeoTools</a>-Bibliothek.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/GridListFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/GridListFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/GridListFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,40 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.lateloading;
+
+import edu.bonn.xulu.io.InstantiationFactory;
+
+// nur fuer Doku
+import schmitzm.data.WritableGrid;
+import edu.bonn.xulu.plugin.data.grid.GridList;
+
+/**
+ * Diese Factory erzeugt Standard-Instanzen von {@link GridList} mit
+ * durch die Factory {@link WritableGridLLFactory} erzeugten (auf Standard-Arrays
+ * basierenden) {@link WritableGrid}-Instanzen als Inhalt.
+ * 
+ * @author Dominik Appl
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ * 
+ * 
+ */
+public class GridListFactory extends edu.bonn.xulu.plugin.io.grid.awt.GridListFactory {
+  /**
+   * Liefert eine Instanz von {@link WritableGridLLFactory}, die auf
+   * Standard-Arrays basierende Instanzen von {@link WritableGrid} erzeugt. Mit diesen
+   * Instanzen wird die GridList gefuellt.
+   */
+  protected InstantiationFactory getWritableGridFactory() {
+    return new WritableGridLLFactory();
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/GridListFactory_ArcInfoAsciiGrid.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/GridListFactory_ArcInfoAsciiGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/GridListFactory_ArcInfoAsciiGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,188 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.lateloading;
+
+import java.io.File;
+
+import appl.data.DataProxy;
+import appl.data.WritableGridLLProxy;
+import appl.ext.XuluConfig;
+import appl.util.RasterUtil;
+
+import schmitzm.io.IOUtil;
+import schmitzm.data.WritableGridArray;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyReadAccess;
+
+import edu.bonn.xulu.io.Factory;
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+import edu.bonn.xulu.plugin.data.grid.GridList;
+import edu.bonn.xulu.plugin.io.grid.array.WritableGridArrayFactory_ArcInfoAsciiGrid;
+
+// fuer Doku
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link GridList} aus/in Dateien im ArcInfo-ASCII-Grid-Format.
+ * Beim Import liefert die Factory eine Standard-Arrays basierendes Raster-Liste
+ * ({@link WritableGridArray}).
+ * Entsprechend koennen beim Export nur {@link GridList GridLists}
+ * verarbeitet werden, die {@link WritableGridArray}-Instanzen in ihrer
+ * Raster-Property besitzen.
+ *
+ * @author Dominik Appl
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class GridListFactory_ArcInfoAsciiGrid extends AbstractFactory implements ImportFactory,ExportFactory {
+ private static final ImportFactory importFac = new WritableGridArrayFactory_ArcInfoAsciiGrid();
+ private static final ExportFactory exportFac = new WritableGridArrayFactory_ArcInfoAsciiGrid();
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link GridList GridList.class}
+   */
+  public Class getImportType() {
+    return GridList.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File[].class}
+   */
+  public Class getImportSourceType() {
+     return File[].class;
+  }
+
+  /**
+   * Importiert Raster aus Dateien im ArcInfoAsciiGrid-Format
+   * und fuegt diese in einer {@link GridList} zusammen.
+   * @param input Eingabe-Quelle (muss ein {@link File File[]} sein!)
+   * @param reg   Instanz der Xulu-Registry, ueber die eine Factory ermittelt
+   *              wird, die eine Standard-Instanz von {@link GridList} erzeugt, in
+   *              die das Objekt importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Dateien angegeben werden
+   */
+  public GridList importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+    InstantiationFactory instFac = AbstractFactory.getInstantiationFactoryFromRegistry(reg,getImportType(),true);
+    GridList gl = (GridList)instFac.newInstance(false);
+    // Raster importieren und in GridList einfuegen
+    for (int i=0; i<((Object[])input).length; i++){
+    	WritableGridLLProxy grid =  new WritableGridLLProxy(
+    			importFac,
+    			RasterUtil.getRasterMetaData_from_ArcGridASCII_File(((File[])input)[i]),
+    			((File[])input)[i],
+    			reg );
+    	//read and apply settings from the registry
+        String unloadFolder = XuluConfig.getXuluConfig().getProperty("Datatypes.proxy.unloadFolder");
+        boolean unloading = XuluConfig.getXuluConfig().getBooleanProperty("Datatypes.proxy.enableUnloading");
+        if(unloadFolder!=null)
+        	grid.setUnloadDir(unloadFolder);
+        grid.setUnloading(unloading);
+    	gl.addGrid(  grid  );
+
+        // Style vom ersten Raster uebernehmen
+        if ( edu.bonn.xulu.plugin.io.IOUtil.getStyleFromXuluObject( gl ) == null )
+          edu.bonn.xulu.plugin.io.IOUtil.importRasterStyle( gl, ((File[])input)[i].toURI().toURL() );
+    }
+
+
+//    // Dateinamen in die Bezeichnung aufnehmen
+//    sg.setDescription(sg.getDescription().concat(" [").concat(((File)input).getName()).concat("]"));
+    return gl;
+  }
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um eine {@link GridList} handelt, die nur Instanzen
+   * von {@link WritableGridArray} als Elemente enthaelt.
+   * @param obj zu pruefendes Objekt
+   */
+  public boolean isExportable(Object obj) {
+    if ( obj==null || !(obj instanceof GridList) )
+      return false;
+    GridList list = (GridList)obj;
+    for (int i=0; i<list.getGridCount(); i++)
+      if ( !(list.getGrid(i) instanceof WritableGridLLProxy) )
+        return false;
+    return true;
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link GridList} (oder eine Unterklasse)
+   * handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return GridList.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt. Dabei handelt es sich um eine <b>einzelne Datei</b>, da
+   * die die letztendlichen Export-Dateien automatisch durchnummeriert werden!!
+   * @return immer {@link File File.class}
+   */
+  public Class getExportDestinationType() {
+    return File.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link GridList} in Dateien des
+   * ArcInfoAsciiGrid-Formats.<br>
+   * <b>Beachte:</b><br>
+   * Als Ausgabe-Objekt ist eine <b>einzelne</b> Datei anzugeben, kein
+   * Array! Die Dateien werden ausgehend von dem angegebenen Dateinamen
+   * durchnummeriert!!
+   * @param object zu exportiertende Raster (muss eine {@link GridList} sein
+   * @param output Export-Ziel (muss ein einzelner {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel keine
+   *            einzelne Datei angegeben wird
+   * @exception IllegalArgumentException falls es sich bei dem angegeben Objekt
+   *            nicht um eine {@link GridList} handelt
+   */
+  public void exportObject(Object object, Object output) throws Exception {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(object) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(object.getClass().getName()));
+
+    // Dateinamen-Teile ermitteln
+    String fileName = IOUtil.getBaseFileName((File)output);
+    String fileExt  = IOUtil.getFileExt((File)output);
+
+    // Grids in der Liste einzeln exportieren
+    GridList               gl         = (GridList)object;
+    ListPropertyReadAccess listAccess = ((ListProperty) (gl.getProperty(GridList.PROP_GRIDS))).getReadAccess(this);
+    for (int i=0; i<listAccess.getCount(); i++) {
+      File outFile = new File( fileName.concat("_"+i).concat(fileExt) );
+      exportFac.exportObject( ((DataProxy)listAccess.getValue(i)).getProxiedObject() , outFile );
+      // Style Raster exportieren
+      edu.bonn.xulu.plugin.io.IOUtil.exportStyle(gl, outFile.toURI().toURL() );
+    }
+    listAccess.release();
+
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/MultiGridFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/MultiGridFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/MultiGridFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,38 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.lateloading;
+
+import edu.bonn.xulu.plugin.io.grid.WritableGridFactory;
+// nur fuer Doku
+import schmitzm.data.WritableGrid;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+
+/**
+ * Diese Factory erzeugt Standard-Instanzen von {@link MultiGrid} mit
+ * durch die Factory {@link WritableGridLLFactory} erzeugten (auf Standard-Arrays
+ * basierenden) {@link WritableGrid}-Instanzen als Inhalt.
+ * 
+ * @author Dominik Appl
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class MultiGridFactory extends edu.bonn.xulu.plugin.io.grid.awt.MultiGridFactory {
+  /**
+   * Liefert eine Instanz von {@link WritableGridLLFactory}, die auf Standard-Arrays
+   * basierende Instanzen von {@link WritableGrid} erzeugt. Mit diesen
+   * Instanzen wird die GridList gefuellt.
+   */
+  protected WritableGridFactory getWritableGridFactory() {
+    return new WritableGridLLFactory();
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/MultiGridFactory_ArcInfoAsciiGrid.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/MultiGridFactory_ArcInfoAsciiGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/MultiGridFactory_ArcInfoAsciiGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,110 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.lateloading;
+
+import java.io.File;
+
+import appl.data.WritableGridLLProxy;
+import appl.ext.XuluConfig;
+import appl.util.RasterUtil;
+
+import schmitzm.data.WritableGrid;
+
+import edu.bonn.xulu.appl.XuluRegistry;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.io.ImportFactory;
+
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+import edu.bonn.xulu.plugin.data.grid.GridList;
+import edu.bonn.xulu.plugin.io.grid.WritableGridFactory;
+import edu.bonn.xulu.plugin.io.grid.array.WritableGridArrayFactory_ArcInfoAsciiGrid;
+//import edu.bonn.xulu.plugin.io.grid.gt.GridListFactory_ArcInfoAsciiGrid;
+
+// nur fuer Doku
+import schmitzm.data.WritableGridArray;
+import edu.bonn.xulu.io.InstantiationFactory;
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link MultiGrid} aus/in Dateien im ArcInfo-ASCII-Grid-Format.
+ * Beim Import liefert die Factory eine Standard-Arrays basierendes Raster-Liste
+ * ({@link WritableGridArray}).
+ * Entsprechend koennen beim Export nur {@link MultiGrid MultiGrids}
+ * verarbeitet werden, die {@link WritableGridArray}-Instanzen in ihrer
+ * Raster-Property besitzen.
+ *
+ * @author Dominik Appl
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class MultiGridFactory_ArcInfoAsciiGrid extends GridListFactory_ArcInfoAsciiGrid {
+  private static final ImportFactory importFac = new WritableGridArrayFactory_ArcInfoAsciiGrid();
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link MultiGrid MultiGrid.class}
+   */
+  public Class getImportType() {
+    return MultiGrid.class;
+  }
+
+  /**
+   * Importiert Raster aus Dateien im ArcInfoAsciiGrid-Format
+   * und fuegt diese in einem {@link MultiGrid} zusammen.
+   * @param input Eingabe-Quelle (muss ein {@link File File[]} sein!)
+   * @param reg   Instanz der Xulu-Registry, ueber die eine Factory ermittelt
+   *              wird, die eine Standard-Instanz von {@link MultiGrid} erzeugt, in
+   *              die das Objekt importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Dateien angegeben werden
+   */
+  public MultiGrid importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+
+    // MultiGrid erst erzeugen, wenn ein Beispiel-Raster vorliegt
+    MultiGrid mg = null;
+    // Raster importieren und in GridList einfuegen
+    for (int i=0; i<((Object[])input).length; i++) {
+      WritableGridLLProxy grid = new WritableGridLLProxy
+                                (importFac,
+                                 RasterUtil.getRasterMetaData_from_ArcGridASCII_File(((File[])input)[i]),
+                                 ((File[])input)[i], reg );
+       //read settings from the registry
+      String unloadFolder = XuluConfig.getXuluConfig().getProperty("Datatypes.proxy.unloadFolder");
+      boolean unloading = XuluConfig.getXuluConfig().getBooleanProperty("Datatypes.proxy.enableUnloading");
+      if(unloadFolder!=null)
+      	grid.setUnloadDir(unloadFolder);
+      grid.setUnloading(unloading);
+      // das erste Grid dient dem MultiGrid als Vorlage
+      if ( mg == null )
+        mg = new MultiGrid(grid,getWritableGridFactory());
+      mg.addGrid(grid);
+      // Style vom ersten Raster uebernehmen
+      if ( edu.bonn.xulu.plugin.io.IOUtil.getStyleFromXuluObject( mg ) == null )
+        edu.bonn.xulu.plugin.io.IOUtil.importRasterStyle( mg, ((File[])input)[i].toURI().toURL() );
+    }
+    return mg;
+  }
+
+  /**
+   * Liefert eine Instanz von {@link WritableGridLLFactory}, die auf Standard-Arrays
+   * basierende Instanzen von {@link WritableGrid} erzeugt. Mit diesen
+   * Instanzen wird das SingleGrid gefuellt.
+   */
+  protected WritableGridFactory getWritableGridFactory() {
+    return new WritableGridLLFactory();
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/SingleGridFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/SingleGridFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/SingleGridFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,37 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.lateloading;
+
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.plugin.io.grid.array.WritableGridArrayFactory;
+// nur fuer Doku
+import schmitzm.data.WritableGrid;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+
+/**
+ * Diese Factory erzeugt Standard-Instanzen von {@link SingleGrid} mit einem
+ * durch die Factory {@link WritableGridArrayFactory} erzeugten (auf Standard-Arrays basierenden)
+ * {@link WritableGrid}.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class SingleGridFactory  extends edu.bonn.xulu.plugin.io.grid.awt.SingleGridFactory{
+
+  /**
+   * Liefert eine Instanz von {@link WritableGridArrayFactory}, die auf Standard-Arrays
+   * basierende Instanzen von {@link WritableGrid} erzeugt. Mit diesen
+   * Instanzen wird das SingleGrid gefuellt.
+   */
+  protected InstantiationFactory getWritableGridFactory() {
+    return new WritableGridLLFactory();
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/SingleGridFactory_ArcInfoAsciiGrid.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/SingleGridFactory_ArcInfoAsciiGrid.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/SingleGridFactory_ArcInfoAsciiGrid.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,158 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.lateloading;
+
+import java.io.File;
+
+import appl.data.DataProxy;
+import appl.data.WritableGridLLProxy;
+import appl.ext.XuluConfig;
+import appl.util.RasterMetaData;
+import appl.util.RasterUtil;
+
+import schmitzm.data.WritableGridArray;
+
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+import edu.bonn.xulu.plugin.io.IOUtil;
+import edu.bonn.xulu.plugin.io.grid.array.WritableGridArrayFactory_ArcInfoAsciiGrid;
+
+// nur fuer Doku
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link SingleGrid} aus/in das ArcInfo-ASCII-Grid-Format.
+ * Beim Import liefert die Factory ein auf Standard-Arrays basierendes Raster
+ * ({@link WritableGridArray}).
+ * Entsprechend koennen beim Export nur {@link SingleGrid SingleGrids}
+ * verarbeitet werden, die eine {@link WritableGridArray}-Instanz in ihrere
+ * Raster-Property besitzen.
+ *
+ * @author Dominik Appl
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class SingleGridFactory_ArcInfoAsciiGrid extends AbstractFactory implements ImportFactory, ExportFactory {
+  private static final ImportFactory importFac = new WritableGridArrayFactory_ArcInfoAsciiGrid();
+  private static final ExportFactory exportFac = new WritableGridArrayFactory_ArcInfoAsciiGrid();
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link SingleGrid SingleGrid.class}
+   */
+  public Class getImportType() {
+    return SingleGrid.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getImportSourceType() {
+    return File.class;
+  }
+
+  /**
+   * Importiert eine Instanz von {@link SingleGrid} aus einer Datei im
+   * ArcInfoAsciiGrid-Format.
+   * @param input Eingabe-Quelle (muss ein {@link File} sein!)
+   * @param reg   Instanz der Xulu-Registry, ueber die eine Factory ermittelt
+   *              wird, die eine Standard-Instanz von {@link SingleGrid} erzeugt, in
+   *              die das Raster importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Datei angegeben wird
+   */
+  public SingleGrid importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+    // Aus Registry die passende Factory fuer SingleGrid suchen
+    InstantiationFactory instFac = AbstractFactory.getInstantiationFactoryFromRegistry(reg,getImportType(),true);
+    // Raster importieren und in ein SingleGrid einfuegen
+    SingleGrid sg = (SingleGrid)instFac.newInstance(false);
+    WritableGridLLProxy newGrid = new WritableGridLLProxy(importFac,
+            RasterUtil.getRasterMetaData_from_ArcGridASCII_File((File) input),
+            (File)input,reg);
+    //read settings from the registry
+    String unloadFolder = XuluConfig.getXuluConfig().getProperty("Datatypes.proxy.unloadFolder");
+    boolean unloading = XuluConfig.getXuluConfig().getBooleanProperty("Datatypes.proxy.enableUnloading");
+    if(unloadFolder!=null)
+    	newGrid.setUnloadDir(unloadFolder);
+    newGrid.setUnloading(unloading);
+    sg.setGrid(newGrid);
+
+    // Style importieren und falls vorhanden in Property einfuegen
+    edu.bonn.xulu.plugin.io.IOUtil.importRasterStyle( sg, ((File)input).toURI().toURL() );
+
+    // Dateinamen in die Bezeichnung aufnehmen
+    sg.setDescription(sg.getDescription().concat(" [").concat(((File)input).getName()).concat("]"));
+    return sg;
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um ein {@link SingleGrid} handelt, das ein
+   * {@link WritableGridArray} in seiner Raster-Eigenschaft besitzt.
+   * @param obj zu pruefendes Objekt
+   */
+  public boolean isExportable(Object obj) {
+    return obj!=null &&
+           obj instanceof SingleGrid &&
+           ((SingleGrid)obj).getGrid() instanceof WritableGridLLProxy;
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link SingleGrid} (oder eine Unterklasse)
+   * handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return SingleGrid.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getExportDestinationType() {
+    return File.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link SingleGrid} in eine ArcInfoAsciiGrid-Datei.
+   * @param grid zu exportiertendes Raster (muss ein {@link SingleGrid} sein
+   * @param output Export-Ziel (muss ein {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel keine
+   *            Datei angegeben wird
+   * @exception IllegalArgumentException falls es sich bei dem angegeben Raster
+   *            nicht um ein {@link SingleGrid} handelt
+   */
+  public void exportObject(Object grid, Object output) throws Exception {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(grid) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(grid.getClass().getName()));
+    SingleGrid sg = (SingleGrid)grid;
+    exportFac.exportObject( ((DataProxy)sg.getGrid()).getProxiedObject(), (File)output );
+    IOUtil.exportStyle( sg, ((File)output).toURI().toURL() );
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/SingleGridFactory_GeoTiff.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/SingleGridFactory_GeoTiff.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/SingleGridFactory_GeoTiff.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,146 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.lateloading;
+
+import java.io.File;
+
+import appl.data.DataProxy;
+import appl.data.WritableGridLLProxy;
+
+import schmitzm.data.WritableGridArray;
+
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+import edu.bonn.xulu.plugin.io.IOUtil;
+import edu.bonn.xulu.plugin.io.grid.array.WritableGridArrayFactory_GeoTiff;
+
+// nur fuer Doku
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link SingleGrid} aus/in das GeoTiff-Format.
+ * Beim Import liefert die Factory ein auf Standard-Arrays basierendes Raster
+ * ({@link WritableGridArray}).
+ * Entsprechend koennen beim Export nur {@link SingleGrid SingleGrids}
+ * verarbeitet werden, die eine {@link WritableGridArray}-Instanz in ihrere
+ * Raster-Property besitzen.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class SingleGridFactory_GeoTiff extends AbstractFactory implements ImportFactory, ExportFactory {
+  private static final WritableGridArrayFactory_GeoTiff GRID_FAC = new WritableGridArrayFactory_GeoTiff();
+  private static final WritableGridArrayFactory_GeoTiff importFac = new WritableGridArrayFactory_GeoTiff();
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link SingleGrid SingleGrid.class}
+   */
+  public Class getImportType() {
+    return SingleGrid.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getImportSourceType() {
+    return File.class;
+  }
+
+  /**
+   * Importiert eine Instanz von {@link SingleGrid} aus einer Datei im
+   * GeoTiff-Format.
+   * @param input Eingabe-Quelle (muss ein {@link File} sein!)
+   * @param reg   Instanz der Xulu-Registry, ueber die eine Factory ermittelt
+   *              wird, die eine Standard-Instanz von {@link SingleGrid} erzeugt, in
+   *              die das Raster importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Datei angegeben wird
+   */
+  public SingleGrid importObject(Object input, XuluRegistry reg) throws Exception {
+    throw new UnsupportedOperationException(getClass().getName()+".importObject(Object,XuluRegistry) not yet implemented");
+//    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+//    // Aus Registry die passende Factory fuer SingleGrid suchen
+//    InstantiationFactory instFac = AbstractFactory.getInstantiationFactoryFromRegistry(reg,getImportType(),true);
+//    // Raster importieren und in ein SingleGrid einfuegen
+//    SingleGrid sg = (SingleGrid)instFac.newInstance(false);
+//    //new WritableGridLLProxy(importFac, new FileInputStream((File)input),reg);
+//
+//    // Style importieren und falls vorhanden in Property einfuegen
+//    edu.bonn.xulu.plugin.io.IOUtil.importRasterStyle( sg, ((File)input).toURI().toURL() );
+//
+//    // Dateinamen in die Bezeichnung aufnehmen
+//    sg.setDescription(sg.getDescription().concat(" [").concat(((File)input).getName()).concat("]"));
+//    return null;
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um ein {@link SingleGrid} handelt, das ein
+   * {@link WritableGridLLProxy} in seiner Raster-Eigenschaft besitzt.
+   * @param obj zu pruefendes Objekt
+   */
+  public boolean isExportable(Object obj) {
+    return obj!=null &&
+           obj instanceof SingleGrid &&
+           ((SingleGrid)obj).getGrid() instanceof WritableGridLLProxy;
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link SingleGrid} (oder eine Unterklasse)
+   * handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return SingleGrid.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getExportDestinationType() {
+    return File.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link SingleGrid} in eine GeoTiff-Datei.
+   * @param grid zu exportiertendes Raster (muss ein {@link SingleGrid} sein
+   * @param output Export-Ziel (muss ein {@link File} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel keine
+   *            Datei angegeben wird
+   * @exception IllegalArgumentException falls es sich bei dem angegeben Raster
+   *            nicht um ein {@link SingleGrid} handelt
+   */
+  public void exportObject(Object grid, Object output) throws Exception {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(grid) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(grid.getClass().getName()));
+    SingleGrid sg = (SingleGrid)grid;
+    GRID_FAC.exportObject( ((DataProxy)sg.getGrid()).getProxiedObject(), (File)output );
+    IOUtil.exportStyle( sg, ((File)output).toURI().toURL() );
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/WritableGridLLFactory.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/WritableGridLLFactory.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/lateloading/WritableGridLLFactory.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,88 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.grid.lateloading;
+
+import java.awt.geom.Rectangle2D;
+import java.awt.image.DataBuffer;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+import appl.data.WritableGridLLProxy;
+import appl.util.RasterMetaData;
+import schmitzm.data.WritableGrid;
+import edu.bonn.xulu.plugin.io.grid.WritableGridFactory;
+import edu.bonn.xulu.plugin.io.grid.array.WritableGridArrayFactory;
+
+// nur fuer Doku
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.io.Factory;
+import edu.bonn.xulu.plugin.data.grid.SingleGrid;
+
+/**
+ * Diese Factory erzeugt Standard-Instanzen des Datentyps {@link WritableGridLLProxy}.<br>
+ * <b>Bemerke:</b><br>
+ * Dieser stellt <b>kein</b> {@linkplain XuluObject Xulu-Objekt} dar, kann also
+ * nicht direkt im Xulu-Datenpool gespeichert werden. Hierzu ist der Datentyp
+ * {@link SingleGrid} (bzw. eine entsprechende Factory) zu verwenden!
+ * 
+ * @author Dominik Appl
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class WritableGridLLFactory extends WritableGridFactory {
+
+
+    WritableGridFactory  targetFactory = new WritableGridArrayFactory();
+
+
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link WritableGridLLProxy WritableGridLLProxy.class}
+   */
+  public Class getInstanceType() {
+    return WritableGridLLProxy.class;
+  }
+
+  /**
+   * Erzeugt ein neues Grid.
+   * @param type    Datentyp der gespeicherten Objekte
+   * @param widthc  Breite in Zellen
+   * @param heightc Hoehe in Zellen
+   * @param minX    Index der ersten Zelle in X-Richtung
+   * @param minY    Index der ersten Zelle in Y-Richtung
+   * @param x       Georeferenz Longitute (Westliche/Linke Kante)
+   * @param y       Georeferenz Latitude (Suedliche/Untere Kante)
+   * @param width   Breite
+   * @param height  Hoehe
+   * @param crs     Referenzsystem fuer das Raster
+   */
+  public WritableGridLLProxy newInstance(int type, int widthc, int heightc, int minX, int minY, double x, double y, double width, double height, CoordinateReferenceSystem crs) {
+	  return new WritableGridLLProxy(
+             targetFactory,
+             new RasterMetaData(
+                     type,
+                     widthc,
+                     heightc,
+                     minX,
+                     minY,
+                     x,
+                     y,
+                     width,
+                     height,
+                     crs
+              )
+          );
+    }
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/grid/package.html
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/grid/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/grid/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,6 @@
+<html>
+<body>
+	In diesem Paket können die Instanziierungs- und Im/Export-Factorys für die
+	benutzerdefinierten Raster-Datentypen der Xulu-Modelling-Platform implementiert werden.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/edu/bonn/xulu/plugin/io/misc/CAAreaListFactory_ShapeFile.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/misc/CAAreaListFactory_ShapeFile.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/misc/CAAreaListFactory_ShapeFile.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,167 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.misc;
+
+import java.io.File;
+import java.awt.geom.Point2D;
+
+import org.geotools.feature.Feature;
+import org.geotools.feature.FeatureIterator;
+import com.vividsolutions.jts.geom.Point;
+
+import schmitzm.geotools.io.GeoImportUtil;
+
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyWriteAccess;
+
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.plugin.data.misc.CAArea;
+import edu.bonn.xulu.appl.XuluRegistry;
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.data.DynamicXuluObject;
+
+/**
+ * Diese Factory importiert Instanzen des Datentyps {@link CAArea} aus einem
+ * Shape-File. Dessen Features muessen folgende Attribute besitzen:
+ * <table width="70%">
+ *   <tr><td><b>Attribut</b></td>
+ *       <td><b>Datentyp</b></td>
+ *       <td><b>Beschreibung</b></td>
+ *       </tr>
+ *   <tr><td><i>Default-Geometry</i></td>
+ *       <td>Punkt</td>
+ *       <td>Lat/Lon-Koordinate der Area</td>
+ *       </tr>
+ *   <tr><td><code>Name</code></td>
+ *       <td><code>String</code></td>
+ *       <td>Name der Area</td>
+ *       </tr>
+ * </table>
+ * Aus den importierten {@link CAArea}-Objekten wird anschliessend ein
+ * {@link XuluObject} erstellt, das aus einer {@link ListProperty} besteht,
+ * in der die Areas gespeichert werden.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class CAAreaListFactory_ShapeFile extends AbstractFactory implements ImportFactory {
+  /** (Unter-)Typ von {@link CAArea} fuer den die {@link ListProperty} des
+   *  {@link XuluObject} erzeugt wird. Unterklassen muessen diese Variable
+   *  neu belegen, um Spezialisierungen von {@link CAArea} zu verwenden.
+   */
+  protected Class<? extends CAArea> caAreaType = CAArea.class;
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link XuluObject XuluObject.class}
+   */
+  public Class getImportType() {
+    return XuluObject.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link File File.class}
+   */
+  public Class getImportSourceType() {
+    return File.class;
+  }
+
+  /**
+   * Importiert eine Instanz von {@link XuluObject} aus einer Datei im
+   * oben beschriebenen ShapeFile-Format (.shp).
+   * @param input Eingabe-Quelle (muss ein {@link File} sein!)
+   * @param reg   Instanz der Xulu-Registry (wird nicht verwendet!)
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            Datei angegeben wird
+   * @see GeoImportUtil#readFeaturesFromShapeFile(File)
+   */
+  public XuluObject importObject(Object input, XuluRegistry reg) throws Exception {
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+
+    // Xulu-Objekt mit einer ListProperty[CAArea] erzeugen
+    DynamicXuluObject xuluObject = new DynamicXuluObject();
+    ListProperty      prop       = new ListProperty("Areas",caAreaType);
+    xuluObject.addProperty( prop );
+    // Features einlesen
+    FeatureIterator featIter = GeoImportUtil.readFeaturesFromShapeFile((File)input).features();
+
+    // CA-Areas erzeugen und der ListProperty hinzufuegen
+    ListPropertyWriteAccess wa = prop.getWriteAccess(this);
+    for (int i=1; featIter.hasNext(); i++ ) {
+      Feature f = featIter.next();
+      try {
+        // Area der Liste hinzufuegen
+        wa.addValue( interpreteFeature(i,f) );
+      } catch (Exception err) {
+        System.err.println("Error in feature "+i+": "+err);
+        System.err.println("    > Feature ignored!");
+      }
+    }
+    wa.release();
+
+    // Dateinamen in die Bezeichnung aufnehmen
+    xuluObject.setDescription(xuluObject.getDescription().concat(" [").concat(((File)input).getName()).concat("]"));
+    return xuluObject;
+
+  }
+
+  /**
+   * Erzeugt eine Instanz vom {@link CAArea} und befuellt diese mit Daten aus
+   * dem Feature.
+   * @param featNo Nummer des Features (beginnend bei 0)
+   * @param f      zu interpretierendes Feature
+   */
+  protected CAArea interpreteFeature(int featNo, Feature f) {
+    return interpreteFeature(featNo,f,null);
+  }
+
+  /**
+   * Befuellt eine Instanz vom {@link CAArea} mit Daten aus dem Feature.
+   * @param featNo Nummer des Features (beginnend bei 0)
+   * @param f      zu interpretierendes Feature
+   * @param area   Area in die die Informationen hineingeschrieben werden (wenn
+   *               {@code null}, wird eine neue {@link CAArea}-Instanz erzeugt)
+   */
+  protected CAArea interpreteFeature(int featNo, Feature f, CAArea area) {
+    Object attr = null;
+    String attrName = "";
+
+    // Startpunkt in Default-Geometry
+    attr = f.getDefaultGeometry();
+    if ( attr != null && attr instanceof Point ) {
+      Point p = (Point)attr;
+      area.setStartLocation( new Point2D.Double(p.getX(),p.getY()) );
+    } else {
+      System.err.println("Feature "+featNo+": No point found in default geometry");
+      System.err.println("    > Area location set to (0,0)");
+      area.setStartLocation( new Point2D.Double(0,0) );
+    }
+
+    // Name der Area
+    attrName = "Name";
+    attr = f.getAttribute(attrName);
+    if ( attr != null && attr instanceof String )
+      area.setName( (String)attr );
+    else {
+      System.err.println("Feature "+featNo+": No string-attribute '"+attrName+"' found");
+      System.err.println("    > Area name set to 'Area "+featNo+"'");
+      area.setName("Area "+featNo);
+    }
+
+    return area;
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/misc/CASettlementAreaListFactory_ShapeFile.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/misc/CASettlementAreaListFactory_ShapeFile.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/misc/CASettlementAreaListFactory_ShapeFile.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,148 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.misc;
+
+import java.io.File;
+import java.awt.geom.Point2D;
+
+import org.geotools.feature.Feature;
+import org.geotools.feature.FeatureIterator;
+import com.vividsolutions.jts.geom.Point;
+
+import schmitzm.geotools.io.GeoImportUtil;
+
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyWriteAccess;
+
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.plugin.data.misc.CASettlementArea;
+import edu.bonn.xulu.appl.XuluRegistry;
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.data.DynamicXuluObject;
+import edu.bonn.xulu.plugin.data.misc.CAArea;
+
+/**
+ * Diese Factory importiert Instanzen des Datentyps {@link CASettlementArea} aus einem
+ * Shape-File. Dessen Features muessen folgende Attribute besitzen:
+ * <table width="70%">
+ *   <tr><td><b>Attribut</b></td>
+ *       <td><b>Datentyp</b></td>
+ *       <td><b>Beschreibung</b></td>
+ *       </tr>
+ *   <tr><td><i>Default-Geometry</i></td>
+ *       <td>Punkt</td>
+ *       <td>Lat/Lon-Koordinate der Area</td>
+ *       </tr>
+ *   <tr><td><code>Name</code></td>
+ *       <td><code>String</code></td>
+ *       <td>Name der Area</td>
+ *       </tr>
+ *   <tr><td><code>Inhabits</code></td>
+ *       <td><code>double</code></td>
+ *       <td>Einwohneranzahl zum Zeitpunkt 0 (kann auch direkt fuer Bedarf genutzt werden)</td>
+ *       </tr>
+ *   <tr><td><code>growthrate</code></td>
+ *       <td><code>double</code></td>
+ *       <td>Wachstumsrate der Einwohner (in %)</td>
+ *       </tr>
+ *   <tr><td><code>demand</code></td>
+ *       <td><code>double</code></td>
+ *       <td>Flaechen-Bedarf pro Einwohner (in qm)</td>
+ *       </tr>
+ * </table>
+ * Aus den importierten {@link CASettlementArea}-Objekten wird anschliessend ein
+ * {@link XuluObject} erstellt, das aus einer {@link ListProperty} besteht,
+ * in der die Areas gespeichert werden.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class CASettlementAreaListFactory_ShapeFile extends CAAreaListFactory_ShapeFile {
+  /**
+   * Erzeugt einen neue Factory.
+   */
+  public CASettlementAreaListFactory_ShapeFile() {
+    // CAArea-Typ fuer den die List-Property im XuluObject erzeugt wird
+    // neu belegen
+    caAreaType = CASettlementArea.class;
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Erzeugt eine Instanz vom {@link CASettlementArea} und befuellt diese mit Daten aus
+   * dem Feature.
+   * @param featNo Nummer des Features (beginnend bei 0)
+   * @param f      zu interpretierendes Feature
+   */
+  protected CASettlementArea interpreteFeature(int featNo, Feature f) {
+    return interpreteFeature(featNo,f,null);
+  }
+
+  /**
+   * Erzeugt eine Instanz vom {@link CASettlementArea} und befuellt diese mit Daten aus
+   * dem Feature.
+   * @param featNo Nummer des Features (beginnend bei 0)
+   * @param f      zu interpretierendes Feature
+   * @param settArea Area in die die Informationen hineingeschrieben werden (wenn
+   *                 {@code null}, wird eine neue {@link CASettlementArea}-Instanz erzeugt)
+   * @throws IllegalArgumentException wenn {@code settArea} keine Instanz von
+   *         {@link CASettlementArea} ist
+   */
+  protected CASettlementArea interpreteFeature(int featNo, Feature f, CAArea settArea) {
+    if ( settArea == null )
+      settArea = new CASettlementArea();
+    if ( !(settArea instanceof CASettlementArea) )
+      throw new IllegalArgumentException(getClass().getSimpleName()+".interpreteFeature(.) can only be applied on CASettlementArea-objects!");
+    CASettlementArea area = (CASettlementArea)settArea;
+
+    // Attribute von CAArea befuellen
+    super.interpreteFeature(featNo,f,settArea);
+
+    // Einwohner pro Zeitschritt
+    String attrName = "Inhabits";
+    Object attr     = f.getAttribute(attrName);
+    if ( attr != null && attr instanceof Number )
+      area.setInhabitants( ((Number)attr).doubleValue() );
+    else {
+      System.err.println("Feature "+featNo+": No double-attribute '"+attrName+"' found");
+      System.err.println("    > Initial inhabitants set to 1.0");
+      area.setInhabitants(1.0);
+    }
+
+    // Wachstumsrate der Einwohner (in %)
+    attrName = "growthrate";
+    attr = f.getAttribute(attrName);
+    if ( attr != null && attr instanceof Number )
+      area.setGrowthRate( ((Number)attr).doubleValue()/100.0 );
+    else {
+      System.err.println("Feature "+featNo+": No double-attribute '"+attrName+"' found");
+      System.err.println("    > Growth rate set to 0.0");
+      area.setGrowthRate(0.0);
+    }
+
+    // Bedarf pro Einwohner
+    attrName = "demand";
+    attr = f.getAttribute(attrName);
+    if ( attr != null && attr instanceof Number ) {
+      area.setDemandPerInhabitant( ((Number)attr).doubleValue() );
+    } else {
+      System.err.println("Feature "+featNo+": No number-attribute '"+attrName+"' found");
+      System.err.println("    > Demand per habitant set to 1");
+      area.setDemandPerInhabitant(1);
+    }
+
+    return area;
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/misc/DynamicXuluObjectFactory_BasicStructure.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/misc/DynamicXuluObjectFactory_BasicStructure.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/misc/DynamicXuluObjectFactory_BasicStructure.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,517 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.io.misc;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.BufferedWriter;
+import java.util.Vector;
+import java.util.Collection;
+import java.util.StringTokenizer;
+
+import schmitzm.lang.LangUtil;
+import schmitzm.data.property.*;
+import schmitzm.temp.BaseTypeUtil;
+
+import edu.bonn.xulu.io.AbstractFactory;
+import edu.bonn.xulu.io.ImportFactory;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.io.ExportFactory;
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.data.DynamicXuluObject;
+import edu.bonn.xulu.data.XuluDataException;
+import edu.bonn.xulu.appl.XuluRegistry;
+
+import org.apache.log4j.Logger;
+import java.io.OutputStreamWriter;
+import java.util.Arrays;
+
+/**
+ * Diese Factory importiert und exportiert Instanzen des Datentyps
+ * {@link DynamicXuluObject} aus einem (in ein) einfaches ASCII-Format.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class DynamicXuluObjectFactory_BasicStructure extends AbstractFactory implements ImportFactory, ExportFactory {
+  /** Logger fuer Debug-Ausgaben und Warnings. */
+  protected final Logger LOGGER = LangUtil.createLogger(this);
+
+  private static final String TAG_OBJNAME  = "XuluObjectName";
+  private static final String TAG_PROPTYPE = "Type";
+  private static final String TAG_DATATYPE = "DataType";
+  private static final String TAG_VALUE    = "Value";
+
+  // Objekt-Parameter
+  private String objectName   = null;
+  // Property-Parameter
+  private String propName     = null;
+  private Class  propClass    = null;
+  private Class  propDataType = null;
+  private Vector propValues   = new Vector<String>();
+  private Vector params       = new Vector();
+
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ImportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert den Datentyp, den die Factory erzeugt.
+   * @return immer {@link DynamicXuluObject DynamicXuluObject.class}
+   */
+  public Class getImportType() {
+    return DynamicXuluObject.class;
+  }
+
+  /**
+   * Liefert den Datentyp, den die Factory als Import-Quelle benoetigt.
+   * @return immer {@link InputStream InputStream.class}
+   */
+  public Class getImportSourceType() {
+    return InputStream.class;
+  }
+
+  /**
+   * Importiert eine Instanz von {@link DynamicXuluObject} aus einem InputStream.
+   * Das Format des Streams ist der Klassendokumentation (siehe oben) zu
+   * entnehmen.
+   * @param input Eingabe-Quelle (muss ein {@link InputStream} sein!)
+   * @param reg bietet Zugriff auf andere registrierte Factories, um eine
+   *            Standard-Instanz von {@link DynamicXuluObject} zu erzeugen,
+   *            in die das Objekt importiert wird
+   * @exception UnsupportedOperationException falls als Eingabe-Quelle keine
+   *            InputStream angegeben wird
+   */
+  public DynamicXuluObject importObject(Object input, XuluRegistry reg) throws Exception {
+    // Factory benoetigt Input-Stream als Eingabe
+    AbstractFactory.checkImportSourceObject(this,input,getImportSourceType(),true);
+    // Factory benoetigt eine InstantiationFactory, die ein DynamicXuluObject
+    // erzeugt
+    InstantiationFactory instFac = AbstractFactory.getInstantiationFactoryFromRegistry(reg,getImportType(),true);
+
+    // Instanz erzeugen und nach und nach mit Propertys fuellen
+    DynamicXuluObject xuluObject = (DynamicXuluObject)instFac.newInstance(false);
+
+    // Datei zeilenweise einlesen
+    BufferedReader in   = new BufferedReader( new InputStreamReader((InputStream)input) );
+    String  line        = null;
+    boolean propSection = false; // Flag, ob generelle Paramater gelesen werden,
+                                 // oder eine Propertry
+    initPropertyVariables();
+    for (int lineNo=1; in.ready() && (line=in.readLine().trim()) != null; lineNo++ ) {
+      try {
+          // Kommentare und Leerzeilen ignorieren
+          if ( line.startsWith("//") || line.startsWith("#") || line.equals("") )
+            continue;
+
+          // Es beginnt eine neue Property-Definition
+          if ( line.startsWith("[") ) {
+            // wenn bereits eine Property eingelesen wurde, diese
+            // erzeugen und dem Objekt hinzufuegen
+            if ( propSection )
+              try {
+                xuluObject.addProperty(createProperty());
+              } catch ( Exception err ) {
+                System.err.println( getClass().getSimpleName().concat(" --> ").concat(err.toString()) );
+                System.err.println( "     Construction of property '".concat(propName).concat("'") );
+              }
+
+            // Nachdem die Property erzeugt wurde, werden die Variablen
+            // fuer die naechste Property initialisiert
+            initPropertyVariables();
+
+            // Namen einlesen
+            propName = line.substring(1, line.indexOf("]"));
+            if ( propName.equals("") )
+              throw new XuluDataException("Property name must be specified!");
+
+            // Flag setzen, dass (von nun an) Propertys gelesen werden
+            propSection = true;
+            continue;
+          }
+
+          Line l = new Line( (Object)line );
+          if ( !propSection ) {
+            // Zeile als globalen Parameter interpretieren
+            if ( l.getTagName().equalsIgnoreCase(TAG_OBJNAME) )
+              // Beschreibung des Xulu-Objekts
+              xuluObject.setDescription( l.getFirstValue() );
+            else
+              // unbekannter Parameter
+              throw new IOException( "Unknown Tag for XuluObject: ".concat(l.getTagName()) );
+          } else {
+            // Zeile als Property-Parameter interpretieren
+            if ( l.getTagName().equalsIgnoreCase(TAG_PROPTYPE) ) {
+              // Typ der Property
+              propClass = Class.forName(l.getFirstValue());
+              // nur Skalar-, List- oder Matrix-Property zulaessig
+              if ( !ScalarProperty.class.equals(propClass) &&
+                   !ListProperty.class.equals(propClass) &&
+                   !MatrixProperty.class.equals(propClass) )
+                throw new IOException( "Only ScalarProperty, ListProperty and MatrixProperty are allowed!" );
+              // Alle Zeilen-Elemente NACH dem Klassennamen sind Parameter
+              params = new Vector( l.values.subList(1,l.values.size()) );
+            }
+            else if ( l.getTagName().equalsIgnoreCase(TAG_DATATYPE) )
+              // Daten-Typ der in der Property gespeichert wird
+              propDataType = Class.forName( l.getFirstValue() );
+            else if ( l.getTagName().equalsIgnoreCase(TAG_VALUE) )
+              // Initiale Werte der Property
+              propValues.addAll( l.getValues() );
+            else
+              // unbekannter Parameter
+              throw new IOException( "Unknown Tag for XuluObject: ".concat(l.getTagName()) );
+          }
+
+      } catch ( Exception err ) {
+        System.err.println( getClass().getSimpleName().concat(" --> ").concat(err.toString()) );
+        System.err.println( "     Line ".concat(String.valueOf(lineNo)).concat(": ").concat(line) );
+      }
+    }
+
+    // wenn bereits eine Property eingelesen wurde, diese
+    // erzeugen und dem Objekt hinzufuegen
+    if ( propSection )
+      try {
+        xuluObject.addProperty(createProperty());
+      } catch ( Exception err ) {
+        System.err.println( getClass().getSimpleName().concat(" --> ").concat(err.toString()) );
+        System.err.println( "     Construction of property '".concat(propName).concat("'") );
+      }
+    // Eingabe-Stream schliessen
+//    in.close();
+    return xuluObject;
+  }
+
+
+  private void initPropertyVariables() {
+    propName     = null;
+    propClass    = null;
+    propDataType = null;
+    propValues.clear();
+    params.clear();
+  }
+
+  private void checkProperty() throws Exception {
+      // Property muss einen Namen haben
+      if ( propName == null )
+        throw new XuluDataException("Property name must be specified!");
+
+      // Wurde kein Property-Typ angegeben, wird eine Liste angenommen,
+      // wenn mehrere Werte angegeben wurden, sonst ein skalarer Wert
+      if ( propClass == null ) {
+        if ( propValues.size() > 1 )
+          propClass = ListProperty.class;
+        else
+          propClass = ScalarProperty.class;
+      }
+      // nur Skalar-, List- oder Matrix-Property zulaessig
+      if ( !ScalarProperty.class.equals(propClass) &&
+           !ListProperty.class.equals(propClass) &&
+           !MatrixProperty.class.equals(propClass) )
+        throw new IOException( "Only ScalarProperty, ListProperty and MatrixProperty are allowed for Property '".concat(propName).concat("'") );
+
+      // Property muss einen Datentyp haben oder (mind.) einen Wert
+      if ( propDataType == null && propValues.isEmpty() )
+        throw new XuluDataException("Data type to store in property must be specified or at least one value!");
+
+      // Wurde kein Daten-Typ angegeben, wird der "optimale" gewaehlt
+      if ( propDataType == null )
+        propDataType = BaseTypeUtil.convertFromString((String)propValues.elementAt(0)).getClass();
+
+      // Wenn fuer eine Matrix Werte angegeben werden, sollten alle Werte
+      // angegeben werden
+      if ( MatrixProperty.class.isAssignableFrom(propClass) ) {
+        int    valueCountNeeded = 1;
+        String sizeDesc = "";
+        for (int i = 0; i < params.size(); i++) {
+          int size = Integer.parseInt((String)params.elementAt(i));
+          valueCountNeeded *= size;
+          // Beschreibung zusammensetzen
+          if ( i > 0 )
+            sizeDesc += ",";
+          sizeDesc.concat(String.valueOf(size));
+        }
+        if ( propValues.size() > valueCountNeeded )
+          System.err.println( "Warning: To much values specified for matix(".concat(sizeDesc).concat(") property '").concat(propName).concat("'") );
+        if ( propValues.size() < valueCountNeeded )
+          System.err.println( "Warning: Less values specified for matix(".concat(sizeDesc).concat(") property '").concat(propName).concat("'") );
+      }
+  }
+
+  private Property createProperty() throws Exception {
+    // Pruefen, ob alle Angaben korrekt sind
+    checkProperty();
+    ValueProperty prop          = null;
+    ValuePropertyType  propType = ValuePropertyType.createValuePropertyType(propDataType);
+
+    // SKALARE PROPERTY
+    if ( ScalarProperty.class.equals(propClass) ) {
+      // Property erzeugen
+      prop = new ScalarProperty(propName, propType);
+      // Property mit initialem Wert belegen
+      if ( propValues.size() > 0 )
+        prop.getOneTimeWriteAccess().setValue( BaseTypeUtil.convertFromString((String)propValues.firstElement(), propDataType) );
+    }
+
+    // LIST PROPERTY
+    if ( ListProperty.class.equals(propClass) ) {
+      // Property erzeugen
+      prop = new ListProperty(propName, propType);
+      // Propertry mit initialen Werten belegen
+      ListPropertyWriteAccess wa = (ListPropertyWriteAccess)prop.getWriteAccess(this);
+      for (int i=0; i<propValues.size(); i++)
+        wa.addValue( BaseTypeUtil.convertFromString((String)propValues.elementAt(i),propDataType) );
+      wa.release();
+    }
+
+    // MATRIX PROPERTY
+    if ( MatrixProperty.class.equals(propClass) ) {
+      // Dimension der Matrix aus Parametern lesen
+      int[] size        = new int[params.size()];
+      int   maxElements = 1; // max. Anzahl an Elementen fuer die Matrix
+      for ( int i=0; i<size.length; i++ ) {
+        size[i] = Integer.parseInt( (String)params.elementAt(i) );
+        maxElements *= size[i];
+      }
+      // Property erzeugen
+      prop = new MatrixProperty(propName,size,propType);
+      // Propertry mit initialen Werten belegen
+      int[] c = new int[size.length]; // Koordinate zum Listenindex
+      PropertyWriteAccess wa = prop.getWriteAccess(this);
+      for (int i=0; i<propValues.size() && i<maxElements; i++, c[0]++) {
+        // Koordinaten-Uebertrag checken
+        for (int j=0; j<size.length && c[j]==size[j]; j++) {
+          c[j] = 0;
+          c[j+1]++;
+        }
+        wa.setValue( BaseTypeUtil.convertFromString((String)propValues.elementAt(i),propDataType), c );
+      }
+      wa.release();
+    }
+
+    return prop;
+  }
+
+  private class Line {
+    private String tagName = "";
+    private Vector values  = new Vector<String>();
+
+    private void initFromString(String line) {
+      StringTokenizer st = new StringTokenizer(line);
+      // erstes Token (bis zum Gleichheitszeichen) = Name des Tags
+      tagName = st.nextToken("=\n").trim();
+      while ( st.hasMoreTokens() )
+        values.add( st.nextToken("=;\n").trim() );
+    }
+
+    public Line(Object line) {
+      initFromString((String)line);
+    }
+
+    public Line(String tagName) {
+      this.tagName = tagName;
+    }
+
+    public String getTagName() {
+      return this.tagName;
+    }
+
+    public int getValueCount() {
+      return values.size();
+    }
+
+    public String getValue(int i) {
+      return (String)values.elementAt(i);
+    }
+
+    public String getFirstValue() {
+      return (String)values.elementAt(0);
+    }
+
+    public void addValue(Object o) {
+      values.add(o);
+    }
+
+    public Collection getValues() {
+      return values;
+    }
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////     Implementierung von ExportFactory     //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob ein Objekt exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um ein {@link DynamicXuluObject} handelt.
+   * @param obj zu pruefendes Objekt
+   */
+  public boolean isExportable(Object obj) {
+    return obj!=null && obj instanceof DynamicXuluObject;
+  }
+
+  /**
+   * Prueft, ob ein Objekttyp exportiert werden kann. Dies ist der
+   * Fall, wenn es sich um {@link Properties} (oder eine Unterklasse)
+   * handelt.
+   * @param c zu pruefender Objekttyp
+   */
+  public boolean isExportable(Class c) {
+    return c != null && Properties.class.isAssignableFrom(c);
+  }
+
+  /**
+   * Liefert den Objekt-Typ, den die Factory als Ziel zum Exportieren
+   * benoetigt.
+   * @return immer {@link OutputStream OutputStream.class}
+   */
+  public Class getExportDestinationType() {
+    return OutputStream.class;
+  }
+
+  /**
+   * Exportiert eine Instanz von {@link Properties} in ein einfaches
+   * ASCII-Format.
+   * @param obj    zu exportiertendes Objekt (muss ein {@link DynamicXuluObject} sein
+   * @param output Export-Ziel (muss ein {@link OutputStream} sein!)
+   * @exception UnsupportedOperationException falls als Export-Ziel kein
+   *            OutputStream angegeben wird
+   * @exception IllegalArgumentException falls es sich bei <code>obj</code>
+   *            nicht um ein {@link Properties}-Objekt handelt
+   */
+  public void exportObject(Object obj, Object output) throws IOException {
+    AbstractFactory.checkExportDestinationObject(this,output,getExportDestinationType(),true);
+    if ( !isExportable(obj) )
+      throw new IllegalArgumentException(getClass().getName().concat(" can not export instances of ").concat(obj.getClass().getName()));
+
+    Properties   propObj = (Properties)obj;
+    BufferedWriter  out     = new BufferedWriter( new OutputStreamWriter((OutputStream)output) );
+    // Name des Objekts schreiben
+    if ( propObj instanceof XuluObject )
+      out.write(TAG_OBJNAME + " = " + ((XuluObject)propObj).getDescription()+"\n\n");
+    // Properties schreiben
+    for (Property prop : propObj.getProperties()) {
+      // Es koennen nur Instanzen von ValueProperty in die Datei
+      // geschrieben werden
+      if ( !(prop instanceof ValueProperty) ) {
+        LOGGER.error("Property type not supported: "+prop.getClass().getSimpleName()+". Property ignored!");
+        continue;
+      }
+      // Als Property-Wert koennen nur Stings, numerische oder boolesche
+      // Werte in die Datei geschrieben werden
+      Class dataType = prop.getType();
+      if ( !BaseTypeUtil.isNumeric( dataType ) &&
+           !BaseTypeUtil.isBoolean( dataType ) &&
+           !BaseTypeUtil.isString( dataType ) &&
+           !BaseTypeUtil.isCharacter( dataType ) ) {
+        LOGGER.error("Property data type not supported: "+prop.getType().getSimpleName()+". Property ignored!");
+        continue;
+      }
+
+      //**** Name ****
+      out.write("["+prop.getName().trim()+"]\n");
+
+      //**** Property-Typ ****
+      out.write(TAG_PROPTYPE+" = "+prop.getClass().getName());
+      // Parameter hinzufuegen
+      if ( prop instanceof MatrixProperty)
+        for (int dimSize : ((MatrixProperty)prop).getSize())
+          out.write("; "+dimSize);
+      // Zeile beenden
+      out.write("\n");
+
+      //**** Daten-Typ ****
+      out.write(TAG_DATATYPE+" = "+prop.getType().getName()+"\n");
+
+      //**** Werte ****
+      if ( prop instanceof ScalarProperty ) {
+        writeValueToOutput( (ScalarProperty)prop, out );
+      } else if ( prop instanceof ListProperty) {
+        writeValueToOutput( (ListProperty)prop, out );
+      } else if ( prop instanceof MatrixProperty) {
+        writeValueToOutput( (MatrixProperty)prop, out );
+      } else
+        LOGGER.error("ValueProperty type not supported: "+prop.getType().getSimpleName()+". Values could not be stored!");
+
+      // Leerzeile nach jeder Property
+      out.write("\n");
+    }
+
+    out.flush();
+    out.close();
+  }
+
+  /**
+   * Exportiert den Wert-Block einer {@link ScalarProperty}.
+   * @param prop zu exportierende {@link ScalarProperty}
+   * @param out  Ausgabe
+   */
+  private void writeValueToOutput(ScalarProperty prop, BufferedWriter out) throws IOException {
+    out.write(TAG_VALUE+" =\t"+prop.getOneTimeReadAccess().getValue()+"\n" );
+  }
+
+  /**
+   * Exportiert den Wert-Block einer {@link ListProperty}.
+   * @param prop zu exportierende {@link ListProperty}
+   * @param out  Ausgabe
+   */
+  private void writeValueToOutput(ListProperty prop, BufferedWriter out) throws IOException {
+    ListPropertyReadAccess RA_prop = prop.getReadAccess(this);
+    for (int i=0; i<RA_prop.getCount(); i++) {
+      if ( i==0 )
+        out.write(TAG_VALUE+" =");
+      out.write("\t"+RA_prop.getValue(i)+(i<RA_prop.getCount()-1 ? ";" : "\n") );
+    }
+    RA_prop.release();
+  }
+
+  /**
+   * Exportiert den Wert-Block einer {@link MatrixProperty}.
+   * @param prop zu exportierende {@link MatrixProperty}
+   * @param out  Ausgabe
+   */
+  private void writeValueToOutput(MatrixProperty prop, BufferedWriter out) throws IOException {
+    PropertyReadAccess RA_prop = prop.getReadAccess(this);
+    int[] dimSize   = prop.getSize();  // Matrix-Groesse in jeder Dimension
+    int[] coord     = new int[dimSize.length]; // Var. fuer eine Koordinate
+    int   lineCount = 1; // Gesamt-Anzahl an VALUE-Zeilen
+    for (int d=1; d<dimSize.length; d++)
+      lineCount *= dimSize[d];
+    // Zeilen erzeugen
+    for (int l=0; l<lineCount; l++) {
+      // Koordinate erhoehen (ab dem 2. Durchlauf, da initial 'coord'
+      // bereits auf (0,0,...,0) steht)
+      for (int d = 1; l > 0 && d < dimSize.length; d++)
+        if (++coord[d] < dimSize[d])
+          break; // Koord. in Dimensionen > d nicht beeinflusst
+        else {
+          coord[d] = 0; // Koord. in Dimension d initialisieren und in d+1 erhoehen
+          out.write("\n");
+        }
+      // Wenn Matrix mehr als 2 Dimensionen hat, vor jedem
+      // Matrix-Block die darin enthaltenen Koordinaten als Kommentar
+      // darstellen
+      if ( dimSize.length > 2 && coord[1] == 0 )
+        out.write("# "  + Arrays.toString( LangUtil.cloneArray(coord,0,0)) +
+                  " - " + Arrays.toString( LangUtil.cloneArray(coord,dimSize[0]-1,dimSize[1]-1) ) + "\n");
+
+      // Zeile erzeugen (= Werte in Dimension 0)
+      out.write(TAG_VALUE+" =");
+      for (coord[0]=0; coord[0]<dimSize[0]; coord[0]++)
+        out.write( "\t"+RA_prop.getValue(coord)+(coord[0]<dimSize[0]-1 ? ";" : "\n") );
+    }
+    RA_prop.release();
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/io/misc/package.html
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/misc/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/misc/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,6 @@
+<html>
+<body>
+	In diesem Paket können die Instanziierungs- und Im/Export-Factorys für sonstige
+	benutzerdefinierte Datentypen der Xulu-Modelling-Platform implementiert werden.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/edu/bonn/xulu/plugin/io/package.html
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/io/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/io/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,6 @@
+<html>
+<body>
+	In diesem Paket können die Instanziierungs- und Im/Export-Factorys für die
+	benutzerdefinierten Datentypen der Xulu-Modelling-Platform implementiert werden.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/edu/bonn/xulu/plugin/model/ca/MultiCellularAutomaton.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/ca/MultiCellularAutomaton.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/model/ca/MultiCellularAutomaton.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,552 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.model.ca;
+
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.TreeSet;
+import java.awt.Point;
+
+import schmitzm.lang.ComparableObject;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.AbstractWritableGrid;
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyWriteAccess;
+import schmitzm.data.property.ListPropertyReadAccess;
+import schmitzm.data.property.PropertyWriteAccess;
+
+import edu.bonn.xulu.data.XuluDataException;
+import edu.bonn.xulu.plugin.data.misc.CAArea;
+import edu.bonn.xulu.model.AbstractStepModel;
+import edu.bonn.xulu.model.AbstractModelContentManager;
+import edu.bonn.xulu.model.ValuePropertyResource;
+import edu.bonn.xulu.model.event.ModelIterationStepFinishedEvent;
+import edu.bonn.xulu.model.event.ModelIterationStepStartedEvent;
+
+// nur fuer Doku
+import edu.bonn.xulu.model.ModelContentManager;
+
+/**
+ * Dieses Modell stellt einen abstrakten zellularen Automaten (CA) dar,
+ * der auf Basis einer {@linkplain #getPreferenceValue(Point,int,CAArea,int) Bewertungsfunktion}
+ * die Expansion <b>eines</b> LUC-Typs simuliert. Es basiert auf folgenden
+ * Ressourcen:
+ * <ul>
+ *   <li>eine Liste mit Start-Regionen ({@link CAArea}), die die Startkonfiguration
+ *       des CA definiert (Siedlungen mit Einwohnerzahlen)</li>
+ *   <li>ein LUC-Typ U (<code>int</code>), dessen Ausbreitung simuliert wird</li>
+ *   <li>Anzahl T (<code>int</code>) der zu modellierender Schritte</li>
+ *   <li>ein Raster ({@link WritableGrid}) mit der initialen LUC</li>
+ *   <li>ein temp. Raster ({@link WritableGrid}), in dem vom Modell die Zuordnung
+ *       der simulierten U-Zellen zu den Regionen hinterlegt werden kann</li>
+ *   <li>ein optionales Ausgabe-Raster ({@link WritableGrid})</li>
+ *   <li>ein Schwellwert MIN_U (<code>int</code>), ab welche Eignungswert eine Zelle
+ *       fuer den LUC-Typ U geeignet ist</li>
+ * </ul>
+ * In jedem Zeitschritt wird iteriert bis Bedarf fuer alle Regionen gedeckt ist.
+ * In jeder Iteration wird jede Zelle des Regionen-Rand (initial die
+ * 8 Zellen um die jeweilige Start-Zelle) betrachtet und bewertet (durch die
+ * Methode {@link #getPreferenceValue(Point,int,CAArea,int)}). Alle fuer U in Frage kommenden
+ * Zellen werden (samt dem Bewertungswert) in einer (sortierten) Liste gespeichert.
+ * Nachdem alle Zellen im Rand betrachtet wurden, werden (reihum) solange die
+ * geeignetsten umgewandelt, bis der Bedarf gedeckt ist.<br>
+ * Fuer jede umgewandelte Zelle werden die 8 umgebenden Zellen in den
+ * Rand aufgenommen, sofern sie noch nicht durch das Modell umgewandelt
+ * wurden.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class MultiCellularAutomaton extends AbstractStepModel {
+  /** Anzahl an Ressourcen, die durch diese Modell-Oberklasse definiert sind. */
+  public static final int BASE_RESCOUNT = CAContentManager.BASE_RESCOUNT;
+
+  // Zugriffsrechte auf Ressourcen
+  private PropertyWriteAccess baseLUC_WA     = null;
+  private PropertyWriteAccess outLUC_WA      = null;
+  private PropertyWriteAccess areaMapping_WA = null;
+  private PropertyWriteAccess areaConf_WA    = null;
+
+  /** Ausgangs-Szenario.*/
+  protected WritableGrid baseLUC = null;
+  /** Ausgabe-Raster. Wenn die entsprechende optionale Ressource unbelegt bleibt,
+   *  ist <code>outLUC = baseLUC</code>. */
+  protected WritableGrid outLUC = null;
+  /** Anzahl der modellierten Gebiete/Siedlungen. */
+  protected int areaCount = 0;
+  /** Die modellierten Gebiete/Siedlungen (@linkplain CAArea Areas). */
+  protected ListPropertyWriteAccess areas = null;
+  /** Speichert die Zuordnung, welche Zelle welcher Area zugeordnet wurde. */
+  protected WritableGrid areaMapping = null;
+  /** LUC-Typ fuer den die Wechsel modelliert werden.<br>
+   *  <b>Bemerke:</b><br>
+   *  Wird in einer zukuenftigen Version ersetzt durch ein Feld in {@link CAArea},
+   *  so dass pro Gebiet/Siedlung unterschiedliche LUC-Typen expandiert werden
+   *  koennen. */
+  protected int luccType = 0;
+  /** Schwellwert der {@link #getPreferenceValue(Point,int,CAArea,int) Praeferenzfunktion}
+   *  ab dem eine Zelle fuer einen potentiellen LUC-Wechsel in Betracht gezogen wird.<br>
+   *  <b>Bemerke:</b><br>
+   *  Wird in einer zukuenftigen Version ersetzt durch ein Feld in {@link CAArea},
+   *  so dass pro Gebiet/Siedlung unterschiedliche Schwellwerte verwendet werden
+   *  koennen. */
+  protected double luccThreshold = 0.0;
+
+  /** Speichert die Groesse (in qm) eine Zelle des {@linkplain #baseLUC Untersuchungsgebiets}. */
+  protected double cellSize      = 0.0;
+
+  /** Definiert die Nachbarschaftsumgebung, ueber die der zellulare Automat
+   *  expandiert. Standardmaessig sind dies die 8 umgebenende Zellen. Kann
+   *  von Sub-Klassen neu definiert werden:
+   *  <ul>
+   *    <li><code>NEIGHBORHOOD_AREA[i,<b>0</b>]</code> definiert die relative <b>horizontale</b>
+   *      Position der i-ten Nachbarschaftszelle (z.B. 1 = eine Zelle weiter rechts,
+   *      -2 = zwei zellen weiter links als die betrachtete Zelle).</li>
+   *    <li><code>NEIGHBORHOOD_AREA[i,<b>1</b>]</code> definiert die relative <b>vertikale</b>
+   *      Position der i-ten Nachbarschaftszelle (z.B. 0 = gleiche Hoehe wie die betrachtete
+   *      Zelle, 1 = eine Zelle weiter unten).</li>
+   *  </ul>
+   *  <b>Bemerke:</b><br>
+   *  <code>NEIGHBORHOOD_AREA[i] = (0,0)</code> wuerde die betrachtete Zelle,
+   *  als einen ihrer eigenen Nachbarn identifizieren! Dies ist nicht sinnvoll
+   *  und wird vom zellularen Automaten abgefangen!
+   */
+  protected int[][] NEIGHBORHOOD_AREA = {
+//     oben    links   rechts   unten
+      { 0, 1},{-1, 0},{ 1, 0}, { 0,-1},
+//     li-ob   re-ob   li-un    re-un
+      {-1, 1},{ 1, 1},{-1,-1}, { 1,-1}
+  };
+
+  /** Speichert (aufsteigend soriert) die bewerteten Zellen fuer jede Area. */
+  private TreeSet[] bestCells = null;
+
+  private Vector<Point>[]  startCells = null;
+
+
+  /**
+   * Erzeugt einen neuen zellularen Automaten (CA).
+   * @param cm ContentManager fuer den CA.
+   */
+  public MultiCellularAutomaton(CAContentManager cm) {
+    super( cm );
+    // Iterations-Ereignisse der Event-Liste hinzufuegen
+    events.add(ModelIterationStepStartedEvent.class);
+    events.add(ModelIterationStepFinishedEvent.class);
+  }
+
+  /**
+   * Initialisiert das Modell.
+   */
+  public void performModelInit() {
+    //########## Lese/Schreib-Rechte auf Ressourcen ##########
+    // Schreibrecht auf Ausgangs-Szenario
+    baseLUC_WA = ((ScalarProperty)contManager.getResource(CAContentManager.BASELUC).getData()).getWriteAccess(this);
+    // Wenn kein Ausgabe-Raster angegeben wird, wird die Ausgabe in das
+    // Ausgangs-Szenatio geschrieben
+    if ( contManager.getResource(CAContentManager.OUTLUC).getData() == null )
+      outLUC_WA = null;
+    else
+      outLUC_WA = ((ScalarProperty)contManager.getResource(CAContentManager.OUTLUC).getData()).getWriteAccess(this);
+    // Schreibrecht auf Temp-Raster fuer Regionen-Zuordnung
+    areaMapping_WA = ((ScalarProperty)contManager.getResource(CAContentManager.AREAMAPPING).getData()).getWriteAccess(this);
+    // Leserecht auf Start-Konfiguration
+    areaConf_WA = ((ListProperty)contManager.getResource(CAContentManager.AREACONF).getData()).getWriteAccess(this);
+
+
+    //########## Ressourcen in lokalen Variablen verlinken ##########
+    stepCount     = ((ScalarProperty)contManager.getResource(CAContentManager.STEPCOUNT).getData()).getOneTimeReadAccess().getValueAsInt();
+    areas         = (ListPropertyWriteAccess)areaConf_WA;
+    areaCount     = areas.getCount();
+    luccType      = ((ScalarProperty)contManager.getResource(CAContentManager.LUCCTYPE).getData()).getOneTimeReadAccess().getValueAsInt();
+    luccThreshold = ((ScalarProperty)contManager.getResource(CAContentManager.THRESHOLD).getData()).getOneTimeReadAccess().getValueAsDouble();
+    baseLUC       = (WritableGrid)baseLUC_WA.getValue();
+    outLUC        = (outLUC_WA == null ) ? baseLUC : (WritableGrid)outLUC_WA.getValue();
+    areaMapping   = (WritableGrid)areaMapping_WA.getValue();
+
+    // Zellengroesse in qm
+    cellSize      = baseLUC.getCellWidth() * baseLUC.getCellWidth();
+
+
+    // modellierte Gebiete initialisieren (Border, Cover)
+    bestCells = new TreeSet[areaCount];
+    for (int i=0; i<areaCount; i++) {
+      CAArea area = (CAArea)areas.getValue(i);
+      area.init();
+      // Raster-Zelle des Start-Punkts in Rand aufnehmen
+      area.getBorder().add( new Point(
+        baseLUC.convertRealToRaster( area.getStartLocation().getX(), 0 ),
+        baseLUC.convertRealToRaster( area.getStartLocation().getY(), 1 )
+      ));
+
+      // Fuer jedes Gebiet werden erst alle Zellen des Rands bewertet und
+      // anschliessend der Reihe nach die besten umgewandelt.
+      bestCells[i] = new TreeSet<ComparableObject<Double, Point>> ();
+    }
+    // Zuordnungsraster (und ggf. das Ausgaberaster) initialisieren.
+    // Das Zuordnungsraster speichert, welche Zelle zu welcher Zone (Area) gehoert
+    int minX = areaMapping.getMinX();
+    int minY = areaMapping.getMinY();
+    for (int y=0; y<areaMapping.getHeight(); y++)
+      for (int x=0; x<areaMapping.getWidth(); x++) {
+        // am Anfang gehoert noch keine Zelle zu irgendeinem Gebiet
+        areaMapping.setRasterSample(-1,x+minX,y+minY);
+        // wenn ein spezielles Ausgabe-Raster verwendet wird, wird das
+        // Ursprungsszenarion dort rein kopiert
+        if ( outLUC != baseLUC )
+          outLUC.setRasterSample( baseLUC.getRasterSample(x+minX,y+minY), x+minX, y+minY);
+      }
+  }
+
+  /**
+   * Zerstoert das Modell. Alle gehaltenen Zugriffsrechte auf Ressourcen
+   * werden wieder freigegeben.
+   */
+  public void performModelDispose() {
+    releaseAccess(baseLUC_WA);
+    releaseAccess(outLUC_WA);
+    releaseAccess(areaMapping_WA);
+    releaseAccess(areaConf_WA);
+  }
+
+  /**
+   * Modelliert genau einen Zeitschritt.
+   * @param stepNo Nummer des Zeitschritts
+   */
+  public void performModelStep(int stepNo) {
+    if ( stepNo == 1 )
+      checkStartPoints();
+
+    // Iterieren, bis alle Gebiete die Anforderung erfuellen
+    boolean allAreasSatisfied = false;
+    for (int iterNo=1; !allAreasSatisfied; iterNo++) {
+      allAreasSatisfied = true;
+      // Iterations-Ereignis initiieren
+      this.fireModelEvent( new ModelIterationStepStartedEvent(this,stepNo,iterNo) );
+
+      // Fuer alle Gebiete den Rand bewerten
+      for (int areaNo=0; areaNo<areaCount; areaNo++) {
+        bestCells[areaNo].clear();
+        CAArea area = (CAArea)areas.getValue(areaNo);
+        // Gebiet nur bewerten, wenn Bedarf noch nicht gedeckt
+        // Bemerke: -1, da stepNo von 1 hochgezaehlt wird!
+        if ( area.isDemandSatisfied(stepNo-1) || area.isDeadlock() )
+          continue;
+        // ein Gebiet erfuellt den Bedarf noch nicht
+        allAreasSatisfied = false;
+
+        // Rand des Gebiets bewerten
+        for (int i = 0; i < area.getBorder().size(); i++) {
+          checkBreakingCommands();
+          Point p = area.getBorder().elementAt(i);
+          // Zelle kommt nur in Frage, wenn sie noch nicht zu der Area gehoert
+          // Diese Abfrage stellt eine Sicherheitsabfrage dar. Fall kann nur
+          // vorkommen, wenn die Startbereiche nicht aus dem Rand geloescht werden
+          // um den Bezug zum Start-Gebiet zu erhalten.
+          if ( areaMapping.getRasterSampleAsByte(p.x,p.y) == areaNo )
+            continue;
+
+          // Bewerten
+          double value = getPreferenceValue(p, luccType, area, areaNo);
+          if ( value >= luccThreshold )
+            bestCells[areaNo].add( new ComparableObject<Double, Point>(value, p) );
+        }
+
+        // Wenn keine geeigneten Zellen gefunden wurden, befindet sich der
+        // CA fuer dieses Gebiet in einem Deadlock!
+        if ( bestCells[areaNo].isEmpty() ) {
+          area.setDeadlock(true);
+          statusOut.println("Warning for area "+areaNo+": No suitable cells found in border! Automaton reached deadlock!");
+        }
+      }
+
+      // Reihum alle Gebiete expandieren
+      boolean allAreasExpanded = false;
+      for (int expRound=1; !allAreasExpanded; expRound++) {
+        allAreasExpanded = true;
+        for (int areaNo=0; areaNo<areaCount; areaNo++) {
+          checkBreakingCommands();
+          CAArea  area = (CAArea)areas.getValue(areaNo);
+          TreeSet best = bestCells[areaNo];
+          // Gebiet nur expandieren, wenn noch Bedarf noch nicht gedeckt und
+          // noch Randzellen uebrig
+          // Bemerke: -1, da stepNo von 1 hochgezaehlt wird!
+          if ( area.isDemandSatisfied(stepNo-1) || area.isDeadlock() || best.isEmpty() )
+            continue;
+          allAreasExpanded = false;
+
+          // Beste Zelle ermitteln
+          ComparableObject<Double,Point> o = (ComparableObject)best.last();
+          Point p = o.getObject();
+          // Zelle umwandeln
+          int prevLUC = outLUC.getRasterSampleAsInt(p.x,p.y);
+          outLUC.setRasterSample(luccType,p.x,p.y);
+          areaMapping.setRasterSample(areaNo,p.x,p.y);
+          area.incCurrentCover(cellSize);
+          // Umgewandelte Zelle aus Rand und besten Zellen (aller Areas!)
+          // entfernen
+          for (int i=0; i<areaCount; i++) {
+            bestCells[i].remove(o);
+            // Start-Punkte bleiben immer im Rand (damit Bezug zum Start - z.B.
+            // beim Brach-Fallen) nie verloren geht)
+            if ( !startCells[i].contains(p) )
+              ((CAArea)areas.getValue(i)).getBorder().remove(p);
+          }
+          // Umgebung der Zelle in Rand aufnehmen
+          addNeighborhoodToBorder(area,p);
+          // Sub-Klassen ermoeglichen, auf Aenderung zu reagieren
+          cellChanged(p,area,luccType,prevLUC);
+        }
+      }
+      this.fireModelEvent( new ModelIterationStepFinishedEvent(this,stepNo,iterNo) );
+//      showDifference(stepNo,iterNo);
+    }
+  }
+
+  /**
+   * Macht nichts. Wird aufgerufen, nachdem eine Zelle umgewandelt wurde.
+   * Sub-Klassen koennen diese Methode ueberschreiben, um auf die Umwandlung
+   * zu reagieren.
+   * @param p       Raster-Koordinaten der umgewandelten Zelle
+   * @param area    Gebiet dem die Zelle zugeordnet wurde
+   * @param newLUC  LUC-Typ, der der Zelle zugeordnet wurde
+   * @param prevLUC LUC-Typ, den die Zelle zuvor hatte
+   */
+  protected void cellChanged(Point p, CAArea area, int newLUC, int prevLUC) {
+
+  }
+
+  private void checkStartPoints() {
+      // Standardmaessig beginnt der CA an dem uebergebenen Startpunkt (Lat/Lon).
+      // Falls die Bewertung dieser Zelle nicht dem Schwellwert entspricht,
+      // iteriert sich der CA jedoch "zu Tode".
+      // Radius um die Startzelle vergroessern, bis eine akzeptable Startzelle
+      // gefunden wird
+      for (int a=0; a<areaCount; a++) {
+        CAArea area = (CAArea)areas.getValue(a);
+        Point p = area.getBorder().firstElement();
+        double val = this.getPreferenceValue(p,luccType,area,a);
+        if ( val < luccThreshold ) {
+          area.getBorder().clear();
+          for (int r=1; area.getBorder().isEmpty() && r<=10; r++) {
+            for (int y=p.y-r; y<=p.y+r; y++)
+              for (int x=p.x-r; x<=p.x+r; x++)
+                if ( x >= baseLUC.getMinX() && x < baseLUC.getMinX()+baseLUC.getWidth() &&
+                     y >= baseLUC.getMinY() && y < baseLUC.getMinY()+baseLUC.getHeight() ) {
+                  Point testPoint = new Point(x,y);
+                  val = this.getPreferenceValue(testPoint,luccType,area,a);
+                  if ( val >= luccThreshold )
+                    area.getBorder().add( testPoint );
+                }
+          }
+          // Warnmeldung geben, falls keine geeigneten Start-Zelle(n)
+          // gefunden wurden
+          if ( area.getBorder().isEmpty() ) {
+            area.setDeadlock(true);
+            statusOut.println("Warning for area "+a+": No suitable starting cell(s) found!");
+          }
+        }
+      }
+
+
+      // Start-Zellen merken
+      startCells = new Vector[areaCount];
+      for (int i=0; i<startCells.length; i++)
+        startCells[i] = (Vector) ((CAArea)areas.getValue(i)).getBorder().clone();
+  }
+
+
+  private void addNeighborhoodToBorder(CAArea area, Point p) {
+    // Umgebung der Zelle in Rand aufnehmen
+    for (int b = 0; b < NEIGHBORHOOD_AREA.length; b++) {
+      Point bp = new Point(p.x + NEIGHBORHOOD_AREA[b][0], p.y + NEIGHBORHOOD_AREA[b][1]);
+
+      if ( !bp.equals(p) && // Zelle entspricht nicht der betrachtaten Zelle
+           areaMapping.getRasterSampleAsByte(bp.x, bp.y) == -1 && // Zelle noch unbelegt
+           !area.getBorder().contains(bp) ) // Zelle noch nicht im Rand
+
+        area.getBorder().add(bp);
+    }
+  }
+
+
+//  private void showDifference(int step, int iter) {
+//    statusOut.print("After Iteration "+step+"/"+iter+":  ");
+//    for (int a=0; a<areaCount; a++) {
+//      CAArea area = (CAArea)areas.getValue(a);
+//      double diff = area.getInhabitants(step-1)*area.getDemandPerInhabitant() - area.getCurrentCover();
+//      statusOut.print("("+a+") "+diff+(area.isDeadlock() ? "*":"")+"\t");
+//    }
+//    statusOut.println();
+//  }
+
+  /**
+   * Bewertet eine Zelle des Untersuchungsgebiets hinsichtlich eines bestimmten
+   * LUC-Typs. Je groesser der Wert, desto geeigneter die Zelle fuer den
+   * LUC-Typ <code>luc</code>.
+   * @param p      Zelle des Untersuchungsgebiets
+   * @param luc    LUC-Typ hinsichtlich dessen die Bewertung durchgefuehrt wird
+   * @param area   CA-Gebiet fuer das die Bewertung durchgefuehrt wird
+   * @param areaNo Nummer des Gebiets
+   */
+  public abstract double getPreferenceValue(Point p, int luc, CAArea area, int areaNo);
+
+  /**
+   * Diese Klasse definiert einen {@link ModelContentManager} fuer einen
+   * {@linkplain MultiCellularAutomaton Multi-Zellularen-Automat} mit folgenden
+   * Ressourcen:
+   * <ol>
+   *   <li><b>StepCount (<code>int</code>)</b><br>
+   *       Spezifiziert die Anzahl zu modellierender Schritte.</li>
+   *   <li><b>LUC-Typ (<code>int</code>)</b><br>
+   *       Spezifiziert den LUC-Typ, dessen Wechsel durch den CA modelliert wird.<br>
+   *       <b>Bemerke:</b><br>
+   *       Wird in einer zukuenftigen Version ersetzt durch ein Feld in {@link CAArea},
+   *       so dass pro Gebiet/Siedlung unterschiedliche LUC-Typen expandiert werden
+   *       koennen.</li>
+   *   <li><b>Schwellwert (<code>double</code>)</b><br>
+   *       Spezifiziert den der {@link #getPreferenceValue(Point,int,CAArea,int) Praeferenzfunktion},
+   *       ab dem eine Zelle fuer einen potentiellen LUC-Wechsel in Betracht gezogen wird.<br>
+   *       <b>Bemerke:</b><br>
+   *       Wird in einer zukuenftigen Version ersetzt durch ein Feld in {@link CAArea},
+   *       so dass pro Gebiet/Siedlung unterschiedliche Schwellwerte verwendet werden
+   *       koennen.</li>
+   *  <li><b>Base-Scenario ({@link WritableGrid})</b><br>
+   *      Ausgangs-Szenarion (LUC) des Untersuchungsgebiets.</li>
+   *  <li><b>Startpunkte (<code>List[{@link CAArea}]</code>)</b><br>
+   *      Startpunkte (Gebiete/Siedlungen) des CA definiert.</li>
+   *  <li><b>Ausgabe-Raster ({@link WritableGrid})</b><br>
+   *      Nimmt die modellierte LUC auf (optional).</li>
+   *  <li><b>Area-Mapping ({@link WritableGrid})</b><br>
+   *      Wird dazu genutzt, die Zuordnung der modellierten Zellen zu den
+   *      Startpunkten (Gebiete/Siedlungen) zu speichern.</li>
+   * </ol>
+   * Fuer Sub-Klassen von {@link MultiCellularAutomaton} kann dieser Content-Manager
+   * um weitere Ressourcen erweitert werden.
+   */
+  public abstract static class CAContentManager extends AbstractModelContentManager {
+    /** Definiert die Anzahl der durch diesen Content-Manager definierten
+     *  Ressourcen */
+    public static final int    BASE_RESCOUNT         = 7;
+
+    /** ID der <code>int</code>-Ressource fuer die Anzahl zu modellierender Modell-Schritte. */
+    public static final int    STEPCOUNT             = 0;
+    /** Beschreibung fuer die {@link #STEPCOUNT}-Ressource. */
+    public static final String STEPCOUNT_DESC        = "Time steps (int)";
+
+    /** ID der <code>int</code>-Ressource fuer den LUC-Typ, dessen Wechsel durch den CA
+     *  simuliert wird. */
+    public static final int    LUCCTYPE              = 1;
+    /** Beschreibung fuer die {@link #LUCCTYPE}-Ressource. */
+    public static final String LUCCTYPE_DESC         = "Modelled LUC-Type (int)";
+
+    /** ID der <code>double</code>-Ressource fuer den Schwellwert der
+     *  {@link MultiCellularAutomaton#getPreferenceValue(Point,int,CAArea,int) Praeferenzfunktion},
+     *  ab dem eine Zelle fuer einen potentiellen LUC-Wechsel in Betracht gezogen wird. */
+    public static final int    THRESHOLD             = 2;
+    /** Beschreibung fuer die {@link #THRESHOLD}-Ressource. */
+    public static final String THRESHOLD_DESC        = "Preference threshold for LUCC (double)";
+
+    /** ID der {@link WritableGrid}-Ressource fuer das Ausgangsszenario des Untersuchungsgebiets. */
+    public static final int    BASELUC               = 3;
+    /** Beschreibung fuer die {@link #BASELUC}-Ressource. */
+    public static final String BASELUC_DESC          = "Base Scenario (Raster)";
+
+    /** ID der <code>List[{@link CAArea}]</code>-Ressource, die die Startpunkte
+     *  (Gebiete/Siedlungen) des CA definiert. */
+    public static final int    AREACONF              = 4;
+    /** Beschreibung fuer die {@link #AREACONF}-Ressource. */
+    public static final String AREACONF_DESC         = "Area configurations (CAArea-List)";
+
+    /** ID der (optionalen) {@link WritableGrid}-Ressource fuer das Raster, in dem
+     *  die Modell-Ausgabe hinterlegt wird. */
+    public static final int    OUTLUC                = 5;
+    /** Beschreibung fuer die {@link #OUTLUC}-Ressource. */
+    public static final String OUTLUC_DESC           = "Output Raster (optional)";
+
+    /** ID der (temporaeren) {@link WritableGrid}-Ressource fuer das Raster, in dem
+     *  die Zuordnung der modellierten LUC zu den Start-Punkten (Gebiete/Siedlungen)
+     *  hinterlegt wird. */
+    public static final int    AREAMAPPING           = 6;
+    /** Beschreibung fuer die {@link #AREAMAPPING}-Ressource. */
+    public static final String AREAMAPPING_DESC      = "Temp-Raster for area mapping";
+
+
+    /**
+     * Erzeugt einen neuen Content-Manager.
+     * @param addResourceCount Anzahl der zuseatzlichen durch eine Sub-Klasse
+     *                         definierten Ressourcen
+     */
+    public CAContentManager(int addResourceCount) {
+      super(BASE_RESCOUNT+addResourceCount);
+      if ( addResourceCount < 0 )
+        throw new IllegalArgumentException("Count of additional resources must be greater zero!");
+
+      // Anzahl Zeitschritte
+      resource[STEPCOUNT] = new ValuePropertyResource(ValuePropertyResource.CATEGORY_INPUT,STEPCOUNT_DESC,ScalarProperty.class,Integer.class,false);
+      // Modellierter LUC-Typ
+      resource[LUCCTYPE] = new ValuePropertyResource(ValuePropertyResource.CATEGORY_INPUT,LUCCTYPE_DESC,ScalarProperty.class,Integer.class,false);
+      // Schwellwert fuer LUCC-Bewertung
+      resource[THRESHOLD] = new ValuePropertyResource(ValuePropertyResource.CATEGORY_INPUT,THRESHOLD_DESC,ScalarProperty.class,Double.class,false);
+      // Raster fuer Base Szenario
+      resource[BASELUC] = new ValuePropertyResource(ValuePropertyResource.CATEGORY_INPUT | ValuePropertyResource.CATEGORY_OUTPUT,BASELUC_DESC,ScalarProperty.class,WritableGrid.class,false);
+      // Area-Konfiguration
+      resource[AREACONF] = new ValuePropertyResource(ValuePropertyResource.CATEGORY_INPUT | ValuePropertyResource.CATEGORY_OUTPUT,AREACONF_DESC,ListProperty.class,CAArea.class,false);
+      // Raster fuer Ausgabe
+      resource[OUTLUC] = new ValuePropertyResource(ValuePropertyResource.CATEGORY_OUTPUT,OUTLUC_DESC,ScalarProperty.class,WritableGrid.class,true);
+      // Temp-Raster um Area-Zuordnung zu speichern
+      resource[AREAMAPPING] = new ValuePropertyResource(ValuePropertyResource.CATEGORY_TEMP,AREAMAPPING_DESC,ScalarProperty.class,WritableGrid.class,false);
+    }
+
+    /**
+     * Prueft die Ressourcen-Zuordnung auf Korrektheit.
+     * <ol>
+     *   <li>Die Anzahl der simulierten Modell-Schritte muss > 0 sein.</li>
+     *   <li>Das Ausgabe-Raster muss das gleiche Format haben, wie das Ausgangsszenario.</li>
+     *   <li>Das temp. Raster fuer die Area-Zuordnung muss das gleiche Format haben, wie das Ausgangsszenario.</li>
+     *   <li>Alle Areas muessen ueber ausreichend Bedarfswerte verfuegen.</li>
+     * </ol>
+     */
+    public void checkAndError() {
+      super.checkAndError();
+
+      // Modellschritte muss > 0 sein
+      int stepCount = ((ScalarProperty)resource[STEPCOUNT].getData()).getOneTimeReadAccess().getValueAsInt();
+      if ( stepCount <= 0 )
+        throw new XuluDataException("Step count must be greater zero!");
+
+      // Wenn ein Ausgabe-Raster angegeben wird, muss dieses das gleiche Format haben,
+      // wie das Ausgangs-Szenario
+      if ( resource[OUTLUC].getData() != null )
+        AbstractWritableGrid.compareStructure(
+                        (WritableGrid)((ScalarProperty)resource[OUTLUC].getData()).getOneTimeReadAccess().getValue(),
+                        OUTLUC_DESC,
+                        (WritableGrid)((ScalarProperty)resource[BASELUC].getData()).getOneTimeReadAccess().getValue(),
+                        BASELUC_DESC,
+                        false
+        );
+
+      // Temp-Raster fuer die Region-Zuordnung muss das gleiche Format haben, wie
+      // das Ausgangs-Szenarion
+      AbstractWritableGrid.compareStructure(
+                      (WritableGrid)((ScalarProperty)resource[AREAMAPPING].getData()).getOneTimeReadAccess().getValue(),
+                      AREAMAPPING_DESC,
+                      (WritableGrid)((ScalarProperty)resource[BASELUC].getData()).getOneTimeReadAccess().getValue(),
+                      BASELUC_DESC,
+                      false
+      );
+
+    }
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/ca/agric/ImpetusCellularAutomaton.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/ca/agric/ImpetusCellularAutomaton.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/model/ca/agric/ImpetusCellularAutomaton.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,477 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.model.ca.agric;
+
+import java.awt.Point;
+import java.awt.geom.Point2D;
+import java.util.Vector;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.AbstractWritableGrid;
+
+import edu.bonn.xulu.plugin.data.misc.CAArea;
+import edu.bonn.xulu.plugin.data.misc.CASettlementArea;
+import edu.bonn.xulu.plugin.model.ca.MultiCellularAutomaton;
+import edu.bonn.xulu.model.ValuePropertyResource;
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.data.property.ListProperty;
+import edu.bonn.xulu.data.XuluDataException;
+import schmitzm.data.property.PropertyReadAccess;
+
+// nur fuer Doku
+import edu.bonn.xulu.model.ModelContentManager;
+
+/**
+ * Dieser zellulare Automat modelliert die Ausbreitung von Feldflaechen (Ackerland)
+ * im Impetus-Untersuchungsgebiet.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class ImpetusCellularAutomaton extends MultiCellularAutomaton {
+  // Zugriffsrechte auf Ressourcen
+  private PropertyReadAccess nutz_RA = null;
+  private PropertyReadAccess brach_RA = null;
+  private PropertyReadAccess dhm_RA = null;
+  private PropertyReadAccess dsm_RA  = null;
+  private PropertyReadAccess lucHist_WA  = null;
+
+  /** Raster mit Gelaende-Hoehe (DHM).*/
+  protected WritableGrid dhm = null;
+  /** Raster mit Gelaende-Neigung (DSM).*/
+  protected WritableGrid dsm = null;
+  /** Raster fuer LUC-Historie.*/
+  protected WritableGrid lucHist = null;
+
+  /**
+   * Erzeugt einen neuen CA.
+   */
+  public ImpetusCellularAutomaton() {
+    super( new CAContentManager() );
+  }
+
+  /**
+   * Initialisiert das Modell.
+   */
+  public void performModelInit() {
+    super.performModelInit();
+    //########## Lese/Schreib-Rechte auf Ressourcen ##########
+    // Leserecht auf Nutzungsdauer
+    nutz_RA = ((ScalarProperty)contManager.getResource(CAContentManager.NUTZSTEPS).getData()).getReadAccess(this);
+    // Leserecht auf Nutzungsdauer
+    brach_RA = ((ScalarProperty)contManager.getResource(CAContentManager.BRACHSTEPS).getData()).getReadAccess(this);
+    // Leserecht auf Hoehen-Modell
+    dhm_RA = ((ScalarProperty)contManager.getResource(CAContentManager.DHM).getData()).getReadAccess(this);
+    // Leserecht auf Neigungs-Modell
+    dsm_RA = ((ScalarProperty)contManager.getResource(CAContentManager.DSM).getData()).getReadAccess(this);
+    // Schreibrecht auf LUC-Historie
+    lucHist_WA = ((ScalarProperty)contManager.getResource(CAContentManager.LUCHISTORY).getData()).getReadAccess(this);
+
+    //########## Ressourcen in lokalen Variablen verlinken ##########
+    dhm = (WritableGrid)dhm_RA.getValue();
+    dsm = (WritableGrid)dsm_RA.getValue();
+    lucHist = (WritableGrid)lucHist_WA.getValue();
+
+    //########## Pro-Kopf-Bedarf ist (noch) nicht im Shape-File ##########
+//    double dpi = ((ScalarProperty)contManager.getResource(CAContentManager.QMDPI).getData()).getOneTimeReadAccess().getValueAsDouble();
+    // Bedarf pro Einwohner im Shape-File ist in ha angegeben
+    for (int a=0; a<areas.getCount(); a++)
+      ((CASettlementArea)areas.getValue(a)).setDemandToQMFactor(10000);
+
+    //########## Nutzungszeiten initialisieren ##########
+    for (int y=lucHist.getMinY(); y<lucHist.getMinY()+lucHist.getHeight(); y++)
+      for (int x=lucHist.getMinX(); x<lucHist.getMinX()+lucHist.getWidth(); x++)
+        lucHist.setRasterSample(0,x,y);
+  }
+
+  /**
+   * Zerstoert das Modell. Alle gehaltenen Zugriffsrechte auf Ressourcen
+   * werden wieder freigegeben.
+   */
+  public void performModelDispose() {
+    super.performModelDispose();
+    releaseAccess(nutz_RA);
+    releaseAccess(brach_RA);
+    releaseAccess(dhm_RA);
+    releaseAccess(dsm_RA);
+    releaseAccess(lucHist_WA);
+  }
+
+  /**
+   * Modelliert genau einen Zeitschritt.
+   * <ol>
+   *   <li>Zu Beginn wird fuer jede Zellen des Untersuchungsgebiets geprueft,
+   *       ob die maximale Nutzungsdauer erreicht ist. Ggf. faellt die Zelle
+   *       brach ({@link #checkBrache()}).</li>
+   *   <li>Es wird ein CA-Schritt modelliert ({@link MultiCellularAutomaton#performModelStep(int)}</li>
+   *   <li>Die Nutzungsdauer (LUC-Historie) wird fuer alle Zellen des
+   *       Untersuchungsgebiets um 1 erhoeht ({@link #incLUCHistory()})</li>
+   * </ol>
+   * @param stepNo Nummer des Zeitschritts
+   */
+  public void performModelStep(int stepNo) {
+    // Deadlock-Flag von allen Gebieten entfernt, da durch das Ablaufen der Brachezeiten
+    // u.U. ein Weiterlaufen moeglich wird
+    for (int a=0; a<areaCount; a++)
+      ((CASettlementArea)areas.getValue(a)).setDeadlock(false);
+
+    // Flaechen brach fallen lassen.
+    checkBrache();
+
+    // Status der Gebiete fuer diesesn Zeitschritt ausgeben
+    statusOut.print("Step "+stepNo+":\t");
+    for (int a=0; a<areaCount; a++) {
+      CASettlementArea area = (CASettlementArea)areas.getValue(a);
+      double demandHA = area.getDemandPerInhabitant()*area.getInhabitants(stepNo-1);
+      double coverHA  = area.getCurrentCover()/area.getDemandToQMFactor();
+      statusOut.print("("+a+") "+coverHA+"/"+demandHA+"ha \t");
+    }
+    statusOut.println();
+
+    // CA ausfuehren
+    super.performModelStep(stepNo);
+
+    // Nutzungszeiten erhoehen
+    incLUCHistory();
+  }
+
+  /**
+   * Setzt die LUC-Historie fuer eine Zelle auf 0 zurueck.
+   * @param p       Raster-Koordinaten der umgewandelten Zelle
+   * @param area    Gebiet dem die Zelle zugeordnet wurde
+   * @param newLUC  LUC-Typ, der der Zelle zugeordnet wurde
+   * @param prevLUC LUC-Typ, den die Zelle zuvor hatte
+   */
+  public void cellChanged(Point p, CASettlementArea area, int newLUC, int prevLUC) {
+    lucHist.setRasterSample(0, p.x, p.y);
+  }
+
+  /**
+   * Bewertet eine Zelle des Untersuchungsgebiets hinsichtlich des LUC-Typs
+   * 'Ackerland'. Folgende LUC-Typen stellen ein Ausschluss-Kriterium dar:
+   * <ul>
+   *   <li>0: Forest Dense</li>
+   *   <li>5: Inselberg mit Vegetation</li>
+   *   <li>8: Fluss</li>
+   *   <li>9: Flussbett</li>
+   *   <li>10: Dichte Siedlung</li>
+   *   <li>11: Lockere Siedlung</li>
+   *   <li>13: Inselberg</li>
+   * </ul>
+   * Daneben entstehen keine Acker-Flaechen in Zellen, die weiter als 5km
+   * vom Startpunkt der Siedlung (Area) entfernt sind oder deren Hangneigung
+   * 4� ueberschreitet.<br>
+   * Ein weiteres Ausschuluss-Kriterium stellen <i>Brache</i>-Zellen (14) dar,
+   * deren Brachezeit ({@link CAContentManager#BRACHSTEPS}) noch nicht
+   * erreicht wurde.<br>
+   * Alle anderen Zellen werden bewertet mit<br>
+   * <center><code>
+   *   value = 2 - distToStart/5000
+   * </code></center>
+   * wobei <code>distToStart</code> die Distanz (in m) zum Siedlungskern
+   * darstellt. Dies bewirkt, dass Zellen nahe des Siedlungskern generell
+   * bevorzugt werden (da 5000m Entfernung ein generelles Ausschlusskriterium
+   * darstellt, ist gewaehrleistet, dass <code>value</code> immer >= 1 ist!).
+   * @param p  zu bewertende Zelle des Untersuchungsgebiets.
+   * @param luc LUC-Typ hinsichtlich dessen die Bewertung durchgefuehrt wird
+   *            (wird nicht genutzt! Bewertung immer hinsichtlich Ackerland)
+   * @param area CA-Gebiet fuer das die Bewertung durchgefuehrt wird
+   * @param areaNo Nummer des Gebiets (wird nicht genutzt!)
+   */
+  public double getPreferenceValue(Point p, int luc, CAArea area, int areaNo) {
+    // Ausschuluss-Kriterium: aktuelle LUC
+    int currLUC  = outLUC.getRasterSampleAsInt(p.x,p.y);
+    int currHist = lucHist.getRasterSampleAsInt(p.x,p.y);
+
+    switch (currLUC) {
+      case 0: // Forest Dense
+      case 5: // Inselberg mit Vegetation
+      case 8: // Fluss
+      case 9: // Flussbett
+      case 10: // Dichte Siedlung
+      case 11: // Lockere Siedlung
+      case 13: // Inselberg
+               return 0;
+      case 14: // Brache (kommt nur in Frage, wenn Brachezeit bereits erreicht)
+               if ( currHist < brach_RA.getValueAsInt() )
+                 return 0;
+    }
+
+    // Ausschuss-Kriterium: > 4.0� Gelaendeneigung
+    float degree = dsm.getRasterSampleAsFloat(p.x,p.y);
+    if ( degree > 4.0 )
+      return 0;
+
+    // Ausschluss-Kriterium: 5km Distanz vom Siedlungskern
+    // -> Mittelpunkt der betrachteten Zelle betrachten
+    double realX = baseLUC.convertRasterToReal(p.x,0);
+    double realY = baseLUC.convertRasterToReal(p.y,1);
+    double distToStart = Math.abs(area.getStartLocation().distance(realX,realY));
+//    int startX = baseLUC.convertRealToRaster(area.getStartLocation().getX(),0);
+//    int startY = baseLUC.convertRealToRaster(area.getStartLocation().getY(),1);
+//    double distToStart = Math.sqrt(Math.pow(startX-p.x,2)+Math.pow(startY-p.y,2))*baseLUC.getCellWidth();
+    if ( distToStart > 5000 )
+      return 0.0;
+
+    // alle anderen Zellen geeignet
+    return 2 - distToStart/5000;
+  }
+
+
+  /**
+   * Prueft fuer jede Zelle des Untersuchungsgebiets, ob die maximale
+   * Nutzungsdauer erreicht ist. Ist dies der Fall faellt die Zelle brach,
+   * d.h. sie wird in den Typ 14 (Brache) umgewandelt.
+   */
+  protected void checkBrache() {
+    Vector<Point> brachCells = new Vector<Point>();
+
+    //###########################################################
+    // Folgender Abschnitt fuegt nur Brach-Zellen in die Border-
+    // Mengen ein, die (NACH dem Brachfallen) noch in der
+    // Nachbarschaft einer Area liegen.
+    //###########################################################
+    // Alle Zellen identifizieren, die brach fallen muessen. Diese werden in
+    // einer Liste zwischen gespeichert, um anschliessend wieder in die
+    // Border-Menge der Areas eingefuegt zu werden
+    // Bemerke: Dies kann nicht on-the-fly geschehen, da die Nachbarzellen
+    //          der brach-gefallenen Zellen auch noch brach fallen koennen!
+    for (int y=lucHist.getMinY(); y<lucHist.getMinY()+lucHist.getHeight(); y++)
+      for (int x=lucHist.getMinX(); x<lucHist.getMinX()+lucHist.getWidth(); x++) {
+        checkBreakingCommands();
+        int currLUC  = outLUC.getRasterSampleAsInt(x,y);
+        int currArea = areaMapping.getRasterSampleAsByte(x,y);
+        int steps    = lucHist.getRasterSampleAsInt(x,y);
+        // wenn Zelle noch nicht brach ist und Nutzungsdauer erreichen, faellt
+        // sie brach (Flaeche des "Besitzer"-Gebiets wird reduziert)
+        if ( currLUC == luccType && // evt. hier noch den anderen Feld-Typ 14 beruecksichtigen
+             steps >= nutz_RA.getValueAsInt() ) {
+          outLUC.setRasterSample(14,x,y);
+          lucHist.setRasterSample(0,x,y);
+          areaMapping.setRasterSample(-1,x,y);
+          ((CASettlementArea)areas.getValue(currArea)).decCurrentCover(cellSize);
+          // alle brach gefallenen Zellen merken
+          brachCells.add( new Point(x,y) );
+        }
+      }
+
+    // Brach-gefallene Zellen in die Border-Menge der angrenzenden Areas einfuegen
+    for (int i=0; i<brachCells.size(); i++) {
+      Point p = brachCells.elementAt(i);
+      // Umgebung der Zelle betrachten
+      // > Wenn eine Area angrenzt, wird die Zelle deren Border-Menge hinzugefuegt
+      for (int n = 0; n<NEIGHBORHOOD_AREA.length; n++) {
+        checkBreakingCommands();
+        Point np = new Point(p.x+NEIGHBORHOOD_AREA[n][0],p.y+NEIGHBORHOOD_AREA[n][1]);
+        int areaIdx = areaMapping.getRasterSampleAsByte(np.x,np.y);
+        if ( areaIdx >= 0 ) {
+          CASettlementArea area = (CASettlementArea)areas.getValue(areaIdx);
+          if ( !area.getBorder().contains(p) )
+            area.getBorder().add(p);
+        }
+      }
+    }
+
+//    //###########################################################
+//    // Folgender Abschnitt fuegt ALLE Brach-Zellen in die Border-
+//    // Mengen ein.
+//    //###########################################################
+//    // Alle Zellen identifizieren, die brach fallen muessen. Diese werden in
+//    // einer Liste zwischen gespeichert, um anschliessend die Area-Zuordnung
+//    // zu loeschen.
+//    // Bemerke: Dies kann nicht on-the-fly geschehen, da die bestehende
+//    //          Nachbarschaftsbeziehung fuer die Border-Zuordnung noch benoetigt
+//    //          wird.
+//    for (int y=lucHist.getMinY(); y<lucHist.getMinY()+lucHist.getHeight(); y++)
+//      for (int x=lucHist.getMinX(); x<lucHist.getMinX()+lucHist.getWidth(); x++) {
+//        int currLUC  = outLUC.getRasterSampleAsInt(x,y);
+//        int currArea = areaMapping.getRasterSampleAsByte(x,y);
+//        int steps    = lucHist.getRasterSampleAsInt(x,y);
+//        // wenn Zelle noch nicht brach ist und Nutzungsdauer erreichen, faellt
+//        // sie brach (Flaeche des "Besitzer"-Gebiets wird reduziert)
+//        if ( currLUC == luccType && // evt. hier noch den anderen Feld-Typ 14 beruecksichtigen
+//             steps >= nutz_RA.getValueAsInt() ) {
+//          Point p = new Point(x,y);
+//          brachCells.add( p ); // alle brach gefallenen Zellen merken
+//          outLUC.setRasterSample(14,x,y);
+//          lucHist.setRasterSample(0,x,y);
+//          ((CASettlementArea)areas.getValue(currArea)).decCurrentCover(cellSize);
+//          // Zelle in Border der angrenzenden Areas einfuegen
+//          for (int n = 0; n<NEIGHBORHOOD_AREA.length; n++) {
+//            checkBreakingCommands();
+//            Point np = new Point(p.x+NEIGHBORHOOD_AREA[n][0],p.y+NEIGHBORHOOD_AREA[n][1]);
+//            int areaIdx = areaMapping.getRasterSampleAsByte(np.x,np.y);
+//            if ( areaIdx >= 0 ) {
+//              CASettlementArea area = (CASettlementArea)areas.getValue(areaIdx);
+//              if ( !area.getBorder().contains(p) )
+//                area.getBorder().add(p);
+//            }
+//          }
+//      }
+//    }
+//
+//    // Area-Zuordnung der brach-gefallene Zellen loeschen
+//    for (int i=0; i<brachCells.size(); i++) {
+//      Point p = brachCells.elementAt(i);
+//      areaMapping.setRasterSample(-1,p.x,p.y);
+//    }
+
+  }
+
+  /**
+   * Erhoeht die Nutzungsdauer aller Zellen im Untersuchungsgebiet um 1.
+   */
+  protected void incLUCHistory() {
+    for (int y=lucHist.getMinY(); y<lucHist.getMinY()+lucHist.getHeight(); y++)
+      for (int x=lucHist.getMinX(); x<lucHist.getMinX()+lucHist.getWidth(); x++) {
+        checkBreakingCommands();
+        lucHist.setRasterSample( lucHist.getRasterSampleAsInt(x,y)+1 ,x,y);
+      }
+  }
+
+
+  /**
+   * Diese Klasse definiert einen {@link ModelContentManager} fuer den
+   * {@linkplain ImpetusCellularAutomaton Impetus-Zellularen-Automat}. Neben den
+   * durch die Oberklasse spezifizierten Ressourcen, definiert dieser Content-Manager
+   * folgende:
+   * <ol>
+   *  <li><b>Nutzungsdauer (<code>int</code>)</b><br>
+   *      Bestimmt nach wie vielen Modellschritten der Nutzung eine modellierte
+   *      Zelle wieder brach faellt.</li>
+   *  <li><b>Brachezeit (<code>int</code>)</b><br>
+   *      Bestimmt nach wie vielen Modellschritten eine brach-gefallene Zelle
+   *      wieder genutzt werden kann.</li>
+   *  <li><b>Hoehen-Modell ({@link WritableGrid})</b><br>
+   *      Hoehen-Modell (DHM) des Untersuchungsgebiets.</li>
+   *  <li><b>Neigungs-Modell ({@link WritableGrid})</b><br>
+   *      Gelaendeneigung des Untersuchungsgebiets.</li>
+   *  <li><b>LUC-Historie ({@link WritableGrid})</b><br>
+   *      Speichert (temporaer) die Dauer, wie lange sich eine jede Zelle
+   *      unter der aktuellen LUC befindet.</li>
+   * </ol>
+   * Fuer Sub-Klassen von {@link MultiCellularAutomaton} kann dieser Content-Manager
+   * um weitere Ressourcen erweitert werden.
+   */
+  public static class CAContentManager extends MultiCellularAutomaton.CAContentManager {
+//    /** ID der <code>int</code>-Ressource, die den Bedarf pro Einwohner
+//     *  (in qm) definiert. */
+//    public static final int    QMDPI                 = BASE_RESCOUNT + 0;
+//    /** Beschreibung fuer die {@link #QMDPI}-Ressource. */
+//    public static final String QMDPI_DESC            = "qm-Demand per Inhabitant (int)";
+
+    /** ID der {@link Long}-Ressource, in der die Nutzungsdauer des modellierten
+     *  LUC-Typs hinterlegt ist (nach der angegebenen Anzahl an Modellschritten
+     *  faellt das Land brach).
+     */
+    public static final int NUTZSTEPS = BASE_RESCOUNT + 0;
+    /** Beschreibung fuer die {@link #NUTZSTEPS}-Ressource. */
+    public static final String NUTZSTEPS_DESC = "Nutzungsdauer (int)";
+
+    /** ID der {@link Long}-Ressource, in der die Brachezeit des modellierten
+     *  LUC-Typs hinterlegt ist. Nachdem eine Zelle brach gefallen ist, kann sie
+     *  erst nach dieser Anzahl an Modellschritten wiederverwendet werden. */
+    public static final int BRACHSTEPS = BASE_RESCOUNT + 1;
+    /** Beschreibung fuer die {@link #BRACHSTEPS}-Ressource. */
+    public static final String BRACHSTEPS_DESC = "Brachezeit (int)";
+
+      /** ID der {@link WritableGrid}-Ressource fuer das Raster, in dem
+     *  das digitale Gelaendemodell hinterlegt ist. */
+    public static final int    DHM = BASE_RESCOUNT + 2;
+    /** Beschreibung fuer die {@link #DHM}-Ressource. */
+    public static final String DHM_DESC = "Height raster (WritableGrid)";
+
+    /** ID der {@link WritableGrid}-Ressource fuer das Raster, in dem
+     *  die Gelaendeneigung hinterlegt ist. */
+    public static final int    DSM = BASE_RESCOUNT + 3;
+    /** Beschreibung fuer die {@link #DSM}-Ressource. */
+    public static final String DSM_DESC = "Slope raster (WritableGrid)";
+
+    /** ID der {@link WritableGrid}-Ressource fuer das Raster, in dem
+     *  die aktuelle Nutzungsdauer der Zellen hinterlegt wird. */
+    public static final int    LUCHISTORY = BASE_RESCOUNT + 4;
+    /** Beschreibung fuer die {@link #LUCHISTORY}-Ressource. */
+    public static final String LUCHISTORY_DESC              = "Temp: LUC history (WritableGrid)";
+
+    public CAContentManager() {
+      super(5);
+//      // Bedarf pro Einwohner
+//      resource[QMDPI] = new ValuePropertyResource(ValuePropertyResource.CATEGORY_INPUT,QMDPI_DESC,ScalarProperty.class,Double.class,false);
+
+      // Area-Konfiguration der Oberklasse verfeinern (muss CASettlementArea enthalten!)
+      resource[AREACONF] = new ValuePropertyResource(ValuePropertyResource.CATEGORY_INPUT | ValuePropertyResource.CATEGORY_OUTPUT,AREACONF_DESC,ListProperty.class,CASettlementArea.class,false);
+      // Nutzungsdauer (in Modellschritten)
+      resource[NUTZSTEPS] = new ValuePropertyResource(ValuePropertyResource.CATEGORY_INPUT,NUTZSTEPS_DESC,ScalarProperty.class,Integer.class,false);
+      // Brachezeit (in Modellschritten)
+      resource[BRACHSTEPS] = new ValuePropertyResource(ValuePropertyResource.CATEGORY_INPUT,BRACHSTEPS_DESC,ScalarProperty.class,Integer.class,false);
+      // Gelaendemodell
+      resource[DHM] = new ValuePropertyResource(ValuePropertyResource.CATEGORY_INPUT,DHM_DESC,ScalarProperty.class,WritableGrid.class,false);
+      // Gelaendeneigung
+      resource[DSM] = new ValuePropertyResource(ValuePropertyResource.CATEGORY_INPUT,DSM_DESC,ScalarProperty.class,WritableGrid.class,false);
+      // LUC-History
+      resource[LUCHISTORY] = new ValuePropertyResource(ValuePropertyResource.CATEGORY_TEMP,LUCHISTORY_DESC,ScalarProperty.class,WritableGrid.class,false);
+    }
+
+    /**
+     * Prueft die Ressourcen-Zuordnung auf Korrektheit. Neben den Checks der
+     * Oberklasse werden folgende Sachverhalte geprueft:
+     * <ol>
+     *   <li>Das Raster mit dem Gelaendemodell muss das gleiche Format haben, wie das Ausgangsszenario.</li>
+     *   <li>Das Raster mit der Gelaendeneigung muss das gleiche Format haben, wie das Ausgangsszenario.</li>
+     * </ol>
+     */
+    public void checkAndError() {
+      super.checkAndError();
+
+//      // Einwohner-Bedarf muss > 0 sein
+//      double dpi = ((ScalarProperty)resource[QMDPI].getData()).getOneTimeReadAccess().getValueAsDouble();
+//      if ( dpi <= 0 )
+//        throw new XuluDataException("Demand per inhabitant must be greater zero!");
+
+      // Nutzungsdauer muss > 0 sein
+      long nutz = ((ScalarProperty)resource[NUTZSTEPS].getData()).getOneTimeReadAccess().getValueAsInt();
+      if ( nutz <= 0 )
+        throw new XuluDataException("'Nutzungsdauer' must be greater zero!");
+
+      // Nutzungsdauer muss > 0 sein
+      long brach = ((ScalarProperty)resource[BRACHSTEPS].getData()).getOneTimeReadAccess().getValueAsInt();
+      if ( brach <= 0 )
+        throw new XuluDataException("'Brachezeit' must be greater zero!");
+
+      // Raster fuer das Gelaendemodell muss das gleiche Format haben, wie
+      // das Ausgangs-Szenarion
+      AbstractWritableGrid.compareStructure(
+                      (WritableGrid)((ScalarProperty)resource[DHM].getData()).getOneTimeReadAccess().getValue(),
+                      DHM_DESC,
+                      (WritableGrid)((ScalarProperty)resource[BASELUC].getData()).getOneTimeReadAccess().getValue(),
+                      BASELUC_DESC,
+                      false );
+
+      // Raster fuer die Gelaendeneigung muss das gleiche Format haben, wie
+      // das Ausgangs-Szenarion
+      AbstractWritableGrid.compareStructure(
+                      (WritableGrid)((ScalarProperty)resource[DSM].getData()).getOneTimeReadAccess().getValue(),
+                      DSM_DESC,
+                      (WritableGrid)((ScalarProperty)resource[BASELUC].getData()).getOneTimeReadAccess().getValue(),
+                      BASELUC_DESC,
+                      false );
+
+      // Raster fuer die LUC-History muss das gleiche Format haben, wie
+      // das Ausgangs-Szenarion
+      AbstractWritableGrid.compareStructure(
+                      (WritableGrid)((ScalarProperty)resource[LUCHISTORY].getData()).getOneTimeReadAccess().getValue(),
+                      LUCHISTORY_DESC,
+                      (WritableGrid)((ScalarProperty)resource[BASELUC].getData()).getOneTimeReadAccess().getValue(),
+                      BASELUC_DESC,
+                      false );
+    }
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/ca/fire/ImpetusFireCA.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/ca/fire/ImpetusFireCA.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/model/ca/fire/ImpetusFireCA.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,940 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.model.ca.fire;
+
+import java.util.Map;
+import java.util.Vector;
+import java.util.HashMap;
+import java.util.Random;
+import java.util.GregorianCalendar;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.awt.Component;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Dimension;
+import java.awt.GridBagLayout;
+import java.awt.BorderLayout;
+import java.awt.GridBagConstraints;
+import java.awt.Insets;
+import javax.swing.JLabel;
+import javax.swing.JSlider;
+import javax.swing.JTable;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.ChangeEvent;
+
+import org.geotools.feature.FeatureCollection;
+import org.geotools.feature.FeatureIterator;
+import org.geotools.feature.Feature;
+
+import com.vividsolutions.jts.geom.Envelope;
+import com.vividsolutions.jts.geom.Geometry;
+import com.vividsolutions.jts.geom.Point;
+import com.vividsolutions.jts.geom.MultiPoint;
+
+import edu.bonn.xulu.data.DynamicXuluObject;
+import edu.bonn.xulu.model.AbstractStepModel;
+import edu.bonn.xulu.plugin.data.feature.SingleFeatureCollection;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.PropertyWriteAccess;
+import schmitzm.data.property.ListPropertyReadAccess;
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.MatrixProperty;
+import schmitzm.lang.LangUtil;
+import schmitzm.swing.CaptionsChangeable;
+import schmitzm.swing.JPanel;
+import schmitzm.swing.InputCompass;
+import schmitzm.swing.SliderSpinnerPanel;
+
+import edu.bonn.xulu.model.event.ModelIterationStepStartedEvent;
+import edu.bonn.xulu.model.event.ModelIterationStepFinishedEvent;
+
+import org.apache.log4j.Logger;
+import schmitzm.lang.ResourceProvider;
+import edu.bonn.xulu.XuluModellingPlatform;
+import java.util.Locale;
+
+/**
+ * Diese Klasse stellt eine Implementierung des Modells {@linkplain ImpetusFireCA}
+ * dar. Dieses benoetigt 7 Ressourcen, welche durch den
+ * {@linkplain ImpetusFireCAContentManager} spezifiziert werden:
+ * <ol>
+ * <li><b>Allgemeine Modell-Parameter ({@code modelParam}):</b>
+ *     Dynamisches Xulu-Objekt mit folgenden Propertys:
+ *     <ul>
+ *     <li><b>Modeltime</b> (int): Anzahl der zu modellierenden Stunden.</li>
+ *     <li><b>LUC_Burning</b> (int): Nummer des LUC-Typs, mit dem die brennenden Zellen
+ *            im Ausgabe-Raster markiert werden.</li>
+ *     <li><b>LUC_BurnedOut</b> (int): Nummer des LUC-Typs, mit dem die ausgebrannten Zellen
+ *            im Ausgabe-Raster markiert werden.</li>
+ *     <li><b>BurnSuitability</b> (double-Liste): Brenn-Wahrscheinlichkeit pro LUC-Typ (globale
+ *            Brenneignung).</li>
+ *     <li><b>BurnTime</b> (double-Liste): Zeit in Stunden pro LUC-Typ, die eine Zelle brennt,
+ *            bevor sie als "burned out" markiert wird.</li>
+ *     <li><b>WindDirection</b> (double): Windrichtung in Grad (Nord = 0Grad, West = 90Grad)</li>
+ *     <li><b>WindPower</b> (double): Windstaerke in m/s. Zur Zeit wird die
+ *            Windstaerke als Ausbreitungsgeschwindigkeit des Feuers verwendet,
+ *            was nicht realistisch ist! Eine Umrechnung von Wind- in Ausbreitungsgeschwindigkeit
+ *            ist noch nicht implementiert.</li>
+ *     <li><b>WindDirectionDev</b> (double): Max. Abweichung der Windrichtung in Grad.</li>
+ *     <li><b>WindPowerDev</b> (double): Max. Abweichung der Windstaerke in m/s (Boeigkeit).</li>
+ *     <li><b>WindPowerMaxBack</b> (double): Windstaerke in m/s ab der kein Rueckschreiten des
+ *            Feuers (entgegen der Windrichtung) mehr moeglich ist.</li>
+ *     </ul>
+ *     </li>
+ * <li><b>Brandherde ({@code startPoints}):</b>
+ *     FeatureCollection (z.B. aus Shape-File) mit ein oder mehreren georeferenzierten
+ *     Punkten, die als Startpunkte fuer die Feuer-Ausbreitung verwendet werden.
+ *     </li>
+ * <li><b>LUC Classification ({@code baseLUC}):</b>
+ *     Raster mit LUC-Klassifikation (Ausgangsszenario).
+ *     </li>
+ * <li><b>Brenn-Eignung ({@code burnFit}, optional):</b>
+ *     Raster mit Brenn-Wahrscheinlichkeiten pro Zelle (lokale Brenneignung)..
+ *     </li>
+ * <li><b>Ausgabe-Raster fuer modellierte LUC ({@code outLUC}):</b>
+ *     Raster, in dem die modellierte LUC ("burning" und "burned out") hinterlegt
+ *     wird.
+ *     </li>
+ * <li><b>Ausgabe-Raster fuer verbrannte Biomasse ({@code outBurnMass}, optional):</b>
+ *     Raster, in dem die verbrannte Biomasse pro Zelle hinterlegt wird.
+ *     Wird zur Zeit noch nicht genutzt!
+ *     </li>
+ * <li><b>Temp-Raster fuer Brenn-Zeit ({@code burnTime}):</b>
+ *     Raster, in dem waehrend des Modellablaufs die Zeiten hinterlegt werden,
+ *     die eine Zelle brennt, um die Zellen "irgendwann" als ausgebrannt zu
+ *     markieren.
+ *     </li>
+ * </ol>
+ * @see ImpetusFireCAContentManager
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class ImpetusFireCA extends AbstractStepModel {
+  /** {@link ResourceProvider}, der die Uebersetzungen fuer die GUI
+   *  bereitstellt: {@code locales.XuluModel_ImpetusFireCA} */
+  protected static ResourceProvider RESOURCE = XuluModellingPlatform.registerResourceProvider("XuluModel_ImpetusFireCA",Locale.ENGLISH);
+
+  /** Logger fuer Debug-Ausgaben und Warnings. */
+  public static final Logger LOGGER = LangUtil.createLogger(ImpetusFireCA.class);
+
+  public static final String PARAM_PROP_MODELTIME  = "Modeltime";
+  public static final String PARAM_PROP_BURNLUC    = "LUC_Burning";
+  public static final String PARAM_PROP_BURNOUTLUC = "LUC_BurnedOut";
+  public static final String PARAM_PROP_BURNSUIT   = "BurnSuitability";
+  public static final String PARAM_PROP_BURNTIME   = "BurnTime";
+//  public static final String PARAM_PROP_WINDMATRIX = "WindMatrix";
+  public static final String PARAM_PROP_WINDDIRECTION     = "WindDirection";
+  public static final String PARAM_PROP_WINDPOWER         = "WindPower";
+  public static final String PARAM_PROP_WINDDIRECTIONDEV  = "WindDirectionDev";
+  public static final String PARAM_PROP_WINDPOWERDEV      = "WindPowerDev";
+  public static final String PARAM_PROP_WINDPOWERMAXBW    = "WindPowerMaxBack";
+  public static final String PARAM_PROP_WINDMATRIX_PCONST = "WindMatrix_PowerConst";
+  public static final String PARAM_PROP_WINDMATRIX_PFACT  = "WindMatrix_PowerFact";
+
+  /** Speichert den ContentManager fuer das Modell.
+   *  @see ImpetusFireCAContentManager */
+  protected ImpetusFireCAContentManager contManager;
+
+  //********** Lese/Schreibrechte, die fuer den gesamten ***********
+  //********** Modellanlauf gehalten werden muessen      ***********
+  private PropertyReadAccess   RA_startPoints = null;  // Brandherde
+  private PropertyReadAccess   RA_baseLUC = null;  // LUC Classification
+  private PropertyReadAccess   RA_burnSuitability = null;  // Brenn-Eignung
+  private PropertyWriteAccess  WA_outLUC = null;  // Ausgabe-Raster für modellierte LUC
+  private PropertyWriteAccess  WA_outBurnMass = null;  // Ausgabe-Raster für verbrannte Biomasse
+  private PropertyWriteAccess  WA_burnTime = null;  // Temp-Raster für Brenn-Zeit
+
+  //**************** Variablen mit denen gearbeitet wird *******************
+  protected  DynamicXuluObject  modelParam = null; // Allgemeine Modell-Parameter
+  protected  FeatureCollection  startPoints = null; // Bandherde
+  protected  WritableGrid       baseLUC = null; // LUC Classification
+  protected  WritableGrid       burnSuitability = null; // Brenn-Eignung
+  protected  WritableGrid       outLUC = null; // Ausgabe-Raster für modellierte LUC
+  protected  WritableGrid       outBurnMass = null; // Ausgabe-Raster für verbrannte Biomasse
+  protected  WritableGrid       burnTime = null; // Temp-Raster für Brenn-Zeit
+
+  protected  int                areaMinX = 0;
+  protected  int                areaMaxX = 0;
+  protected  int                areaMinY = 0;
+  protected  int                areaMaxY = 0;
+  protected  double             cellSize = 0;
+  protected  int                lucCount = 0;
+  protected  int                burningLUC = 0;
+  protected  int                burnedOutLUC = 0;
+  protected  double[]           lucBurningSuitability = null;
+  protected  double[]           lucBurningTime = null;
+  protected  double[]           windMatrix = new double[8]; // Wind-Matrix als Liste (ohne Zentrum)
+  protected  double             windMatrix_powerConst = 0;
+  protected  double             windMatrix_powerFact  = 0;
+  protected  double             windDir = 0; // Windrichtung
+  protected  double             windDirDev = 0; // max. Abw. Windrichtung
+  protected  double             windPow = 0; // Windstaerke
+  protected  double             windPowDev = 0; // max. Abw. Windstaerke
+  protected  double             windPowMaxBW = 0; // Windstaerke ab der kein Rueckschreiten mehr moeglich ist
+  protected  int                iterCount = 0;
+  protected  double             iterSeconds = 0;
+
+  protected double              MAX_lucBurningSuitability = 0;
+  protected double              MAX_windMatrix = 0;
+  protected double              MAX_burningSuitability = 0;
+
+  // Nachbar-Zellen relativ zur Zentrum-Zelle
+  private  static final int[][] NEIGHBOR = new int[][] {
+      {-1,-1}, {0,-1}, {1,-1},
+      {-1, 0},         {1, 0},
+      {-1, 1}, {0, 1}, {1, 1}
+  };
+
+  protected  Vector<int[]>         burningCells = new Vector<int[]>();
+  protected  Vector<int[]>         uselessBurningCells = new Vector<int[]>();
+  protected  HashMap<int[],Object> newBurningCells = new HashMap<int[],Object>();
+
+  // Modell-Spezifische GUI
+  protected  Component modelGUI = null;
+
+  /**
+   * Erzeugt eine neue Instanz des Modells.
+   */
+  public ImpetusFireCA() {
+    super( new ImpetusFireCAContentManager() );
+    contManager = (ImpetusFireCAContentManager)super.contManager;
+    modelResourceProvider = RESOURCE;
+
+    // Iterations-Ereignisse der Event-Liste hinzufuegen
+    events.add(ModelIterationStepStartedEvent.class);
+    events.add(ModelIterationStepFinishedEvent.class);
+    // GUI erzeugen
+    modelGUI = new GUI();
+    modelGUI.setEnabled(false);
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////   Implementierung von AbstractXuluModel   //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Initialisiert das Model, indem die Ressourcen aus dem ContentManager
+   * geladen werden und mit Lese/Schreib-Rechten versehen werden. Zudem
+   * werden Referenzen auf die Ressourcen in lokalen Variablen
+   * gespeichert, um waehrend des Modellablaufs effizienter darauf zugreifen
+   * zu koennen.
+   */
+  public void performModelInit() {
+    if ( contManager == null )
+      return;
+    // Zugriffsrechte aus Ressourcen/Propertys holen
+    RA_startPoints = null;
+    if ( contManager.getResource(1).getData() != null )
+      RA_startPoints = ((ScalarProperty)((SingleFeatureCollection)contManager.getResource(1).getData()).getProperty("FEATURES")).getReadAccess(this);
+    RA_baseLUC = null;
+    if ( contManager.getResource(2).getData() != null )
+      RA_baseLUC = ((ScalarProperty)contManager.getResource(2).getData()).getReadAccess(this);
+    RA_burnSuitability = null;
+    if ( contManager.getResource(3).getData() != null )
+      RA_burnSuitability = ((ScalarProperty)contManager.getResource(3).getData()).getReadAccess(this);
+    WA_outLUC = null;
+    if ( contManager.getResource(4).getData() != null )
+      WA_outLUC = ((ScalarProperty)contManager.getResource(4).getData()).getWriteAccess(this);
+    WA_outBurnMass = null;
+    if ( contManager.getResource(5).getData() != null )
+      WA_outBurnMass = ((ScalarProperty)contManager.getResource(5).getData()).getWriteAccess(this);
+    WA_burnTime = null;
+    if ( contManager.getResource(6).getData() != null )
+      WA_burnTime = ((ScalarProperty)contManager.getResource(6).getData()).getWriteAccess(this);
+
+    // Variablen belegen mit denen gearbeitet wird
+    modelParam      = (DynamicXuluObject)contManager.getResource(0).getData();
+    startPoints     = (FeatureCollection)RA_startPoints.getValue();
+    baseLUC         = (WritableGrid)RA_baseLUC.getValue();
+    areaMinX        = baseLUC.getMinX();
+    areaMaxX        = baseLUC.getMinX() + baseLUC.getWidth() - 1;
+    areaMinY        = baseLUC.getMinY();
+    areaMaxY        = baseLUC.getMinY() + baseLUC.getHeight() - 1;
+    cellSize        = baseLUC.getCellWidth();
+    burnSuitability = RA_burnSuitability != null ? (WritableGrid)RA_burnSuitability.getValue() : null;
+    outLUC          = (WritableGrid)WA_outLUC.getValue();
+    outBurnMass     = WA_outBurnMass != null ? (WritableGrid)WA_outBurnMass.getValue() : null;
+    burnTime        = (WritableGrid)WA_burnTime.getValue();
+    // Der Effizienz halber Parameter aus dyn. Xulu-Objekt heraus holen
+    burningLUC      = ((ScalarProperty)modelParam.getProperty(PARAM_PROP_BURNLUC)).getOneTimeReadAccess().getValueAsInt();
+    burnedOutLUC    = ((ScalarProperty)modelParam.getProperty(PARAM_PROP_BURNOUTLUC)).getOneTimeReadAccess().getValueAsInt();
+    lucCount        = ((ListProperty)modelParam.getProperty(PARAM_PROP_BURNSUIT)).getOneTimeReadAccess().getCount();
+    lucBurningSuitability = new double[lucCount];
+    lucBurningTime        = new double[lucCount];
+    ListPropertyReadAccess RA_lucBurningSuitability = ((ListProperty)modelParam.getProperty(PARAM_PROP_BURNSUIT)).getReadAccess(this);
+    ListPropertyReadAccess RA_lucBurningTime        = ((ListProperty)modelParam.getProperty(PARAM_PROP_BURNTIME)).getReadAccess(this);
+    for (int luc=0; luc<lucCount; luc++) {
+      lucBurningSuitability[luc] = RA_lucBurningSuitability.getValueAsDouble(luc);
+      lucBurningTime[luc]        = RA_lucBurningTime.getValueAsDouble(luc);
+      // maximale Brenn-Eignung ermitteln (fuer Normierung)
+      if ( luc==0 || lucBurningSuitability[luc] > MAX_lucBurningSuitability )
+        MAX_lucBurningSuitability = lucBurningSuitability[luc];
+    }
+    RA_lucBurningSuitability.release();
+    RA_lucBurningTime.release();
+    windDir      = ((ScalarProperty)modelParam.getProperty(PARAM_PROP_WINDDIRECTION)).getOneTimeReadAccess().getValueAsDouble();
+    windDirDev   = ((ScalarProperty)modelParam.getProperty(PARAM_PROP_WINDDIRECTIONDEV)).getOneTimeReadAccess().getValueAsDouble();
+    windPow      = ((ScalarProperty)modelParam.getProperty(PARAM_PROP_WINDPOWER)).getOneTimeReadAccess().getValueAsDouble();
+    windPowDev   = ((ScalarProperty)modelParam.getProperty(PARAM_PROP_WINDPOWERDEV)).getOneTimeReadAccess().getValueAsDouble();
+    windPowMaxBW = ((ScalarProperty)modelParam.getProperty(PARAM_PROP_WINDPOWERMAXBW)).getOneTimeReadAccess().getValueAsDouble();
+    // Faktoren zur Gewichtung der Windgeschwindigkeit bei
+    // der Berechnung der Wind-Matrix
+    if ( modelParam.containsProperty(PARAM_PROP_WINDMATRIX_PCONST) )
+    	windMatrix_powerConst = ((ScalarProperty)modelParam.getProperty(PARAM_PROP_WINDMATRIX_PCONST)).getOneTimeReadAccess().getValueAsDouble();
+    else
+    	windMatrix_powerConst = 0.0;
+    if ( modelParam.containsProperty(PARAM_PROP_WINDMATRIX_PFACT) )
+    	windMatrix_powerFact  = ((ScalarProperty)modelParam.getProperty(PARAM_PROP_WINDMATRIX_PFACT)).getOneTimeReadAccess().getValueAsDouble();
+    else
+    	windMatrix_powerConst = 1.0;
+    // Wind-Matrix berechnen
+    calculateWindMatrix(windDir,windPow,windDirDev,windPowDev,windPowMaxBW,windMatrix_powerConst,windMatrix_powerFact);
+//    PropertyReadAccess RA_windMatrix = ((MatrixProperty)modelParam.getProperty(PARAM_PROP_WINDMATRIX)).getReadAccess(this);
+//    int offset = 0;
+//    for (int y=0; y<3; y++)
+//      for (int x=0; x<3; x++) {
+//        // Zelle in der Mitte ausnehmen
+//        if ( y==1 && x==1 ) {
+//          offset = 1; // um Position im Array zu reduzieren
+//          continue;
+//        }
+//        double windValue = RA_windMatrix.getValueAsDouble(x,y);
+//        windMatrix[y*3+x-offset] = windValue;
+//        // maximalen Wert der Wind-Matrix ermitteln (fuer Normierung)
+//        if ( (y==0 && x==0) || windValue > MAX_windMatrix )
+//          MAX_windMatrix = windValue;
+//      }
+//    RA_windMatrix.release();
+
+    // Startzellen initialisieren
+    initBurningCells( startPoints );
+
+    // Ausgabe-LUC mit NoData initialisieren
+    // Ausgaberaster fuer BioMasse initialisieren
+    // Raster fuer Brennzeit initialisieren
+    for (int y=areaMinY; y<=areaMaxY; y++)
+      for (int x=areaMinX; x<=areaMaxX; x++) {
+        outLUC.setRasterSample( Float.NaN, x, y );
+        if ( outBurnMass != null )
+          outBurnMass.setRasterSample( 0, x, y );
+        burnTime.setRasterSample( 0, x, y );
+        // maximalen Wert des Eignungsrasters ermitteln (fuer Normierung)
+        if ( burnSuitability != null ) {
+          double value = burnSuitability.getRasterSampleAsDouble(x,y);
+          if ( (y == areaMinY && x == areaMinX) || value > MAX_burningSuitability )
+            MAX_burningSuitability = value;
+        }
+      }
+
+    // WICHTIG:
+    // An dieser Stelle die Anzahl an Modellschritten (aus einer
+    // Ressource) zuweisen, die das Modell laufen soll!
+    // Sonst laeuft das Modell nicht an!!
+    this.stepCount = ((ScalarProperty)modelParam.getProperty(PARAM_PROP_MODELTIME)).getOneTimeReadAccess().getValueAsInt();
+
+    // 1 Modellschritt = 1 Stunde
+    // -> Anzahl an Iterationen pro Schritt richtet sich nach der Windgeschwindigkeit
+    // -> ein CA-Schritt (Iteration) modelliert die Ausbreitung um eine Zelle,
+    //    also S Meter, was bei Windstaerke P (in m/s) genau S/P Sekunden
+    //    (= S/(3600*P) Stunden) entspricht
+    // -> Fuer eine Stunde (ein Modellschritt) muss 3600*P/S mal iteriert werden
+    this.iterCount = (int)Math.round( 3600 * windPow / baseLUC.getCellWidth() );
+    this.iterCount = Math.max(1,this.iterCount);
+    // Anzahl an Sekunden pro Iteration
+    this.iterSeconds = baseLUC.getCellWidth() / windPow;
+    statusOut.println( RESOURCE.getString("Model.ModelTime.Step") );
+    statusOut.println( RESOURCE.getString("Model.ModelTime.Iter",iterSeconds) );
+    statusOut.println("-----------------------");
+
+    // GUI initialisieren
+    if ( modelGUI != null ) {
+      ((GUI)modelGUI).setWindDirection(windDir);
+      ((GUI)modelGUI).setWindDirectionDeviation(windDirDev);
+      ((GUI)modelGUI).setWindPower(windPow);
+      ((GUI)modelGUI).setWindPowerDeviation(windPowDev);
+      modelGUI.setEnabled(true);
+    }
+  }
+
+  /**
+   * Gibt die Lese/Schreibrechte auf das Ein- und Ausgaberaster wieder frei.
+   * Interne Ressourcen brauchen keine aus dem Speicher entfernt werden.
+   */
+  public void performModelDispose() {
+    // Ressourcen wieder freigeben
+    releaseAccess(RA_startPoints);
+    releaseAccess(RA_baseLUC);
+    releaseAccess(RA_burnSuitability);
+    releaseAccess(WA_outLUC);
+    releaseAccess(WA_outBurnMass);
+    releaseAccess(WA_burnTime);
+  }
+
+  /**
+   * Fuehrt einen Schritt des Modellablaufs durch.
+   * @param stepNo zu modellierender Schritt (beginnend bei 1!)
+   */
+  public void performModelStep(int stepNo) {
+    Random RANDOM = new Random();
+
+    GregorianCalendar calendar = new GregorianCalendar();
+    DateFormat        format   = new SimpleDateFormat("HH:mm:ss.SSS");
+    for (int iterNo=1; iterNo<=iterCount; iterNo++) {
+      this.fireModelEvent( new ModelIterationStepStartedEvent(this,stepNo,iterNo) );
+
+      // Wind-Matrix neu berechnen
+      calculateWindMatrix(windDir,windPow,windDirDev,windPowDev,windPowMaxBW,windMatrix_powerConst,windMatrix_powerFact);
+      ((GUI)modelGUI).repaintWindMatrx();
+
+      long millis = Math.round( ((stepNo-2)*3600+iterNo*iterSeconds) * 1000 );
+      calendar.setTimeInMillis( millis );
+      statusOut.println("Iteration "+stepNo+"."+iterNo+": "+format.format(calendar.getTime()));
+//      LOGGER.debug( "Burning cells: "+burningCells.size() + "   Useless burning: " + uselessBurningCells.size() );
+
+      // neu brennende Zellen muessen zunaecht in eine eigene Menge
+      // aufgenommen werden
+      newBurningCells.clear();
+
+      // Alle brennenden Zellen betrachten
+      int[] bCell = null;
+      int[] nbCell = null;
+      int x   = 0; // X-Koordinate einer brennenden Zelle
+      int y   = 0; // Y-Koordinate einer brennenden Zelle
+      int nbX = 0; // X-Koordinate einer Nachbarzelle
+      int nbY = 0; // Y-Koordinate einer Nachbarzelle
+      float luc = 0;
+      for (int bCellIdx=0; bCellIdx<burningCells.size(); bCellIdx++) {
+        bCell = burningCells.elementAt(bCellIdx);
+
+        x   = bCell[0];
+        y   = bCell[1];
+
+        // Alle Nachbarzellen betrachten
+        boolean useless = true;
+        for (int nbCellIdx=0; nbCellIdx<NEIGHBOR.length; nbCellIdx++) {
+          checkBreakingCommands();
+          nbX = x+NEIGHBOR[nbCellIdx][0];
+          nbY = y+NEIGHBOR[nbCellIdx][1];
+          nbCell = new int[] {nbX,nbY};
+          // Zelle nicht verarbeiten, wenn
+          // - Zelle ausserhalb des Untersuchungsgebiets liegt
+          // - Zelle keinen Wert hat
+          // - Zelle bereits brennt
+          // - Zelle bereits fuer diesen Schritt als brennend klassifiziert
+          if ( nbX < areaMinX || nbY < areaMinY || nbX > areaMaxX || nbY > areaMaxY ||
+               newBurningCells.containsKey(nbCell) ||
+               Float.isNaN(baseLUC.getRasterSampleAsFloat(nbX,nbY)) )
+            continue;
+          luc = outLUC.getRasterSampleAsFloat(nbX,nbY);
+          if ( luc == burningLUC || luc == burnedOutLUC )
+            continue;
+          // Brenn-Wahrscheinlichkeit erreichen
+          double burnProb = calculateBurnProbability(nbX,nbY,windMatrix[nbCellIdx]);
+          double random   = RANDOM.nextDouble(); // Zufalls-Wert aus [0..1[
+          if ( random < burnProb ) {
+            // Zelle als brennend markieren und Brennzeit initialisieren
+            outLUC.setRasterSample(burningLUC,nbX,nbY);
+            burnTime.setRasterSample(0,nbX,nbY);
+            // Zelle in Liste der neuen brennenden Zellen aufnehmen
+            newBurningCells.put( nbCell, null );
+          } else {
+            // Laufzeit-Optimierung:
+            // Wenn Nachbar potentiell brennbar ist, ist die betrachtete Zelle
+            // nicht "nutzlos", sondern muss im naechsten Schritt nochmals
+            // betrachtet werden
+            if ( burnProb > 0 )
+              useless = false;
+          }
+        }
+
+        // Laufzeit-Optimierung:
+        // Wenn Zelle nicht mehr zur Feuerausbreitung beitragen kann, braucht
+        // sie im naechsten Schritt nicht mehr betrachtet werden
+        if ( useless ) {
+          burningCells.remove( bCell );
+          uselessBurningCells.add( bCell );
+        }
+      }
+
+      // Verbrannte Biomasse und Brennzeit erhoehen
+      performBurning(burningCells);
+      performBurning(uselessBurningCells);
+
+      // neue brennende Zellen in Liste aufnehmen
+      for ( int[] cell : newBurningCells.keySet() ) {
+        checkBreakingCommands();
+        burningCells.add(cell);
+      }
+      this.fireModelEvent( new ModelIterationStepFinishedEvent(this,stepNo,iterNo) );
+    }
+
+  }
+
+  /**
+   * Erhoeht die Menge der verbrannten Biomasse einer Zelle, sowie die
+   * Brennzeit. Ist die maximale Brennzeit ueberschritten wird die Zelle
+   * aus der Menge der Brennenden Zellen entfernt.
+   * @param bCells Zellen
+   */
+  protected void performBurning(Vector<int[]> bCells) {
+    int[] bCell = null;
+    int x = 0;
+    int y = 0;
+    for (int bCellIdx=0;  bCellIdx<bCells.size(); bCellIdx++) {
+      checkBreakingCommands();
+      bCell = bCells.elementAt(bCellIdx);
+      x     = bCell[0];
+      y     = bCell[1];
+
+      // Brennzeit der betrachteten Zelle erhoehen
+      float bTime = burnTime.getRasterSampleAsFloat(x, y);
+      bTime += iterSeconds;
+      burnTime.setRasterSample(bTime, x, y);
+
+      // TODO: Menge der verbrannten Biomasse erhoehen
+      if (outBurnMass != null) {
+        float bMass = outBurnMass.getRasterSampleAsFloat(x, y);
+//        bMass += ...;
+        outBurnMass.setRasterSample(bMass, x, y);
+      }
+
+      // Wenn Zelle ausgebrannt, als solche markieren und aus Rand
+      // entfernen
+      int luc = baseLUC.getRasterSampleAsInt(x, y);
+      if (bTime > lucBurningTime[ (int) luc] * 3600) {
+        outLUC.setRasterSample(burnedOutLUC, x, y);
+        bCells.remove(bCellIdx--);
+      }
+    }
+  }
+
+  /**
+   * Initialisiert die Liste der Brandherd-Zellen ueber die georeferenzierten
+   * Punkte einer {@link FeatureCollection}.
+   * @param burnSource FeatureCollection von {@link Point} und {@link MultiPoint}
+   */
+  protected void initBurningCells(FeatureCollection burnSource) {
+    // brennende Zellen
+    if ( burningCells == null )
+      burningCells = new Vector<int[]>();
+    else
+      burningCells.clear();
+    // brennende Zellen, die keinen Einfluss mehr auf Ihre Nachbarzellen
+    // haben (also nicht mehr fuer die Expansion betrachtet werden muessen)
+    if ( uselessBurningCells == null )
+      uselessBurningCells = new Vector<int[]>();
+    else
+      uselessBurningCells.clear();
+
+    FeatureIterator fi = burnSource.features();
+    for (; fi.hasNext();) {
+      Geometry g = fi.next().getDefaultGeometry();
+      if ( g == null )
+        continue;
+      if ( g instanceof Point ) {
+        Point p = (Point)g;
+        burningCells.add( new int[] {
+          baseLUC.convertRealToRaster(p.getX(),0),
+          baseLUC.convertRealToRaster(p.getY(),1),
+        } );
+      }
+      if ( g instanceof MultiPoint ) {
+        MultiPoint mp = (MultiPoint)g;
+        for (int i=0; i<mp.getNumPoints(); i++)
+          burningCells.add( new int[] {
+            baseLUC.convertRealToRaster(((Point)mp.getGeometryN(i)).getX(),0),
+            baseLUC.convertRealToRaster(((Point)mp.getGeometryN(i)).getY(),1),
+          } );
+      }
+    }
+
+    for ( int[] p : burningCells )
+      LOGGER.debug("initial burning cell: "+p[0]+" / "+p[1]);
+  }
+
+  /**
+   * Berechnet die Wahrscheinlichkeit, dass eine Zelle brennt.
+   * @param x    horizontale Raster-Koordinate
+   * @param y    vertikale Raster-Koordinate
+   * @param wind Wert der Wind-Matrix (fuer Windrichtung)
+   * @return einen Wert zwischen 0 und 1
+   */
+  protected double calculateBurnProbability(int x, int y, double wind) {
+    int luc = baseLUC.getRasterSampleAsByte(x,y);
+
+    double burnProb = 1;
+    // lokale Eignung einrechnen (pro Zelle)
+    if ( burnSuitability != null )
+      burnProb *= burnSuitability.getRasterSampleAsDouble(x,y) / MAX_burningSuitability;
+    // globale Eignung einrechnen (pro LUC-Typ)
+    burnProb *= lucBurningSuitability[luc] / MAX_lucBurningSuitability;
+    // Wind einrechnen
+    burnProb *= wind;
+
+    return burnProb;
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  /////////////////////   Berechnung der Wind-Matrix   ///////////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Berechnet die Windmatrix fuer gegebene Windrichtung und -staerke.
+   * @param direction Windrichtung in Grad (Nord = 0°, West = 90°)
+   * @param power Windstaerke in m/s
+   * @param directionDev Max. Abweichung der Windrichtung in Grad
+   * @param powerDev Max. Abweichung der Windstaerke in m/s
+   * @param powerMaxBW Windstaerke ab der kein Rueckschreiten des Feuers
+   *                   (entgegen der Windrichtung) mehr moeglich ist
+   */
+  private void calculateWindMatrix(double direction, double power, double directionDev, double powerDev, double powerMaxBW, double powerConst, double powerFact) {
+  	// Die Windgeschwindigkeit fuer die Berechnung der Matrix
+  	// wie folgt gewichten: power_for_matrix = powerConst + powerFact * power
+  	power = powerConst + powerFact * power;
+  	
+  	// Zufaellige Abweichung in Windrichtung und -staerke einrechnen
+    Random random = new Random();
+    direction += directionDev * (random.nextDouble()*2 - 1);
+    power     += powerDev     * (random.nextDouble()*2 - 1);
+
+    // Mittelpunkt der 3x3-Matrix (>>> Ursprung links-oben)
+    double mX = 1.5 * cellSize;
+    double mY = 1.5 * cellSize;
+
+    // Referenz-Quadrat, welches fuer die Ueberlageung mit den "Matrix"-Zellen
+    // verwendet wird
+    //== Durchmesser ==
+    double windEnvW = calculateReferenceSize(cellSize, power, powerMaxBW);
+    //== Flaeche ==
+    double windArea = windEnvW * windEnvW;
+    //== Mittelpunkt ==
+    double windEnvMX = mX - cellSize*Math.sin(direction/180 * Math.PI);
+    double windEnvMY = mY - cellSize*Math.cos(direction/180 * Math.PI);
+    //== Referenz-Quadrat ==
+    Envelope windEnv = new Envelope(
+      windEnvMX-windEnvW/2, // X1
+      windEnvMX+windEnvW/2, // X2
+      windEnvMY-windEnvW/2, // Y1
+      windEnvMY+windEnvW/2  // Y2
+    );
+    // Ueberlagerung jeder "Matrix"-Zelle mit dem Referenz-Quadrat berechnen
+    Envelope cellEnv = new Envelope();
+    double   totalIntersectionArea = 0.0;
+    for (int i=0; i<windMatrix.length; i++) {
+      initEnvelopeForMatrixCell(cellEnv, i<4 ? i : i+1,cellSize);
+      windMatrix[i] = calculateIntersection(cellEnv,windEnv);
+      totalIntersectionArea += windMatrix[i];
+    }
+
+    // Eintrag in Wind-Matrix entspricht dem Anteil am Referenz-Quadrat
+    for (int i=0; i<windMatrix.length; i++)
+      windMatrix[i] = Math.round(windMatrix[i]/totalIntersectionArea*10000)/10000.0;
+
+  }
+
+  /**
+   * Berechnet den Durchmesser des Referenzkreises (oder Quadrats), welches
+   * fuer die Ueberlageung mit den "Matrix"-Zellen verwendet wird.
+   * @param cellSize Groesse (Breite) einer Zelle
+   * @param power    Windstaerke
+   * @param powerMaxBW Windstaerke ab der kein Rueckschreiten des Feuers
+   *                   (entgegen der Windrichtung) mehr moeglich ist
+   */
+  private double calculateReferenceSize(double cellSize, double power, double powerMaxBW) {
+    // ????
+    return 3*cellSize * powerMaxBW / power;
+  }
+
+  /**
+   * Bestimmt das Rechteck einer Matrix-Zelle (3x3).
+   * @param env      Rechteck, das mit den Eckpunkten der Matrix-Zelle initialisiert wird
+   * @param i        Index der Matrix-Zelle (0..8)
+   * @param cellSize Groesse (Breite) einer Raster-Zelle
+   */
+  private void initEnvelopeForMatrixCell(Envelope env, int i, double cellSize) {
+    int col = i % 3;
+    int row = i / 3;
+
+    double x1 = col*cellSize;
+    double x2 = x1 + cellSize;
+    double y1 = row*cellSize;
+    double y2 = y1 + cellSize;
+
+    env.init(x1,x2,y1,y2);
+  }
+
+  /**
+   * Berechnet die Groesse der Schnittflaeche zwischen zwei Rechtecken.
+   * @param env1 Rechteck 1
+   * @param env2 Rechteck 2
+   */
+  private double calculateIntersection(Envelope env1, Envelope env2) {
+    Envelope intersectionEnv  = env1.intersection( env2 );
+    return intersectionEnv.getWidth() * intersectionEnv.getHeight();
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ////////////////   Implementierung der modellspez. GUI   ///////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Liefert die modellspezifische GUI.
+   */
+  public Component getModelSpecificGUI() {
+    return this.modelGUI;
+  }
+
+  private class GUI extends JPanel implements CaptionsChangeable {
+    /** GUI-Komponente fuer die Windrichtung (Kompass). */
+    protected InputCompass windDirection = null;
+    /** Slider fuer die Abweichung der Windrichtung. */
+    protected SliderSpinnerPanel windDirectionDev = null;
+    /** Slider fuer die Windstaerke. */
+    protected SliderSpinnerPanel windPower = null;
+    /** Slider fuer die Abweichung der Windstaerke. */
+    protected SliderSpinnerPanel windPowerDev = null;
+    /** Beschriftung der Wind-Matrix. */
+    protected JLabel windMatrixLabel = null;
+    /** Tabelle fuer Windmatrix. */
+    protected JTable windMatrixTable = null;
+    /** Grafische Darstellung der Windmatrix. */
+    protected JPanel windMatrixGraphic = null;
+    /**
+     * Erzeugt einen neue GUI fuer das Feuer-Modell.
+     */
+    public GUI() {
+      super();
+      setLayout( new GridBagLayout() );
+
+      // Kompass fuer Windrichtung
+      windDirection = new InputCompass(0);
+      windDirection.setPreferredSize( new Dimension(250,150) );
+      // Slider fuer Abweichung der Windrichtung
+      windDirectionDev = new SliderSpinnerPanel(JSlider.HORIZONTAL,0,360,0.1,10," ");
+      initSlider( windDirectionDev.getSlider(), 45 );
+      // Slider fuer Windstaeke
+      windPower = new SliderSpinnerPanel(JSlider.HORIZONTAL,1,40,0.1,10," ");
+      initSlider( windPower.getSlider(), 5 );
+      // Slider fuer Boeigkeit
+      windPowerDev = new SliderSpinnerPanel(JSlider.HORIZONTAL,0,100,0.1,2," ");
+      initSlider( windPowerDev.getSlider(), 20 );
+      this.add( windDirection, new GridBagConstraints(
+          0, 0, 1, 5, 0.2, 0.5, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 0), 0, 0) );
+      this.add( windPower, new GridBagConstraints(
+          1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0) );
+      this.add( windDirectionDev, new GridBagConstraints(
+          1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0) );
+      this.add( windPowerDev, new GridBagConstraints(
+          1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0) );
+
+      // Anzeige der Wind-Matrix
+      windMatrixTable = new JTable( new AbstractTableModel() {
+        public Object getValueAt(int row, int col) {
+          // Zentrum der Matrix enthaelt keinen Wert
+          if ( windMatrix == null || (row == 1 && col == 1) )
+            return "";
+          int idx = row*3+col;
+          if ( idx > 4 )
+            idx--;
+          return windMatrix[idx];
+        }
+        public int getRowCount() {
+          return 3;
+        }
+        public int getColumnCount() {
+          return 3;
+        }
+        public boolean isCellEditable(int row, int col) {
+          return false;
+        }
+      });
+      windMatrixTable.setCellSelectionEnabled(false);
+      // Eintraege horizontal zentrieren
+      windMatrixTable.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
+        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+          JLabel comp = (JLabel)super.getTableCellRendererComponent(table,value,isSelected,hasFocus,row,column);
+          comp.setHorizontalAlignment(JLabel.CENTER);
+          return comp;
+        }
+      });
+      windMatrixLabel = new JLabel(" ");
+      windMatrixLabel.setFont( windDirectionDev.getHeaderLabel().getFont() );
+      this.add( windMatrixLabel, new GridBagConstraints(
+         1, 3, 1, 1, 0.0, 0.0, GridBagConstraints.SOUTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 0, 5), 0, 0) );
+      this.add( windMatrixTable, new GridBagConstraints(
+         1, 4, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0, 5, 5, 5), 0, 0) );
+
+      ChangeListener l = new ChangeListener() {
+        public void stateChanged(ChangeEvent e) {
+          windDir = windDirection.getValue();
+          windPow = windPower.getValue();
+          windDirDev = windDirectionDev.getValue();
+          windPowDev = windPowerDev.getValue();
+          // Waehrend des Modellablaufs werden nur die Modell-Variablen neu gesetzt,
+          // die Neuberechnung  (und Anzeige) der Matrix erfolgt zu Beginn der
+          // naechsten Iteration
+          if ( !isRunning() ) {
+            // Wind-Matrix ohne Abweichung berechnen und anzeigen
+            calculateWindMatrix(
+              windDir,
+              windPow,
+              0,
+              0,
+              windPowMaxBW,
+              windMatrix_powerConst,
+              windMatrix_powerFact
+            );
+            repaintWindMatrx();
+            if ( windMatrixGraphic != null )
+              windMatrixGraphic.repaint();
+          }
+        }
+      };
+      windDirection.addChangeListener(l);
+      windPower.getSpinner().addChangeListener(l);
+
+      // grafische Darstellung der Wind-Matrix
+      windMatrixGraphic = new JPanel() {
+        public void paint(Graphics g) {
+          super.paint(g);
+          int cellSize = Math.min(getWidth(), getHeight()) / 3;
+          // Mittelpunkt der Komponente
+          int xM       = getWidth() / 2;
+          int yM       = getHeight() / 2;
+          // Ursprung der Matrix (links-oben)
+          int x0       = (int) (xM - 1.5 * cellSize);
+          int y0       = (int) (yM - 1.5 * cellSize);
+          // Matrix
+          g.setColor( Color.BLACK );
+          g.drawRect(x0,          y0,          3*cellSize, 3*cellSize);
+          g.drawRect(x0,          y0+cellSize, 3*cellSize, cellSize);
+          g.drawRect(x0+cellSize, y0,          cellSize,   3*cellSize);
+          // Basis-Kreis (Radius 1 Zelle)
+          g.setColor( Color.BLUE );
+          g.drawArc(xM-cellSize, yM-cellSize,2*cellSize,2*cellSize,0,360);
+          // Referenzquadrat, welches fuer die Ueberlageung mit den
+          // "Matrix"-Zellen verwendet wird
+          //== Durchmesser ==
+          int windEnvW = (int)Math.round( calculateReferenceSize(cellSize,windPow,windPowMaxBW) );
+          //== Mittelpunkt ==
+          int windEnvMX = (int)Math.round( xM - cellSize*Math.sin(windDir/180 * Math.PI) );
+          int windEnvMY = (int)Math.round( yM - cellSize*Math.cos(windDir/180 * Math.PI) );
+          //== Referenz-Quadrat ==
+          g.setColor( Color.RED );
+          g.drawRect(windEnvMX-windEnvW/2,windEnvMY-windEnvW/2,windEnvW,windEnvW);
+        }
+      };
+      windMatrixGraphic.setPreferredSize( new Dimension(100,100) );
+      this.add( windMatrixGraphic, new GridBagConstraints(
+         1, 5, 1, 1, 1.0, 1.0, GridBagConstraints.NORTH, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0) );
+      
+      // Labels belegen
+      resetCaptions(null);
+    }
+
+    /**
+     * Belegt die Labels in der GUI neu. Sind in der uebergebenen Map fuer die Keys
+     * keine Werte hinterlegt (oder wenn {@code captionMap = null}, wird auf den
+     * {@linkplain ImpetusFireCA#RESOURCE Resource-Provider} des Modells zurueckgegriffen.
+     * @param captionMap Map in der nach den Label-Bezeichnungen gesucht wird (kann
+     *                   {@code null} sein)
+     */
+    public void resetCaptions(Map<String,Object> captionMap) {
+      windDirectionDev.getHeaderLabel().setText( determineCaption(captionMap, RESOURCE, "Model.GUI.WindDir.Dev") );
+      windPower.getHeaderLabel().setText( determineCaption(captionMap, RESOURCE, "Model.GUI.WindPower") );
+      windPowerDev.getHeaderLabel().setText( determineCaption(captionMap, RESOURCE, "Model.GUI.WindPower.Dev") );
+      windMatrixLabel.setText( determineCaption(captionMap, RESOURCE, "Model.GUI.WindMatrix") );
+    } 
+  
+    /**
+     * Aktualisiert die Anzeige der Wind-Matrix.
+     */
+    public void repaintWindMatrx() {
+      ((AbstractTableModel)windMatrixTable.getModel()).fireTableDataChanged();
+    }
+
+    /**
+     * Initialisiert das Slider-Layer fuer die GUI.
+     * @param slider zu initialisierender Slider
+     * @param tickSize Abstand fuer die Ticks/Labels
+     */
+    private void initSlider(JSlider slider, int tickSize) {
+      slider.setMajorTickSpacing(tickSize);
+      slider.setPaintLabels(true);
+      slider.setPaintTicks(true);
+    }
+
+    /**
+     * Setzt die eingestellte Windrichtung.
+     * @param degree Windrichtung in Grad (Nord = 0°, West = 90°)
+     */
+    public void setWindDirection(double degree) {
+      windDirection.setValue(degree);
+    }
+
+    /**
+     * Liefert die eingestellte Windrichtung.
+     */
+    public double getWindDirection() {
+      return windDirection.getValue();
+    }
+
+    /**
+     * Setzt die eingestellte Abweichung der Windrichtung.
+     * @param degree Abweichung der Windrichtung in Grad
+     */
+    public void setWindDirectionDeviation(double degree) {
+      windDirectionDev.setValue((int)degree);
+    }
+
+    /**
+     * Liefert die eingestellte Abweichung der Windrichtung.
+     */
+    public double getWindDirectionDeviation() {
+      return windDirectionDev.getValue();
+    }
+
+    /**
+     * Setzt die eingestellte Windstaerke.
+     * @param power Windstaerke in m/s
+     */
+    public void setWindPower(double power) {
+      windPower.setValue((int)power);
+    }
+
+    /**
+     * Liefert die eingestellte Windstaeke.
+     */
+    public double getWindPower() {
+      return windPower.getValue();
+    }
+
+    /**
+     * Setzt die eingestellte Abweichung der Windstaerke.
+     * @param power Abweichung der Windstaerke in m/s
+     */
+    public void setWindPowerDeviation(double power) {
+      windPowerDev.setValue((int)power);
+    }
+
+    /**
+     * Liefert die eingestellte Abweichung der Windstaerke.
+     */
+    public double getWindPowerDeviation() {
+      return windPowerDev.getValue();
+    }
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/ca/fire/ImpetusFireCAContentManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/ca/fire/ImpetusFireCAContentManager.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/model/ca/fire/ImpetusFireCAContentManager.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,213 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.model.ca.fire;
+
+import java.util.Map;
+
+import edu.bonn.xulu.data.DynamicXuluObject;
+import edu.bonn.xulu.data.XuluDataException;
+import edu.bonn.xulu.model.AbstractModelContentManager;
+import edu.bonn.xulu.model.ModelResource;
+import edu.bonn.xulu.model.PropertiesResource;
+import edu.bonn.xulu.model.ValuePropertyResource;
+import edu.bonn.xulu.plugin.data.feature.SingleFeatureCollection;
+
+import org.geotools.feature.FeatureCollection;
+import org.geotools.feature.FeatureIterator;
+import com.vividsolutions.jts.geom.Geometry;
+import com.vividsolutions.jts.geom.Point;
+import com.vividsolutions.jts.geom.MultiPoint;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.AbstractWritableGrid;
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.MatrixProperty;
+import schmitzm.lang.ResourceProvider;
+
+
+/**
+ * Diese Klasse definiert und verwaltet die 7
+ * Ressourcen fuer das Modell {@linkplain ImpetusFireCA}
+ * und prueft diese auf Korrektheit.<br>
+ * Die Art der benoetigten Ressourcen ist der {@linkplain ImpetusFireCA}-Doku
+ * zu entnehmen.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class ImpetusFireCAContentManager extends AbstractModelContentManager {
+
+  /**
+   * Erzeugt einen neuen ContentManager fuer das Modell {@linkplain ImpetusFireCA}.
+   */
+  public ImpetusFireCAContentManager() {
+    super(7);
+    // ===== Ressourcen festlegen =====
+    // Allgemeine Modell-Parameter
+    resource[0] = new PropertiesResource(ModelResource.CATEGORY_INPUT,"",DynamicXuluObject.class,false);
+    // Bandherde
+    resource[1] = new PropertiesResource(ModelResource.CATEGORY_INPUT,"",SingleFeatureCollection.class,false);
+    // LUC Classification
+    resource[2] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"",ScalarProperty.class,WritableGrid.class,false);
+    // Brenn-Eignung
+    resource[3] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"",ScalarProperty.class,WritableGrid.class,true);
+    // Ausgabe-Raster fuer modellierte LUC
+    resource[4] = new ValuePropertyResource(ModelResource.CATEGORY_OUTPUT,"",ScalarProperty.class,WritableGrid.class,false);
+    // Ausgabe-Raster fuer verbrannte Biomasse
+    resource[5] = new ValuePropertyResource(ModelResource.CATEGORY_OUTPUT,"",ScalarProperty.class,WritableGrid.class,true);
+    // Temp-Raster fuer Brenn-Zeit
+    resource[6] = new ValuePropertyResource(ModelResource.CATEGORY_TEMP,"",ScalarProperty.class,WritableGrid.class,false);
+  
+    // Ressourcen-Beschreibungen neu belegen
+    resetCaptions(null);
+  }
+  
+  /**
+   * Belegt die Ressourcen-Beschreibungen neu. Sind in der uebergebenen Map fuer die Keys
+   * keine Werte hinterlegt (oder wenn {@code captionMap = null}), wird auf den
+   * {@linkplain ImpetusFireCA#RESOURCE Resource-Provider} des Modells zurueckgegriffen.
+   * @param captionMap Map in der nach den Ressourcen-Beschreibungen gesucht wird (kann
+   *                   {@code null} sein)
+   */
+  public void resetCaptions(Map<String,Object> captionMap) {
+    resetResourceDescription(0, captionMap, ImpetusFireCA.RESOURCE, "MRDesc.In.ModelParams");
+    resetResourceDescription(1, captionMap, ImpetusFireCA.RESOURCE, "MRDesc.In.BurnSource");
+    resetResourceDescription(2, captionMap, ImpetusFireCA.RESOURCE, "MRDesc.In.BaseLUC");
+    resetResourceDescription(3, captionMap, ImpetusFireCA.RESOURCE, "MRDesc.In.BurnSuit");
+    resetResourceDescription(4, captionMap, ImpetusFireCA.RESOURCE, "MRDesc.Out.LUs");
+    resetResourceDescription(5, captionMap, ImpetusFireCA.RESOURCE, "MRDesc.Out.BioMass");
+    resetResourceDescription(6, captionMap, ImpetusFireCA.RESOURCE, "MRDesc.Temp.BurnTime");
+  }
+  
+  public void checkAndError() {
+    super.checkAndError();
+
+    // Pruefen, ob Modell-Parameter alle erforderlichen Properties enthaelt
+    DynamicXuluObject modelParam = (DynamicXuluObject)getResource(0).getData();
+    if ( !modelParam.containsProperty(ImpetusFireCA.PARAM_PROP_MODELTIME) ||
+         !(modelParam.getProperty(ImpetusFireCA.PARAM_PROP_MODELTIME) instanceof ScalarProperty) ||
+         ((ScalarProperty)modelParam.getProperty(ImpetusFireCA.PARAM_PROP_MODELTIME)).getOneTimeReadAccess().getValueAsInt() <= 0 )
+      throwResourceException(0, ImpetusFireCA.RESOURCE.getString("Error.In.ModelParams.ModelTime",ImpetusFireCA.PARAM_PROP_MODELTIME));
+    if ( !modelParam.containsProperty(ImpetusFireCA.PARAM_PROP_BURNLUC) ||
+         !(modelParam.getProperty(ImpetusFireCA.PARAM_PROP_BURNLUC) instanceof ScalarProperty) ||
+         ((ScalarProperty)modelParam.getProperty(ImpetusFireCA.PARAM_PROP_BURNLUC)).getOneTimeReadAccess().getValueAsInt() <= 0 )
+      throwResourceException(0, ImpetusFireCA.RESOURCE.getString("Error.In.ModelParams.BurnLuc",ImpetusFireCA.PARAM_PROP_BURNLUC));
+    if ( !modelParam.containsProperty(ImpetusFireCA.PARAM_PROP_BURNOUTLUC) ||
+         !(modelParam.getProperty(ImpetusFireCA.PARAM_PROP_BURNOUTLUC) instanceof ScalarProperty) ||
+         ((ScalarProperty)modelParam.getProperty(ImpetusFireCA.PARAM_PROP_BURNOUTLUC)).getOneTimeReadAccess().getValueAsInt() <= 0 )
+      throwResourceException(0, ImpetusFireCA.RESOURCE.getString("Error.In.ModelParams.BurnOutLuc",ImpetusFireCA.PARAM_PROP_BURNOUTLUC));
+    if ( !modelParam.containsProperty(ImpetusFireCA.PARAM_PROP_BURNSUIT) ||
+         !(modelParam.getProperty(ImpetusFireCA.PARAM_PROP_BURNSUIT) instanceof ListProperty) ||
+         !Number.class.isAssignableFrom( modelParam.getProperty(ImpetusFireCA.PARAM_PROP_BURNSUIT).getPropertyType().getType() ) )
+      throwResourceException(0, ImpetusFireCA.RESOURCE.getString("Error.In.ModelParams.BurnSuit",ImpetusFireCA.PARAM_PROP_BURNSUIT));
+    if ( !modelParam.containsProperty(ImpetusFireCA.PARAM_PROP_BURNTIME) ||
+         !(modelParam.getProperty(ImpetusFireCA.PARAM_PROP_BURNTIME) instanceof ListProperty) ||
+         !Number.class.isAssignableFrom( modelParam.getProperty(ImpetusFireCA.PARAM_PROP_BURNTIME).getPropertyType().getType() ) )
+      throwResourceException(0, ImpetusFireCA.RESOURCE.getString("Error.In.ModelParams.BurnTime",ImpetusFireCA.PARAM_PROP_BURNTIME));
+    if ( !modelParam.containsProperty(ImpetusFireCA.PARAM_PROP_WINDDIRECTION) ||
+         !(modelParam.getProperty(ImpetusFireCA.PARAM_PROP_WINDDIRECTION) instanceof ScalarProperty) ||
+         ((ScalarProperty)modelParam.getProperty(ImpetusFireCA.PARAM_PROP_WINDDIRECTION)).getOneTimeReadAccess().getValueAsDouble() < 0 )
+      throwResourceException(0, ImpetusFireCA.RESOURCE.getString("Error.In.ModelParams.WindDir",ImpetusFireCA.PARAM_PROP_WINDDIRECTION));
+    if ( !modelParam.containsProperty(ImpetusFireCA.PARAM_PROP_WINDPOWER) ||
+         !(modelParam.getProperty(ImpetusFireCA.PARAM_PROP_WINDPOWER) instanceof ScalarProperty) ||
+         ((ScalarProperty)modelParam.getProperty(ImpetusFireCA.PARAM_PROP_WINDPOWER)).getOneTimeReadAccess().getValueAsDouble() <= 0 )
+      throwResourceException(0, ImpetusFireCA.RESOURCE.getString("Error.In.ModelParams.WindPower",ImpetusFireCA.PARAM_PROP_WINDPOWER));
+    if ( !modelParam.containsProperty(ImpetusFireCA.PARAM_PROP_WINDDIRECTIONDEV) ||
+         !(modelParam.getProperty(ImpetusFireCA.PARAM_PROP_WINDDIRECTIONDEV) instanceof ScalarProperty) ||
+         ((ScalarProperty)modelParam.getProperty(ImpetusFireCA.PARAM_PROP_WINDDIRECTIONDEV)).getOneTimeReadAccess().getValueAsDouble() < 0 )
+      throwResourceException(0, ImpetusFireCA.RESOURCE.getString("Error.In.ModelParams.WindDirDev",ImpetusFireCA.PARAM_PROP_WINDDIRECTIONDEV));
+    if ( !modelParam.containsProperty(ImpetusFireCA.PARAM_PROP_WINDPOWERDEV) ||
+         !(modelParam.getProperty(ImpetusFireCA.PARAM_PROP_WINDPOWERDEV) instanceof ScalarProperty) ||
+         ((ScalarProperty)modelParam.getProperty(ImpetusFireCA.PARAM_PROP_WINDPOWERDEV)).getOneTimeReadAccess().getValueAsDouble() < 0 )
+      throwResourceException(0, ImpetusFireCA.RESOURCE.getString("Error.In.ModelParams.WindPowerDev",ImpetusFireCA.PARAM_PROP_WINDPOWERDEV));
+    if ( !modelParam.containsProperty(ImpetusFireCA.PARAM_PROP_WINDPOWERMAXBW) ||
+         !(modelParam.getProperty(ImpetusFireCA.PARAM_PROP_WINDPOWERMAXBW) instanceof ScalarProperty) ||
+         ((ScalarProperty)modelParam.getProperty(ImpetusFireCA.PARAM_PROP_WINDPOWERMAXBW)).getOneTimeReadAccess().getValueAsDouble() <= 0 )
+      throwResourceException(0, ImpetusFireCA.RESOURCE.getString("Error.In.ModelParams.WindPowerMaxBW",ImpetusFireCA.PARAM_PROP_WINDPOWERMAXBW));
+//    if ( !modelParam.containsProperty(ImpetusFireCA.PARAM_PROP_WINDMATRIX) ||
+//         !(modelParam.getProperty(ImpetusFireCA.PARAM_PROP_WINDMATRIX) instanceof MatrixProperty) ||
+//         ((MatrixProperty)modelParam.getProperty(ImpetusFireCA.PARAM_PROP_WINDMATRIX)).getDimension() < 2 ||
+//         ((MatrixProperty)modelParam.getProperty(ImpetusFireCA.PARAM_PROP_WINDMATRIX)).getSize(0) < 3 ||
+//         ((MatrixProperty)modelParam.getProperty(ImpetusFireCA.PARAM_PROP_WINDMATRIX)).getSize(1) < 3 ||
+//         !Number.class.isAssignableFrom( modelParam.getProperty(ImpetusFireCA.PARAM_PROP_WINDMATRIX).getPropertyType().getType() ) )
+//      throwResourceException(0, ImpetusFireCA.RESOURCE.getString("Error.In.ModelParams.WindMatrix",ImpetusFireCA.PARAM_PROP_WINDMATRIX));
+    // Konstante fuer Gewichtung der Windgeschwindigkeit in Windmatrix-
+    // Berechnung ist optional; Wenn angegeben, dann muss es ein Double-Wert sein
+    if ( !modelParam.containsProperty(ImpetusFireCA.PARAM_PROP_WINDMATRIX_PCONST) )
+    	LOGGER.warn( ImpetusFireCA.RESOURCE.getString("Warn.In.ModelParams.Missing",ImpetusFireCA.PARAM_PROP_WINDMATRIX_PCONST,0) );
+    else
+    	if ( !(modelParam.getProperty(ImpetusFireCA.PARAM_PROP_WINDMATRIX_PCONST) instanceof ScalarProperty) )
+    		throwResourceException(0, ImpetusFireCA.RESOURCE.getString("Error.In.ModelParams.WindMatrix_PowerConst",ImpetusFireCA.PARAM_PROP_WINDMATRIX_PCONST));
+    // Faktor fuer Gewichtung der Windgeschwindigkeit in Windmatrix-
+    // Berechnung ist optional; Wenn angegeben, dann muss es ein Double-Wert
+    // <> 0 sein
+    if ( !modelParam.containsProperty(ImpetusFireCA.PARAM_PROP_WINDMATRIX_PFACT) )
+    	LOGGER.warn( ImpetusFireCA.RESOURCE.getString("Warn.In.ModelParams.Missing",ImpetusFireCA.PARAM_PROP_WINDMATRIX_PFACT,1) );
+    else
+    	if ( !(modelParam.getProperty(ImpetusFireCA.PARAM_PROP_WINDMATRIX_PFACT) instanceof ScalarProperty) ||
+    			 ((ScalarProperty)modelParam.getProperty(ImpetusFireCA.PARAM_PROP_WINDMATRIX_PFACT)).getOneTimeReadAccess().getValueAsDouble() == 0 )
+    		throwResourceException(0, ImpetusFireCA.RESOURCE.getString("Error.In.ModelParams.WindMatrix_PowerFact",ImpetusFireCA.PARAM_PROP_WINDMATRIX_PCONST));
+
+    // Pruefen, ob FeatureCollection "Punkte" enthaelt
+    FeatureCollection fc = ((SingleFeatureCollection)getResource(1).getData()).getFeatureCollection();
+    FeatureIterator   fi = fc.features();
+    Geometry          g  = null;
+    if ( !fi.hasNext() ||
+         (g = fi.next().getDefaultGeometry()) == null ||
+         !( g instanceof Point || g instanceof MultiPoint ) )
+      throwResourceException(1,ImpetusFireCA.RESOURCE.getString("Error.In.BurnSource.Data"));
+
+    WritableGrid baseLUC = (WritableGrid)((ScalarProperty)getResource(2).getData()).getOneTimeReadAccess().getValue();
+    // wenn angegeben, muss Brenneignungs-Raster mit LUC-Szenario uebereinstimmen
+    if ( getResource(3).getData() != null ) {
+      WritableGrid burnSuit = (WritableGrid)((ScalarProperty)getResource(3).getData()).getOneTimeReadAccess().getValue();
+      AbstractWritableGrid.compareStructure(
+          baseLUC,  ImpetusFireCA.RESOURCE.getString("Error.In.BaseLUC.Grid"),
+          burnSuit, ImpetusFireCA.RESOURCE.getString("Error.In.BurnSuit.Grid"),
+          false
+      );
+    }
+    // Ausgabe-Raster fuer LUC muss mit LUC-Szenario uebereinstimmen
+    WritableGrid outLUC = (WritableGrid)((ScalarProperty)getResource(4).getData()).getOneTimeReadAccess().getValue();
+    AbstractWritableGrid.compareStructure(
+        baseLUC,  ImpetusFireCA.RESOURCE.getString("Error.In.BaseLUC.Grid"),
+        outLUC,   ImpetusFireCA.RESOURCE.getString("Error.Out.LUC.Grid"),
+        false
+    );
+
+    if ( getResource(5).getData() != null ) {
+      WritableGrid burnedMass = (WritableGrid)((ScalarProperty)getResource(5).getData()).getOneTimeReadAccess().getValue();
+      AbstractWritableGrid.compareStructure(
+          baseLUC,    ImpetusFireCA.RESOURCE.getString("Error.In.BaseLUC.Grid"),
+          burnedMass, ImpetusFireCA.RESOURCE.getString("Error.Out.BioMass.Grid"),
+          false
+      );
+    }
+    // Temp-Raster fuer Brennzeit muss mit LUC-Szenario uebereinstimmen
+    WritableGrid burnTime = (WritableGrid)((ScalarProperty)getResource(6).getData()).getOneTimeReadAccess().getValue();
+    AbstractWritableGrid.compareStructure(
+        baseLUC,  ImpetusFireCA.RESOURCE.getString("Error.In.BaseLUC.Grid"),
+        burnTime, ImpetusFireCA.RESOURCE.getString("Error.Temp.BurnTime.Grid"),
+        false
+    );
+  }
+
+  private void throwResourceException(int resIdx, String errDesc) {
+    throw new XuluDataException(
+      ImpetusFireCA.RESOURCE.getString(
+        "Error.Global.Mess",
+        getResource(resIdx).getDesc(),
+        errDesc
+      )
+    );
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/ca/reservoir/SmallReservoirModel.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/ca/reservoir/SmallReservoirModel.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/model/ca/reservoir/SmallReservoirModel.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,830 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.model.ca.reservoir;
+
+import java.util.Locale;
+import java.util.Map;
+import java.util.Random;
+import java.util.GregorianCalendar;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Vector;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.text.DecimalFormat;
+import java.awt.Component;
+import java.awt.Point;
+import java.awt.GridBagLayout;
+import java.awt.GridBagConstraints;
+import java.awt.Insets;
+import javax.swing.JLabel;
+import javax.swing.JCheckBox;
+
+import org.geotools.feature.FeatureCollection;
+import org.geotools.coverage.grid.GridCoverage2D;
+
+import com.vividsolutions.jts.geom.Geometry;
+import com.vividsolutions.jts.geom.LineString;
+import com.vividsolutions.jts.geom.MultiLineString;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.PropertyWriteAccess;
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.lang.LangUtil;
+import schmitzm.lang.ResourceProvider;
+import schmitzm.swing.JPanel;
+import schmitzm.swing.SliderSpinnerPanel;
+import schmitzm.geotools.grid.GridUtil;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyWriteAccess;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.data.XuluDataException;
+import edu.bonn.xulu.model.XuluModel;
+import edu.bonn.xulu.model.AbstractStepModel;
+import edu.bonn.xulu.model.event.ModelIterationStepStartedEvent;
+import edu.bonn.xulu.model.event.ModelIterationStepFinishedEvent;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+import edu.bonn.xulu.plugin.data.feature.SingleFeatureCollection;
+import edu.bonn.xulu.plugin.model.ca.fire.ImpetusFireCA;
+import static edu.bonn.xulu.plugin.model.ca.reservoir.SmallReservoirModelContentManager.*;
+
+import org.apache.log4j.Logger;
+
+/**
+ * Diese Klasse stellt eine Implementierung des Modells {@linkplain ImpetusFireCA}
+ * dar. Dieses benoetigt 7 Ressourcen, welche durch den
+ * {@linkplain ImpetusFireCAContentManager} spezifiziert werden:
+ * <ol>
+ * <li><b>DHM ({@code dhm}):</b>
+ *     Raster mit einem Hoehenmodell (Ausgangsszenario).
+ *     </li>
+ * <li><b>Staumauer ({@code damWall}):</b>
+ *     FeatureCollection (z.B. aus Shape-File) mit einem Line-String, die die
+ *     Lage der Staumauer definiert.
+ *     </li>
+ * <li><b>Hoehe der Staumauer ({@code damWallHeight}):</b>
+ *     Hoehe der Staumauer ueber NN.
+ *     </li>
+ * <li><b>Versickerung pro Tag ({@code infiltration}):</b>
+ *     Versickerung in mm pro Tag.
+ *     </li>
+ * <li><b>Verdunstung pro Tag ({@code evaporation}):</b>
+ *     Verdunstung in mm pro Tag.
+ *     </li>
+ * <li><b>Modell-Schrittweite ({@code stepSize}):</b>
+ *     Schrittweite in Tagen, mit welcher das "Entleeren" des Stausees
+ *     (durch Verdunstung und Versickerung) in Rastern und Zwischenwerten
+ *     in den Ausgabe-Ressourcen protokolliert wird.
+ *     </li>
+ * <li><b>Ausgabe: Groesse der ueberfluteten Flaeche in qm ({@code outFloodedAreaSize}):</b>
+ *     Flaeche in Hektar, die ueberflutet wird, sowie die Flaeche zu den
+ *     spaeteren Zeitpunkten, wenn Versickerung und Verdunstung (pro Tag)
+ *     beruecksichtigt wird.
+ *     </li>
+ * <li><b>Ausgabe: Groesse der ueberfluteten Flaeche in qqm ({@code outFloodedAreaVol}):</b>
+ *     Volumen in Qubikmeter, die ueberflutet wird, das Volumen zu den
+ *     spaeteren Zeitpunkten, wenn Versickerung und Verdunstung (pro Tag)
+ *     beruecksichtigt wird.
+ *     </li>
+ * <li><b>Ausgabe: Ueberfluteten Flaeche als Raster ({@code outFloodedArea}):</b>
+ *     Enthaelt die ueberfluteten Zellen als Raster zum Zeitpunkt 0 (wenn der
+ *     Stausee voll ist) und zu den spaeteren Zeitpunkten, wenn Versickerung
+ *     und Verdunstung (pro Tag) beruecksichtigt wird.
+ *     </li>
+ * <li><b>Temporaere: Staumauer als DHM ({@code damDHM}):</b>
+ *     Enthaelt ein Hoehenmodell, in dem der Staumauer-Vektor dargestellt wird.
+ *     Dieses wird automatisch berechnen.
+ *     </li>
+ * </ol>
+ * @see SmallReservoirModelContentManager
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class SmallReservoirModel extends AbstractStepModel {
+  /** {@link ResourceProvider}, der die Uebersetzungen fuer die GUI
+   *  bereitstellt: {@code locales.XuluModel_SmallReservoirModel} */
+  protected static ResourceProvider RESOURCE = XuluModellingPlatform.registerResourceProvider("XuluModel_SmallReservoirModel",Locale.ENGLISH);
+
+	  /** Logger fuer Debug-Ausgaben und Warnings. */
+  public static final Logger LOGGER = LangUtil.createLogger(SmallReservoirModel.class);
+
+  /** Speichert den ContentManager fuer das Modell.
+   *  @see SmallReservoirModelContentManager */
+  protected SmallReservoirModelContentManager contManager;
+
+  //********** Lese/Schreibrechte, die fuer den gesamten ***********
+  //********** Modellanlauf gehalten werden muessen      ***********
+  private PropertyReadAccess       RA_dhm = null;  // Hoehenmodell
+  private PropertyReadAccess       RA_damWall = null;  // Lage der Staumauer
+  private PropertyReadAccess       RA_damWallHeight = null;  // Damm-Hoehe
+  private PropertyReadAccess       RA_infiltration = null;  // Versickerung
+  private PropertyReadAccess       RA_evaporation = null;  // Verdunstung
+  private PropertyReadAccess       RA_stepSize = null;  // Schrittgroesse des Modells
+  private ListPropertyWriteAccess  WA_outFloodedAreaSize= null;  // Ausgabe: Ueberflutete Flaeche in qm
+  private ListPropertyWriteAccess  WA_outFloodedAreaVol= null;  // Ausgabe: Ueberflutete Flaeche in m³
+  private PropertyWriteAccess      WA_outFloodedArea = null;  // Ausgabe-Raster: Ueberflutete Flaeche als Raster
+  private PropertyWriteAccess      WA_damWallDHM = null;  // Temp-Raster: Staumauer als DHM
+
+  //**************** Variablen mit denen gearbeitet wird *******************
+  protected  WritableGrid       dhm = null; // Hoehenmodell
+  protected  FeatureCollection  damWall = null; // Lage der Staumauer
+  protected  double[]           damWallHeight = null; // Hoehe der Staumauer ueber NN
+  protected  double[]           damWallHeightMin = null; // min. Hoehe der Staumauer ueber NN
+  protected  double[]           damWallHeightMax = null; // max. Hoehe der Staumauer ueber NN
+  protected  double             infiltration = 0; // Versickerung in mm
+  protected  double             evaporation = 0; // Verdunstung in mm
+  protected  MultiGrid          outFloodedArea = null; // Ueberflutete Flaechen als Raster
+  protected  double             outFloodedAreaSize = 0; // akt. ueberflutete Flaeche in qm
+  protected  double             outFloodedAreaVol = 0; // akt. ueberflutetes Volumen in qqm
+  protected  WritableGrid       outFloodedAreaGrid = null; // akt. ueberflutete Flaeche als Raster
+  protected  WritableGrid       damWallDHM = null; // Staumauer als DHM
+  protected  int                stepSize = 0; // Groesse in Tagen eines Modellschritts
+  protected  boolean            storeStepResults = true;
+  protected  int                areaMinX = 0;
+  protected  int                areaMaxX = 0;
+  protected  int                areaMinY = 0;
+  protected  int                areaMaxY = 0;
+  protected  double             areaCellSize = 0;
+  protected  int                iterCount = 0;
+  protected  Set<Point>[]       damCells = null;
+  protected  Set<Point>         floodedCells = new HashSet<Point>();
+
+// Nachbar-Zellen relativ zur Zentrum-Zelle
+//  private  static final int[][] NEIGHBOR = new int[][] {
+//      {-1,-1}, {0,-1}, {1,-1},
+//      {-1, 0},         {1, 0},
+//      {-1, 1}, {0, 1}, {1, 1}
+//  };
+  private  static final int[][] NEIGHBOR = new int[][] {
+               {0,-1},
+      {-1, 0},         {1, 0},
+               {0, 1}
+  };
+
+  // Modell-Spezifische GUI
+  protected  GUI modelGUI = null;
+
+  /**
+   * Erzeugt eine neue Instanz des Modells.
+   */
+  public SmallReservoirModel() {
+    super( new SmallReservoirModelContentManager() );
+    contManager = (SmallReservoirModelContentManager)super.contManager;
+    modelResourceProvider = RESOURCE;
+    modelGUI    = new GUI();
+    modelGUI.setEnabled(false);
+    // Iterations-Ereignisse der Event-Liste hinzufuegen
+    events.add(ModelIterationStepStartedEvent.class);
+    events.add(ModelIterationStepFinishedEvent.class);
+  }
+
+  /**
+   * Liefert die modell-spezifische GUI des Kleinstausee-Modells.
+   */
+  public Component getModelSpecificGUI() {
+    return modelGUI;
+  }
+
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////   Implementierung von AbstractXuluModel   //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Initialisiert das Model, indem die Ressourcen aus dem ContentManager
+   * geladen werden und mit Lese/Schreib-Rechten versehen werden. Zudem
+   * werden Referenzen auf die Ressourcen in lokalen Variablen
+   * gespeichert, um waehrend des Modellablaufs effizienter darauf zugreifen
+   * zu koennen.
+   */
+  public void performModelInit() {
+    if ( contManager == null )
+      return;
+    // Zugriffsrechte aus Ressourcen/Propertys holen
+    RA_dhm                = ((ScalarProperty)contManager.getResource(DHM_NO).getData()).getReadAccess(this);
+    RA_damWall            = ((ScalarProperty)((SingleFeatureCollection)contManager.getResource(DAM_LOC_NO).getData()).getProperty("FEATURES")).getReadAccess(this);
+    RA_damWallHeight      = ((ScalarProperty)contManager.getResource(DAM_HEIGHT_NO).getData()).getReadAccess(this);
+    RA_evaporation        = ((ScalarProperty)contManager.getResource(EVAPO_NO).getData()).getReadAccess(this);
+    RA_infiltration       = ((ScalarProperty)contManager.getResource(INFILT_NO).getData()).getReadAccess(this);
+    RA_stepSize           = ((ScalarProperty)contManager.getResource(STEP_SIZE_NO).getData()).getReadAccess(this);
+    WA_outFloodedAreaSize = ((ListProperty)contManager.getResource(OUT_AREA_SIZE_NO).getData()).getWriteAccess(this);
+    WA_outFloodedAreaVol  = ((ListProperty)contManager.getResource(OUT_AREA_VOL_NO).getData()).getWriteAccess(this);
+    WA_damWallDHM         = ((ScalarProperty)contManager.getResource(TMP_DHM_NO).getData()).getWriteAccess(this);
+
+    // Variablen belegen mit denen gearbeitet wird
+    dhm                = (WritableGrid)RA_dhm.getValue();
+    damWall            = (FeatureCollection)RA_damWall.getValue();
+    damWallDHM         = (WritableGrid)WA_damWallDHM.getValue();
+    outFloodedAreaSize = 0;
+    outFloodedAreaVol  = 0;
+    outFloodedArea     = (MultiGrid)contManager.getResource(OUT_AREA_NO).getData();
+    evaporation        = RA_evaporation.getValueAsDouble();
+    infiltration       = RA_infiltration.getValueAsDouble();
+    stepSize           = RA_stepSize.getValueAsInt();
+    // Ausmasse des Rasters
+    areaMinX       = dhm.getMinX();
+    areaMaxX       = dhm.getMinX() + dhm.getWidth() - 1;
+    areaMinY       = dhm.getMinY();
+    areaMaxY       = dhm.getMinY() + dhm.getHeight() - 1;
+    areaCellSize   = dhm.getCellWidth() * dhm.getCellHeight();
+
+    // Ausgabe und Temp-Raster initialisieren
+    for (;outFloodedArea.getGridCount() > 0;)
+      outFloodedArea.removeGrid(0);
+    outFloodedArea.setTemplateDimension(dhm);
+    //    LangUtil.gc();
+    WA_outFloodedAreaSize.removeAll();
+    WA_outFloodedAreaVol.removeAll();
+    for (int y=areaMinY; y<=areaMaxY; y++)
+      for (int x=areaMinX; x<=areaMaxX; x++) {
+        damWallDHM.setRasterSample(0, x, y);
+      }
+
+    // Schrittanzahl unbestimmt
+    this.stepCount = Integer.MAX_VALUE;
+
+    // Rasterzellen und min/max. Hoehe der Staumauer(n) ermitteln
+    determineDamWallCells();
+
+    if ( modelGUI != null ) {
+      // Ausmasse des Sliders neu einstellen
+      modelGUI.damHeightSlider.setRestrictions(
+        RA_damWallHeight.getValueAsDouble(),
+        damWallHeightMin[0],
+        damWallHeightMax[0],
+        1
+      );
+      // Schnittweite, Infiltration und Evaporation aus
+      // Modell-Parametern anzeigen
+      modelGUI.setModelStepSize( stepSize );
+      modelGUI.setEvaporation( evaporation );
+      modelGUI.setInfiltration( infiltration );
+
+      // GUI aktivieren
+      modelGUI.setEnabled(true);
+    }
+
+  }
+
+  /**
+   * Gibt die Lese/Schreibrechte auf das Ein- und Ausgaberaster wieder frei.
+   * Interne Ressourcen brauchen keine aus dem Speicher entfernt werden.
+   */
+  public void performModelDispose() {
+    // Ressourcen wieder freigeben
+    releaseAccess(RA_dhm);
+    releaseAccess(RA_damWall);
+    releaseAccess(RA_damWallHeight);
+    releaseAccess(RA_evaporation);
+    releaseAccess(RA_infiltration);
+    releaseAccess(RA_stepSize);
+    releaseAccess(WA_outFloodedAreaSize);
+    releaseAccess(WA_outFloodedAreaVol);
+    releaseAccess(WA_outFloodedArea);
+    releaseAccess(WA_damWallDHM);
+  }
+
+  /**
+   * Fuehrt die Modell-Berechnung durch.
+   */
+  public void performModelStep(int stepNo) {
+//    Random            RANDOM   = new Random();
+//    GregorianCalendar calendar = new GregorianCalendar();
+//    DateFormat        format   = new SimpleDateFormat("HH:mm:ss.SSS");
+
+    if ( stepNo == 1 ) {
+      // GUI sperren
+    	modelGUI.setEnabled( false );
+    	// Staudam-Hoehe aus GUI verwenden
+    	damWallHeight[0] = modelGUI.getDamnHeight();
+    	// Schrittweite in welcher die Stausee-Daten
+    	// protokolliert werden
+    	stepSize = modelGUI.getModelStepSize();
+    	storeStepResults = modelGUI.checkStoreStepGrids();
+    	
+    	// Ausgabe-Raster fuer initialen Zustand erzeugen und
+    	// Variablen fuer initialien Schritt initialisieren
+    	outFloodedArea.addGrid(Float.NaN);
+    	outFloodedAreaSize = 0;
+    	outFloodedAreaVol  = 0;
+    	outFloodedAreaGrid = outFloodedArea.getGrid(0);
+    	// Startzellen initialisieren
+    	determineDamWallDHMAndInitStartCells();
+    	// Ausmasse des gefuellten Stausees berechnen
+    	fillReservoir();
+    	// Ergebnis in Ausgabe schreiben
+    	WA_outFloodedAreaSize.addValue( (float)outFloodedAreaSize );
+    	WA_outFloodedAreaVol.addValue( (float)outFloodedAreaVol );
+    }
+
+    // Ausgabe-Raster fuer Entleerungs-Schritt erzeugen und
+    // Variablen fuer Entleerungs-Schritt initialisieren
+    if ( storeStepResults ) {
+      outFloodedArea.addGrid(Float.NaN);
+      outFloodedAreaGrid = outFloodedArea.getGrid( outFloodedArea.getGridCount()-1 );
+    } else
+      outFloodedAreaGrid = null;
+    outFloodedAreaSize = 0;
+    outFloodedAreaVol  = 0;
+    // Stausee fuer einen Zeit-Abschnitt leeren
+    emptyReservoir(stepNo, stepSize);
+    // Ergebnis in Ausgabe schreiben
+    WA_outFloodedAreaSize.addValue( (float)outFloodedAreaSize );
+    WA_outFloodedAreaVol.addValue( (float)outFloodedAreaVol );
+
+    // Wenn keine ueberfluteten Zellen mehr vorhanden sind, Modell abbrechen
+    if ( floodedCells.isEmpty() ) {
+      // letztes Raster aus der Liste entfernen, da dieses leer ist
+      outFloodedArea.removeGrid(outFloodedArea.getGridCount()-1);
+      this.stopModelling();
+    }
+  }
+
+  /**
+   * Entleert den Stausee und berechnet pro Tag (oder je Modellschritt-Groesse)
+   * verbleibende die Ausmasse des Stausees.
+   */
+  protected void emptyReservoir(int stepNo, int dayCount) {
+    statusOut.print( RESOURCE.getString("Model.Calc.Empty",stepNo*dayCount) );
+
+    //******* vorerst fuer alles die Hoehe des ersten Damms verwenden *********
+    // @todo: individuelle Damm-Hoehe verwenden
+    final double damHeight = damWallHeight[0];
+
+    // Hoehe, um die der Wasserstand reduziert wird
+    final double reducing = dayCount * (infiltration + evaporation) * 0.001;
+
+    double newHeightAbs     = damHeight - stepNo*reducing;
+    double cellGroundHeight = 0;
+    double newHeightRel     = 0;
+    Set<Point> lastStepFloodedCells = new HashSet<Point>(floodedCells);
+    for (Point p : lastStepFloodedCells) {
+      checkBreakingCommands();
+
+      // Hoehe der (unueberfluteten) Zelle ueber NN
+      cellGroundHeight = dhm.getRasterSampleAsFloat(p.x,p.y);
+      // Wenn neue Stau-Hoehe noch groesser ist, als die
+      // Hoehe der Zellen, bleibt die Zelle ueberflutet
+      if ( cellGroundHeight < newHeightAbs ) {
+        // Relative Stau-Hoehe (ueber Grund)
+        newHeightRel = newHeightAbs - cellGroundHeight;
+        // Zelle bleibt ueberflutet
+        if ( outFloodedAreaGrid != null )
+          outFloodedAreaGrid.setRasterSample(newHeightRel,p.x,p.y);
+        // Ueberflutete Flaeche in qm summieren
+        outFloodedAreaSize += areaCellSize;
+        // Ueberflutetes Volumen in m³ erhoehen
+        outFloodedAreaVol  += areaCellSize * newHeightRel;
+      } else {
+        // Zelle aus den ueberfluteten entfernen
+        floodedCells.remove(p);
+      }
+    }
+    // berechnete Werte in der GUI anzeigen
+    if ( modelGUI != null ) {
+      modelGUI.setCalculatedArea( outFloodedAreaSize );
+      modelGUI.setCalculatedVolume( outFloodedAreaVol );
+    }
+    statusOut.println( RESOURCE.getString("Model.Calc.Done") );
+  }
+
+  /**
+   * Berechnet die Ausmasse des Stausees (fuellt den Stausee).
+   */
+  protected void fillReservoir() {
+    statusOut.print( RESOURCE.getString("Model.Calc.Fill") );
+
+    //******* vorerst fuer alles die Hoehe des ersten Damms verwenden *********
+    // @todo: individuelle Damm-Hoehe verwenden
+    final double damHeight = damWallHeight[0];
+
+    double nbhHeight        = 0;
+    int    nbhX             = 0;
+    int    nbhY             = 0;
+    double relHeight        = 0;
+    // "floodedCells" soll nach der Befuellung alle ueberfluteten Zellen
+    // enthalten. Fuer das Ueberfluten wird aber immer nur der "Rand"
+    // betrachtet, aus dem immer wieder Zellen entfernt werden (bis der Rand
+    // leer ist) -> neben "floodedCells" eine temp. Menge fuer Rand verwalten
+    Set<Point> floodedCellsBorder = new HashSet<Point>(floodedCells);
+    for (int iterNo=1; !floodedCellsBorder.isEmpty(); iterNo++) {
+      this.fireModelEvent( new ModelIterationStepStartedEvent(this,0,iterNo) );
+      // Die Nachbarn aller im letzten Schritt zur Ueberflutung markierte
+      // Zellen ueberfluten und die geeigneten Nachbarzellen markieren
+      Set<Point> lastStepFloodedCells = new HashSet<Point>(floodedCellsBorder);
+      for (Point cell : lastStepFloodedCells) {
+        // Zelle aus Rand entfernen
+        floodedCellsBorder.remove(cell);
+        // Stausee-Hoehe ueber Grund
+        relHeight = damHeight - dhm.getRasterSampleAsFloat(cell.x,cell.y);
+        // Zelle ueberfluten (im Ausabe-Raster markieren)
+        outFloodedAreaGrid.setRasterSample(relHeight,cell.x,cell.y);
+        floodedCells.add( cell );
+        // Ueberflutete Flaeche in qm summieren
+        outFloodedAreaSize += areaCellSize;
+        // Ueberflutetes Volumen in m³ erhoehen
+        outFloodedAreaVol  += areaCellSize * relHeight;
+
+        // berechnete Werte in der GUI anzeigen
+        if ( modelGUI != null ) {
+          modelGUI.setCalculatedArea( outFloodedAreaSize );
+          modelGUI.setCalculatedVolume( outFloodedAreaVol );
+        }
+
+        // Noch nicht ueberflutete Nachbarzellen ueberpruefen und
+        // ggf. markieren (in Rand aufnehmen)
+        for (int[] nbhOffset : NEIGHBOR) {
+          checkBreakingCommands();
+
+          nbhX = cell.x + nbhOffset[0];
+          nbhY = cell.y + nbhOffset[1];
+          if ( nbhX >= areaMinX && nbhX <= areaMaxX &&
+               nbhY >= areaMinY && nbhY <= areaMaxY &&
+               Float.isNaN( outFloodedAreaGrid.getRasterSampleAsFloat(nbhX,nbhY) ) ) {
+            // Hoehe der Zelle bestimmen
+            nbhHeight = dhm.getRasterSampleAsFloat(nbhX,nbhY);
+            // Staumauer beruecksichtigen
+            nbhHeight = Math.max(nbhHeight, damWallDHM.getRasterSampleAsFloat(nbhX,nbhY));
+            // Wenn Hoehe unterhalb der Staumauer-Hoehe liegt, wird
+            // Zelle ueberflutet
+            if ( nbhHeight < damHeight )
+              floodedCellsBorder.add( new Point(nbhX,nbhY) );
+          }
+        }
+      }
+      this.fireModelEvent( new ModelIterationStepFinishedEvent(this,0,iterNo) );
+    }
+
+    statusOut.println( RESOURCE.getString("Model.Calc.Done") );
+  }
+
+  /**
+   * Ermittelt die von dem Staumauer-Shape ueberlagerten Rasterzellen.
+   * Zudem wird die minimale/maximale Staumauer-Hoehe ermittelt.
+   */
+  protected void determineDamWallCells() {
+    // Erstes Feature aus der Collection holen
+    Geometry           g   = damWall.features().next().getDefaultGeometry();
+    // LineString(s) in Vector einfuegen
+    Vector<LineString> lineStrings  = new Vector<LineString>();
+    if ( g instanceof LineString )
+      lineStrings.add( (LineString)g );
+    if ( g instanceof MultiLineString )
+      for (int i=0; i<((MultiLineString)g).getNumGeometries(); i++)
+        lineStrings.add( (LineString)g.getGeometryN(i) );
+    if ( lineStrings.isEmpty() )
+      throw new XuluDataException( RESOURCE.getString("Error.In.Dam.Loc.Type") );
+
+    GridCoverage2D gc = GridUtil.convertToGridCoverage2D( dhm );
+    damCells         = new HashSet[lineStrings.size()];
+    damWallHeight    = new double[damCells.length];
+    damWallHeightMin = new double[damCells.length];
+    damWallHeightMax = new double[damCells.length];
+    for (int i=0; i<damCells.length; i++) {
+      LineString ls = lineStrings.elementAt(i);
+      damCells[i] = GridUtil.getOverlappingCells( gc, ls, (Set)null );
+      // Minimale Staumauer-Hoehe = Hoehe der Tiefenlinie
+      damWallHeightMin[i] = Double.MAX_VALUE;
+      for (Point p : damCells[i])
+        damWallHeightMin[i] = Math.min(
+            damWallHeightMin[i],
+            dhm.getRasterSampleAsDouble(p.x,p.y)
+        );
+        // Maximale Staumauer-Hoehe = Niedrigstes Ende der Staumauer
+        damWallHeightMax[i] = Math.min(
+            dhm.getGridSampleAsDouble( ls.getStartPoint().getX(), ls.getStartPoint().getY() ),
+            dhm.getGridSampleAsDouble( ls.getEndPoint().getX(), ls.getEndPoint().getY() )
+        );
+        // Default-Hoehe = Minimale Hoehe
+        damWallHeight[i] = damWallHeightMax[i];
+    }
+  }
+
+  /**
+   * Berechnet ein DHM, welches an den Stellen der Staumauer die Hoehe der
+   * Staumauer ueber NN enthaelt und ansonsten 0. Zudem werden die Start-Zellen
+   * fuer den Wasserzufluss, sowie die minimale/maximale Staumauer-Hoehe ermittelt.
+   */
+  protected void determineDamWallDHMAndInitStartCells() {
+    statusOut.print( RESOURCE.getString("Model.Calc.Dam.DHM") );
+
+    
+    for (int i=0; i<damCells.length; i++)
+      for (Point p : damCells[i])
+        this.damWallDHM.setRasterSample(damWallHeight[i], p.x, p.y );
+
+    // Start-Zelle(n) fuer die Ueberflutung berechnen
+    // --> Fuer alle Damm-Zellen jeweils die 4 Umgebungen NO, NW, SW, SO
+    //     betrachten und die Umgebung mit der GERINGSTE Durchschnittshoehe
+    //     suchen
+    // --> die Umgebung liegt IN Fluss-Richtung vom Staudamm
+    // --> fuer die gefundene Damm-Zelle diejenige Umgebung als Start-Zellen
+    //     waehlen, welche die GROESSTE Durchschnittshoehe hat
+    // --> diese Umgebung liegt vom Staudamm aus GEGEN die Fluss-Richtung
+    final int[][][] NBH_AREA = initNbhOffset(5);
+    Point        minCell                = null;
+    float        minCellMinNbhHeight    = 0;
+    Set<Point>[] minCellNbhCells        = new HashSet[4];
+    float[]      minCellNbhHeights      = new float[4];
+    Point        nbhCell                = new Point();
+    float        nbhCellHeight          = 0;
+
+    // Alle Daemme betrachten
+    floodedCells.clear();
+    for (int damNo=0; damNo<damCells.length; damNo++) {
+      // Alle Damm-Zellen betrachten
+      for (Point p : damCells[damNo]) {
+        Set<Point>[] nbhCells     = new HashSet[4];
+        float[]      nbhHeights   = new float[4];
+        // Alle 4 Richtungen um die Zelle betrachten
+        for (int d=0; d<NBH_AREA.length; d++) {
+          float nbhHeightSum = 0;
+          nbhCells[d] = new HashSet<Point>();
+          // Alle Nachbarzellen betrachten und Hoehen-Summe berechnen
+          for (int i=0; i<NBH_AREA[d].length; i++) {
+            nbhCell.x = p.x + NBH_AREA[d][i][0];
+            nbhCell.y = p.y + NBH_AREA[d][i][1];
+            if ( nbhCell.x >= areaMinX && nbhCell.x <= areaMaxX &&
+                 nbhCell.y >= areaMinY && nbhCell.y <= areaMaxY  &&
+                 !damCells[damNo].contains(nbhCell) ) {
+              nbhCellHeight = dhm.getRasterSampleAsFloat(nbhCell.x,nbhCell.y);
+              if ( nbhCellHeight < damWallHeight[damNo] ) {
+                nbhCells[d].add( (Point)nbhCell.clone() );
+                nbhHeightSum += dhm.getRasterSampleAsFloat(nbhCell.x,nbhCell.y);
+              }
+            }
+          }
+          // Durchschnittshoehe berechnen und ggf. das Minimum neu setzen
+          if ( !nbhCells[d].isEmpty() ) {
+            nbhHeights[d] = nbhHeightSum / nbhCells[d].size();
+            if ( nbhHeights[d] < minCellMinNbhHeight || minCell == null ) {
+              minCell             = p;
+              minCellMinNbhHeight = nbhHeights[d];
+              minCellNbhHeights   = nbhHeights;
+              minCellNbhCells     = nbhCells;
+            }
+          }
+        }
+      }
+
+      // Die Richtung der minimalen Umgebung suchen, die die groesste
+      // Durchschnittshoehe besitzt (diese Umgebung liegt von der Staumauer
+      // aus GEGEN die Flussrichtung)
+      int   minCellMaxDir       = 0;
+      float minCellMaxNbhHeight = 0;
+      for (int d=0; d<minCellNbhHeights.length; d++) {
+        if ( minCellNbhHeights[d] > minCellMaxNbhHeight ) {
+          minCellMaxNbhHeight = minCellNbhHeights[d];
+          minCellMaxDir       = d;
+        }
+      }
+      // Die Umgebungszellen der Maximum-Richtung als Start-Zellen setzen
+      for (Point cell : minCellNbhCells[minCellMaxDir])
+        this.floodedCells.add(cell);
+    }
+    statusOut.println( RESOURCE.getString("Model.Calc.Done") );
+  }
+
+  /**
+   * Erstellt eine Array von 2-dimensionalen Offset-Koordinaten.
+   * Dieser ist in die 4 Quadranten eingeteilt.<br>
+   * Dimension 1: Quadrant (0=NO, 1=NW, 2=SW, 3=SO)<br>
+   * Dimension 2: Koordinaten-Index (0 bis {@code (size+1)^2)})<br>
+   * Dimension 3: X oder Y (0=X, 1=Y)<br>
+   * Beispiel: area[2][3][0] = 3. X-Koordinate in 2. Quadranten
+   * @param size Radius der Umgebung (in Zellen)
+   */
+  private int[][][] initNbhOffset(int size) {
+    int arrSize = size+1;
+
+    int[][][] offset = new int[4][arrSize*arrSize][2];
+    for (int d=0; d<4; d++) {
+      int fx = (d==0 | d==3) ? 1 : -1;
+      int fy = (d==2 | d==3) ? 1 : -1;
+      for (int y=0; y<arrSize; y++)
+        for (int x=0; x<arrSize; x++) {
+          offset[d][y*arrSize+x][0] = x*fx;
+          offset[d][y*arrSize+x][1] = y*fy;
+        }
+    }
+    return offset;
+  }
+
+  /////////////////////////////////////////////////////////////////////////
+  /////////////////////   Modellspezifische GUI   /////////////////////////
+  /////////////////////////////////////////////////////////////////////////
+  /**
+   * Modell-spezifische GUI des {@linkplain SmallReservoirModel Kleinstausee-Modells}.
+   * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a>
+   */
+  protected class GUI extends JPanel {
+    /** Zahlenformat, in dem die berechneten Werte angezeigt werden. */
+    protected final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.00");
+
+
+    /** Slider, mit dem die Hoehe der Staumauer ueber NN eingestellt wird. */
+    protected SliderSpinnerPanel damHeightSlider = null;
+    /** Slider, mit dem die Schrittweite (in Tagen) eingestellt wird, mit
+     *  der sie Stausee-Daten protokolliert werden. */
+    protected SliderSpinnerPanel modelStepSizeSlider = null;
+    /** Slider, mit dem die Evaporation (in mm) eingestellt wird. */
+    protected SliderSpinnerPanel evaporationSlider = null;
+    /** Slider, mit dem die Infiltration (in mm) eingestellt wird. */
+    protected SliderSpinnerPanel infiltrationSlider = null;
+    /** CheckBox, ob Zwischenschritte als Raster gespeichert werden sollen. */
+    protected JCheckBox storeStepGridsCheckBox = null;
+    /** Label in dem die Ueberschrift der berechneten Stau-Flaeche angezeigt wird. */
+    protected JLabel dammedAreaTitle = null;
+    /** Label in dem die berechnete Stau-Flaeche angezeigt wird. */
+    protected JLabel dammedAreaValue = null;
+    /** Label in dem die Ueberschrift des berechneten Stau-Volumens angezeigt wird */
+    protected JLabel dammedVolumeTitle = null;
+    /** Label in dem das berechnete Stau-Volumen angezeigt wird. */
+    protected JLabel dammedVolumeValue = null;
+
+    /**
+     * Erzeugt eine neue GUI. Ruft {@link #initGUI()} auf.
+     */
+    public GUI() {
+      this.setLayout( new GridBagLayout() );
+
+      initGUI();
+
+      this.add(damHeightSlider, new GridBagConstraints(
+          0, 0, 2, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5,5,5,5), 0, 0) );
+      this.add(modelStepSizeSlider, new GridBagConstraints(
+          0, 1, 2, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5,5,5,5), 0, 0) );
+      this.add(infiltrationSlider, new GridBagConstraints(
+          0, 2, 2, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5,5,5,5), 0, 0) );
+      this.add(evaporationSlider, new GridBagConstraints(
+          0, 3, 2, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5,5,5,5), 0, 0) );
+      this.add(storeStepGridsCheckBox, new GridBagConstraints(
+          0, 4, 2, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5,5,5,5), 0, 0) );
+      this.add(dammedAreaTitle, new GridBagConstraints(
+          0, 5, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5,5,5,5), 0, 0) );
+      this.add(dammedAreaValue, new GridBagConstraints(
+          1, 5, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5,5,5,5), 0, 0) );
+      this.add(dammedVolumeTitle, new GridBagConstraints(
+          0, 6, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5,5,5,5), 0, 0) );
+      this.add(dammedVolumeValue, new GridBagConstraints(
+          1, 6, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5,5,5,5), 0, 0) );
+    }
+
+    /**
+     * Erzeugt die Komponenten der modellspezifischen GUI.
+     */
+    protected void initGUI() {
+      this.damHeightSlider = new SliderSpinnerPanel(
+          SliderSpinnerPanel.HORIZONTAL, "");
+      this.modelStepSizeSlider = new SliderSpinnerPanel(
+          SliderSpinnerPanel.HORIZONTAL, 1, 500, 1, 1, "" );
+      this.infiltrationSlider = new SliderSpinnerPanel(
+          SliderSpinnerPanel.HORIZONTAL, 0.1, 100, 0.1, 1, "");
+      this.evaporationSlider = new SliderSpinnerPanel(
+          SliderSpinnerPanel.HORIZONTAL, 0.1, 100, 0.1, 1, "");
+      this.storeStepGridsCheckBox = new JCheckBox("",true);
+      this.dammedAreaTitle        = new JLabel("");
+      this.dammedAreaValue        = new JLabel("");
+      this.dammedVolumeTitle      = new JLabel("");
+      this.dammedVolumeValue      = new JLabel("");
+      // Labels lokalisieren
+      resetCaptions( null );
+    }
+
+    /**
+     * Belegt die Labels in der GUI neu. Sind in der uebergebenen Map fuer die Keys
+     * keine Werte hinterlegt (oder wenn {@code captionMap = null}, wird auf den
+     * {@linkplain ImpetusFireCA#RESOURCE Resource-Provider} des Modells zurueckgegriffen.
+     * @param captionMap Map in der nach den Label-Bezeichnungen gesucht wird (kann
+     *                   {@code null} sein)
+     */
+    public void resetCaptions(Map<String,Object> captionMap) {
+      this.damHeightSlider.getHeaderLabel().setText( determineCaption(captionMap, RESOURCE, "Model.GUI.DamHeight") );
+      this.modelStepSizeSlider.getHeaderLabel().setText( determineCaption(captionMap, RESOURCE, "Model.GUI.ModelSteps") );
+      this.infiltrationSlider.getHeaderLabel().setText( determineCaption(captionMap, RESOURCE, "Model.GUI.Infilt") );
+      this.evaporationSlider.getHeaderLabel().setText( determineCaption(captionMap, RESOURCE, "Model.GUI.Evapo") );
+      this.storeStepGridsCheckBox.setText( determineCaption(captionMap, RESOURCE, "Model.GUI.Store.StepResults") );
+      this.dammedAreaTitle.setText( determineCaption(captionMap, RESOURCE, "Model.GUI.Calc.Area") );
+      this.dammedVolumeTitle.setText( determineCaption(captionMap, RESOURCE, "Model.GUI.Calc.Vol") );
+    } 
+
+    /**
+     * Deaktiviert die Eingabe-Komponenten der GUI (nicht wie die
+     * {@code super}-Methode alle Komponenten)
+     */
+    public void setEnabled(boolean enabled) {
+      damHeightSlider.setEnabled( enabled );
+      modelStepSizeSlider.setEnabled( enabled );
+      infiltrationSlider.setEnabled( enabled );
+      evaporationSlider.setEnabled( enabled );
+      storeStepGridsCheckBox.setEnabled( enabled );
+    }
+
+    /**
+     * Liefert die in der GUI eingestellte Staumauer-Hoehe.
+     */
+    public double getDamnHeight() {
+      return damHeightSlider.getValue();
+    }
+
+    /**
+     * Setzt die in der GUI eingestellte Staumauer-Hoehe.
+     * @param value einzustellender Wert
+     */
+    public void setDamnHeight(double value) {
+      damHeightSlider.setValue(value);
+    }
+
+    /**
+     * Liefert die in der GUI eingestellte Schrittweite des Modells.
+     */
+    public int getModelStepSize() {
+      return (int)modelStepSizeSlider.getValue();
+    }
+
+    /**
+     * Setzt die in der GUI eingestellte Schrittweite des Modells.
+     * @param value einzustellender Wert
+     */
+    public void setModelStepSize(int value) {
+      modelStepSizeSlider.setValue(value);
+    }
+
+    /**
+     * Liefert die in der GUI eingestellte Evaporation.
+     */
+    public double getEvaporation() {
+      return evaporationSlider.getValue();
+    }
+
+    /**
+     * Setzt die in der GUI eingestellte Evaporation.
+     * @param value einzustellender Wert
+     */
+    public void setEvaporation(double value) {
+      evaporationSlider.setValue(value);
+    }
+
+    /**
+     * Liefert die in der GUI eingestellte Infiltration.
+     */
+    public double getInfiltration() {
+      return infiltrationSlider.getValue();
+    }
+
+    /**
+     * Setzt die in der GUI eingestellte Infiltration.
+     * @param value einzustellender Wert
+     */
+    public void setInfiltration(double value) {
+      infiltrationSlider.setValue(value);
+    }
+
+    /**
+     * Prueft, ob in der GUI eingestellt ist, dass die Zwischenergebnisse
+     * als Raster gespeichert werden.
+     */
+    public boolean checkStoreStepGrids() {
+      return storeStepGridsCheckBox.isSelected();
+    }
+
+    /**
+     * Bestimmt, ob in der GUI eingestellt ist, dass die Zwischenergebnisse
+     * als Raster gespeichert werden.
+     * @param storeStepGrids einzustellender Wert
+     */
+    public void setStoreStepGrids(boolean storeStepGrids) {
+      storeStepGridsCheckBox.setSelected( storeStepGrids );
+    }
+
+    /**
+     * Setzt die in der GUI angezeigte (berechnete) "Stau-Flaeche".
+     * @param area anzuzeigender Wert
+     */
+    public void setCalculatedArea(double area) {
+      dammedAreaValue.setText(
+          DECIMAL_FORMAT.format(area) );
+    }
+
+    /**
+     * Setzt das in der GUI angezeigte (berechnete) "Stau-Volumen".
+     * @param volume anzuzeigender Wert
+     */
+    public void setCalculatedVolume(double volume) {
+      dammedVolumeValue.setText(
+          DECIMAL_FORMAT.format(volume) );
+    }
+
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/ca/reservoir/SmallReservoirModelContentManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/ca/reservoir/SmallReservoirModelContentManager.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/model/ca/reservoir/SmallReservoirModelContentManager.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,177 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.model.ca.reservoir;
+
+import java.util.Map;
+
+import edu.bonn.xulu.data.XuluDataException;
+import edu.bonn.xulu.model.AbstractModelContentManager;
+import edu.bonn.xulu.model.AbstractXuluModel;
+import edu.bonn.xulu.model.ModelResource;
+import edu.bonn.xulu.model.PropertiesResource;
+import edu.bonn.xulu.model.ValuePropertyResource;
+import edu.bonn.xulu.plugin.data.feature.SingleFeatureCollection;
+
+import org.geotools.feature.FeatureCollection;
+import org.geotools.feature.FeatureIterator;
+import com.vividsolutions.jts.geom.Geometry;
+import com.vividsolutions.jts.geom.LineString;
+import com.vividsolutions.jts.geom.MultiLineString;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.AbstractWritableGrid;
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.MatrixProperty;
+import schmitzm.lang.ResourceProvider;
+import edu.bonn.xulu.model.DefaultModelResource;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+import edu.bonn.xulu.plugin.model.ca.fire.ImpetusFireCA;
+
+
+/**
+ * Diese Klasse definiert und verwaltet die 7 Ressourcen fuer das Modell
+ * {@linkplain SmallReservoirModel} und prueft diese auf Korrektheit.<br>
+ * Die Art der benoetigten Ressourcen ist der {@linkplain SmallReservoirModel}-Doku
+ * zu entnehmen.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class SmallReservoirModelContentManager extends AbstractModelContentManager {
+  public static final int    DHM_NO             = 0;
+  private             String DHM_DESC           = "";
+  public static final int    DAM_LOC_NO         = 1;
+  private             String DAM_LOC_DESC       = "";
+  public static final int    DAM_HEIGHT_NO      = 2;
+  private             String DAM_HEIGHT_DESC    = "";
+  public static final int    INFILT_NO          = 3;
+  private             String INFILT_DESC        = "";
+  public static final int    EVAPO_NO           = 4;
+  private             String EVAPO_DESC         = "";
+  public static final int    STEP_SIZE_NO       = 5;
+  private             String STEP_SIZE_DESC     = "";
+  public static final int    OUT_AREA_SIZE_NO   = 6;
+  private             String OUT_AREA_SIZE_DESC = "";
+  public static final int    OUT_AREA_VOL_NO    = 7;
+  private             String OUT_AREA_VOL_DESC  = "";
+  public static final int    OUT_AREA_NO        = 8;
+  private             String OUT_AREA_DESC      = "";
+  public static final int    TMP_DHM_NO         = 9;
+  private             String TMP_DHM_DESC       = "";
+
+  /**
+   * Erzeugt einen neuen ContentManager fuer das Modell
+   * {@linkplain SmallReservoirModel}.
+   */
+  public SmallReservoirModelContentManager() {
+    super(10);
+    // ===== Ressourcen festlegen =====
+    // DHM
+    resource[DHM_NO] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,DHM_DESC,ScalarProperty.class,WritableGrid.class,false);
+    // Staumauer
+    resource[DAM_LOC_NO] = new PropertiesResource(ModelResource.CATEGORY_INPUT,DAM_LOC_DESC,SingleFeatureCollection.class,false);
+    // Staumauerhoehe
+    resource[DAM_HEIGHT_NO] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,DAM_HEIGHT_DESC,ScalarProperty.class,Double.class,false);
+    // Versickerungsrate
+    resource[INFILT_NO] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,INFILT_DESC,ScalarProperty.class,Double.class,false);
+    // Verdunstungsrate
+    resource[EVAPO_NO] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,EVAPO_DESC,ScalarProperty.class,Double.class,false);
+    // Modell-Schrittweite
+    resource[STEP_SIZE_NO] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,STEP_SIZE_DESC,ScalarProperty.class,Integer.class,false);
+    // Ausgabe: Ueberflutete Flaeche
+    resource[OUT_AREA_SIZE_NO] = new ValuePropertyResource(ModelResource.CATEGORY_OUTPUT,OUT_AREA_SIZE_DESC,ListProperty.class,Double.class,false);
+    // Ausgabe: Ueberflutetes Volumen
+    resource[OUT_AREA_VOL_NO] = new ValuePropertyResource(ModelResource.CATEGORY_OUTPUT,OUT_AREA_VOL_DESC,ListProperty.class,Double.class,false);
+    // Ausgabe: Ueberflutete Flaeche (Raster)
+    resource[OUT_AREA_NO] = new DefaultModelResource(ModelResource.CATEGORY_OUTPUT,OUT_AREA_DESC,MultiGrid.class,false);
+    // Temp: DHM fuer Staumauer (Raster)
+    resource[TMP_DHM_NO] = new ValuePropertyResource(ModelResource.CATEGORY_TEMP,TMP_DHM_DESC,ScalarProperty.class,WritableGrid.class,false);
+
+    // ===== Ressourcen Bezeichnungen lokalisieren =====
+    resetCaptions(null);
+}
+
+  /**
+   * Belegt die Ressourcen-Beschreibungen neu. Sind in der uebergebenen Map fuer die Keys
+   * keine Werte hinterlegt (oder wenn {@code captionMap = null}), wird auf den
+   * {@linkplain SmallReservoirModel#RESOURCE Resource-Provider} des Modells zurueckgegriffen.
+   * @param captionMap Map in der nach den Ressourcen-Beschreibungen gesucht wird (kann
+   *                   {@code null} sein)
+   */
+  public void resetCaptions(Map<String,Object> captionMap) {
+    ResourceProvider rp = SmallReservoirModel.RESOURCE;
+    DHM_DESC            = AbstractXuluModel.determineCaption(captionMap, rp, "MRDesc.In.DHM");
+    DAM_LOC_DESC        = AbstractXuluModel.determineCaption(captionMap, rp, "MRDesc.In.Dam.Loc");
+    DAM_HEIGHT_DESC     = AbstractXuluModel.determineCaption(captionMap, rp, "MRDesc.In.Dam.Height");
+    INFILT_DESC         = AbstractXuluModel.determineCaption(captionMap, rp, "MRDesc.In.Infilt");
+    EVAPO_DESC          = AbstractXuluModel.determineCaption(captionMap, rp, "MRDesc.In.Evapo");
+    STEP_SIZE_DESC      = AbstractXuluModel.determineCaption(captionMap, rp, "MRDesc.In.StepSize");
+    OUT_AREA_SIZE_DESC  = AbstractXuluModel.determineCaption(captionMap, rp, "MRDesc.Out.Area.Size");
+    OUT_AREA_VOL_DESC   = AbstractXuluModel.determineCaption(captionMap, rp, "MRDesc.Out.Area.Vol");
+    OUT_AREA_DESC       = AbstractXuluModel.determineCaption(captionMap, rp, "MRDesc.Out.Area.Grid");
+    TMP_DHM_DESC        = AbstractXuluModel.determineCaption(captionMap, rp, "MRDesc.Temp.DHM");
+    
+    resource[DHM_NO].setDesc(DHM_DESC);
+    resource[DAM_LOC_NO].setDesc(DAM_LOC_DESC);
+    resource[DAM_HEIGHT_NO].setDesc(DAM_HEIGHT_DESC);
+    resource[INFILT_NO].setDesc(INFILT_DESC);
+    resource[EVAPO_NO].setDesc(EVAPO_DESC);
+    resource[STEP_SIZE_NO].setDesc(STEP_SIZE_DESC);
+    resource[OUT_AREA_SIZE_NO].setDesc(OUT_AREA_SIZE_DESC);
+    resource[OUT_AREA_VOL_NO].setDesc(OUT_AREA_VOL_DESC);
+    resource[OUT_AREA_NO].setDesc(OUT_AREA_DESC);
+    resource[TMP_DHM_NO].setDesc(TMP_DHM_DESC);
+  }
+
+  public void checkAndError() {
+    super.checkAndError();
+
+    // Pruefen, ob FeatureCollection "eine Linie" enthaelt
+    SingleFeatureCollection sfc = (SingleFeatureCollection)getResource(1).getData();
+    if ( sfc != null || sfc.getFeatureCollection().size() > 0 ) {
+      FeatureCollection fc = sfc.getFeatureCollection();
+      FeatureIterator   fi = fc.features();
+      Geometry          g  = null;
+      if ( (g = fi.next().getDefaultGeometry()) == null ||
+          !( g instanceof LineString || g instanceof MultiLineString ) )
+       throwResourceException(2, SmallReservoirModel.RESOURCE.getString("Error.In.Dam.Loc"));
+    } else
+    	throwResourceException(2, SmallReservoirModel.RESOURCE.getString("Error.In.Dam.Loc"));
+
+    // Ausgabe-Raster muss mit DHM uebereinstimmen
+    WritableGrid dhm = (WritableGrid)((ScalarProperty)getResource(0).getData()).getOneTimeReadAccess().getValue();
+    WritableGrid floodedArea = ((MultiGrid)getResource(8).getData()).getTemplateGrid();
+    AbstractWritableGrid.compareStructure(
+    		dhm, SmallReservoirModel.RESOURCE.getString("Error.In.DHM.Grid"),
+    		floodedArea, SmallReservoirModel.RESOURCE.getString("Error.Out.Area.Grid"),
+    		false
+    );
+
+    // Temp-Raster fuer Staumauer-DHM muss mit DHM uebereinstimmen
+    WritableGrid tempDHM = (WritableGrid)((ScalarProperty)getResource(9).getData()).getOneTimeReadAccess().getValue();
+    AbstractWritableGrid.compareStructure(
+    		dhm, SmallReservoirModel.RESOURCE.getString("Error.In.DHM.Grid"),
+    		tempDHM, SmallReservoirModel.RESOURCE.getString("Error.Temp.DHM.Grid"),
+    		false
+    );
+  }
+
+  private void throwResourceException(int resIdx, String errDesc) {
+    throw new XuluDataException(
+    		SmallReservoirModel.RESOURCE.getString(
+    				"Error.Global.Mess",
+            getResource(resIdx).getDesc(),
+            errDesc
+        )
+    );
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/clue/ClueModel.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/clue/ClueModel.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/model/clue/ClueModel.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,1864 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.model.clue;
+
+import java.awt.Component;
+import java.awt.Font;
+import java.awt.geom.AffineTransform;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+import java.util.Locale;
+import java.lang.reflect.Array;
+
+import javax.swing.BorderFactory;
+import javax.swing.JCheckBox;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JSlider;
+import javax.swing.SpringLayout;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyReadAccess;
+import schmitzm.data.property.ListPropertyWriteAccess;
+import schmitzm.data.property.MatrixProperty;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.PropertyWriteAccess;
+import schmitzm.lang.LangUtil;
+import schmitzm.lang.ResourceProvider;
+import schmitzm.swing.ExpansionBar;
+import schmitzm.swing.SpringUtilities;
+import schmitzm.swing.SwingUtil;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.model.AbstractStepModel;
+import edu.bonn.xulu.model.event.ModelIterationStepFinishedEvent;
+import edu.bonn.xulu.model.event.ModelIterationStepStartedEvent;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+import edu.bonn.xulu.plugin.model.ca.fire.ImpetusFireCA;
+
+/**
+ * Diese Klasse stellt eine Nachbildung des
+ * <a href="http://www.cluemodel.nl/" target="_blank">CLUE</a>-Modells dar
+ * (CLUE = The <b>C</b>onversion of <b>L</b>and <b>U</b>se and its <b>E</b>ffects).
+ * Es wird nicht garantiert, dass diese Klasse identisch zum CLUE-Modell arbeitet.
+ * Alle Rechte am CLUE-Algrithmus liegen beim CLUE-Team um
+ * <a href="mailto:peter.verburg at wur.nl">Peter Verburg</a>.<br>
+ * <br>
+ * Das CLUE-Modell arbeitet mit Rasterdaten und berechnet die zeitliche
+ * Landnutzungsveraenderung (LUCC) in einem Untersuchungsgebiet iterativ auf
+ * Basis von statistischen Eingabeparametern und vorgegebenen Landnutzungsbedarfen.<br>
+ * Das CLUE-Modell benoetigt folgende Ressourcen, welche durch den
+ * {@link ClueModelContentManager} spezifiziert werden:
+ * <ol>
+ * <li><b>Modellparameter:</b>
+ *     <ul>
+ *     <li><i>n</i> = Anzahl modellierter LU-Typen (<b>implizit</b> durch die LU-Conversion-Matrix gegeben!)</li>
+ *     <li><i>m</i> = Anzahl an Driving Forces (<b>implizit</b> durch die Anzahl der Driving-Force-Raster gegeben!))</li>
+ *     <li><i>o</i> = Anzahl an dynamischen Driving Forces (<b>implizit</b> durch die Liste der dynamischen DF gegeben!))</li>
+ *     <li><i>t</i> = Anzahl zu simulierende Zeitschritte (Integer)</li>
+ *     <li><i>x</i> = Breite des Untersuchungsgebiets (<b>implizit</b> durch das Ausgangsszenario gegeben!)</li>
+ *     <li><i>y</i> = Anzahl zu simulierende Zeitschritte (<b>implizit</b> durch das Ausgangsszenario gegeben!)</li>
+ *     <li><i>a</i> = Erlaubte Durchschnitts-Abweichung zu den vorgegebenen LU-Bedarfen</li>
+ *     <li><i>s</i> = Erlaubte Abweichung eines jeden LU-Typs zum vorgegebenen LU-Bedarf</li>
+ *     <li><i>d</i> = Art der Abweichungsangaben (0=prozentual, 1=absolut in Bedarf-Einheit)</li>
+ *     </ul></li>
+ * <li><b>Ein Ausgangsszenario ({@link WritableGrid})</b><br>
+ *     Stellt die Ausgangs-Landnutzung dar und muss Werte zwischen 0 und <i>n</i>
+ *     (sowie {@link Float#NaN} = NoData) enthalten.<br>
+ *     Dieses Raster bestimmt die Groesse (<i>x</i>, <i>y</i>) des
+ *     betrachteten Untersuchungsgebiets. Alle anderen Ein/Ausgabe-Raster muessen
+ *     dieser Dimension entsprechen.</li>
+ * <li><b>LU-History ({@link WritableGrid})</b><br>
+ *     Stellt die Vergangenheit des Ausgangsszenarios dar. Fuer jede Zelle
+ *     wird angegeben, wie lange die aktuelle Landnutzung bereits besteht.<br>
+ *     Das Raster muss dieselbe Dimension besitzen, wie das Ausgangsszenario.</li>
+ * <li><b>Eine LU-Conversion-Matrix ({@link MatrixProperty MatrixProperty[Integer]})</b><br>
+ *     Beschreibt ob und wie ein direkterWechsel zwischen den LU-Typen erlaubt
+ *     ist. Stellt eine <i>n</i>x<i>n</i>-Matrix dar und bestimmt somit,
+ *     wie viele LU-Typen modelliert werden.</li>
+ * <li><b>Eine LU-Conversion-Deviation-Matrix ({@link MatrixProperty MatrixProperty[Integer]})</b><br>
+ *     Stellt eine <i>n</i>x<i>n</i>-Matrix dar und beschreibt eine Abweichungen
+ *     fuer die LU-Conversion-Matrix-Eintraege > 100 und < -100, damit nicht
+ *     alle Zellen gleichzeitig welchseln, sobald die Grenze erreicht ist.</li>
+ * <li><b>Conversion Elasticity ({@link ListProperty ListProperty[Float]})</b><br>
+ *     Beschreibt die Bestaendigkeit der LU-Typen und stellt so eine weitere
+ *     Einschraenkung an den LU-Wechsel dar. Die Liste muss fuer jeden LU-Typ
+ *     einen Wert zwischen 0 und 1 enthalten (also <i>n</i> Float-Werte).<br>
+ *     <ul>
+ *     <li><i>ELAS[U] = 1</i> bedeutet, dass wenn an einer Stelle eine U-Zelle "verschwindet",
+ *     an anderer Stelle im gleichen Zeitschritt keine Zelle vom Typ U entstehen darf.</li>
+ *     <li><i>ELAS[U] = 0</i> bedeutet, dass uneingeschraenkt an einer Stelle ein Wechsel von U
+ *         nach A und gleichzeitig an anderer Stelle von B nach U moeglich ist.</li>
+ *     <li><i>0 < ELAS[U] < 1</i> drueckt eine Tendenz zu einem der beiden Extremwerte 0 oder
+ *         1 aus.</li>
+ *     </ul></li>
+ * <li><b>Area Restrictions, Spatial policies ({@link WritableGrid})</b><br>
+ *     Beschreiben, an welchen Stellen des Untersuchungsgebiets ein LU-Wechsel generell
+ *     verboten ist (z.B. Schutzgebiete oder Bereiche, die nicht zum Untersuchungsgebiet
+ *     gehoeren).<br>
+ *     Das Raster muss dieselbe Dimension besitzen, wie das Ausgangsszenario.
+ *     Der Rasterwert NoData ({@link Float#NaN}) bedeutet, dass ein LU-Wechsel
+ *     verboten ist, jeder andere Wert erlaubt den Wechsel.</li>
+ * <li><b>Demand Scenario ({@link MatrixProperty MatrixProperty[Integer]})</b><br>
+ *     Beschreibt den LU-Bedarf (in Zellen!) fuer jeden LU-Typ zu jedem
+ *     modellierten Zeitschritt. Muss eine <i>n</i>x(<i>t</i>+1)-Matrix darstellen,
+ *     die Integer-Werte enthaelt.<br>
+ *     <u>Bemerke:</u><br>
+ *     Der "Bedarf" in der Zeile 0 stellt die Situation
+ *     des Ausgangsszenarios dar. Deshalb sind <i>t</i>+1 Zeilen anzugeben!</li>
+ * <li><b>Static Driving Forces ({@link MultiGrid})</b><br>
+ *     Beschreiben die Auspraegung der statischen Einflussfaktoren an jeder Stelle des
+ *     Untersuchungsgebiets. Zusammen mit den Regressionsparametern werden
+ *     hieraus die LU-Wahrscheinlichkeiten errechnet.<br>
+ *     Das MultiGrid muss mind. <i>m</i> numerische Raster enthalten, die alle dieselbe
+ *     Dimension besitzen, wie das Ausgangsszenario. Werden dynamische DF verwendet
+ *     werden die Elemente an deren Index <b>nicht</b> verwendet, sie muessen
+ *     jedoch vorhanden sein!</li>
+ * <li><b>Opt: Dynamic Driving Force Types ({@link ListProperty ListProperty[Integer]})</b><br>
+ *     Diese Liste enthaelt die Nummern der dynamischen Driving Forces. Die
+ *     Angabe ist optional, muss aber - wenn angegeben - Werte zwischen
+ *     0 und <i>m</i> enthalten.</li>
+ * <li><b>Opt: Dynamic Driving Forces ({@link MultiGrid})</b><br>
+ *     Beschreiben die Auspraegung der dynamischen Einflussfaktoren an jeder Stelle des
+ *     Untersuchungsgebiets ueber die Zeit. Zusammen mit den Regressionsparametern werden
+ *     hieraus die LU-Wahrscheinlichkeiten errechnet.<br>
+ *     Das MultiGrid muss mind. <i>t</i>*<i>o</i> numerische Raster enthalten,
+ *     die alle dieselbe Dimension besitzen, wie das Ausgangsszenario. Es koennen
+ *     aber auch mehr Raster angegeben werden. Bedingung ist aber, dass fuer alle
+ *     dyn. DF gleich viele Raster (=Zeitpunkte) angegeben werden! Die Grids
+ *     sind in der Liste gruppiert nach DF anzugeben, d.h. erst alle Grids
+ *     fuer den ersten dyn. DF, dann alle Grids fuer den zweiten, usw.</li>
+ * <li><b>Regression Results ({@link MatrixProperty MatrixProperty[Float]})</b><br>
+ *     Beschreiben die Einfluss-Staerke (Betas) der Driving Forces auf jeden einzelnen
+ *     LU-Typ. Muss eine (<i>m</i>+1)x<i>n</i>-Matrix darstellen,
+ *     die Float-Werte enthaelt.</li>
+ * <li><b>Opt: Neigborhood Weights ({@link ListProperty ListProperty[Float]})</b><br>
+ *     Diese (optionale) Liste enthaelt die Gewichte, wie stark der Nachbarschaftsfaktor
+ *     in die Berechnung der LU-Wahrscheinlichkeit fuer jeden LU-Typ eingeht.
+ *     Sie muss <i>n</i> Werte enthalten.</li>
+ * <li><b>Opt: Neighborhood Settings ({@link MatrixProperty MatrixProperty[Float]}})</b><br>
+ *     Beschreibt die Nachbarschaft, die fuer jeden LU-Typ betrachtet wird.
+ *     Muss eine <i>w</i>x<i>h</i>x<i>n</i>-Matrix darstellen, die Float-Werte enthaelt.
+ *     Dabei bestimmten <i>w</i> und <i>h</i> die Hoehe und Breit der betrachteten
+ *     Nachbarschaft. Werden Neighborhodd Weights angegeben, so werden auch die
+ *     Settings zu einer Pflicht-Angabe.
+ * <li><b>Opt: Neighborhood Regression Results ({@link MatrixProperty MatrixProperty[Float]}})</b><br>
+ *     Beschreibt die Einfluss-Staerke (Betas) eines jeden LU-Typs fuer den
+ *     Fall, dass er in der Nachbarschaft eines anderen LU-Typs auftritt.
+ *     Muss eine (<i>n</i>+1)x<i>n</i>-Matrix darstellen, die Float-Werte enthaelt.
+ *     Werden Neighborhodd Weights angegeben, so werden auch die Regression Results
+ *     zu einer Pflicht-Angabe.
+ * <li><b>Opt: Location specific preference addition (LSPA) ({@link MultiGrid})</b><br>
+ *     Enthaelt Faktoren, die (gewichtet) der Gesamt-Wahrscheinlichkeit
+ *     hinzuaddiert werden. Sie dienen dazu, bestimmte Regionen fuer bestimmte
+ *     LUC-Typen zu bevorzugen. Das MultiGrid muss mind. <i>n</i> numerische Raster
+ *     enthalten, die alle dieselbe Dimension besitzen, wie das Ausgangsszenario.</li>
+ * <li><b>Opt: Location specific preference addition factors ({@link ListProperty ListProperty[Float]})</b><br>
+ *     Enthaelt Gewichte, mit denen die LSPA-W'keiten gewichtet werden. Die Liste
+ *     muss min. <i>n</i> Eintraege haben.
+ * <li><b>Ein Ausgaberaster fuer die aktuelle LU ({@link WritableGrid})</b><br>
+ *     Hierin wird die aktuell modellierte LU-Konfiguration gespeichert.
+ *     Das Raster muss dieselbe Dimension besitzen, wie das Ausgangsszenario.</li>
+ * <li><b>Ein Ausgaberaster fuer die aktuelle LU Historie ({@link WritableGrid})</b><br>
+ *     Hierin wird die aktuelle Dauer gespeichert, fuer die eine Zelle
+ *     unter der aktuellen LU befindet.<br>
+ *     Das Raster muss dieselbe Dimension besitzen, wie das Ausgangsszenario.</li>
+ * <li><b>Ein temp. Ausgaberaster fuer die LU-Wahrscheinlichkeiten ({@link MultiGrid})</b><br>
+ *     Hierin werden die ueber die Driving Forces und Regression Results errechneten
+ *     LU-Wahrscheinlichkeiten gespeichert.
+ *     Das Raster muss dieselbe Dimension besitzen, wie das Ausgangsszenario.</li>
+ * <li><b>Ein temp. Ausgaberaster fuer die Nachbarschafts-Wahrscheinlichkeiten ({@link MultiGrid})</b><br>
+ *     Hierin werden die ueber die Nachbarschaftszellen und Nachbarschaftsregression errechneten
+ *     Wahrscheinlichkeiten gespeichert.
+ *     Das Raster muss dieselbe Dimension besitzen, wie das Ausgangsszenario.</li>
+ * <li><b>Ausgabeliste fuer die Iterations-Variablen ({@link ListProperty ListProperty[Float]})</b><br>
+ *     Speichert die aktuellen Werte der Iterationsvariablen ITER(U).</li>
+ * <li><b>Ausgaberaster fuer die LU zu jedem Zeitpunkt ({@link MultiGrid})</b><br>
+ *     Hierin wird die fuer jeden Zeitschritt modellierte LU-Konfiguration gespeichert.<br>
+ *     Das MultiGrid muss dieselbe Dimension besitzen, wie das Ausgangsszenario.</li>
+ * </ol>
+ * Die LU-Wahrscheinlichkeiten P1 (fuer Driving Forces) und P2 (fuer Nachbarschaft)
+ * werden jeweils ueber ein <i>Binary Logit Model</i> errechnet und gehen anteilig
+ * in die Gesamtwahrscheinlichkeit TPROB ein:
+ * <center>
+ *    TPROB(i,U) = P1(i,U) * (1-NBH_WEIGHT(U)) + P2(i,U) * NBH_WEIGHT + ELAS(U) - ITER(U)
+ * </center><br>
+ * Die Elastizitaet ELAS(U) wird nur eingerechnet, wenn sich die Zelle i im vorangegebenen
+ * Zeitschritt bereits unter der Landnutzung U befindet.
+ * In jedem Zeitschritt wird solgange iteriert, bis die vorgegebenen Bedarfe fuer
+ * jeden LU-Typ (bis auf die Abweichungen <i>a</i> und <i>s</i>) erfuellt sind.
+ * Nach jedem Iterationsschritt werden die ITER(U)-Variablen (einzige variable
+ * Groesse innerhalb einer Zeitschritt-Iteration!) auf Basis der
+ * Bedarfsabweichnung <i>DEMAND(U) - COVER(U)</i> angepasst, um die
+ * Gesamtwahrscheinlicheiten "in eine geeignete Richtung" zu lenken.
+ * <br><br>
+ * <b><u>BEACHTE</u>:</b><br>
+ * Zur Zeit werden folgende in CLUE integriert Regeln noch nicht unterstuetzt:
+ * <ul>
+ * <li>Area Restrictions fuer bestimmte Wechsel LU1 -> LU2 (Angabe ueber LU-Conversion
+ *     Matrix zusammen mit speziellen Eingabe-Rastern)</li>
+ * <li>Aufteilung des Untersuchungsgebiets in mehrere Regionen</li>
+ * </ul>
+ * @see ClueModelContentManager
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class ClueModel extends AbstractStepModel {
+  /** {@link ResourceProvider}, der die Uebersetzungen fuer die Clue-GUI
+   *  bereitstellt: {@code locales.XuluModel_Clue} */
+  protected static ResourceProvider CLUE_RES = XuluModellingPlatform.registerResourceProvider("XuluModel_Clue",Locale.ENGLISH);
+
+  /** Konstante fuer die Toleranz-Art "prozentual". */
+  public static final int TOLTYPE_PCT = 0;
+  /** Konstante fuer die Toleranz-Art "absolut in Bedarf-Einheit". */
+  public static final int TOLTYPE_ABS = 1;
+
+  /** Speichert den ContentManager fuer das Modell.
+   *  @see ClueModelContentManager */
+  protected ClueModelContentManager contManager;
+
+  private final ClueModelGUI  modelGUI = new ClueModelGUI();
+  private final Logger        LOG      = LogManager.getLogger(this.getClass().getName());
+
+  //********** Lese/Schreibrechte, die fuer den gesamten ***********
+  //********** Modellanlauf gehalten werden muessen      ***********
+  private PropertyReadAccess      RA_baseLU       = null; // Base Scenario
+  private PropertyReadAccess      RA_baseLUHist   = null; // Base LU History
+  private PropertyReadAccess      RA_luConv       = null; // LU-Conversion-Matrix
+  private PropertyReadAccess      RA_luConvDev    = null; // Deviation of LU-Conversion-Matrix
+  private PropertyReadAccess      RA_luElas       = null; // LU-Conversion-Elasticity
+  private PropertyReadAccess      RA_areaRestr    = null; // Area Restrictions
+  private PropertyReadAccess      RA_luDemand     = null; // LU-Bedarfe
+  private PropertyReadAccess      RA_sdfGrids     = null; // Static Driving Forces
+  private PropertyReadAccess      RA_ddfList      = null; // List of dynmic Driving Forces
+  private PropertyReadAccess      RA_ddfGrids     = null; // Dynamic Driving Forces
+  private PropertyReadAccess      RA_regrRes      = null; // Regression Results
+  private PropertyReadAccess      RA_nbhWeights   = null; // Gewichtung der Nachbarschaft pro LU-Typ
+  private PropertyReadAccess      RA_nbhSettings  = null; // Definition der Umgebung pro LU-Typ
+  private PropertyReadAccess      RA_nbhRegrRes   = null; // Regression Results fuer Nachbarschaft
+  private PropertyReadAccess      RA_lspaProb     = null; // Regression Results fuer Nachbarschaft
+  private PropertyWriteAccess     WA_outActLU     = null; // speichert die aktuell sim. LU
+  private PropertyWriteAccess     WA_outActLUHist = null; // speichert die aktuell sim. LU Historie
+  private PropertyWriteAccess     WA_outLUProb    = null; // speichert die LU-Wahrscheinlichkeiten
+  private PropertyWriteAccess     WA_outNbhProb   = null; // speichert die Nachbarschafts-Wahrscheinlichkeiten
+  private ListPropertyWriteAccess WA_outTotProb   = null; // speichert die TPROB fuer jeden LUC-Typ
+  private PropertyWriteAccess     WA_outStepLU    = null; // speichert die LU fuer jeden Zeitpunkt
+
+  //**************** Variablen mit denen gearbeitet wird *******************
+  // Modell-Parameter
+  private int    luCount    = 0;    // Anzahl an LU-Typen
+  private int    dfCount    = 0;    // Anzahl an Driving Forces
+  private int    ddfCount   = 0;    // Anzahl an dynamischen Driving Forces
+  private int    areaWidth  = 0;    // Breite des Untersuchungsgebiets (Rasterzellen)
+  private int    areaHeight = 0;    // Hoehe des Untersuchungsgebiets (Rasterzellen)
+  private int    areaMinX   = 0;    // Start-Index des Rasters in X-Richtung
+  private int    areaMinY   = 0;    // Start-Index des Rasters in Y-Richtung
+  private int    areaMaxX   = 0;    // End-Index des Rasters in X-Richtung (EXKLUSIVE!)
+  private int    areaMaxY   = 0;    // End-Index des Rasters in Y-Richtung (EXKLUSIVE!)
+  private int    demandTolType    = 0;  // Art der Abweichungsangaben
+  private float  demandTolSingle  = 0;  // erlaubte Abweichung fuer jeden einzelnen LU-Typ vom Bedarf
+  private float  demandTolAverage = 0;  // erlaubte Durchschnitts-Abweichung fuer das Untersuchungsgebiet
+  private float  demandConv = 0;    // Umrechnungsfaktor Bedarfseingeit -> qm
+  private float  cellSize   = 0;    // Flaeche einer Rasterzelle (in Bedarfseinheit)
+  // Eingabe-Daten, die ueber den gesamten Modellablauf benoetigt werden
+  private WritableGrid            baseLU        = null; // Base Scenario
+  private WritableGrid            baseLUHist    = null; // Base LU History
+  private int[][]                 luConv        = null; // LU-Conversion-Matrix
+  private boolean                 CALC_WITH_DEV = false; // Flag, ob mit Abweichungen in LUC-Conversion-Matrix gerechnet wird
+  private int[][]                 luConvDev     = null; // Deviation of LU-Conversion-Matrix
+  private float[]                 luElas        = null; // LU-Conversion-Elasticity
+  private WritableGrid            areaRestr     = null; // Area Restrictions
+  private float[][]               luDemand      = null; // LU-Bedarfe
+  private WritableGrid[]          sdfGrids      = null; // Static Driving Forces
+  private boolean                 CALC_WITH_DDF = false; // Flag, ob dynamische DF beruecksichtigt werden
+  private WritableGrid[]          ddfGrids      = null; // Dynamic Driving Forces
+  private int[]                   ddfStartIdx   = null; // Listenindex an dem ein dyn. DF beginnt
+  private float[][]               regrRes       = null; // Regression Results fuer LUCC
+  private boolean                 CALC_WITH_NBH = false; // Flag, ob Nachbarschaftsw'keit beruecksichtigt wird
+  private float[]                 nbhWeights    = null; // Gewichtung der Nachbarschaft pro LU-Typ
+  private float[][][]             nbhSettings   = null; // Definition der Umgebung pro LU-Typ
+  private float[][]               nbhRegrRes    = null; // Regression Results fuer Nachbarschaft
+  private int                     nbhRadiusX    = 0;    // horizontaler Radius der betrachteten Nachbarschaft
+  private int                     nbhRadiusY    = 0;    // vertikaler Radius der betrachteten Nachbarschaft
+  private boolean                 CALC_WITH_LSPA = false; // Flag, ob LSPA beruecksichtigt wird
+  private WritableGrid[]          lspaProb      = null; // Location specific preference addition
+  private float[]                 lspaFact      = null; // Faktoren der Location specific preference addition
+  private float[][]               luCover       = null; // LU-Bedeckung der Typen ueber die Zeit in Bedarfseinheit
+  private float                   totCover      = 0;    // Gesamte Landbedeckungsflaeche (ohne NoData!)
+  private Random                  rand          = null; // Zufallsgenerator
+  private float[]                 iterSpeed     = null; // Geschwindigkeit fuer die ITER-Variablen
+  // Ausgabe-Daten, die ueber den gesamten Modellablauf benoetigt werden
+  private WritableGrid            outActLU      = null; // speichert die aktuell sim. LU
+  private WritableGrid            outActLUHist  = null; // speichert die aktuell sim. LU History
+  private WritableGrid[]          outLUProb     = null; // speichert die LU-Wahrscheinlichkeiten
+  private WritableGrid[]          outNbhProb    = null; // speichert die Nachbarschafts-Wahrscheinlichkeiten
+  private WritableGrid[]          outTotProb    = null; // speichert die TPROB fuer jeden LUC-Typ
+  private float[]                 outIter       = null; // speichert die Iterationsvariablen
+  private MultiGrid               outStepLU     = null; // speichert die LU fuer jeden Zeitpunkt
+  private Map<Float,Float>        luMap         = new HashMap<Float,Float>(); // speichert das Mapping von LUCC-Typen im BAseScenario zu 0,1,2,...
+  private Map<Float,Float>        luMapReverse  = new HashMap<Float,Float>(); // speichert das Mapping von LUCC-Typen im BAseScenario zu 0,1,2,...
+
+
+  /**
+   * Erzeugt eine neue Instanz des CLUE-Modells.
+   */
+  public ClueModel() {
+    super( new ClueModelContentManager() );
+    contManager = (ClueModelContentManager)super.contManager;
+    modelResourceProvider = CLUE_RES;
+    
+    // In dieser optimierten Clue-Implementierung, werden die Iterationsvariablen
+    // lokal verwaltet und brauchen deshalb nicht als Ressource zur Verfuegung
+    // gestellt werden
+    contManager.getResource( contManager.ITERVAR ).setNullable(true);
+    // Iterations-Ereignisse der Event-Liste hinzufuegen
+    events.add(ModelIterationStepStartedEvent.class);
+    events.add(ModelIterationStepFinishedEvent.class);
+  }
+
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////   Implementierung von AbstractXuluModel   //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Initialisiert das Model, indem die Ressourcen aus dem ContentManager
+   * geladen werden und mit Lese/Schreib-Rechten versehen werden. Zudem
+   * werden Referenzen auf einen Teil der Ressourcen in lokalen Variablen
+   * gespeichert, um waehrend des Modellablaufs effizienter darauf zugreifen
+   * zu koennen.
+   */
+  public void performModelInit() {
+    if ( contManager == null )
+      return;
+    //######### Zugriffsrechte aus Ressourcen/Propertys holen #########
+    RA_baseLU       = contManager.getBaseScenario().getReadAccess(this);
+    RA_baseLUHist   = contManager.getLUHistory().getReadAccess(this);
+    MatrixProperty conversionMatrix = contManager.getLUConversionMatrix();
+    RA_luConv       = conversionMatrix.getReadAccess(this);
+    // Abweichungen in der LUC-Matrix sind optional
+    CALC_WITH_DEV   = contManager.getLUConversionDeviationMatrix() != null;
+    RA_luConvDev    = CALC_WITH_DEV ? contManager.getLUConversionDeviationMatrix().getReadAccess(this) : null;
+    RA_luElas       = contManager.getConversionElasticity().getReadAccess(this);
+    RA_areaRestr    = contManager.getAreaRestrictions().getReadAccess(this);
+    RA_luDemand     = contManager.getDemandScenario().getReadAccess(this);
+    RA_regrRes      = contManager.getRegressionResults().getReadAccess(this);
+    RA_sdfGrids     = ((ListProperty)contManager.getStaticDrivingForces().getProperty(MultiGrid.PROP_GRIDS)).getReadAccess(this);
+    // Dynamische Driving Forces sind optional
+    CALC_WITH_DDF   = contManager.getDynamicDrivingForceTypes() != null;
+    if ( CALC_WITH_DDF ) {
+      RA_ddfList    = contManager.getDynamicDrivingForceTypes().getReadAccess(this);
+      RA_ddfGrids   = ((ListProperty)contManager.getDynamicDrivingForces().getProperty(MultiGrid.PROP_GRIDS)).getReadAccess(this);
+    } else {
+      RA_ddfList    = null;
+      RA_ddfGrids   = null;
+    }
+    // Nachbarschafts-W'keiten sind optional
+    CALC_WITH_NBH   = (contManager.getNeighborhoodWeights() != null);
+    if ( CALC_WITH_NBH ) {
+      RA_nbhWeights  = contManager.getNeighborhoodWeights().getReadAccess(this);
+      RA_nbhSettings = contManager.getNeighborhoodSettings().getReadAccess(this);
+      RA_nbhRegrRes  = contManager.getNeighborhoodRegression().getReadAccess(this);
+      WA_outNbhProb  = ((ListProperty)contManager.getNeighborhoodProbabilities().getProperty(MultiGrid.PROP_GRIDS)).getWriteAccess(this);
+    } else {
+      RA_nbhWeights  = null;
+      RA_nbhSettings = null;
+      RA_nbhRegrRes  = null;
+      WA_outNbhProb  = null;
+    }
+    // Location specific preference addition ist optional
+    CALC_WITH_LSPA = (contManager.getLSPAProbabilities() != null);
+    if ( CALC_WITH_LSPA )
+      RA_lspaProb = ((ListProperty)contManager.getLSPAProbabilities().getProperty(MultiGrid.PROP_GRIDS)).getReadAccess(this);
+    else
+      RA_lspaProb = null;
+
+    WA_outActLU     = contManager.getActLUResult().getWriteAccess(this);
+    WA_outActLUHist = contManager.getActLUHistory().getWriteAccess(this);
+    WA_outLUProb    = ((ListProperty)contManager.getLUProbabilities().getProperty(MultiGrid.PROP_GRIDS)).getWriteAccess(this);
+    WA_outStepLU    = ((ListProperty)contManager.getStepLUResults().getProperty(MultiGrid.PROP_GRIDS)).getWriteAccess(this);
+    // Speichern der Gesamt-W'keiten ist optional
+    if ( contManager.getTotalProbabilities() != null )
+      WA_outTotProb = ((ListProperty)contManager.getTotalProbabilities().getProperty( MultiGrid.PROP_GRIDS )).getWriteAccess(this);
+    else
+      WA_outTotProb = null;
+
+    //#########  Variablen belegen mit denen gearbeitet wird  ###########
+    this.stepCount    = contManager.getStepCount().getOneTimeReadAccess().getValueAsInt(); // WICHTIG!!
+    this.dfCount      = contManager.getStaticDrivingForces().getGridCount();
+    this.demandTolType    = contManager.getDemandToleranceType().getOneTimeReadAccess().getValueAsInt();
+    this.demandTolSingle  = contManager.getSingleDemandTolerance().getOneTimeReadAccess().getValueAsFloat();
+    this.demandTolAverage = contManager.getAverageDemandTolerance().getOneTimeReadAccess().getValueAsFloat();
+    this.demandConv   = contManager.getConversionFactor().getOneTimeReadAccess().getValueAsFloat();
+    this.luCount      = conversionMatrix.getSize(0);
+
+    this.baseLU       = (WritableGrid)RA_baseLU.getValue();
+    this.areaWidth    = baseLU.getWidth();
+    this.areaHeight   = baseLU.getHeight();
+    this.areaMinX     = baseLU.getMinX();
+    this.areaMinY     = baseLU.getMinY();
+    this.areaMaxX     = baseLU.getMinX() + areaWidth;
+    this.areaMaxY     = baseLU.getMinY() + areaHeight;
+    this.cellSize     = ((float)(baseLU.getCellWidth() * baseLU.getCellHeight())) / demandConv;
+    this.baseLUHist   = (WritableGrid)RA_baseLUHist.getValue();
+    this.outActLU     = (WritableGrid)WA_outActLU.getValue();
+    this.outActLUHist = (WritableGrid)WA_outActLUHist.getValue();
+    this.outStepLU    = contManager.getStepLUResults();
+    this.outIter      = new float[luCount];
+
+    // LU-Conversion-Matrix und Abweichung in Arrays kopieren (PERFORMANZ!)
+    this.luConv    = new int[conversionMatrix.getSize(0)][conversionMatrix.getSize(1)];
+    this.luConvDev = new int[conversionMatrix.getSize(0)][conversionMatrix.getSize(1)];;
+    for (int i=0; i<luConv.length; i++)
+      for (int j=0; j<luConv[i].length; j++) {
+        luConv[i][j]    = RA_luConv.getValueAsInt(i,j);
+        luConvDev[i][j] = CALC_WITH_DEV ? RA_luConvDev.getValueAsInt(i,j) : 0;
+      }
+    // LU-Demand-Matrix in Array kopieren (PERFORMANZ!)
+    this.luDemand    = new float[contManager.getDemandScenario().getSize(0)][contManager.getDemandScenario().getSize(1)];
+    for (int i=0; i<luDemand.length; i++)
+      for (int j=0; j<luDemand[i].length; j++)
+        luDemand[i][j] = RA_luDemand.getValueAsFloat(i,j);
+    // LUCC Elastizitaet in Array kopieren (PERFORMANZ!)
+    this.luElas      = new float[((ListPropertyReadAccess)RA_luElas).getCount()];
+    for (int i=0; i<luElas.length; i++)
+      this.luElas[i] = RA_luElas.getValueAsFloat(i);
+    this.areaRestr   = (WritableGrid)RA_areaRestr.getValue();
+    // Statische DF in Array kopieren (PERFORMANZ!)
+    this.sdfGrids    = new WritableGrid[contManager.getStaticDrivingForces().getGridCount()];
+    for (int i=0; i<sdfGrids.length; i++)
+      sdfGrids[i] = contManager.getStaticDrivingForces().getGrid(i);
+
+    // Die Liste der dyn. DF ist blockweise nach DF grupperiert
+    // Es koennen mehr Zeitschritt-Raster angegeben werden, als simuliert
+    // werden.
+    // Im Array 'ddfStartIdx' wird fuer die dynamischen DF gespeichert, an
+    // welcher Stelle in der Liste der Block beginnt.
+    // -1 bedeutet, dass der DF ein statische DF ist!
+    this.ddfStartIdx = new int[dfCount];
+    for (int i=0; i<dfCount; i++)
+      ddfStartIdx[i] = - 1;
+
+    // Variablen fuer dynamische Driving Forces nur belegen, wenn auch mit
+    // diesen gerechnet wird.
+    if ( CALC_WITH_DDF ) {
+      ListPropertyReadAccess ddfList = (ListPropertyReadAccess)RA_ddfList;
+      this.ddfCount    = ddfList.getCount();
+      // Raster mit dyn. DF in Array kopieren (PERFORMANZ!)
+      this.ddfGrids    = new WritableGrid[contManager.getDynamicDrivingForces().getGridCount()];
+      for (int i=0; i<ddfGrids.length; i++)
+        ddfGrids[i] = contManager.getDynamicDrivingForces().getGrid(i);
+      // Start-Indizes der DDF in der Liste der DDF-Grids
+      for (int i=0; i<ddfCount; i++)
+        ddfStartIdx[ddfList.getValueAsInt(i)] = i * ddfGrids.length / ddfCount;
+    } else {
+      this.ddfCount = 0;
+      this.ddfGrids = null;
+    }
+
+    // Regression Results fuer LUCC-W'keiten in Array kopieren (PERFORMANZ!)
+    this.regrRes = new float[contManager.getRegressionResults().getSize(0)][contManager.getRegressionResults().getSize(1)];
+    for (int i=0; i<regrRes.length; i++)
+      for (int j=0; j<regrRes[i].length; j++)
+        this.regrRes[i][j] = RA_regrRes.getValueAsFloat(i,j);
+
+    // Ausgabe-Raster-Liste fuer LUC-W'keiten aus Ressource holen,
+    // auf benoetigte Groesse erweitern und in Array kopieren (PERFORMANZ!)
+    MultiGrid outLUProbTemp = contManager.getLUProbabilities();
+    for (int i=0; outLUProbTemp.getGridCount()<luCount; i++)
+      outLUProbTemp.addGrid(); // Liste muss ein Raster fuer jeden LU-Typ enthalten
+    this.outLUProb  = new WritableGrid[luCount];
+    for (int i=0; i<luCount; i++)
+      this.outLUProb[i]  = outLUProbTemp.getGrid(i);
+
+    // Variablen fuer Nachbarschaftsw'keiten nur belegen, wenn auch mit diesen
+    // gerechnet wird
+    if ( CALC_WITH_NBH ) {
+      this.nbhRadiusX  = (contManager.getNeighborhoodSettings().getSize(0)-1)/2;
+      this.nbhRadiusY  = (contManager.getNeighborhoodSettings().getSize(1)-1)/2;
+      // Nbh.-Gewichtungen in Array kopieren (PERFORMANZ!)
+      this.nbhWeights  = new float[((ListPropertyReadAccess)RA_nbhWeights).getCount()];
+      for (int i=0; i<nbhWeights.length; i++)
+        this.nbhWeights[i] = RA_nbhWeights.getValueAsFloat(i);
+      // Nbh.-Settings in Array kopieren (PERFORMANZ!)
+      this.nbhSettings = new float[contManager.getNeighborhoodSettings().getSize(0)][contManager.getNeighborhoodSettings().getSize(1)][contManager.getNeighborhoodSettings().getSize(2)];
+      for (int i=0; i<nbhSettings.length; i++)
+        for (int j=0; j<nbhSettings[i].length; j++)
+          for (int k=0; k<nbhSettings[i][j].length; k++)
+            this.nbhSettings[i][j][k] = RA_nbhSettings.getValueAsFloat(i,j,k);
+      // Regression Results fuer Nbh. in Array kopieren (PERFORMANZ!)
+      this.nbhRegrRes  = new float[contManager.getNeighborhoodRegression().getSize(0)][contManager.getNeighborhoodRegression().getSize(1)];
+      for (int i=0; i<nbhRegrRes.length; i++)
+        for (int j=0; j<nbhRegrRes[i].length; j++)
+          this.nbhRegrRes[i][j] = RA_nbhRegrRes.getValueAsFloat(i,j);
+      // Ausgabe-Raster-Liste fuer Nachbarschafts-W'keiten aus Ressource holen,
+      // auf benoetigte Groesse erweitern und in Array kopieren (PERFORMANZ)
+      MultiGrid outNbhProbTemp = contManager.getNeighborhoodProbabilities();
+      for (int i=0; outNbhProbTemp.getGridCount()<luCount; i++)
+        outNbhProbTemp.addGrid(); // Liste muss ein Raster fuer jeden LU-Typ enthalten
+      this.outNbhProb = new WritableGrid[luCount];
+      for (int i=0; i<luCount; i++)
+        this.outNbhProb[i] = outNbhProbTemp.getGrid(i);
+    } else {
+      this.nbhRadiusX  = 0;
+      this.nbhRadiusY  = 0;
+      this.nbhWeights  = null;
+      this.nbhSettings = null;
+      this.nbhRegrRes  = null;
+      this.outNbhProb  = null;
+    }
+
+    // Bei Toleranz-Art "prozentual" werden die Werte in Prozent
+    // angegeben (intern wird aber mit Abweichungen zwischen 0 und 1 gerechnet!)
+    if ( demandTolType == TOLTYPE_PCT ) {
+      this.demandTolSingle  /= 100.0;
+      this.demandTolAverage /= 100.0;
+    }
+
+    // "Geschwindigkeit" fuer die Iterationsvariablen
+    this.iterSpeed = new float[luCount];
+
+    // Speichert die Flaechendeckung (in der Bedarfseinheit, z.B. ha)
+    // fuer die einzelnen LU-Typen zu jedem Zeitpunkt
+    // --> Die initialen Werte stehen in der 0-Zeile der Demand-Matrix
+    this.luCover  = new float[luCount][stepCount+1];
+    this.totCover = 0;
+    statusOut.print(CLUE_RES.getString("Model.InitCover")+": ");
+    for (int lu=0; lu<luCount; lu++) {
+      luCover[lu][0] = luDemand[lu][0];
+      totCover += luCover[lu][0]; // Gesamt-Flaeche des Untersuchungsgebiets
+      statusOut.print(luCover[lu][0]+"   ");
+    }
+    statusOut.println("   >> "+CLUE_RES.getString("Model.TotalCover")+" "+totCover);
+
+    // Ausgabe-Raster leeren
+    for (int y=outActLU.getMinY(); y<outActLU.getMinY()+outActLU.getHeight(); y++)
+      for (int x=outActLU.getMinX(); x<outActLU.getMinX()+outActLU.getWidth(); x++)
+        outActLU.setRasterSample(Float.NaN,x,y);
+    // Liste der Schritt-Resultate leeren (damit bei vorzeitigem Modellende
+    // nicht neue mit alten Daten vermischt werden)
+    while ( outStepLU.getGridCount() > 0 )
+      outStepLU.removeGrid(0);
+
+    // (optionale) Ausgabe-Raster-Liste fuer Gesamt-W'keiten aus Ressource holen,
+    // auf benoetigte Groesse erweitern und in Array kopieren (PERFORMANZ!)
+    MultiGrid outTotProbTemp = contManager.getTotalProbabilities();
+    if ( outTotProbTemp != null ) {
+      for (; outTotProbTemp.getGridCount()<luCount;)
+        outTotProbTemp.addGrid(); // Liste muss ein Raster fuer jeden LU-Typ enthalten
+      this.outTotProb  = new WritableGrid[luCount];
+      for (int i=0; i<luCount; i++)
+        this.outTotProb[i] = outTotProbTemp.getGrid(i);
+    } else
+      outTotProb = null;
+
+    // (optionale) LSPA-Raster und -Faktoren in Array kopieren (PERFORMANZ!)
+    if ( CALC_WITH_LSPA ) {
+      // Raster in Array kopieren
+      this.lspaProb = new WritableGrid[luCount];
+      for (int i=0; i<lspaProb.length; i++)
+        this.lspaProb[i] = (WritableGrid)RA_lspaProb.getValue(i);
+      // Wenn Faktoren angegeben, dann in Array kopieren
+      this.lspaFact = new float[luCount];
+      ListProperty lspaFactProp = contManager.getLSPAFactors();
+      if ( lspaFactProp == null )
+        // wenn Faktoren nicht angegeben, dann 1 annehmen
+        Arrays.fill(lspaFact, 1.0f);
+      else {
+        ListPropertyReadAccess RA_lspaFact = lspaFactProp.getReadAccess(this);
+        for (int i=0; i<lspaFact.length; i++)
+          this.lspaFact[i] = RA_lspaFact.getValueAsFloat(i);
+        RA_lspaFact.release();
+      }
+    } else {
+      this.lspaProb = null;
+      this.lspaFact = null;
+    }
+
+    // spezielle GUI initialisieren
+    if (modelGUI != null)
+      modelGUI.init(this);
+
+    LOG.info("Scanning for all LU-Values in the Base-Scenario and mapping to 0...");
+    // Alle Zellen des Untersuchungsgebiets...
+    Set<Float> luccs = new HashSet<Float>();
+
+    for (Integer y=0; y<this.areaHeight; y++)
+      for (Integer x=0; x<this.areaWidth; x++){
+    	  float rasterSampleAsFloat = (float)baseLU.getRasterSampleAsFloat(x,y);
+    	  if (! Float.isNaN(rasterSampleAsFloat) )
+    		 luccs.add( rasterSampleAsFloat );
+  	}
+    Object[] lmo = luccs.toArray() ;
+	Arrays.sort(lmo);
+	//statusOut.println(CLUE_RES.getString("Model.LucTypes")+": ");
+	luMap.put(Float.NaN, Float.NaN );
+	luMapReverse.put(Float.NaN, Float.NaN );
+	for (Integer i = 0; i < lmo.length; i++ ){
+		luMap.put((Float) lmo[i], new Float(i) );
+		luMapReverse.put( new Float(i), (Float) lmo[i]);
+	}
+
+	LOG.info("========================================");
+    LOG.info("MODEL INITIALISED (Log-Level "+LOG.getLevel()+")");
+  }
+
+  /**
+   * Gibt die Lese/Schreibrechte auf das Ein- und Ausgaberaster wieder frei.
+   * Interne Ressourcen brauchen keine aus dem Speicher entfernt werden.
+   */
+  public void performModelDispose() {
+    // Ressourcen wieder freigeben
+    releaseAccess(RA_baseLU);
+    releaseAccess(RA_baseLUHist);
+    releaseAccess(RA_luConv);
+    releaseAccess(RA_luConvDev);
+    releaseAccess(RA_luElas);
+    releaseAccess(RA_areaRestr);
+    releaseAccess(RA_luDemand);
+    releaseAccess(RA_sdfGrids);
+    releaseAccess(RA_ddfList);
+    releaseAccess(RA_ddfGrids);
+    releaseAccess(RA_regrRes);
+    releaseAccess(RA_nbhWeights);
+    releaseAccess(RA_nbhSettings);
+    releaseAccess(RA_nbhRegrRes);
+    releaseAccess(RA_lspaProb);
+    releaseAccess(WA_outActLU);
+    releaseAccess(WA_outActLUHist);
+    releaseAccess(WA_outLUProb);
+    releaseAccess(WA_outNbhProb);
+    releaseAccess(WA_outStepLU);
+    releaseAccess(WA_outTotProb);
+    LOG.info("MODEL DISPOSED");
+    LOG.info("========================================");
+  }
+
+  /**
+   * Fuehrt einen Schritt des Modellablaufs durch.
+   * @param stepNo zu modellierender Schritt (beginnend bei 1!)
+   */
+  public void performModelStep(int stepNo) {
+    // Unloading no longer needed Data:
+    if(stepNo>2)
+      outStepLU.getGrid(stepNo-3).unloadData();
+
+    // Raster festlegen, in dem die LU des vorangegangenen
+    // Schritts zu finden ist
+    WritableGrid lastLUGrid = (stepNo==1) ? baseLU : outStepLU.getGrid(stepNo-2);
+    // Raster festlegen, in dem die aktuelle LU History
+    // zu finden ist
+    WritableGrid luHistGrid = (stepNo==1) ? baseLUHist : outActLUHist;
+
+    // Merken, ob an einer Stelle bereits eine U-Zelle in einen anderen
+    // Typ gewechselt hat
+    boolean[] alreadyLUCCFromType = new boolean[luCount];
+    // Merken, ob an einer Stelle bereits eine U-Zelle neu entstanden ist
+    boolean[] alreadyLUCCToType = new boolean[luCount];
+
+    // LU-Wahrscheinlichkeiten berechnen
+    calculateLUProbabilities(stepNo);
+
+    // Nachbarschafts-Wahrscheinlichkeiten berechnen
+    calulateNeighborhoodProbabilities(stepNo,lastLUGrid);
+
+    // Randomizer fuer diesen Zeitschritt erzeugen
+    rand = new Random(System.currentTimeMillis());
+
+    int   iterNo     = 0;
+    int   x          = 0;
+    int   y          = 0;
+    int   lu         = 0;
+    int   lastLU     = 0;
+    int   bestLU     = 0;
+    float bestLUProb = 0;
+    float baseProb   = 0;
+    float nbhProb    = 0;
+    float nbhWeight  = 0;
+    float elas       = 0;
+    float lspa       = 0;
+    float totalProb  = 0;
+    float lastLUC    = 0;
+    float actLUC     = 0;
+
+    statusOut.print( CLUE_RES.getString("Model.Step.Calc.Iter", stepNo) );
+    for (iterNo=1; !checkDemandCompliedAndCalculateIterVar(stepNo,iterNo); iterNo++) {
+      this.fireModelEvent( new ModelIterationStepStartedEvent(this,stepNo,iterNo) );
+      if ( modelGUI != null /*&& modelGUI.isDeviationUpdateEnabled()*/ )
+        modelGUI.setIterationNumber(stepNo+"/"+iterNo);
+      // Arrays fuer Iterationsschritt initialisieren
+      for (lu = 0; lu < luCount; lu++) {
+        // noch kein Wechsel von einem LU-Typ
+        alreadyLUCCFromType[lu] = false;
+        // noch kein Wechsel zu einem LU-Typ
+        alreadyLUCCToType[lu] = false;
+        // Flaechen der LU-Typen fuer diesen Zeitschritt
+        luCover[lu][stepNo] = 0;
+        // Speed fuer die Iterationsvariablen initialisieren
+        // --> liegt die Nachfrage bei weniger als 5% des U'gebiets
+        //     wird langsamer begonnen
+        if ( luDemand[lu][stepNo]/totCover < 0.05f )
+          iterSpeed[lu] = 0.01f;
+        else
+          iterSpeed[lu] = 0.05f;
+      }
+
+      // Fuer alle Zellen des Untersuchungsgebiets
+      for (y = areaMinY; y < areaMaxY; y++)
+        for (x = areaMinX; x < areaMaxX; x++) {
+          checkBreakingCommands();
+
+          // Rasterzellen ausserhalb des Untersuchungsgebiets komplett
+          // ignorieren
+          // Grund: NoData-Zellen (Float.NaN) werden beim Cast in int zu 0,
+          //        also zur Landnutzung 0!!
+          if ( checkNoData(x,y,areaRestr) || checkNoData(x,y,baseLU) )
+            continue;
+
+          // Nutzungsdauern erhoehen
+          if (iterNo==1)
+            outActLUHist.setRasterSample(luHistGrid.getRasterSampleAsFloat(x, y) + 1, x, y);
+
+          // vorangegangene LU merken.
+          // Diese steht im Raster nicht unbedingt 0-basiert
+          lastLU = luMap.get( new Float (lastLUGrid.getRasterSampleAsInt(x, y)) ).intValue();
+
+          // Beste gefundene LU wird mit aktueller LU initialisiert
+          bestLU = lastLU;
+          bestLUProb = 0;
+
+          // Pruefen, ob Zelle die LU wechseln darf
+          if (checkLUCCGeneralAllowed(x, y, stepNo, lastLU, alreadyLUCCToType[ lastLU ])) {
+            // Alle LU-Typen auf Wechsel pruefen
+            for (lu = 0; lu < luCount; lu++) {
+              // Pruefen, ob Zelle in den betrachteten Typ wechseln darf
+              if (checkLUCCAllowed(x, y, stepNo, lastLU, lu, alreadyLUCCFromType[lu])) {
+                // Gesamt-Wahrscheinlichkeit berechnen
+                // a) DF-W'keit und Nachbarschaft-W'keit gehen anteilig ein
+                // b) Elastizitaet geht nur ein, wenn Zelle bereits fuer den
+                //    LU-Typ genutzt wird
+                // c) ITER geht negativ ein, da es auf Basis der Abweichung
+                //    luCover-luDemand berechnet wird. Ein negatives Iter
+                //    kennzeichnet also einen Mangel und muss die Gesamtw'keit
+                //    erhoehen
+                baseProb  = outLUProb[lu].getRasterSampleAsFloat(x, y);
+                nbhProb   = !CALC_WITH_NBH ? 0 : outNbhProb[lu].getRasterSampleAsFloat(x, y);
+                nbhWeight = !CALC_WITH_NBH ? 0 : nbhWeights[lu];
+                elas      = (lu == lastLU && luElas[lu] < 1) ? luElas[lu] : 0;
+                lspa      = !CALC_WITH_LSPA ? 0 : lspaProb[lu].getRasterSampleAsFloat(x, y) * lspaFact[lu];
+                // LU-Wahrscheinlichkeit zusammensetzen
+                totalProb = baseProb * (1-nbhWeight)
+                          + nbhProb  * nbhWeight
+                          + elas
+                          + lspa
+                          - outIter[lu];
+                // Gesamt-Wahrscheinlichkeit speichern
+                if ( outTotProb != null )
+                  outTotProb[lu].setRasterSample(totalProb,x,y);
+
+                // betrachteter Typ ist geeigneter als der bisher beste
+                if (totalProb > bestLUProb) {
+                  bestLU = lu;
+                  bestLUProb = totalProb;
+                }
+              }
+            }
+            // Merken wenn wirklich ein Wechsel stattfindet
+            if (bestLU != lastLU) {
+              alreadyLUCCFromType[ lastLU ] = true;
+              alreadyLUCCToType[ bestLU ] = true;
+            }
+          }
+
+          // LU fuer diesen Iterationschritt setzen
+          outActLU.setRasterSample( luMapReverse.get ( (float) bestLU) , x, y);
+          // Flaechendeckung fuer LU-Typ erhoehen
+          luCover[ bestLU ][stepNo] += cellSize;
+        }
+      this.fireModelEvent( new ModelIterationStepFinishedEvent(this,stepNo,iterNo) );
+    }
+    statusOut.println( CLUE_RES.getString("Model.Step.Calc.Iter.done",iterNo) );
+
+    // Liste der Zeitschritt-Ausgaberaster vergroessern
+    if ( outStepLU.getGridCount() <= stepNo-1 )
+      outStepLU.addGrid();
+
+    // LU in Ausgaberaster des Zeitschritts uebernehmen und ggf.
+    // Nutzungsdauer initialisieren
+    WritableGrid outStepLUGrid = outStepLU.getGrid(stepNo-1);
+    for (y=areaMinY; y<areaMaxY; y++)
+      for (x=areaMinX; x<areaMaxX; x++) {
+        checkBreakingCommands();
+        lastLUC = luMap.get( lastLUGrid.getRasterSampleAsFloat(x,y) );
+        actLUC  = luMap.get( outActLU.getRasterSampleAsFloat(x,y) );
+        // Wenn die Landnutzung gewechselt hat, wird die Historie zurueck
+        // gesetzt
+        if ( actLUC != lastLUC )
+          outActLUHist.setRasterSample(0f,x,y);
+
+        // LU in Ausgabe-Raster des simulierten Schritts uebernehmen
+        // Die 0-basierten LU-Nummern werden wieder zurueckgemapped. (SK)
+        outStepLUGrid.setRasterSample( luMapReverse.get( actLUC) ,x,y);
+      }
+  }
+
+  /**
+   * Liefert eine CLUE-spezifische GUI, in der die Abweichungen waehrend der
+   * Iteration angezeigt werden und ueber die die Toleranzen eingestellt
+   * werden koennen
+   * @return Instannz von {@link ClueModelGUI}
+   */
+  public Component getModelSpecificGUI() {
+    return modelGUI;
+  }
+
+  //////////////////////////////////////////////////////////////////////
+  ////////////////////////   Clue-Methoden   ///////////////////////////
+  //////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob eine Rasterzelle mit <code>NoData</code> belegt ist
+   * @param x     Raster-Koordinate
+   * @param y     Raster-Koordinate
+   * @param grid  zu pruefendes Raster
+   */
+  protected static boolean checkNoData(int x, int y, WritableGrid grid) {
+    return Float.isNaN(grid.getRasterSampleAsFloat(x,y));
+  }
+
+  /**
+   * Berechnet die auf den Driving Forces basierenden
+   * Landnutzungs-Wahrscheinlichkeiten fuer einen Modell-Schritt und speichert
+   * diese in der Ressource "temp. Ausgaberaster fuer die LU-Wahrscheinlichkeiten".<br>
+   * Werden keine dynamischen Driving Forces verwendet, geschieht die Berechnung
+   * nur beim ersten Modellierungsschritt.
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   */
+  protected void calculateLUProbabilities(int stepNo) {
+    // Wenn keine dynamischen Driving Forces verwendet werden
+    // braucht die Berechnung nur fuer den ersten Schritt
+    // durchgefuehrt werden
+    if ( ddfCount == 0 && stepNo > 1 )
+      return;
+
+    statusOut.print( CLUE_RES.getString("Model.Step.Calc.LUCProb", stepNo) );
+    int x            = 0;
+    int y            = 0;
+    int lu           = 0;
+    int df           = 0;
+    float betaSum    = 0;
+    float expBetaSum = 0;
+    float prob       = 0;
+
+    // Fuer Zellen des Untersuchungsgebiets
+    for (y=areaMinY; y<areaMaxY; y++)
+      for (x=areaMinX; x<areaMaxX; x++)
+        // NotData-Bereich und Area Restrictions ignorieren
+        if ( !checkNoData(x,y,baseLU) && areaRestr.getRasterSampleAsFloat(x,y)==0 ) {
+          // Fuer alle LU-Typen
+          for (lu = 0; lu < luCount; lu++) {
+            betaSum = 0;
+            // Fuer alle Driving Forces die Summe der Betas berechnen
+            for (df = 0; df < dfCount; df++) {
+              checkBreakingCommands();
+              // DF-Grid festlegen:
+              // Bei dynamischem DF das jew. Zeitschritt-Raster aus der Liste
+              // ansonsten das statische Raster
+              WritableGrid dfGrid = null;
+              if ( ddfStartIdx[df] >= 0 )
+                dfGrid = this.ddfGrids[ddfStartIdx[df]+stepNo-1];
+              else
+                dfGrid = this.sdfGrids[df];
+
+///
+//   if ( ddfStartIdx[df] >= 0 ) {
+//     if ( x == dfGrid.convertRealToRaster(379755.2,0) &&
+//          y == dfGrid.convertRealToRaster(1028214.7,1) ) {
+//       LOG.debug("Step "+stepNo+", LUC "+lu+", "+x+"/"+y+":  "+dfGrid.getGridSampleAsFloat(379755.2, 1028214.7)+"    "+dfGrid);
+//     }
+//   }
+///
+              // Beim ersten Driving Force wird die Summe mit der
+              // Regressionskonstante initialisiert
+              if (df == 0)
+                betaSum = regrRes[0][lu];
+              // betaSum = BETA0(U) + Sum( BETA(df+1,U) * DF(df,x,y) )
+              betaSum += regrRes[df + 1][lu]
+                       * dfGrid.getRasterSampleAsFloat(x, y);
+///
+//  if ( x == 184 && y == 396 )
+//    LOG.debug("Step "+stepNo+", LUC "+lu+", DF "+df+", "+x+"/"+y+":  beta = "+regrRes[df + 1][lu]+"     dfValue = "+dfGrid.getRasterSampleAsFloat(x, y)+"     mult = "+(regrRes[df + 1][lu] * dfGrid.getRasterSampleAsFloat(x, y))+"    BetaSum = "+betaSum);
+///
+            }
+            expBetaSum = (float)Math.exp(betaSum);
+            prob = expBetaSum / (1 + expBetaSum);
+            // errechnete W'keit im Raster speichern
+///
+//  if ( x == 184 && y == 396 )
+//    LOG.debug("Step "+stepNo+", LUC "+lu+", "+x+"/"+y+":  Prob = "+prob);
+///
+            this.outLUProb[lu].setRasterSample( (float) prob, x, y);
+          }
+        }
+    //unloading no longer used ddfs to save memory (if supported by WritableGrid)
+    for (df = 0; df < dfCount; df++) {
+        WritableGrid grid = null;
+        if ( ddfStartIdx[df] >= 0 )
+          grid = this.ddfGrids[ddfStartIdx[df]+stepNo-1];
+        if(grid!=null) grid.unloadData();
+     }
+
+    statusOut.println( CLUE_RES.getString("Model.Step.Calc.done") );
+  }
+
+  /**
+   * Berechnet die auf den Nachbarschaftsbeziehungen basierenden
+   * Landnutzungs-Wahrscheinlichkeiten fuer einen Modell-Schritt und speichert
+   * diese in der Ressource "temp. Ausgaberaster fuer die Nachbarschafts-Wahrscheinlichkeiten".<br>
+   * Da sich die Landnutzung mit jedem Zeitschritt aendert geschieht dies
+   * vor jedem Zeitschritt neu.<br>
+   * Diese Methode macht nichts, wenn ohne Nachbarschafts-W'keiten simuliert wird,
+   * also wenn keine Angabe fuer die "Neighborhood-Weights" gemacht wird.
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   * @param luGrid LU-Raster aus dem die Umgebung der jeweiligen Zellen
+   *               ermittelt werden
+   */
+  protected void calulateNeighborhoodProbabilities(int stepNo, WritableGrid luGrid) {
+    // Wenn ohne Nachbarschaftsbeziehungen simuliert wird
+    if ( !CALC_WITH_NBH )
+      return;
+
+    statusOut.print( CLUE_RES.getString("Model.Step.Calc.NbhProb", stepNo) );
+
+    int      x            = 0;
+    int      y            = 0;
+    int      lu           = 0;
+    int      i            = 0;
+    int      dx           = 0;
+    int      dy           = 0;
+    int      totCellCount = 0;
+    float[]  luCellCount  = new float[luCount];
+    float    betaSum      = 0;
+    float    beta         = 0;
+    float    nbhFact      = 0;
+    float    expBetaSum   = 0;
+    float    lucc         = 0;
+    float    setting      = 0;
+    // Fuer Zellen des Untersuchungsgebiets
+    for (y=areaMinY; y<areaMaxY; y++)
+      for (x=areaMinX; x<areaMaxX; x++)
+        // NoData-Bereich und Area Restrictions ignorieren
+        if ( !checkNoData(x,y,baseLU) && areaRestr.getRasterSampleAsFloat(x,y)==0 )
+          // Fuer alle LU-Typen
+          for (lu = 0; lu < luCount; lu++) {
+            checkBreakingCommands();
+
+            // Anzahl der Zellen in der Umgebung initialisieren
+            totCellCount = 0;
+            for (i=0; i<luCount; i++)
+              luCellCount[i] = 0;
+
+            // Umgebung der Zelle betrachten
+            for (dy=-nbhRadiusY; dy<=nbhRadiusY; dy++)
+              if ( areaMinY <= y+dy && y+dy<areaMaxY )
+                for (dx=-nbhRadiusX; dx<=nbhRadiusX; dx++)
+                  if ( areaMinX <= x+dx && x+dx<areaMaxX ) {
+
+
+                    lucc = luGrid.getRasterSampleAsFloat(x+dx,y+dy); // PERFORMANZ > nur einmal den Zellen-Wert ermitteln
+                    if ( !Float.isNaN(lucc) /*!checkNoData(x+dx,y+dy,baseLU)*/ ) {
+                    	// Die LU-Typen stehen im Raster nicht 0-basiert, deshalb mapping
+                   		lucc = luMap.get( lucc );
+
+                        // Alle Zellen in Umgebung zaehlen (jedoch nur diejenigen,
+                        // die potentiell auch in die Bewertung eingehen koennen!)
+                        setting = nbhSettings[dx+nbhRadiusX][dy+nbhRadiusY][lu];
+                        if ( setting != 0.0 ) {
+                          totCellCount++;
+                          // Anzahl der Zellen eines bestimmten Typs aufsummieren
+                          // (relativ zum in der Umgebung angegebenen Faktor)
+//                          luCellCount[ luGrid.getRasterSampleAsInt(x+dx,y+dy) ] += setting;
+
+                          //TODO Bricht hier ab, wenn LUCC-Klassen nicht 0,1,2 ... zaehlen...
+//                         luCellCount[ (int)lucc ] += setting;
+
+                          luCellCount[ (int)lucc ] += setting;
+
+                        }
+                      }
+                    }
+              // Summe der Betas berechnen
+              betaSum = nbhRegrRes[0][lu]; // Regr.Konstante
+              for (i=0; i<luCount; i++) {
+                beta    = nbhRegrRes[i + 1][lu];
+                nbhFact = (luCellCount[i]/totCellCount) / (luCover[i][stepNo-1]/totCover);
+                betaSum += beta * nbhFact;
+              }
+              // Wahrscheinlichkeit berechnen
+              expBetaSum = (float)Math.exp(betaSum);
+              outNbhProb[lu].setRasterSample((float)(expBetaSum/(1 + expBetaSum)),x,y);
+          }
+    statusOut.println( CLUE_RES.getString("Model.Step.Calc.done") );
+  }
+
+
+  /**
+   * Prueft, ob ein genereller LU-Wechsel fuer eine Zelle erlaubt ist.
+   * <ul>
+   * <li>Schliessen die Area Restrictions einen Wechsel aus?<br>
+   *     > Rasterwert(x,y) != 0
+   *     </li>
+   * <li>Schliesst die Conversion Elasticity einen Wechsel aus (Elastizitaet 1
+   *     und steigende Bedarf)?<br>
+   *     > ELAS(lastLU) == 1 und DEMAND(lastLU,t) >= DEMAND(lastLU,t-1)
+   *     </li>
+   * </ul>
+   * @param x      Raster-Koordinate
+   * @param y      Raster-Koordinate
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   * @param lastLU Bedeckung von (x,y) zum Zeitpunkt stepNo-1
+   * @param alreadyLUCCToActualType Flag gibt an, ob in der laufenden Iteration
+   *                                bereits ein LU-Wechsel in den den aktuellen
+   *                                Typ der Zelle (lastLU) vorgenommen wurde.<br>
+   *                                <b>Dieses Flag wird zur Zeit nicht verwendet!</b>
+   */
+  protected boolean checkLUCCGeneralAllowed(int x, int y, int stepNo, int lastLU, boolean alreadyLUCCToActualType) {
+    // Area Restrictions checken
+    if ( areaRestr.getRasterSampleAsFloat(x,y) != 0 )
+      return false;
+// DER ERSTE TEIL IST KEINE ORIGINAL-CLUE-REGEL!
+//    // Conversion Elasticity checken
+//    // --> wenn Elasticity 1 und bereits an anderer Stelle eine Zelle des
+//    //     bisherigen Typs entstanden ist, darf sie nicht wechseln
+//    // --> wenn Elasticity 1 und Bedarf steigt, darf kein Wechsel
+//    //     stattfinden, denn dann muessten (um den Bedarf zu decken)
+//    //     an anderer Stelle neue entstehen
+//    if (  luElas.getValueAsFloat(lastLU) == 1.0
+//       && ( alreadyLUCCToActualType ||
+//           luDemand.getValueAsFloat(lastLU,stepNo) >= luCover[lastLU][stepNo-1] ) )
+//      return false;
+
+    // Conversion Elasticity checken
+    // --> wenn Elasticity 1 und Bedarf steigt, darf kein Wechsel
+    //     stattfinden, denn dann muessten (um den Bedarf zu decken)
+    //     an anderer Stelle neue entstehen
+    if (  luElas[ lastLU ] == 1.0 &&
+//          luDemand[lastLU][stepNo] >= luCover[lastLU][stepNo-1] )
+          luDemand[ lastLU ][stepNo] >= luDemand[ lastLU ][stepNo-1] )
+      return false;
+
+    return true;
+  }
+
+  /**
+   * Prueft, ob ein bestimmter LU-Wechsel fuer eine Zelle erlaubt ist.
+   * <ul>
+   * <li>Schliesst die Conversion Elasticity einen Wechsel aus (Elastizitaet des
+   *     potentiellen Wechseltyps 1 und sinkender Bedarf)?<br>
+   *     > lastLU != newLU und ELAS(newLU) == 1 und DEMAND(newLU,t) <= DEMAND(newLU,t-1)
+   *     </li>
+   * <li>Schliesst die Conversion Matrix einen Wechsel aus (generell oder ueber
+   *     Historie)?<br>
+   *     > CONV(lastLU,newLU) == 0 oder<br>
+   *     > CONV(lastLU,newLU) > 100 und HIST(x,y) < CONV(lastLU,newLU)-101 oder<br>
+   *     > CONV(lastLU,newLU) < -100 und HIST(x,y) > -CONV(lastLU,newLU)-101
+   *     </li>
+   * </ul>
+   * @param x      Raster-Koordinate
+   * @param y      Raster-Koordinate
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   * @param lastLU Bedeckung von (x,y) zum Zeitpunkt stepNo-1
+   * @param newLU  potentielle neue Bedeckung von (x,y)
+   * @param alreadyLUCCFromNewType  Flag gibt an, ob in der laufenden Iteration
+   *                                bereits ein LU-Wechsel vom potentiellen neuen
+   *                                Typ in einen anderen Typ vorgenommen wurde.<br>
+   *                                <b>Dieses Flag wird zur Zeit nicht verwendet!</b>
+   */
+  protected boolean checkLUCCAllowed(int x, int y, int stepNo, int lastLU, int newLU, boolean alreadyLUCCFromNewType) {
+// IST KEINE ORIGINAL-CLUE-REGEL!
+//    // LU-Conversion-Elasticity des neuen Typs checken
+//    // --> wenn Elasticity des neuen Typs 1 ist und an anderer Stelle bereits
+//    //     eine Zelle des dieses Typs "verloren" ging, darf er hier
+//    //     nicht entstehen
+//    if (  alreadyLUCCFromNewType && luElas.getValueAsFloat(newLU) == 1.0 )
+//      return false;
+
+    // Conversion Elasticity checken
+    // --> wenn Elasticity des neuen Typs "newLU" 1 und dessen Bedarf sinkt,
+    //     darf kein Wechsel in diesen Typ stattfinden, denn dann muessten (um
+    //     den Bedarf fuer "newLU" zu erreichen) an anderer Stelle newLU-Zellen
+    //     entfernt werden
+    if (  lastLU != newLU &&
+          luElas[ newLU ] == 1.0 &&
+          luDemand[ newLU ][stepNo] <= luCover[ newLU ][stepNo-1] )
+//          luDemand.getValueAsFloat(newLU,stepNo) <= luDemand.getValueAsFloat(newLU,stepNo-1) )
+      return false;
+
+    // Wert aus LU-Conversion-Matrix ermitteln
+    // Bemerke: "von" steht in den Zeilen (also Y, also Dim1)
+    //          "nach" steht in den Spalten (also X, also Dim2)
+    int conv    = luConv[ newLU ][ lastLU ];
+    // 1 --> LUCC generell erlaubt
+    if ( conv == 1 )
+      return true;
+    // 0 --> LUCC generell verboten
+    if ( conv == 0 )
+      return false;
+
+    // Max. Abweichung der LU-Conversion
+    int convDev = Math.abs( luConvDev[ newLU ][ lastLU ] );
+    // Zufallswert zwischen -convDev und +convDev
+    if ( convDev > 0 )
+      convDev = rand.nextInt(2*convDev+1) - convDev;
+
+    // 100+t --> Wechsel erst nach t Schritten der vorangegangenen
+    //           LU moeglich
+    if ( conv > 100 ) {
+//      int minLUHist = conv-100;
+//      int luHist    = outActLUHist.getRasterSampleAsInt(x,y);
+//      return luHist >= minLUHist;
+      int minLUHist = conv-101 + convDev;
+      int luHist    = outActLUHist.getRasterSampleAsInt(x,y);
+      return luHist >= minLUHist;
+    }
+
+    // -100-t --> Wechsel nicht mehr moeglich, wenn Zelle bereits
+    //            t Schritte unter der vorangegangenen LU
+    if ( conv < -100 ) {
+//      int maxLUHist = -conv-100;
+//      int luHist    = outActLUHist.getRasterSampleAsInt(x,y);
+//      return luHist < maxLUHist;
+      int maxLUHist = -conv-101 + convDev;
+      int luHist    = outActLUHist.getRasterSampleAsInt(x,y);
+      return luHist <= maxLUHist;
+    }
+
+    return true;
+  }
+
+  /**
+   * Prueft, ob die aktuelle LU-Konfiguration die einzelenen Bedarfsanforderungen
+   * (bis auf eine Abweichung) erfuellt und berechnet die Iterationsvariablen
+   * neu.
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   * @param iterNo aktuelle Iteration (beginnend bei 1)
+   */
+  protected boolean checkDemandCompliedAndCalculateIterVar(int stepNo, int iterNo) {
+    boolean updateEnabled  = (modelGUI!=null && modelGUI.isDeviationUpdateEnabled());
+    boolean demandComplied = true;
+    // Abweichnungen berechnen
+    float[] singleDevAbs = new float[luCount];
+    float[] singleDevPct = new float[luCount];
+    float   averageDevAbs = 0;
+    float   averageDevPct = 0;
+    float   totalDevAbs = 0;
+    float   totalDevPct = 0;
+    for (int lu = 0; lu < luCount; lu++) {
+      // ##### Einzelabweichungen #####
+      // Absolute Abweichung der Landbedeckung vom Bedarf berechnen
+      float demand = luDemand[lu][stepNo];
+      singleDevAbs[lu]  = luCover[lu][stepNo] - demand;
+      // Prozentuale Einzel-Abweichnung relativ zum Bedarf
+      if (demand == 0)
+        // ist der Bedarf 0, aber auch die Bedeckung, ist die Abw. 0%
+        singleDevPct[lu] = luCover[lu][stepNo] == 0 ? 0 : 1;
+      else
+        singleDevPct[lu] = singleDevAbs[lu] / demand;
+
+      // Abweichung ueber erlaubter Toleranz?
+      float singleDev = (demandTolType == TOLTYPE_PCT) ? singleDevPct[lu] : singleDevAbs[lu];
+      if ( updateEnabled ) {
+        modelGUI.setDeviation(lu,singleDev);
+        modelGUI.setIterationVariable(lu, outIter[lu]);
+      }
+      if (Math.abs(singleDev) > demandTolSingle)
+        demandComplied = false;
+
+//      // Abweichung des LU-Typs ausgeben
+//      appendLog(singleDevAbs[lu],singleDevPct[lu],luDemand.getValueAsFloat(lu, stepNo),luCover[lu][stepNo]);
+
+      // ##### Gesamtabweichungen aufsummieren #####
+      totalDevAbs += Math.abs(singleDevAbs[lu]);
+    }
+
+    // Prozentuale Gesamt-Abweichnung relativ zum Gesamt-Untersuchungsgebiet
+    totalDevPct = totalDevAbs / totCover;
+    if ( updateEnabled )
+      modelGUI.setDeviation(luCount,(demandTolType == TOLTYPE_PCT) ? totalDevPct : totalDevAbs);
+
+    // Durchschnittliche Abweichnung pro LU-Typ
+    averageDevAbs = totalDevAbs / luCount;
+
+    // Durchschnittliche Abweichnung pro LU-Typ relativ zum Gesamt-Untersuchungsgebiet
+    averageDevPct = averageDevAbs / totCover;
+
+    // Abweichung ueber erlaubter Toleranz?
+    float avgDev = (demandTolType == TOLTYPE_PCT) ? averageDevPct : averageDevAbs;
+    if ( updateEnabled )
+      modelGUI.setDeviation(luCount+1,avgDev);
+    if ( Math.abs(avgDev) > demandTolAverage )
+      demandComplied = false;
+
+    // Iterationsvariablen neu berechnen
+    for (int lu = 0; lu < luCount; lu++) {
+      // Um Alternieren zwischen 2 Konfiguration zu verhindern
+      // eine kleine Zufallszahl hinzuaddieren (zwischen -0,005 und 0,005)
+      float randomValue = (rand.nextFloat()-0.5f)/100;
+
+      // --> Im ersten Schritt erhalten alle Iterationsvariablen den Wert 0,5
+      float iter = outIter[lu];
+      if (iterNo == 1)
+        iter = 0.5f+randomValue;
+//        iter = 0.5 + new float[] {0.002f,0f,0.002f,0f,0f,-0.003f}[lu];
+//        iter = 0.5 + new float[] {0.002f,0f,0.001f,0f,0f,-0.002f}[lu];
+      else {
+//        // Anteil der Einzelabweichnung an der Gesamtabweichnung
+////        float dev = (totalDevAbs!=0) ? singleDevAbs[lu] / totalDevAbs : 0.0;
+//        float dev  = singleDevPct[lu];
+//        iter = outIter.getValueAsFloat(lu) // alter Iter-Wert
+//             + dev // Anteil der Abweichung zum Bedarf
+//             + randomValue;
+        /////////////////////////////////////////
+        // Original-Iter-Berechnung aus CLUE
+        iterSpeed[lu] += 0.00005;
+        iter += (singleDevAbs[lu]/totCover)/(iterSpeed[lu]*(rand.nextInt(101)+1));
+
+        if (iter > 2f)
+          iter = 0.5f;
+        if ( Math.abs(iter) < 0.001 )
+          iter = 0.01f * Math.signum(iter);
+        if (iter < -0.5f)
+          iter = -0.4f;
+        /////////////////////////////////////////
+      }
+      // Iter speichern
+      outIter[lu] = iter;
+    }
+
+    return demandComplied;
+  }
+
+  //////////////////////////////////////////////////////////////////////
+  /////////////////////   Clue-spezifische GUI   ///////////////////////
+  //////////////////////////////////////////////////////////////////////
+
+  /**
+   * Diese Klasse stellt eine modellspezifische GUI-Komponente fuer das
+   * {@link ClueModel CLUE-Modell} dar.
+   * In dieser wird fuer jeden modellierten LU-Typ ein {@linkplain ExpansionBar Status-Balken}
+   * fuer die Abweichnung vom geforderten Bedarf angezeigt. Sowie je ein Balken
+   * fuer die aktuelle Gesamt- und Durchschittsabweichung. Je nach gewaehlter
+   * Abweichungsart (prozentual oder absolute Angaben), werden Abweichungen
+   * von +/- 100% oder +/- 10000 Bedarfseinheiten angezeigt.<br>
+   * Darueber hinaus enthaelt sie je einen Regler, ueber den die maximal
+   * erlaubte Abweichung von den Bedarfen (Einzelabweichung der LU-Typen und
+   * Durchschnittsabweichung) eingestellt werden kann.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class ClueModelGUI extends JComponent {
+    private       float MIN = -1;
+    private       float MAX = 1;
+    private final float TOL = 0.2f;
+    private       float SLIDER_FACT = 1000;
+    // Format fuer Wert-Anzeige des Sliders
+    private DecimalFormat sliderPctFormat = new DecimalFormat("0.0%");
+    private DecimalFormat sliderDecFormat = new DecimalFormat("0.0");
+    // Format fuer Wert-Anzeige im Balken
+    private DecimalFormat statusPctFormat = new DecimalFormat("0.0000%");
+    private DecimalFormat statusDecFormat = new DecimalFormat("0.0");
+    // Format fuer Wert-Anzeige unterhalb der Balken (Max/Min/Middle)
+    private DecimalFormat infoPctFormat   = new DecimalFormat("0.0%");
+    private DecimalFormat infoDecFormat   = new DecimalFormat("0.0");
+
+    private DeviationContainer  divCont          = null;
+    private JSlider             singleDivSlider  = null;
+    private JSlider             averageDivSlider = null;
+    private ClueModel           model            = null;
+    private DeviationLabel      singleDivLabel   = new DeviationLabel(" ",sliderPctFormat);
+    private DeviationLabel      averageDivLabel  = new DeviationLabel(" ",sliderPctFormat);
+    private Font                labelFont        = singleDivLabel.getFont().deriveFont(Font.BOLD | Font.CENTER_BASELINE);
+    private boolean             alreadyPacked    = false;
+    private JCheckBox           updateCheckBox   = null;
+    private JLabel              iterationLabel   = null;
+    private String              iterationText    = "";
+
+    /**
+     * Erzeugt eine neue Clue-GUI. Diese wird jedoch erst nach Aufruf
+     * der {@link #init(ClueModel)}-Methode komplett erzeugt, da erst dann
+     * die Anzahl der angezeigten Balken (= Anzahl LU-Typen) feststeht.
+     */
+    public ClueModelGUI() {
+      super();
+      this.setLayout( new SpringLayout() );
+      // Label in dem die Iterationsnummer angezeigt wird
+      iterationLabel = new JLabel(" ");
+      iterationLabel.setBorder( BorderFactory.createLoweredBevelBorder() );
+      // Slider/Label fuer Abweichnug der einzelnen Typen
+      singleDivSlider  = new JSlider(JSlider.HORIZONTAL,0,(int)(SLIDER_FACT*MAX),(int)(SLIDER_FACT*TOL));
+      singleDivSlider.setPaintTicks(true);
+      singleDivSlider.setPaintLabels(true);
+      singleDivSlider.setPaintTrack(true);
+      singleDivSlider.setEnabled(false);
+      singleDivSlider.addChangeListener( new ChangeListener() {
+        public void stateChanged(ChangeEvent e) {
+          float tol = singleDivSlider.getValue() / SLIDER_FACT;
+          if ( model!=null )
+            model.demandTolSingle = tol;
+          if ( singleDivLabel!=null )
+            singleDivLabel.setValue(tol);
+          if ( divCont!=null )
+            for (int i=0; i<divCont.getCount()-1; i++)
+              divCont.setTolerance(i,tol);
+        }
+      });
+      singleDivLabel.setFont(labelFont);
+      singleDivLabel.setValue(singleDivSlider.getValue()/SLIDER_FACT);
+
+      // Slider/Label fuer Abweichnug der einzelnen Typen
+      averageDivSlider  = new JSlider(JSlider.HORIZONTAL,0,(int)(SLIDER_FACT*MAX),(int)(SLIDER_FACT*TOL));
+      averageDivSlider.setPaintTicks(true);
+      averageDivSlider.setPaintLabels(true);
+      averageDivSlider.setPaintTrack(true);
+      averageDivSlider.setEnabled(false);
+      averageDivSlider.addChangeListener( new ChangeListener() {
+        public void stateChanged(ChangeEvent e) {
+          float tol = averageDivSlider.getValue() / SLIDER_FACT;
+          if ( model!=null )
+            model.demandTolAverage = tol;
+          if ( averageDivLabel!=null )
+            averageDivLabel.setValue(tol);
+          if ( divCont!=null )
+            divCont.setTolerance( divCont.getCount()-1, tol );
+        }
+      });
+      averageDivLabel.setFont(labelFont);
+      averageDivLabel.setValue(averageDivSlider.getValue()/SLIDER_FACT);
+
+      // Checkbox zur (De)Aktivierung der Anzeige-Aktualisierung
+      updateCheckBox = new JCheckBox(" ",true);
+
+      // Labels lokalisieren
+      resetCaptions(null);
+
+      this.add( averageDivLabel );
+      this.add( averageDivSlider );
+      this.add( singleDivLabel );
+      this.add( singleDivSlider );
+      this.add( updateCheckBox );
+      this.add( iterationLabel );
+      SpringUtilities.makeCompactGrid(this,6,1,0,0,0,5);
+    }
+
+    /**
+     * Initialisiert die GUI fuer eine <b>initialisierte</b> Modell-Instanz.
+     * Wird zum Ende {@link ClueModel#performModelInit()} aufgerufen.
+     */
+    public void init(ClueModel model) {
+      this.model = model;
+      if ( divCont != null )
+        remove(divCont);
+      SLIDER_FACT = (model.demandTolType == TOLTYPE_PCT) ? 1000 : 1;
+      MIN         = (model.demandTolType == TOLTYPE_PCT) ? -1 : ((float)-Math.pow(10,(int)Math.log10(model.totCover)))/1000;
+      MAX         = (model.demandTolType == TOLTYPE_PCT) ?  1 : -MIN;
+      averageDivSlider.setMaximum((int)(MAX*SLIDER_FACT));
+      averageDivLabel.setNumberFormat( model.demandTolType == TOLTYPE_PCT ? sliderPctFormat : sliderDecFormat );
+      singleDivSlider.setMaximum((int)(MAX*SLIDER_FACT));
+      singleDivLabel.setNumberFormat( model.demandTolType == TOLTYPE_PCT ? sliderPctFormat : sliderDecFormat );
+
+      String[] divDesc = new String[model.luCount+2];
+      for (int i=0; i<model.luCount; i++)
+        divDesc[i] = String.valueOf(i);
+      divDesc[model.luCount]   = "";
+      divDesc[model.luCount+1] = "";
+
+      divCont = new DeviationContainer(
+                         divDesc.length,
+                         divDesc,
+                         MIN,
+                         MAX,
+                         0,
+                         model.demandTolSingle,
+                         model.demandTolType == TOLTYPE_PCT ? statusPctFormat : statusDecFormat,
+                         model.demandTolType == TOLTYPE_PCT ? infoPctFormat   : infoDecFormat
+      );
+      divCont.setBarDescHeader( CLUE_RES.getString("Model.GUI.LucType") );
+      divCont.setBarHeader( CLUE_RES.getString("Model.GUI.CurrDemandDev") );
+      this.add(divCont,4);
+
+      // Wert des Balkens darf erst hier (nach Neu-Erstellung des
+      // Abweichungs-Containers) neu gesetzt werden, da beim Setzen
+      // des neuen Wertes automatisch die Toleranzen der Abweichungsbalken
+      // aktualisiert werden
+      setSingleTolerance(model.demandTolSingle);
+      setAverageTolerance(model.demandTolAverage);
+
+      // Labels lokalisieren
+      resetCaptions(null);
+      
+      SpringUtilities.makeCompactGrid(this,7,1,0,0,0,5);
+      if ( !alreadyPacked )
+        SwingUtil.packParentWindow(this);
+      else
+        this.validate();
+      alreadyPacked = true;
+      singleDivSlider.setEnabled( true );
+      averageDivSlider.setEnabled( true );
+    }
+
+    /**
+     * Belegt die Labels in der GUI neu. Sind in der uebergebenen Map fuer die Keys
+     * keine Werte hinterlegt (oder wenn {@code captionMap = null}, wird auf den
+     * {@linkplain ClueModel#CLUE_RES Resource-Provider} des Modells zurueckgegriffen.
+     * @param captionMap Map in der nach den Label-Bezeichnungen gesucht wird (kann
+     *                   {@code null} sein)
+     */
+    public void resetCaptions(Map<String,Object> captionMap) {
+      singleDivLabel.setText( determineCaption(captionMap, CLUE_RES, "Model.GUI.Single.Dev.Allowed") );
+      averageDivLabel.setText( determineCaption(captionMap, CLUE_RES, "Model.GUI.Avg.Dev.Allowed") );
+      iterationText = determineCaption(captionMap, CLUE_RES, "Model.GUI.Iteration");
+      updateCheckBox.setText( determineCaption(captionMap, CLUE_RES, "Model.GUI.AutoUpdate") );
+      
+      if ( divCont != null ) {
+        divCont.setBarDescHeader( determineCaption(captionMap, CLUE_RES, "Model.GUI.LucType") );
+        divCont.setBarHeader( determineCaption(captionMap, CLUE_RES, "Model.GUI.CurrDemandDev") ); 
+        divCont.setBarDesc( model.luCount,   determineCaption(captionMap, CLUE_RES, "Model.GUI.Total") );
+        divCont.setBarDesc( model.luCount+1, determineCaption(captionMap, CLUE_RES, "Model.GUI.Avg") );
+      } 
+    }
+    
+    /**
+     * Setzt die in der GUI angezeigte Interationsnummer. Diese wird
+     * durch einen String repraesentiert, damit auch berliebige andere
+     * Informationen (anstelle der Nummer) dargestellt werden koennen (z.B.
+     * zusaetzlich noch die Schrittnummer).
+     * @param iterString dargestellte Iterationsnummer
+     */
+    public void setIterationNumber(String iterString) {
+      iterationLabel.setText( iterationText+": "+iterString );
+    }
+
+    /**
+     * Stellt den Slider fuer die Einzelabweichung auf einen bestimmten Wert
+     * ein. Hierdurch wird automatisch auch der Wert fuer das Modell neu
+     * gesetzt.
+     */
+    public void setSingleTolerance(float tol) {
+      singleDivSlider.setValue((int)(tol*SLIDER_FACT));
+    }
+
+    /**
+     * Stellt den Slider fuer die Durchschnittsabweichung auf einen bestimmten Wert
+     * ein. Hierdurch wird automatisch auch der Wert fuer das Modell neu
+     * gesetzt.
+     */
+    public void setAverageTolerance(float tol) {
+      averageDivSlider.setValue((int)(tol*SLIDER_FACT));
+    }
+
+    /**
+     * Setzt die Abweichnungswerte fuer alle Statusbalken.
+     * @param value Array mit den Abweichungen
+     */
+    public void setDeviation(float[] value) {
+      if ( divCont!= null && isDeviationUpdateEnabled() )
+        divCont.setExpansion(value);
+    }
+
+    /**
+     * Setzt den Abweichnungswert fuer einen Statusbalken.
+     * @param idx   Index eines Balkens
+     * @param value Abweichung die im Balken dargestellt wird
+     */
+    public void setDeviation(int idx, float value) {
+      if ( divCont!= null && isDeviationUpdateEnabled() )
+        divCont.setExpansion(idx,value);
+    }
+
+    /**
+     * Setzt die Anzeige Iterations-Variablen fuer alle Statusbalken (LUC-Typen).
+     * @param value Array mit den Iterations-Variablen
+     */
+    public void setIterationVariable(float[] value) {
+      if ( divCont!= null && isDeviationUpdateEnabled() )
+        divCont.setIterVariable(value);
+    }
+
+    /**
+     * Setzt die Anzeige Iterations-Variablen fuer einen Statusbalken (LUC-Typ).
+     * @param idx   Index eines Balkens
+     * @param value Wert der Iterations-Variablen
+     */
+    public void setIterationVariable(int idx, float value) {
+      if ( divCont!= null && isDeviationUpdateEnabled() )
+        divCont.setIterVariable(idx,value);
+    }
+
+    /**
+     * Aktiviert oder Deaktiviert die Aktualisierung der Abweichungsbalken.
+     */
+    public void setDeviationUpdateEnabled(boolean enabled) {
+      updateCheckBox.setSelected(enabled);
+    }
+
+    /**
+     * Aktiviert oder Deaktiviert die Aktualisierung der Abweichungsbalken.
+     */
+    public boolean isDeviationUpdateEnabled() {
+      return updateCheckBox.isSelected();
+    }
+
+    /**
+     * Diese Klasse stellt ein Label dar, in dem (hinter einem Basistext)
+     * ein numerischer Abweichungswert (z.B. erlaubte Maximalabweichung) angezeigt wird.
+     * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+     * @version 1.0
+     */
+    private static class DeviationLabel extends JLabel {
+      private String baseText        = "";
+      private float dev              = 0;
+      private NumberFormat numFormat = null;
+
+      /**
+       * Erzeugt ein neues leeres Label.
+       */
+      public DeviationLabel() {
+        this("");
+      }
+
+      /**
+       * Erzeugt ein neues Label. Der dargestellte Wert ist initial 0%.
+       * @param text      Basistext
+       */
+      public DeviationLabel(String text) {
+        this(text,new DecimalFormat("0.0%"));
+      }
+
+      /**
+       * Erzeugt ein neues Label. Der dargestellte Wert ist initial 0.
+       * @param text      Basistext
+       * @param numFormat Anzeigeformat fuer den dargestellten Abweichungswert
+       */
+      public DeviationLabel(String text, NumberFormat numFormat) {
+        this(text,numFormat,0);
+      }
+
+      /**
+       * Erzeugt ein neues Label.
+       * @param text      Basistext
+       * @param numFormat Anzeigeformat fuer den dargestellten Abweichungswert
+       * @param dev       initialer Wert fuer den Abweichungswert
+       */
+      public DeviationLabel(String text, NumberFormat numFormat, float dev) {
+        super();
+        this.baseText  = text;
+        this.dev    = dev;
+        setNumberFormat(numFormat);
+        setText(baseText);
+      }
+
+      /**
+       * Setzt den darzustellenden numerischen Abweichungswert.
+       */
+      public void setValue(float dev) {
+        this.dev = dev;
+        setText(baseText);
+      }
+
+      /**
+       * Setzt den Basistext des Labels.
+       */
+      public void setText(String text) {
+        this.baseText = text;
+        String displayText = baseText;
+        if ( numFormat != null )
+          displayText = displayText+" "+numFormat.format(this.dev);
+        super.setText(displayText);
+      }
+
+      /**
+       * Setzt das Darstellungsformat fuer den Abweichungswert.
+       */
+      public void setNumberFormat(NumberFormat format) {
+        this.numFormat = format;
+      }
+    }
+
+    /**
+     * Diese Klasse stellt einen Container dar, in dem vertikal eine Reihe von
+     * {@linkplain ExpansionBar Status-Balken} angezeigt werden. Alle Balken
+     * haben dieselben Extremwerte (Min, Max, Middle). Deshalb erhaelt nur
+     * der unterste Balken eine Info-Leiste mit diesen Extremwerten.
+     * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+     * @version 1.0
+     */
+    private static class DeviationContainer extends JComponent {
+      private static final NumberFormat DEV_NUM_FORMAT = new DecimalFormat("0.0%");
+      private static final NumberFormat ITER_NUM_FORMAT = new DecimalFormat("0.0000");
+      /** Konstante fuer eine vertikale Ausrichtung der Status-Balken */
+      public static final int VERTICAL   = ExpansionBar.VERTICAL;
+      /** Konstante fuer eine horizontale Ausrichtung der Status-Balken */
+      public static final int HORIZONTAL = ExpansionBar.HORIZONTAL;
+
+      private ExpansionBar[] expansionBar   = null;
+      private JLabel[]       expansionLabel = null;
+      private JLabel[]       iterLabel      = null;
+      private JLabel         typeHeader     = null;
+      private JLabel         divHeader      = null;
+      private JLabel         iterHeader     = null;
+      private Font           sampleFont     = new JLabel().getFont();
+
+      /**
+       * Erzeugt einen neuen Container. Die Balken stellen eine prozentuale
+       * Abweichung von +/- 100% um 0% dar. Die Balken erhalten keine Beschreibung,
+       * sondern werden durchnummeriert.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param tol      Toleranzwert fuer alle Balken (siehe {@link ExpansionBar})
+       */
+      public DeviationContainer(int count, float tol) {
+        this(count,-1,1,0,tol,DEV_NUM_FORMAT);
+      }
+
+      /**
+       * Erzeugt einen neuen Container. Als Mitte-Wert fuer die Balken wird
+       * 0 verwendet. Die Balken erhalten keine Beschreibung, sondern werden
+       * durchnummeriert.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param min      Minimum-Wert fuer die Balken
+       * @param max      Maximum-Wert fuer die Balken
+       * @param tol      Toleranzwert fuer alle Balken (siehe {@link ExpansionBar})
+       * @param form     Darstellungsformat fuer die Zahlen im Balken und in der
+       *                 Info-Leiste des untersten Balken
+       */
+      public DeviationContainer(int count, float min, float max, float tol, NumberFormat form) {
+        this(count,min,max,0,tol,form);
+      }
+
+      /**
+       * Erzeugt einen neuen Container. Die Balken werden durchnummeriert.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param min      Minimum-Wert fuer die Balken
+       * @param max      Maximum-Wert fuer die Balken
+       * @param mid      Mitte-Wert fuer die Balken
+       * @param tol      Toleranzwert fuer alle Balken (siehe {@link ExpansionBar})
+       * @param form     Darstellungsformat fuer die Zahlen im Balken und in der
+       *                 Info-Leiste des untersten Balken
+       */
+      public DeviationContainer(int count, float min, float max, float mid, float tol, NumberFormat form) {
+        this(count,null,min,max,mid,tol,form,form);
+      }
+
+      /**
+       * Erzeugt einen neuen Container.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param desc     Beschreibungen fuer die Balken (kann <code>null</code> sein!)
+       * @param min      Minimum-Wert fuer die Balken
+       * @param max      Maximum-Wert fuer die Balken
+       * @param mid      Mitte-Wert fuer die Balken
+       * @param tol      Toleranzwert fuer alle Balken (siehe {@link ExpansionBar})
+       * @param barForm  Darstellungsformat fuer die Zahlen im Balken
+       * @param infoForm Darstellungsformat fuer die Zahlen in der Info-Leiste
+       *                 des untersten Balken
+       */
+      public DeviationContainer(int count, String[] desc, float min, float max, float mid, float tol, NumberFormat barForm, NumberFormat infoForm) {
+        this(count,desc,min,max,mid,LangUtil.createArray(count,tol),barForm,infoForm);
+      }
+
+      /**
+       * Erzeugt einen neuen Container.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param desc     Beschreibungen fuer die Balken (kann <code>null</code> sein!)
+       * @param min      Minimum-Wert fuer die Balken
+       * @param max      Maximum-Wert fuer die Balken
+       * @param mid      Mitte-Wert fuer die Balken
+       * @param tol      Toleranzwert fuer jeden einzelnen Balken (siehe {@link ExpansionBar})
+       * @param barForm  Darstellungsformat fuer die Zahlen im Balken
+       * @param infoForm Darstellungsformat fuer die Zahlen in der Info-Leiste
+       *                 des untersten Balken
+       */
+      public DeviationContainer(int count, String[] desc, float min, float max, float mid, float[] tol, NumberFormat barForm, NumberFormat infoForm) {
+        super();
+        if ( count <= 0 )
+          throw new IllegalArgumentException("At least one divergence bar must specified!");
+        if ( desc!=null && desc.length < count )
+          throw new IllegalArgumentException("Less describtions specified!");
+
+        this.setLayout( new SpringLayout() );
+
+        // PROBLEME mit den Labels bei VERTICAL
+        // --> Label-Breite wird wohl zu 0
+        int orient = HORIZONTAL;
+
+        sampleFont = sampleFont.deriveFont(Font.BOLD);
+        if (orient == VERTICAL)
+          sampleFont = sampleFont.deriveFont( AffineTransform.getRotateInstance(Math.PI/2) );
+
+        // Label erzeugen
+        typeHeader = new JLabel( CLUE_RES.getString("Model.GUI.Type") );
+        divHeader  = new JLabel( CLUE_RES.getString("Model.GUI.Divergence") );
+        iterHeader = new JLabel( CLUE_RES.getString("Model.GUI.IterVar") );
+        typeHeader.setFont(sampleFont);
+        divHeader.setFont(sampleFont);
+        iterHeader.setFont(sampleFont);
+
+        // Statusbalken erzeugen
+        this.expansionBar   = new ExpansionBar[count];
+        this.expansionLabel = new JLabel[count];
+        this.iterLabel      = new JLabel[count];
+        for (int i=0; i<count; i++) {
+          expansionBar[i]   = new ExpansionBar(orient,ExpansionBar.LINEAR,min,max,mid,-tol[i],tol[i],0,barForm,infoForm);
+          expansionLabel[i] = new JLabel( desc!=null && i<desc.length ? desc[i] : String.valueOf(i));
+          iterLabel[i]      = new JLabel("");
+          if ( orient == HORIZONTAL ) {
+            expansionLabel[i].setHorizontalAlignment(JLabel.CENTER);
+            expansionLabel[i].setVerticalAlignment(JLabel.TOP);
+          } else {
+            expansionLabel[i].setFont( expansionLabel[i].getFont().deriveFont( AffineTransform.getRotateInstance(Math.PI/2) ) );
+            expansionLabel[i].setHorizontalAlignment(JLabel.LEFT);
+            expansionLabel[i].setVerticalAlignment(JLabel.CENTER);
+          }
+        }
+        // beim untersten Balken sollen die Labels erscheinen
+        expansionBar[count-1].setValueLabelsPainted(true);
+
+        // Komponenten einfuegen und ausrichten
+        if ( orient == HORIZONTAL ) {
+          typeHeader.setHorizontalAlignment(JLabel.CENTER);
+          typeHeader.setVerticalAlignment(JLabel.BOTTOM);
+          divHeader.setHorizontalAlignment(JLabel.CENTER);
+          divHeader.setVerticalAlignment(JLabel.BOTTOM);
+          iterHeader.setHorizontalAlignment(JLabel.CENTER);
+          iterHeader.setVerticalAlignment(JLabel.BOTTOM);
+          add( typeHeader );
+          add( divHeader );
+          add( iterHeader );
+          for (int i=0; i<count; i++) {
+            add( expansionLabel[i] );
+            add( expansionBar[i] );
+            add( iterLabel[i] );
+          }
+          // Layout ausrichten
+          SpringUtilities.makeCompactGrid(this,getComponentCount()/3,3,0,0,10,0);
+        } else {
+          typeHeader.setHorizontalAlignment(JLabel.CENTER);
+          typeHeader.setVerticalAlignment(JLabel.CENTER);
+          divHeader.setHorizontalAlignment(JLabel.CENTER);
+          divHeader.setVerticalAlignment(JLabel.CENTER);
+          iterHeader.setHorizontalAlignment(JLabel.CENTER);
+          iterHeader.setVerticalAlignment(JLabel.CENTER);
+          add( divHeader );
+          for (int i=0; i<count; i++)
+            add( expansionBar[i] );
+          add( typeHeader );
+          for (int i=0; i<count; i++)
+            add( expansionLabel[i] );
+          add( iterHeader );
+          for (int i=0; i<count; i++)
+            add( iterLabel[i] );
+          // Layout ausrichten
+          SpringUtilities.makeCompactGrid(this,3,getComponentCount()/3,0,0,10,0);
+        }
+      }
+
+      /**
+       * Liefert die Anzahl an Balken.
+       */
+      public int getCount() {
+        return expansionBar.length;
+      }
+
+      /**
+       * Setzt den Toleranzwert fuer alle Balken.
+       */
+      public void setTolerance(float tol) {
+        for (int i=0; i<expansionBar.length; i++)
+          setTolerance(i,tol);
+      }
+
+      /**
+       * Setzt den Toleranzwert fuer einen Balken.
+       */
+      public void setTolerance(int i, float tol) {
+        expansionBar[i].setMinimumTolerance( -tol );
+        expansionBar[i].setMaximumTolerance(  tol );
+      }
+
+      /**
+       * Setzt den Wert fuer alle Balken.
+       */
+      public void setExpansion(float[] value) {
+        for (int i=0; i<value.length; i++)
+          setExpansion(i,value[i]);
+      }
+
+      /**
+       * Setzt den Wert fuer einen Balken.
+       */
+      public void setExpansion(int idx, float value) {
+        expansionBar[idx].setValue(value);
+      }
+
+      /**
+       * Setzt die Anzeige der Iterations-Variablen fuer alle Balken (LUC-Typ).
+       */
+      public void setIterVariable(float[] value) {
+        for (int i=0; i<value.length; i++)
+          setIterVariable(i,value[i]);
+      }
+
+      /**
+       * Setzt die Anzeige der Iterations-Variablen fuer einen Balken (LUC-Typ).
+       */
+      public void setIterVariable(int idx, float value) {
+        iterLabel[idx].setText( ITER_NUM_FORMAT.format( value ) );
+      }
+
+      /**
+       * Setzt die Beschreibung fuer einen Balken.
+       */
+      public void setBarDesc(int idx, String text) {
+        expansionLabel[idx].setText(text);
+      }
+
+      /**
+       * Setzt die Beschreibung die oberhalb der Balken-Beschreibungen steht.
+       */
+      public void setBarDescHeader(String text) {
+        typeHeader.setText(text);
+      }
+
+      /**
+       * Setzt die Beschreibung die oberhalb der Balken steht.
+       */
+      public void setBarHeader(String text) {
+        divHeader.setText(text);
+      }
+
+      /**
+       * Setzt die Beschreibung die oberhalb der Iterations-Variablen steht.
+       */
+      public void setIterHeader(String text) {
+        iterHeader.setText(text);
+      }
+
+    }
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/clue/ClueModelContentManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/clue/ClueModelContentManager.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/model/clue/ClueModelContentManager.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,995 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.model.clue;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyReadAccess;
+import schmitzm.data.property.MatrixProperty;
+
+import schmitzm.temp.BaseTypeUtil;
+import schmitzm.lang.ResourceProvider;
+
+import edu.bonn.xulu.model.ModelResource;
+import edu.bonn.xulu.model.AbstractModelResource;
+import edu.bonn.xulu.model.ValuePropertyResource;
+import edu.bonn.xulu.model.AbstractModelContentManager;
+import edu.bonn.xulu.data.XuluDataException;
+
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+import edu.bonn.xulu.plugin.model.ca.fire.ImpetusFireCA;
+
+import java.util.Locale;
+import java.util.Map;
+
+import edu.bonn.xulu.appl.XuluConstants;
+import edu.bonn.xulu.XuluModellingPlatform;
+
+/**
+ * Diese Klasse verwaltet die Ressourcen fuer das {@linkplain ClueModel Clue-Modell}
+ * und prueft diese auf Korrektheit.<br>
+ * Die Art der benoetigten Ressourcen ist der {@linkplain ClueModel Model-Doku}
+ * zu entnehmen.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class ClueModelContentManager extends AbstractModelContentManager {
+  /** Ressource: Simulation step count */
+  public  static final int    MODELSTEPS  = 0; // Nummer der Ressource
+  private static final int    MODELSTEPS_MIN  = 1;
+  private static final int    MODELSTEPS_MAX  = 50;
+  private              String MODELSTEPS_DESC = "";
+  /** Ressource: Type of tolerance expression for demand compliance */
+  public  static final int    TOLERANCETYPE      = 1; // Nummer der Ressource
+  private              String TOLERANCETYPE_DESC = "";
+  /** Ressource: Tolerance for demand compliance for each lu type */
+  public  static final int    TOLERANCESINGLE      = 2; // Nummer der Ressource
+  private              String TOLERANCESINGLE_DESC = "";
+  /** Ressource: Average tolerance for demand compliance */
+  public  static final int    TOLERANCEAVERAGE      = 3; // Nummer der Ressource
+  private              String TOLERANCEAVERAGE_DESC = "";
+  /** Ressource: Toleranz fuer Bedarfe */
+  public  static final int    CONVFACTQM      = 4; // Nummer der Ressource
+  private              String CONVFACTQM_DESC = "";
+  /** Ressource: Base scenario */
+  public  static final int    BASESCENARIO      = 5; // Nummer der Ressource
+  private              String BASESCENARIO_DESC = "";
+  /** Ressource: Land use history of base scenario */
+  public  static final int    LUHISTORY      = 6; // Nummer der Ressource
+  private              String LUHISTORY_DESC = "";
+  /** Ressource: LU-Conversion-Matrix */
+  public  static final int    LUCONV      = 7; // Nummer der Ressource
+  private              String LUCONV_DESC = "";
+  /** Ressource: LU-Conversion-Matrix */
+  public  static final int    LUCONVDEV   = 8; // Nummer der Ressource
+  private              String LUCONVDEV_DESC = "";
+  /** Ressource: Conversion elasticity */
+  public  static final int    ELASTICITY      = 9; // Nummer der Ressource
+  private              String ELASTICITY_DESC = "";
+  // Ressource: Area restrictions
+  public  static final int    AREARESTR      = 10; // Nummer der Ressource
+  private              String AREARESTR_DESC = "";
+  /** Ressource: Demand scenario */
+  public  static final int    DEMAND      = 11; // Nummer der Ressource
+  private              String DEMAND_DESC = "";
+  /** Ressource: Static driving forces */
+  public  static final int    STATDF      = 12; // Nummer der Ressource
+  private              String STATDF_DESC = "";
+  /** Ressource: List of the dynamic driving force types */
+  public  static final int    DYNDFTYPES      = 13; // Nummer der Ressource
+  private              String DYNDFTYPES_DESC = "";
+  /** Ressource: Dynamic driving forces */
+  public  static final int    DYNDF      = 14; // Nummer der Ressource
+  private              String DYNDF_DESC = "";
+  /** Ressource: Regression results */
+  public  static final int    REGRESSION      = 15; // Nummer der Ressource
+  private              String REGRESSION_DESC = "";
+  /** Ressource: Gewichtung der Neighborhood-Regression results */
+  public  static final int    NBHWEIGHTS     = 16; // Nummer der Ressource
+  private              String NBHWEIGHTS_DESC = "";
+  /** Ressource: Neighborhood-Settings */
+  public  static final int    NBHSETTINGS      = 17; // Nummer der Ressource
+  private              String NBHSETTINGS_DESC = "";
+  /** Ressource: Neighborhood-Regression results */
+  public  static final int    NBHREGRESSION      = 18; // Nummer der Ressource
+  private              String NBHREGRESSION_DESC = "";
+  /** Ressource: RasterList for "Location specific preference addition" */
+  public  static final int    LSPAPROB = 19; // Nummer der Ressource
+  private              String LSPAPROB_DESC = "";
+  /** Ressource: Factors for "Location specific preference addition" */
+  public  static final int    LSPAFACT = 20; // Nummer der Ressource
+  private              String LSPAFACT_DESC = "";
+
+  /** Ressource: Temp-Raster for actual LU History */
+  public  static final int    ACTLUHISTORY      = 21; // Nummer der Ressource
+  private              String ACTLUHISTORY_DESC = "";
+  /** Ressource: Temp-Raster for LU Probabilities */
+  public  static final int    LUPROB      = 22; // Nummer der Ressource
+  private              String LUPROB_DESC = "";
+  /** Ressource: Temp-Raster for LU Probabilities */
+  public  static final int    NBHPROB      = 23; // Nummer der Ressource
+  private              String NBHPROB_DESC = "";
+  /** Ressource: Temp-List for iteration variables */
+  public  static final int    ITERVAR      = 24; // Nummer der Ressource
+  private              String ITERVAR_DESC = "";
+
+  /** Ressource: Temp-Raster for actual LU */
+  public  static final int    ACTLU      = 25; // Nummer der Ressource
+  private              String ACTLU_DESC = "";
+  /** Ressource: Out-Rasters for time step results */
+  public  static final int    STEPRESULTS      = 26; // Nummer der Ressource
+  private              String STEPRESULTS_DESC = "";
+  /** Ressource: Temp-RasterList for total probabilities */
+  public  static final int    TOTALPROB      = 27; // Nummer der Ressource
+  private              String TOTALPROB_DESC = "";
+
+  /**
+   * Erzeugt einen neuen ContentManager fuer das {@linkplain ClueModel ClueModel}.
+   */
+  public ClueModelContentManager() {
+    super(28);
+    // Ressourcen festlegen
+    resource[MODELSTEPS]       = new ModelStepResource(ModelResource.CATEGORY_INPUT,MODELSTEPS_DESC,MODELSTEPS_MIN,MODELSTEPS_MAX);
+    resource[TOLERANCETYPE]    = new ToleranceTypeResource(ModelResource.CATEGORY_INPUT,TOLERANCETYPE_DESC);
+    resource[TOLERANCESINGLE]  = new SingleToleranceResource(ModelResource.CATEGORY_INPUT,TOLERANCESINGLE_DESC);
+    resource[TOLERANCEAVERAGE] = new AverageToleranceResource(ModelResource.CATEGORY_INPUT,TOLERANCEAVERAGE_DESC);
+    resource[CONVFACTQM]       = new ConversionFactorQMResource(ModelResource.CATEGORY_INPUT,CONVFACTQM_DESC);
+    resource[BASESCENARIO]     = new InitialScenarioResource(ModelResource.CATEGORY_INPUT,BASESCENARIO_DESC);
+    resource[LUHISTORY]        = new LUHistoryResource(ModelResource.CATEGORY_INPUT,LUHISTORY_DESC);
+    resource[LUCONV]           = new LUConversionMatrixResource(ModelResource.CATEGORY_INPUT,LUCONV_DESC,false);
+    resource[LUCONVDEV]        = new LUConversionMatrixResource(ModelResource.CATEGORY_INPUT,LUCONVDEV_DESC,true);
+    resource[ELASTICITY]       = new ConversionElasticityResource(ModelResource.CATEGORY_INPUT,ELASTICITY_DESC);
+    resource[AREARESTR]        = new AreaRestrictionsResource(ModelResource.CATEGORY_INPUT,AREARESTR_DESC);
+    resource[DEMAND]           = new DemandScenarioResource(ModelResource.CATEGORY_INPUT,DEMAND_DESC);
+    resource[STATDF]           = new StaticDrivingForcesResource(ModelResource.CATEGORY_INPUT,STATDF_DESC);
+    resource[DYNDFTYPES]       = new DynamicDrivingForceTypesResource(ModelResource.CATEGORY_INPUT,DYNDFTYPES_DESC);
+    resource[DYNDF]            = new DynamicDrivingForcesResource(ModelResource.CATEGORY_INPUT,DYNDF_DESC);
+    resource[REGRESSION]       = new RegressionResultsResource(ModelResource.CATEGORY_INPUT,REGRESSION_DESC);
+    resource[NBHWEIGHTS]       = new NeighborhoodWeightsResource(ModelResource.CATEGORY_INPUT,NBHWEIGHTS_DESC);
+    resource[NBHSETTINGS]      = new NeighborhoodSettingsResource(ModelResource.CATEGORY_INPUT,NBHSETTINGS_DESC);
+    resource[NBHREGRESSION]    = new NeighborhoodRegressionResultsResource(ModelResource.CATEGORY_INPUT,NBHREGRESSION_DESC);
+    resource[ACTLU]            = new ActualLUResource(ModelResource.CATEGORY_OUTPUT,ACTLU_DESC);
+    resource[ACTLUHISTORY]     = new ActualLUHistoryResource(ModelResource.CATEGORY_TEMP,ACTLUHISTORY_DESC);
+    resource[LUPROB]           = new LUProbabilitiesResource(ModelResource.CATEGORY_TEMP,LUPROB_DESC);
+    resource[NBHPROB]          = new NeighborhoodProbabilitiesResource(ModelResource.CATEGORY_TEMP,NBHPROB_DESC);
+    resource[LSPAPROB]         = new LSPAProbabilitiesResource(ModelResource.CATEGORY_INPUT,LSPAPROB_DESC);
+    resource[LSPAFACT]         = new LSPAFactorsResource(ModelResource.CATEGORY_INPUT,LSPAFACT_DESC);
+    resource[TOTALPROB]        = new TotalProbabilitiesResource(ModelResource.CATEGORY_TEMP,TOTALPROB_DESC);
+    resource[ITERVAR]          = new IterationVariablesResource(ModelResource.CATEGORY_TEMP,ITERVAR_DESC);
+    resource[STEPRESULTS]      = new StepResultsResource(ModelResource.CATEGORY_OUTPUT,STEPRESULTS_DESC);
+    // Ressource-Beschreibungen lokalisieren
+    resetCaptions(null);
+  }
+
+  /**
+   * Belegt die Ressourcen-Beschreibungen neu. Sind in der uebergebenen Map fuer die Keys
+   * keine Werte hinterlegt (oder wenn {@code captionMap = null}), wird auf den
+   * {@linkplain ClueModel#CLUE_RES Resource-Provider} des Modells zurueckgegriffen.
+   * @param captionMap Map in der nach den Ressourcen-Beschreibungen gesucht wird (kann
+   *                   {@code null} sein)
+   */
+  public void resetCaptions(Map<String,Object> captionMap) {
+    MODELSTEPS_DESC       = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.ModelSteps",MODELSTEPS_MIN,MODELSTEPS_MAX);
+    TOLERANCETYPE_DESC    = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.Tol.Type",ClueModel.TOLTYPE_PCT,ClueModel.TOLTYPE_ABS);
+    TOLERANCESINGLE_DESC  = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.Tol.Single");
+    TOLERANCEAVERAGE_DESC = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.Tol.Avg");
+    CONVFACTQM_DESC       = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.qmConvFactor");
+    BASESCENARIO_DESC     = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.LUC.Scenario");
+    LUHISTORY_DESC        = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.LUC.History");
+    LUCONV_DESC           = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.LUC.ConvMatrix");
+    LUCONVDEV_DESC        = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.LUC.ConvDev");
+    ELASTICITY_DESC       = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.LUC.ConvElas");
+    AREARESTR_DESC        = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.AreaRestr");
+    DEMAND_DESC           = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.Demand.Scenario");
+    STATDF_DESC           = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.DF.Static.Grids");
+    DYNDFTYPES_DESC       = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.DF.Dynamic.Types");
+    DYNDF_DESC            = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.DF.Dynamic.Grids");
+    REGRESSION_DESC       = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.Regression");
+    NBHWEIGHTS_DESC       = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.Nbh.Weight");
+    NBHSETTINGS_DESC      = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.Nbh.Setting");
+    NBHREGRESSION_DESC    = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.Nbh.Regr");
+    LSPAPROB_DESC         = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.LSPA.Prob");
+    LSPAFACT_DESC         = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.LSPA.Fact");
+    ACTLUHISTORY_DESC     = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.Temp.LucHist");
+    LUPROB_DESC           = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.Temp.LucProb");
+    NBHPROB_DESC          = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.Temp.NbhProb");
+    ITERVAR_DESC          = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.Temp.IterVar");
+    ACTLU_DESC            = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.Temp.Luc");
+    STEPRESULTS_DESC      = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.Out.StepRes");
+    TOTALPROB_DESC        = ClueModel.determineCaption(captionMap, ClueModel.CLUE_RES, "MRDesc.Temp.TotalProb");
+
+    resource[MODELSTEPS].setDesc(MODELSTEPS_DESC);
+    resource[TOLERANCETYPE].setDesc(TOLERANCETYPE_DESC);
+    resource[TOLERANCESINGLE].setDesc(TOLERANCESINGLE_DESC);
+    resource[TOLERANCEAVERAGE].setDesc(TOLERANCEAVERAGE_DESC);
+    resource[CONVFACTQM].setDesc(CONVFACTQM_DESC);
+    resource[BASESCENARIO].setDesc(BASESCENARIO_DESC);
+    resource[LUHISTORY].setDesc(LUHISTORY_DESC);
+    resource[LUCONV].setDesc(LUCONV_DESC);
+    resource[LUCONVDEV].setDesc(LUCONVDEV_DESC);
+    resource[ELASTICITY].setDesc(ELASTICITY_DESC);
+    resource[AREARESTR].setDesc(AREARESTR_DESC);
+    resource[DEMAND].setDesc(DEMAND_DESC);
+    resource[STATDF].setDesc(STATDF_DESC);
+    resource[DYNDFTYPES].setDesc(DYNDFTYPES_DESC);
+    resource[DYNDF].setDesc(DYNDF_DESC);
+    resource[REGRESSION].setDesc(REGRESSION_DESC);
+    resource[NBHWEIGHTS].setDesc(NBHWEIGHTS_DESC);
+    resource[NBHSETTINGS].setDesc(NBHSETTINGS_DESC);
+    resource[NBHREGRESSION].setDesc(NBHREGRESSION_DESC);
+    resource[ACTLU].setDesc(ACTLU_DESC);
+    resource[ACTLUHISTORY].setDesc(ACTLUHISTORY_DESC);
+    resource[LUPROB].setDesc(LUPROB_DESC);
+    resource[NBHPROB].setDesc(NBHPROB_DESC);
+    resource[LSPAPROB].setDesc(LSPAPROB_DESC);
+    resource[LSPAFACT].setDesc(LSPAFACT_DESC);
+    resource[TOTALPROB].setDesc(TOTALPROB_DESC);
+    resource[ITERVAR].setDesc(ITERVAR_DESC);
+    resource[STEPRESULTS].setDesc(STEPRESULTS_DESC);
+  }
+
+  /**
+   * Prueft alle Modell-Ressourcen auf Korrektheit.
+   * Neben den lokalen Bedingungen an die Ressourcen (die bereits durch
+   * die Methode der Oberklasse gechecked werden), prueft diese Methode, ob
+   * <ul>
+   * <li>ob die Raster alle dieselbe Groesse haben, wie das Base Scenario</li>
+   * <li>die MultiGrids genug Raster enthalten</li>
+   * <li>die Matrizen die passenden Groessen haben</li>
+   * </ul>
+   */
+  public void checkAndError() {
+    super.checkAndError();
+
+    // Parameter ermitteln, die fuer die Konsistenz relevant sind
+    int n = getLUConversionMatrix().getSize(0);
+    int m = getStaticDrivingForces().getGridCount();
+    int t = getStepCount().getOneTimeReadAccess().getValueAsInt();
+    WritableGrid baseGrid = (WritableGrid)getBaseScenario().getOneTimeReadAccess().getValue();
+    WritableGrid testGrid = null;
+
+    // Wenn angegeben, muss Abweichungsmatrix die selbe groesse habem, wie
+    // die LU-Conversion-Matrix
+    MatrixProperty luConvDev = getLUConversionDeviationMatrix();
+    if ( luConvDev != null && luConvDev.getSize(0) < n )
+      throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.LUC.ConvDev.Col",n) );
+    if ( luConvDev != null && luConvDev.getSize(1) < n )
+      throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.LUC.ConvDev.Row",n) );
+
+    // Conversion Elasticity muss n Eintraege haben
+    int ceCount = getConversionElasticity().getOneTimeReadAccess().getCount();
+    if ( ceCount < n )
+      throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.LUC.ConvElas.Size",n) );
+    // Area Restriction Raster muss dem Base Scenario entsprechen
+    testGrid = (WritableGrid)getAreaRestrictions().getOneTimeReadAccess().getValue();
+    checkRasterDim(baseGrid,BASESCENARIO_DESC,testGrid,AREARESTR_DESC);
+
+    // Demand Scenario muss (n,t)-Matrix sein
+    int[] dsSize = getDemandScenario().getSize();
+    if ( dsSize[0] < n )
+      throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.Demand.Scenario.Col",n) );
+    if ( dsSize[1] < t )
+      throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.Demand.Scenario.Row",t) );
+
+    // Driving Forces muessen m Raster, die dem Base Scenario entsprechen,
+    MultiGrid sdfGrid = getStaticDrivingForces();
+    if ( sdfGrid.getGridCount() < m )
+      throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.DF.Static.Grids",m) );
+    // erstes befuelltes Raster checken
+    checkRasterDim(baseGrid,BASESCENARIO_DESC,sdfGrid.getFirstNotNullGrid(),STATDF_DESC);
+
+    // Liste der Dynamischen DF darf nur m Eintraege haben und Werte zwischen 0 und m enthalten
+    int ddfCount = 0;
+    if ( getDynamicDrivingForceTypes() != null ) {
+      ListPropertyReadAccess ddf = getDynamicDrivingForceTypes().getReadAccess(this);
+      ddfCount = ddf.getCount();
+      if ( ddfCount > m )
+        throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.DF.Dynamic.Types.Size",m) );
+      for (int i=0; i<ddfCount; i++)
+        if ( ddf.getValueAsInt(i) < 0 || ddf.getValueAsInt(i) >= m )
+          throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.DF.Dynamic.Types.Value",0,m-1) );
+      ddf.release();
+    }
+
+    // Werden dyn. DF verwendet, muessen auch Raster angegeben werden
+    MultiGrid ddfGrids = getDynamicDrivingForces();
+    if ( ddfCount > 0 && ddfGrids == null )
+      throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.DF.Dynamic.Grids.Null",ClueModel.CLUE_RES.getString("MRDesc.DF.Dynamic.Grids")) );
+    // Es muessen mind. t Raster fuer jeden dyn. DF angegeben werden
+    if ( ddfCount > 0 && ddfGrids.getGridCount() < ddfCount*t )
+      throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.DF.Dynamic.Grids.Size1",ddfCount*t) );
+    // Fuer jeden DF muss dieselbe Anzahl an Grids enthalten sein
+    if ( ddfCount > 0 && ddfGrids.getGridCount() % ddfCount != 0 )
+      throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.DF.Dynamic.Grids.Size2") );
+
+    // Regression Results muss (m+1,n)-Matrix sein
+    int[] rrSize = getRegressionResults().getSize();
+    if ( rrSize[0] < m+1 )
+      throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.Regression.Col",m+1) );
+    if ( rrSize[1] < n )
+      throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.Regression.Row",n) );
+
+    // Wenn angegeben, muss die Liste der Neighborhood Weights mind. n Eintraege haben
+    ListProperty nbhWeights = getNeighborhoodWeights();
+    if ( nbhWeights != null ) {
+      if ( nbhWeights.getOneTimeReadAccess().getCount() < n )
+        throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.Nbh.Weight.Size",n) );
+    }
+
+    // Wenn angegeben, muss die Matrix der Neighborhood Settings in der 3. Dimension
+    // die Groessen n haben
+    if ( nbhWeights != null ) {
+      if ( getNeighborhoodSettings() == null )
+        throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.Nbh.Setting.Null") );
+      int[] nbSize = getNeighborhoodSettings().getSize();
+      if ( nbSize[0]%2 == 0 || nbSize[1]%2 == 0 )
+        throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.Nbh.Setting.Size1") );
+      if ( getNeighborhoodSettings().getSize(2) < n )
+        throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.Nbh.Setting.Size2",n) );
+
+    }
+
+    // Wenn angegeben, muss die Matrix der Neighborhood Regression eine
+    // (n+1,n)-Matrix sein
+    if ( nbhWeights != null ) {
+      if ( getNeighborhoodRegression() == null )
+        throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.Nbh.Regr.Null") );
+      int[] nbSize = getNeighborhoodRegression().getSize();
+      if ( nbSize[0] < n+1 )
+        throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.Nbh.Regr.Col",n+1) );
+      if ( nbSize[1] < n )
+        throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.Nbh.Regr.Row",n) );
+    }
+
+    // Raster fuer die aktuelle LU muss dem Base Scenario entsprechen
+    testGrid = (WritableGrid)getActLUResult().getOneTimeReadAccess().getValue();
+    checkRasterDim(baseGrid,BASESCENARIO_DESC,testGrid,ACTLU_DESC);
+
+    // Raster fuer die aktuelle LU History muss dem Base Scenario entsprechen
+    testGrid = (WritableGrid)getActLUHistory().getOneTimeReadAccess().getValue();
+    checkRasterDim(baseGrid,BASESCENARIO_DESC,testGrid,ACTLUHISTORY_DESC);
+
+//    // MultiGrid fuer die LU-Wahrscheinlichkeiten muss n Raster enthalten,
+//    // die dem Base Scenario entsprechen
+//    MultiGrid luProbGrids = this.getLUProbabilities();
+//    if ( luProbGrids.getGridCount() < n )
+//      throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.Temp.LucProb.Size",n) );
+//    checkRasterDim(baseGrid,BASESCENARIO_DESC,luProbGrids.getGrid(0),LUPROB_DESC);
+    // MultiGrid fuer die LU-Wahrscheinlichkeiten muss dem Base Scenario entsprechen
+    // Die n Inhalt-Grids werden bei der Modell-Initialisierung dynamisch erzeugt!
+    MultiGrid luProbGrids = this.getLUProbabilities();
+    checkRasterDim(baseGrid,BASESCENARIO_DESC,luProbGrids.getTemplateGrid(),LUPROB_DESC);
+
+//    // MultiGrid fuer die Nachbarschafts-Wahrscheinlichkeiten muss n Raster enthalten,
+//    // die dem Base Scenario entsprechen
+//    if ( nbhWeights != null ) {
+//      MultiGrid nbhProbGrids = this.getNeighborhoodProbabilities();
+//      if ( nbhProbGrids == null )
+//        throw new XuluDataException("Temp. raster for neighborhood probabilities must be specified...");
+//      if ( nbhProbGrids.getGridCount() < n )
+//        throw new XuluDataException("MultiGrid for neighborhood probabilities must contain at leat "+n+" grids (one for each land use type)...");
+//      checkRasterDim(baseGrid,BASESCENARIO_DESC,nbhProbGrids.getGrid(0),LUPROB_DESC);
+//    }
+    // MultiGrid fuer die Nachbarschafts-Wahrscheinlichkeiten muss dem Base Scenario entsprechen
+    // Die n Inhalt-Grids werden bei der Modell-Initialisierung dynamisch erzeugt!
+    if ( nbhWeights != null ) {
+      MultiGrid nbhProbGrids = this.getNeighborhoodProbabilities();
+      if ( nbhProbGrids == null )
+        throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.Temp.NbhProb.Null") );
+      checkRasterDim(baseGrid,BASESCENARIO_DESC,nbhProbGrids.getTemplateGrid(),LUPROB_DESC);
+    }
+
+    // Werden die LSPA-Raster verwendet, muss fuer jeden LUC-Typ ein Raster
+    // hinterlegt sein
+    MultiGrid lspaGrids = getLSPAProbabilities();
+    if ( lspaGrids != null ) {
+      if ( lspaGrids.getGridCount() < n )
+        throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.LSPA.Prob.Size",n) );
+      checkRasterDim(baseGrid,BASESCENARIO_DESC,lspaGrids.getTemplateGrid(),LSPAPROB_DESC);
+    }
+    // Werden die LSPA-Faktoren verwendet, muss fuer jeden LUC-Typ ein Faktor
+    // hinterlegt sein
+    ListProperty lspaFact = getLSPAFactors();
+    if ( lspaGrids != null && lspaFact != null ) {
+      if ( lspaFact.getOneTimeReadAccess().getCount() < n )
+        throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.LSPA.Fact.Size",n) );
+    }
+
+    // MultiGrid fuer die Gesamt-Wahrscheinlichkeiten muss dem Base Scenario entsprechen
+    // Die n Inhalt-Grids werden bei der Modell-Initialisierung dynamisch erzeugt!
+    MultiGrid totProbGrids = this.getNeighborhoodProbabilities();
+    if ( totProbGrids != null ) {
+      checkRasterDim(baseGrid,BASESCENARIO_DESC,totProbGrids.getTemplateGrid(),TOTALPROB_DESC);
+    }
+
+//    // Wenn angegeben, muss das MultiGrid fuer die Zeitschritt-Ergebnisse
+//    // t Raster enthalten, die dem Base Scenario entsprechen
+//    MultiGrid resultGrids = this.getStepLUResults();
+//    if (resultGrids != null) {
+//      if ( resultGrids.getGridCount() < t )
+//        throw new XuluDataException("MultiGrid for time step results must contain at leat "+t+" grids (one for each time step)...");
+//      checkRasterDim(baseGrid, BASESCENARIO_DESC, resultGrids.getGrid(0),STEPRESULTS_DESC);
+//    }
+    // Das MultiGrid fuer die Zeitschritt-Ergebnisse dem Base Scenario entsprechen
+    // Die t Inhalt-Grids werden waehrend des Modellablaufs dynamisch erzeugt!
+    MultiGrid resultGrids = this.getStepLUResults();
+    checkRasterDim(baseGrid, BASESCENARIO_DESC, resultGrids.getTemplateGrid(),STEPRESULTS_DESC);
+  }
+
+  /**
+   * Vergleicht zwei Raster auf gleiche Struktur (Hoehe, Breite, Zell-Hoehe,
+   * Zell-Breite, Sample-Type).
+   */
+  private static void checkRasterDim(WritableGrid grid1, String desc1, WritableGrid grid2, String desc2) {
+    if ( grid1.getWidth() != grid2.getWidth() )
+      throw new XuluDataException(createCompareMessage(ClueModel.CLUE_RES.getString("Error.RasterDim.GridWidth"),desc1,desc2));
+    if ( grid1.getHeight() != grid2.getHeight() )
+      throw new XuluDataException(createCompareMessage(ClueModel.CLUE_RES.getString("Error.RasterDim.GridHeight"),desc1,desc2));
+    if ( grid1.getCellWidth() != grid2.getCellWidth() )
+      throw new XuluDataException(createCompareMessage(ClueModel.CLUE_RES.getString("Error.RasterDim.CellWidth"),desc1,desc2));
+    if ( grid1.getCellHeight() != grid2.getCellHeight() )
+      throw new XuluDataException(createCompareMessage(ClueModel.CLUE_RES.getString("Error.RasterDim.CellHeight"),desc1,desc2));
+    if ( grid1.getSampleType() != grid2.getSampleType() )
+      throw new XuluDataException(createCompareMessage(ClueModel.CLUE_RES.getString("Error.RasterDim.SampleType"),desc1,desc2));
+  }
+
+  /**
+   * Erzeugt eine Fehlermeldung fuer eine bestimmte inkompatible Raster-Struktur.
+   */
+  private static String createCompareMessage(String compType, String objDesc1, String objDesc2) {
+    return ClueModel.CLUE_RES.getString("Error.RasterDim",compType,objDesc1,objDesc2);
+  }
+
+  //////////////////////////////////////////////////////////////////////
+  ///////   vereinfachende Zugriffsmethoden auf Ressourcen   ///////////
+  //////////////////////////////////////////////////////////////////////
+  /** Liefert Zugriff auf die Ressource "Time Steps". */
+  public ScalarProperty getStepCount() {
+    return (ScalarProperty)getResourceData(this.MODELSTEPS);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Art der Abweichungsangaben". */
+  public ScalarProperty getDemandToleranceType() {
+    return (ScalarProperty)getResourceData(this.TOLERANCETYPE);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Einzel-Abweichung von Bedarfen". */
+  public ScalarProperty getSingleDemandTolerance() {
+    return (ScalarProperty)getResourceData(this.TOLERANCESINGLE);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Durchschnitts-Abweichung von Bedarfen". */
+  public ScalarProperty getAverageDemandTolerance() {
+    return (ScalarProperty)getResourceData(this.TOLERANCEAVERAGE);
+  }
+
+
+  /** Liefert Zugriff auf die Ressource "Umrechnungsfaktor Bedarfseinheit -> qm". */
+  public ScalarProperty getConversionFactor() {
+    return (ScalarProperty)getResourceData(this.CONVFACTQM);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Base Scenario". */
+  public ScalarProperty getBaseScenario() {
+    return (ScalarProperty)getResourceData(this.BASESCENARIO);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Land use History". */
+  public ScalarProperty getLUHistory() {
+    return (ScalarProperty)getResourceData(this.LUHISTORY);
+  }
+
+  /** Liefert Zugriff auf die Ressource "LU Conversion Matrix". */
+  public MatrixProperty getLUConversionMatrix() {
+    return (MatrixProperty)getResourceData(this.LUCONV);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Deviation of LU Conversion Matrix". */
+  public MatrixProperty getLUConversionDeviationMatrix() {
+    return (MatrixProperty)getResourceData(this.LUCONVDEV);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Conversion Elasticity". */
+ public ListProperty getConversionElasticity() {
+    return (ListProperty)getResourceData(this.ELASTICITY);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Area Restrictions". */
+  public ScalarProperty getAreaRestrictions() {
+    return (ScalarProperty)getResourceData(this.AREARESTR);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Demand Scenario". */
+  public MatrixProperty getDemandScenario() {
+    return (MatrixProperty)getResourceData(this.DEMAND);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Static Driving Forces". */
+  public MultiGrid getStaticDrivingForces() {
+    return (MultiGrid)getResourceData(this.STATDF);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Dynamic Driving Force Types". */
+ public ListProperty getDynamicDrivingForceTypes() {
+    return (ListProperty)getResourceData(this.DYNDFTYPES);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Dynamic Driving Forces". */
+ public MultiGrid getDynamicDrivingForces() {
+    return (MultiGrid)getResourceData(this.DYNDF);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Regression Results". */
+  public MatrixProperty getRegressionResults() {
+    return (MatrixProperty)getResourceData(this.REGRESSION);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Neighborhood Weights". */
+  public ListProperty getNeighborhoodWeights() {
+    return (ListProperty)getResourceData(this.NBHWEIGHTS);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Neighborhood Settings". */
+  public MatrixProperty getNeighborhoodSettings() {
+    return (MatrixProperty)getResourceData(this.NBHSETTINGS);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Neighborhood Regression Results". */
+  public MatrixProperty getNeighborhoodRegression() {
+    return (MatrixProperty)getResourceData(this.NBHREGRESSION);
+  }
+
+  /** Liefert Zugriff auf die Ausgabe-Ressource "Aktuelle Landnutzung". */
+  public ScalarProperty getActLUResult() {
+    return (ScalarProperty)getResourceData(this.ACTLU);
+  }
+
+  /** Liefert Zugriff auf die Ausgabe-Ressource "LU-Wahrscheinlichkeiten". */
+  public MultiGrid getLUProbabilities() {
+    return (MultiGrid)getResourceData(this.LUPROB);
+  }
+
+  /** Liefert Zugriff auf die Ausgabe-Ressource "Nachbarschafts-Wahrscheinlichkeiten". */
+  public MultiGrid getNeighborhoodProbabilities() {
+    return (MultiGrid)getResourceData(this.NBHPROB);
+  }
+
+  /** Liefert Zugriff auf die Ausgabe-Ressource "Iterationsvariablen". */
+
+  public ListProperty getIterationVariables() {
+//    throw new UnsupportedOperationException("Iteration variables are no longer stored in a resource!");
+    return (ListProperty)getResourceData(this.ITERVAR);
+  }
+
+  /** Liefert Zugriff auf die Ausgabe-Ressource "Gesamt-Wahrscheinlichkeiten". */
+  public MultiGrid getTotalProbabilities() {
+    return (MultiGrid)getResourceData(this.TOTALPROB);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Location specific preferece addition". */
+  public MultiGrid getLSPAProbabilities() {
+    return (MultiGrid)getResourceData(this.LSPAPROB);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Factors for the location specific preferece addition". */
+  public ListProperty getLSPAFactors() {
+    return (ListProperty)getResourceData(this.LSPAFACT);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Aktuelle Land use History". */
+  public ScalarProperty getActLUHistory() {
+    return (ScalarProperty)getResourceData(this.ACTLUHISTORY);
+  }
+
+  /** Liefert Zugriff auf die Ausgabe-Ressource "LU zu jedem Zeitschritt". */
+  public MultiGrid getStepLUResults() {
+    return (MultiGrid)getResourceData(this.STEPRESULTS);
+  }
+
+  //////////////////////////////////////////////////////////////////////
+  ///////////   Klassen fuer die benoetigten Ressourcen   //////////////
+  //////////////////////////////////////////////////////////////////////
+  /**
+   * Ressource fuer Simulationsschritte.
+   */
+  private class ModelStepResource extends ValuePropertyResource {
+    private int stepMin = 0;
+    private int stepMax = 0;
+
+    public ModelStepResource(int cat,String desc, int stepMin, int stepMax) {
+      super(cat,desc,ScalarProperty.class,Number.class,false);
+      this.stepMin = stepMin;
+      this.stepMax = stepMax;
+    }
+
+    public void checkTypeAndError(Object data) {
+      super.checkTypeAndError(data);
+      // muss als Datentyp Long oder Integer haben
+      if ( !BaseTypeUtil.isNumeric(((ScalarProperty)data).getType()) ||
+            BaseTypeUtil.isDecimal(((ScalarProperty)data).getType()) )
+        throwDataException( ClueModel.CLUE_RES.getString("Error.ModelSteps.Type") );
+    }
+
+    public void checkAndError(Object data) {
+      super.checkAndError(data);
+      // muss zwischen 1 und 20 liegen
+      checkRangeAndError(this,((ScalarProperty)data).getOneTimeReadAccess().getValueAsLong(),stepMin,stepMax);
+    }
+  }
+
+  /**
+   * Ressource fuer Art der Toleranz-Angaben (prozentual, absolut).
+   */
+  private class ToleranceTypeResource extends ValuePropertyResource {
+    public ToleranceTypeResource(int cat,String desc) {
+      super(cat,desc,ScalarProperty.class,Integer.class,false);
+    }
+    public void checkAndError(Object data) {
+      super.checkAndError(data);
+      // Flag muss 0 (prozentual) oder 1 (absolut) sein
+      checkRangeAndError(this,((ScalarProperty)data).getOneTimeReadAccess().getValueAsInt(),0,1);
+    }
+  }
+
+  /**
+   * Ressource fuer Toleranz der einzelnen Bedarfe.
+   */
+  private class SingleToleranceResource extends ValuePropertyResource {
+    public SingleToleranceResource(int cat,String desc) {
+      super(cat,desc,ScalarProperty.class,Number.class,false);
+    }
+    public void checkAndError(Object data) {
+      super.checkAndError(data);
+      // muss groesser 0 sein
+      checkRangeAndError(this,((ScalarProperty)data).getOneTimeReadAccess().getValueAsDouble(),0,Double.MAX_VALUE);
+    }
+  }
+
+  /**
+   * Ressource fuer Durchschnitts-Toleranz der einzelnen Bedarfe.
+   */
+  private class AverageToleranceResource extends ValuePropertyResource {
+    public AverageToleranceResource(int cat,String desc) {
+      super(cat,desc,ScalarProperty.class,Number.class,false);
+    }
+    public void checkAndError(Object data) {
+      super.checkAndError(data);
+      // muss groesser 0 sein
+      checkRangeAndError(this,((ScalarProperty)data).getOneTimeReadAccess().getValueAsDouble(),0,Double.MAX_VALUE);
+    }
+  }
+
+  /**
+   * Ressource fuer Umrechnungsfaktor Bedarfseinheit >> Quadratmeter.
+   */
+  private class ConversionFactorQMResource extends ValuePropertyResource {
+    public ConversionFactorQMResource(int cat,String desc) {
+      super(cat,desc,ScalarProperty.class,Double.class,false);
+    }
+  }
+
+  /**
+   * Ressource fuer Ausgangsszenario.
+   */
+  private class InitialScenarioResource extends ValuePropertyResource {
+    public InitialScenarioResource(int cat,String desc) {
+      super(cat,desc,ScalarProperty.class,WritableGrid.class,false);
+    }
+  }
+
+  /**
+   * Ressource fuer LU-History.
+   */
+  private class LUHistoryResource extends ValuePropertyResource {
+    public LUHistoryResource(int cat,String desc) {
+      super(cat,desc,ScalarProperty.class,WritableGrid.class,false);
+    }
+  }
+
+  /**
+   * Ressource fuer LU-Conversion-Matrix.
+   */
+  private class LUConversionMatrixResource extends ValuePropertyResource {
+    public LUConversionMatrixResource(int cat,String desc,boolean nullable) {
+      super(cat,desc,MatrixProperty.class,Integer.class,nullable);
+    }
+    public void checkTypeAndError(Object data) {
+      super.checkTypeAndError(data);
+      // Matrix muss mindestens 2-dimensional sein
+      if ( data != null && ((MatrixProperty)data).getDimension() < 2 )
+        throwDataException( ClueModel.CLUE_RES.getString("Error.Expected.Matrix2") );
+    }
+  }
+
+  /**
+   * Ressource fuer Conversion Elasticity.
+   */
+  private class ConversionElasticityResource extends ValuePropertyResource {
+    public ConversionElasticityResource(int cat,String desc) {
+      super(cat,desc,ListProperty.class,Double.class,false);
+    }
+
+    public void checkAndError(Object data) {
+      super.checkAndError(data);
+      // Alle Werte der Liste muessen zwischen 0 und 1 liegen
+      ListPropertyReadAccess a = ((ListProperty)data).getReadAccess(this);
+      for (int i=0; i<a.getCount(); i++) {
+        double v = a.getValueAsDouble(i);
+        if ( v < 0 || 1 < v ) {
+          a.release();
+          throwDataException( ClueModel.CLUE_RES.getString("Error.LUC.ConvElas.Value") );
+        }
+      }
+      a.release();
+    }
+  }
+
+  /**
+   * Ressource fuer Area Restrictions.
+   */
+  private class AreaRestrictionsResource extends ValuePropertyResource {
+    public AreaRestrictionsResource(int cat,String desc) {
+      super(cat,desc,ScalarProperty.class,WritableGrid.class,false);
+    }
+  }
+
+  /**
+   * Ressource fuer Demand Scenario.
+   */
+  private class DemandScenarioResource extends ValuePropertyResource {
+    public DemandScenarioResource(int cat,String desc) {
+      super(cat,desc,MatrixProperty.class,Integer.class,false);
+    }
+
+    public void checkTypeAndError(Object data) {
+      super.checkTypeAndError(data);
+      // Matrix muss mindestens 2-dimensional sein
+      if ( ((MatrixProperty)data).getDimension() < 2 )
+        throwDataException( ClueModel.CLUE_RES.getString("Error.Expected.Matrix2") );
+    }
+  }
+
+  /**
+   * Ressource fuer Static Driving Forces.
+   */
+  private class StaticDrivingForcesResource extends AbstractModelResource {
+    public StaticDrivingForcesResource(int cat,String desc) {
+      super(cat,desc,MultiGrid.class,false);
+    }
+
+    public void checkTypeAndError(Object data) {
+      if ( data!=null && !(data instanceof MultiGrid) ||
+           data==null && !nullable)
+        throwDataException("MultiGrid");
+    }
+
+    public void checkAndError(Object data) {
+      checkTypeAndError(data);
+    }
+  }
+
+  /**
+   * Ressource fuer Dynamic Driving Force Types.
+   */
+  private class DynamicDrivingForceTypesResource extends ValuePropertyResource {
+    public DynamicDrivingForceTypesResource(int cat,String desc) {
+      super(cat,desc,ListProperty.class,Integer.class,true);
+    }
+  }
+
+  /**
+   * Ressource fuer Dynamic Driving Forces.
+   */
+  private class DynamicDrivingForcesResource extends AbstractModelResource {
+    public DynamicDrivingForcesResource(int cat,String desc) {
+      super(cat,desc,MultiGrid.class,true);
+    }
+
+    public void checkTypeAndError(Object data) {
+      if ( data != null && !(data instanceof MultiGrid) ||
+           data == null && !nullable)
+        throwDataException("MultiGrid");
+    }
+
+    public void checkAndError(Object data) {
+      checkTypeAndError(data);
+    }
+  }
+
+  /**
+   * Ressource fuer Regression Results.
+   */
+  private class RegressionResultsResource extends ValuePropertyResource {
+    public RegressionResultsResource(int cat,String desc) {
+      super(cat,desc,MatrixProperty.class,Double.class,false);
+    }
+    public void checkTypeAndError(Object data) {
+      super.checkTypeAndError(data);
+      // Matrix muss mindestens 2-dimensional sein
+      if ( ((MatrixProperty)data).getDimension() < 2 )
+        throwDataException( ClueModel.CLUE_RES.getString("Error.Expected.Matrix2") );
+    }
+  }
+
+  /**
+   * Ressource fuer Neighborhood Weight.
+   */
+  private class NeighborhoodWeightsResource extends ValuePropertyResource {
+    public NeighborhoodWeightsResource(int cat,String desc) {
+      super(cat,desc,ListProperty.class,Double.class,true);
+    }
+  }
+
+  /**
+   * Ressource fuer Neighborhood Settings.
+   */
+  private class NeighborhoodSettingsResource extends ValuePropertyResource {
+    public NeighborhoodSettingsResource(int cat,String desc) {
+      super(cat,desc,MatrixProperty.class,Double.class,true);
+    }
+    public void checkTypeAndError(Object data) {
+      super.checkTypeAndError(data);
+      // Matrix muss mindestens 3-dimensional sein
+      if ( data!=null && ((MatrixProperty)data).getDimension() < 3 )
+        throwDataException( ClueModel.CLUE_RES.getString("Error.Expected.Matrix3") );
+    }
+  }
+
+  /**
+   * Ressource fuer Neighborhood Regression Results.
+   */
+  private class NeighborhoodRegressionResultsResource extends ValuePropertyResource {
+    public NeighborhoodRegressionResultsResource(int cat,String desc) {
+      super(cat,desc,MatrixProperty.class,Double.class,true);
+    }
+    public void checkTypeAndError(Object data) {
+      super.checkTypeAndError(data);
+      // Matrix muss mindestens 2-dimensional sein
+      if ( data!=null && ((MatrixProperty)data).getDimension() < 2 )
+        throwDataException( ClueModel.CLUE_RES.getString("Error.Expected.Matrix2") );
+    }
+  }
+
+  /**
+   * Ressource fuer die simulierte LU.
+   */
+  private class ActualLUResource extends ValuePropertyResource {
+    public ActualLUResource(int cat,String desc) {
+      super(cat,desc,ScalarProperty.class,WritableGrid.class,false);
+    }
+  }
+
+  /**
+   * Ressource fuer aktuelle LU-History.
+   */
+  private class ActualLUHistoryResource extends ValuePropertyResource {
+    public ActualLUHistoryResource(int cat,String desc) {
+      super(cat,desc,ScalarProperty.class,WritableGrid.class,false);
+    }
+  }
+
+  /**
+   * Ressource fuer die errechneten LU-Wahrscheinlichkeiten.
+   */
+  private class LUProbabilitiesResource extends AbstractModelResource {
+    public LUProbabilitiesResource(int cat,String desc) {
+      super(cat,desc,MultiGrid.class,false);
+    }
+    public void checkTypeAndError(Object data) {
+      if ( data!=null && !(data instanceof MultiGrid) ||
+           data==null && !nullable )
+        throwDataException("MultiGrid");
+    }
+    public void checkAndError(Object object) {
+      checkTypeAndError(object);
+    }
+  }
+
+  /**
+   * Ressource fuer die errechneten Nachbarschafts-Wahrscheinlichkeiten.
+   */
+  private class NeighborhoodProbabilitiesResource extends AbstractModelResource {
+    public NeighborhoodProbabilitiesResource(int cat,String desc) {
+      super(cat,desc,MultiGrid.class,true);
+    }
+    public void checkTypeAndError(Object data) {
+      if ( data!=null && !(data instanceof MultiGrid) ||
+           data==null && !nullable )
+        throwDataException("MultiGrid");
+    }
+    public void checkAndError(Object object) {
+      checkTypeAndError(object);
+    }
+  }
+
+  /**
+   * Optionale Ressource fuer die "Location specific preference addition".
+   */
+  private class LSPAProbabilitiesResource extends AbstractModelResource {
+    public LSPAProbabilitiesResource(int cat,String desc) {
+      super(cat,desc,MultiGrid.class,true);
+    }
+    public void checkTypeAndError(Object data) {
+      if ( data!=null && !(data instanceof MultiGrid) ||
+           data==null && !nullable )
+        throwDataException("MultiGrid");
+    }
+    public void checkAndError(Object object) {
+      checkTypeAndError(object);
+    }
+  }
+
+  /**
+   * Optionale Ressource fuer die Faktoren der "Location specific preference addition".
+   */
+  private class LSPAFactorsResource extends ValuePropertyResource {
+    public LSPAFactorsResource(int cat,String desc) {
+      super(cat,desc,ListProperty.class,Double.class,true);
+    }
+  }
+
+  /**
+   * Ressource fuer die errechneten Gesamt-Wahrscheinlichkeiten pro LUC-Typ.
+   */
+  private class TotalProbabilitiesResource extends AbstractModelResource {
+    public TotalProbabilitiesResource(int cat,String desc) {
+      super(cat,desc,MultiGrid.class,true);
+    }
+    public void checkTypeAndError(Object data) {
+      if ( data!=null && !(data instanceof MultiGrid) ||
+           data==null && !nullable )
+        throwDataException("MultiGrid");
+    }
+    public void checkAndError(Object object) {
+      checkTypeAndError(object);
+    }
+  }
+
+  /**
+   * Ressource fuer Iterationsvariablen.
+   */
+  private class IterationVariablesResource extends ValuePropertyResource {
+    public IterationVariablesResource(int cat,String desc) {
+      super(cat,desc,ListProperty.class,Float.class,false);
+    }
+  }
+
+  /**
+   * Ressource fuer die einzelnen Zeit-Schritt-Ergebnisse.
+   */
+  private class StepResultsResource extends AbstractModelResource {
+    public StepResultsResource(int cat,String desc) {
+      super(cat,desc,MultiGrid.class,false);
+    }
+
+    public void checkTypeAndError(Object data) {
+      if ( data!=null && !(data instanceof MultiGrid) ||
+           data==null && !nullable )
+        throwDataException("MultiGrid");
+    }
+
+    public void checkAndError(Object object) {
+      checkTypeAndError(object);
+    }
+  }
+
+  /**
+   * Prueft, ob ein Wert in einem bestimmten Bereich liegt. Wenn nicht, wird
+   * fuer die angegebene Ressource eine Exception geworfen.
+   */
+  private static void checkRangeAndError(ModelResource r, double value, double min, double max) {
+    if ( value < min ||  max < value )
+     throw new XuluDataException( ClueModel.CLUE_RES.getString("Error.Resource.Not.Allowed",r.getDesc(),value));
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/clue/ClueModel_Optimized.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/clue/ClueModel_Optimized.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/model/clue/ClueModel_Optimized.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,1014 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.model.clue;
+
+import java.util.Random;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.LogManager;
+
+import schmitzm.lang.LangUtil;
+
+import schmitzm.data.property.Access;
+import schmitzm.data.property.ValueProperty;
+import schmitzm.data.property.ValuePropertyType;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.ListPropertyReadAccess;
+import schmitzm.data.property.ListPropertyWriteAccess;
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.MatrixProperty;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.PropertyWriteAccess;
+import schmitzm.data.WritableGrid;
+
+import edu.bonn.xulu.data.XuluDataException;
+import edu.bonn.xulu.model.AbstractStepModel;
+import edu.bonn.xulu.model.ModelContentManager;
+import edu.bonn.xulu.model.AbstractModelContentManager;
+import edu.bonn.xulu.model.ModelResource;
+import edu.bonn.xulu.model.AbstractModelResource;
+import edu.bonn.xulu.model.ValuePropertyResource;
+import edu.bonn.xulu.model.event.ModelIterationStepStartedEvent;
+import edu.bonn.xulu.model.event.ModelIterationStepFinishedEvent;
+
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+
+import schmitzm.temp.BaseTypeUtil;
+
+/**
+ * Diese Klasse stellt den Versuch einer Laufzeit-verbesserten Implementierung der
+ * ersten <a href="http://www.dow.wau.nl/clue/" target="_blank">CLUE</a>-Modell-Implementierung
+ * {@link ClueModel_Original} dar (CLUE = The <b>C</b>onversion of <b>L</b>and
+ * <b>U</b>se and its <b>E</b>ffects).<br>
+ * Der Algorithmus ist der gleiche, jedoch wurde versucht, insbesondere im Ablauf
+ * der Iteration auf alle Operationen zu verzichten, die sich negative auf die
+ * Laufzeit auswirken koennten:
+ * <ul>
+ *   <li>ueberfluessige (temporaere) Objekt-Erzeugungen</li>
+ *   <li>Status-Ausgaben</li>
+ *   <li>GUI</li>
+ *   <li>Debugging in Dateien</li>
+ *   <li>usw.</li>
+ * </ul>
+ * @see ClueModelContentManager
+ * @see ClueModel
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class ClueModel_Optimized extends AbstractStepModel {
+  /** Konstante fuer die Toleranz-Art "prozentual". */
+  public static final int TOLTYPE_PCT = 0;
+  /** Konstante fuer die Toleranz-Art "absolut in Bedarf-Einheit". */
+  public static final int TOLTYPE_ABS = 1;
+
+  /** Speichert den ContentManager fuer das Modell.
+   *  @see ClueModelContentManager */
+  protected ClueModelContentManager contManager;
+
+  private final Logger LOG = LogManager.getLogger(this.getClass().getName());
+
+  //********** Lese/Schreibrechte, die fuer den gesamten ***********
+  //********** Modellanlauf gehalten werden muessen      ***********
+  private PropertyReadAccess  RA_baseLU       = null; // Base Scenario
+  private PropertyReadAccess  RA_baseLUHist   = null; // Base LU History
+  private PropertyReadAccess  RA_luConv       = null; // LU-Conversion-Matrix
+  private PropertyReadAccess  RA_luElas       = null; // LU-Conversion-Elasticity
+  private PropertyReadAccess  RA_areaRestr    = null; // Area Restrictions
+  private PropertyReadAccess  RA_luDemand     = null; // LU-Bedarfe
+  private PropertyReadAccess  RA_sdfGrids     = null; // Static Driving Forces
+  private PropertyReadAccess  RA_ddfList      = null; // List of dynmic Driving Forces
+  private PropertyReadAccess  RA_ddfGrids     = null; // Dynamic Driving Forces
+  private PropertyReadAccess  RA_regrRes      = null; // Regression Results
+  private PropertyReadAccess  RA_nbhWeights   = null; // Gewichtung der Nachbarschaft pro LU-Typ
+  private PropertyReadAccess  RA_nbhSettings  = null; // Definition der Umgebung pro LU-Typ
+  private PropertyReadAccess  RA_nbhRegrRes   = null; // Regression Results fuer Nachbarschaft
+  private PropertyWriteAccess WA_outActLU     = null; // speichert die aktuell sim. LU
+  private PropertyWriteAccess WA_outActLUHist = null; // speichert die aktuell sim. LU Historie
+  private PropertyWriteAccess WA_outLUProb    = null; // speichert die LU-Wahrscheinlichkeiten
+  private PropertyWriteAccess WA_outNbhProb   = null; // speichert die Nachbarschafts-Wahrscheinlichkeiten
+  private PropertyWriteAccess WA_outIter      = null; // speichert die Iterationsvariablen
+  private PropertyWriteAccess WA_outStepLU    = null; // speichert die LU fuer jeden Zeitpunkt
+
+  //**************** Variablen mit denen gearbeitet wird *******************
+  // Modell-Parameter
+  private int    luCount    = 0;    // Anzahl an LU-Typen
+  private int    dfCount    = 0;    // Anzahl an Driving Forces
+  private int    ddfCount   = 0;    // Anzahl an dynamischen Driving Forces
+  private int    areaWidth  = 0;    // Breite des Untersuchungsgebiets (Rasterzellen)
+  private int    areaHeight = 0;    // Hoehe des Untersuchungsgebiets (Rasterzellen)
+  private int    areaMinX   = 0;    // Start-Index des Rasters in X-Richtung
+  private int    areaMinY   = 0;    // Start-Index des Rasters in Y-Richtung
+  private int    areaMaxX   = 0;    // End-Index des Rasters in X-Richtung (EXKLUSIVE!)
+  private int    areaMaxY   = 0;    // End-Index des Rasters in Y-Richtung (EXKLUSIVE!)
+  private int    demandTolType    = 0;     // Art der Abweichungsangaben
+  private float  demandTolSingle  = 0.0f;  // erlaubte Abweichung fuer jeden einzelnen LU-Typ vom Bedarf
+  private float  demandTolAverage = 0.0f;  // erlaubte Durchschnitts-Abweichung fuer das Untersuchungsgebiet
+  private float  demandConv = 0.0f;  // Umrechnungsfaktor Bedarfseingeit -> qm
+  private float  cellSize   = 0f;    // Flaeche einer Rasterzelle (in Bedarfseinheit)
+  // Eingabe-Daten, die ueber den gesamten Modellablauf benoetigt werden
+  private WritableGrid            baseLU       = null; // Base Scenario
+  private WritableGrid            baseLUHist   = null; // Base LU History
+  // ---
+  // Versuch der Performance-Steigerung (D):
+  //       Zugriff auf LU-Elastizitaet nicht ueber Property-Liste,
+  //       sondern ueber lokalen Array
+  // -> Steigerung der Iteration um 11,4%
+//  private ListPropertyReadAccess  luElas       = null; // LU-Conversion-Elasticity
+  private float[]                 luElas       = null;
+  // ---
+  private WritableGrid            areaRestr    = null; // Area Restrictions
+  // ---
+  // Versuch der Performance-Steigerung (F):
+  //       Zugriff auf Demand und LUC-Conversion nicht ueber Propertys,
+  //       sondern ueber lokales Array-Matrizen
+  // -> Steigerung der Iteration um 65% (Conv-Matrix ~11%, Demand ~52%)
+//  private PropertyReadAccess      luDemand     = null; // LU-Bedarfe
+//  private PropertyReadAccess      luConv       = null; // LU-Conversion-Matrix
+  private float[][]               luDemand     = null;
+  private int[][]                 luConv       = null;
+  // ---
+  // Versuch der Performance-Steigerung (C):
+  //       Zugriff auf statische DF und dynamische DF nicht ueber Property-Liste,
+  //       sondern ueber in lokalem Array hinterlegte Referenzen
+  // -> Steigerung der LUC-W'keitsberechnung um 6,5 %
+//  private MultiGrid               sdfGrids     = null; // Static Driving Forces
+  private WritableGrid[]          sdfGrids     = null;
+//  private ListPropertyReadAccess  ddfList      = null; // Dynamic Driving Force Types
+//  private MultiGrid               ddfGrids     = null; // Dynamic Driving Forces
+  private WritableGrid[]          ddfGrids     = null;
+  // ---
+  private int[]                   ddfStartIdx  = null; // Listenindex an dem ein dyn. DF beginnt
+  // Versuch der Performance-Steigerung (G):
+  //       Zugriff auf Statistik-Parameter nicht ueber Property-Matrix,
+  //       sondern ueber lokalen Array
+  // -> Steigerung der LUC-W'keitsberechnung um 6,2%
+//  private PropertyReadAccess      regrRes      = null; // Statistik
+  private float[][]               regrRes      = null;
+  // ---
+
+  // Versuch der Performance-Steigerung (H):
+  //       Zugriff auf Statistik-Parameter nicht ueber Property-Matrix,
+  //       sondern ueber lokale Arrays
+  // -> Steigerung der LUC-W'keitsberechnung um 84%
+  //    Steigerung der Iteration um 30%
+//  private ListPropertyReadAccess  nbhWeights   = null; // Gewichtung der Nachbarschaft pro LU-Typ
+//  private PropertyReadAccess      nbhSettings  = null; // Definition der Umgebung pro LU-Typ
+//  private PropertyReadAccess      nbhRegrRes   = null; // Regression Results fuer Nachbarschaft
+  private float[]                 nbhWeights   = null;
+  private float[][][]             nbhSettings  = null;
+  private float[][]               nbhRegrRes   = null;
+  // ---
+  private int                     nbhRadiusX   = 0;    // horizontaler Radius der betrachteten Nachbarschaft
+  private int                     nbhRadiusY   = 0;    // vertikaler Radius der betrachteten Nachbarschaft
+  private float[][]               luCover      = null; // LU-Bedeckung der Typen ueber die Zeit in Bedarfseinheit
+  private float                   totCover     = 0;    // Gesamte Landbedeckungsflaeche (ohne NoData!)
+  private Random                  rand         = null; // Zufallsgenerator
+  private float[]                 iterSpeed    = null; // Geschwindigkeit fuer die ITER-Variablen
+  // Ausgabe-Daten, die ueber den gesamten Modellablauf benoetigt werden
+  private WritableGrid            outActLU     = null; // speichert die aktuell sim. LU
+  private WritableGrid            outActLUHist = null; // speichert die aktuell sim. LU History
+  // ---
+  // Versuch der Performance-Steigerung (A):
+  //       Zugriff auf LUC-Probs- und NBH-Probs-Raster nicht ueber Property-Liste,
+  //       sondern ueber in lokalem Array hinterlegte Referenzen
+  // -> Steigerung der Iteration um 43%
+//  private MultiGrid               outLUProb    = null; // speichert die LU-Wahrscheinlichkeiten
+//  private MultiGrid               outNbhProb   = null; // speichert die Nachbarschafts-Wahrscheinlichkeiten
+  private WritableGrid[]            outLUProbGrid = null;
+  private WritableGrid[]            outNbhProbGrid = null;
+  //---
+  // Versuch der Performance-Steigerung (E):
+  //       Zugriff auf Iterations-Variablen ueber Property-Liste,
+  //       sondern ueber lokalen Array
+  // -> Steigerung der Iteration um 5,6%
+//  private ListPropertyWriteAccess outIter      = null; // speichert die Iterationsvariablen
+  private float[]                 outIter      = null;
+  // ---
+  private MultiGrid               outStepLU    = null; // speichert die LU fuer jeden Zeitpunkt
+
+//  // Versuch der Performance-Steigerung (B):
+//  //       LUC-Probs und NBH-Probs nicht in Raster-Objekten speichern,
+//  //       sondern komplett in lokalem Array
+//  // -> Steigerung der Iteration um 47%
+//  private float[][][]             outLUProb  = null;
+//  private float[][][]             outNbhProb = null;
+
+  /**
+   * Erzeugt eine neue Instanz des CLUE-Modells.
+   */
+  public ClueModel_Optimized() {
+    super( new ClueModelContentManager() );
+    contManager = (ClueModelContentManager)super.contManager;
+    // Iterations-Ereignisse der Event-Liste hinzufuegen
+    events.add(ModelIterationStepStartedEvent.class);
+    events.add(ModelIterationStepFinishedEvent.class);
+  }
+
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////   Implementierung von AbstractXuluModel   //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Initialisiert das Model, indem die Ressourcen aus dem ContentManager
+   * geladen werden und mit Lese/Schreib-Rechten versehen werden. Zudem
+   * werden Referenzen auf einen Teil der Ressourcen in lokalen Variablen
+   * gespeichert, um waehrend des Modellablaufs effizienter darauf zugreifen
+   * zu koennen.
+   */
+  public void performModelInit() {
+    if ( contManager == null )
+      return;
+    // Zugriffsrechte aus Ressourcen/Propertys holen
+    RA_baseLU       = contManager.getBaseScenario().getReadAccess(this);
+    RA_baseLUHist   = contManager.getLUHistory().getReadAccess(this);
+    RA_luConv       = contManager.getLUConversionMatrix().getReadAccess(this);
+    RA_luElas       = contManager.getConversionElasticity().getReadAccess(this);
+    RA_areaRestr    = contManager.getAreaRestrictions().getReadAccess(this);
+    RA_luDemand     = contManager.getDemandScenario().getReadAccess(this);
+    RA_sdfGrids     = ((ListProperty)contManager.getStaticDrivingForces().getProperty(MultiGrid.PROP_GRIDS)).getReadAccess(this);
+    if ( contManager.getDynamicDrivingForceTypes() != null ) {
+      RA_ddfList      = contManager.getDynamicDrivingForceTypes().getReadAccess(this);
+      RA_ddfGrids     = ((ListProperty)contManager.getDynamicDrivingForces().getProperty(MultiGrid.PROP_GRIDS)).getReadAccess(this);
+    } else {
+      RA_ddfList      = null;
+      RA_ddfGrids     = null;
+    }
+    RA_regrRes      = contManager.getRegressionResults().getReadAccess(this);
+    if ( contManager.getNeighborhoodWeights() != null ) {
+      RA_nbhWeights  = contManager.getNeighborhoodWeights().getReadAccess(this);
+      RA_nbhSettings = contManager.getNeighborhoodSettings().getReadAccess(this);
+      RA_nbhRegrRes  = contManager.getNeighborhoodRegression().getReadAccess(this);
+      WA_outNbhProb  = ((ListProperty)contManager.getNeighborhoodProbabilities().getProperty(MultiGrid.PROP_GRIDS)).getWriteAccess(this);
+    } else {
+      RA_nbhWeights  = null;
+      RA_nbhSettings = null;
+      RA_nbhRegrRes  = null;
+      WA_outNbhProb  = null;
+    }
+    WA_outActLU     = contManager.getActLUResult().getWriteAccess(this);
+    WA_outActLUHist = contManager.getActLUHistory().getWriteAccess(this);
+    WA_outLUProb    = ((ListProperty)contManager.getLUProbabilities().getProperty(MultiGrid.PROP_GRIDS)).getWriteAccess(this);
+    WA_outIter      = contManager.getIterationVariables().getWriteAccess(this);
+    WA_outStepLU    = ((ListProperty)contManager.getStepLUResults().getProperty(MultiGrid.PROP_GRIDS)).getWriteAccess(this);
+
+    // Variablen belegen mit denen gearbeitet wird
+    this.stepCount   = contManager.getStepCount().getOneTimeReadAccess().getValueAsInt(); // WICHTIG!!
+    this.dfCount     = contManager.getStaticDrivingForces().getGridCount();
+    this.demandTolType    = contManager.getDemandToleranceType().getOneTimeReadAccess().getValueAsInt();
+    this.demandTolSingle  = contManager.getSingleDemandTolerance().getOneTimeReadAccess().getValueAsFloat();
+    this.demandTolAverage = contManager.getAverageDemandTolerance().getOneTimeReadAccess().getValueAsFloat();
+    this.demandConv  = contManager.getConversionFactor().getOneTimeReadAccess().getValueAsFloat();
+    this.luCount     = contManager.getLUConversionMatrix().getSize(0);
+    this.baseLU      = (WritableGrid)RA_baseLU.getValue();
+    this.areaWidth   = baseLU.getWidth();
+    this.areaHeight  = baseLU.getHeight();
+    this.areaMinX    = baseLU.getMinX();
+    this.areaMinY    = baseLU.getMinY();
+    this.areaMaxX    = baseLU.getMinX() + areaWidth;
+    this.areaMaxY    = baseLU.getMinY() + areaHeight;
+    this.cellSize    = ((float)(baseLU.getCellWidth() * baseLU.getCellHeight())) / demandConv;
+    this.baseLUHist  = (WritableGrid)RA_baseLUHist.getValue();
+    // PERFORMANZ D: Elastizitaet in lokalem Array
+//    this.luElas      = (ListPropertyReadAccess)RA_luElas;
+    this.luElas      = new float[((ListPropertyReadAccess)RA_luElas).getCount()];
+    for (int i=0; i<luElas.length; i++)
+      this.luElas[i] = RA_luElas.getValueAsFloat(i);
+
+    this.areaRestr   = (WritableGrid)RA_areaRestr.getValue();
+    // PERFORMANZ F: Demand und Conversion-Matrix in lokalen Array
+//    this.luConv      = RA_luConv;
+//    this.luDemand    = RA_luDemand;
+    this.luConv      = new int[contManager.getLUConversionMatrix().getSize(0)][contManager.getLUConversionMatrix().getSize(1)];
+    for (int i=0; i<luConv.length; i++)
+      for (int j=0; j<luConv[i].length; j++)
+        luConv[i][j] = RA_luConv.getValueAsInt(i,j);
+    this.luDemand    = new float[contManager.getDemandScenario().getSize(0)][contManager.getDemandScenario().getSize(1)];
+    for (int i=0; i<luDemand.length; i++)
+      for (int j=0; j<luDemand[i].length; j++)
+        luDemand[i][j] = RA_luDemand.getValueAsFloat(i,j);
+
+    ListPropertyReadAccess ddfList     = (RA_ddfList != null) ? (ListPropertyReadAccess)RA_ddfList : null;
+    this.ddfCount    = (ddfList != null)    ? ddfList.getCount() : 0;
+    // PERFORMANZ C: Raster-Listen in lokale Arrays kopieren
+//    this.ddfGrids    = (ddfList != null)    ? contManager.getDynamicDrivingForces() : null;
+//    this.sdfGrids    = contManager.getStaticDrivingForces();
+    this.ddfGrids    = (ddfList != null)    ? new WritableGrid[contManager.getDynamicDrivingForces().getGridCount()] : null;
+    for (int i=0; i<ddfGrids.length; i++)
+      ddfGrids[i] = contManager.getDynamicDrivingForces().getGrid(i);
+    this.sdfGrids    = new WritableGrid[contManager.getStaticDrivingForces().getGridCount()];
+    for (int i=0; i<sdfGrids.length; i++)
+      sdfGrids[i] = contManager.getStaticDrivingForces().getGrid(i);
+
+    // PERFORMANZ G
+//    this.regrRes     = RA_regrRes;
+    this.regrRes = new float[contManager.getRegressionResults().getSize(0)][contManager.getRegressionResults().getSize(1)];
+    for (int i=0; i<regrRes.length; i++)
+      for (int j=0; j<regrRes[i].length; j++)
+        this.regrRes[i][j] = RA_regrRes.getValueAsFloat(i,j);
+    // PERFORMANZ H
+//    this.nbhWeights  = (RA_nbhWeights != null) ? (ListPropertyReadAccess)RA_nbhWeights : null;
+    this.nbhWeights  = (RA_nbhWeights != null) ? new float[((ListPropertyReadAccess)RA_nbhWeights).getCount()] : null;
+    for (int i=0; i<nbhWeights.length; i++)
+      this.nbhWeights[i] = RA_nbhWeights.getValueAsFloat(i);
+//    this.nbhSettings = (nbhWeights != null)    ? RA_nbhSettings : null;
+    this.nbhSettings = (nbhWeights != null)    ? new float[contManager.getNeighborhoodSettings().getSize(0)][contManager.getNeighborhoodSettings().getSize(1)][contManager.getNeighborhoodSettings().getSize(2)] : null;
+    for (int i=0; i<nbhSettings.length; i++)
+      for (int j=0; j<nbhSettings[i].length; j++)
+        for (int k=0; k<nbhSettings[i][j].length; k++)
+        this.nbhSettings[i][j][k] = RA_nbhSettings.getValueAsFloat(i,j,k);
+//    this.nbhRegrRes  = (nbhWeights != null)    ? RA_nbhRegrRes : null;
+    this.nbhRegrRes = (nbhWeights != null)    ? new float[contManager.getNeighborhoodRegression().getSize(0)][contManager.getNeighborhoodRegression().getSize(1)] : null;
+    for (int i=0; i<nbhRegrRes.length; i++)
+      for (int j=0; j<nbhRegrRes[i].length; j++)
+        this.nbhRegrRes[i][j] = RA_nbhRegrRes.getValueAsFloat(i,j);
+
+    this.nbhRadiusX  = (nbhWeights != null)    ? (contManager.getNeighborhoodSettings().getSize(0)-1)/2 : 0;
+    this.nbhRadiusY  = (nbhWeights != null)    ? (contManager.getNeighborhoodSettings().getSize(1)-1)/2 : 0;
+
+    MultiGrid outNbhProb  = (nbhWeights != null)    ? contManager.getNeighborhoodProbabilities() : null;
+    for (int i=0; outNbhProb!=null && outNbhProb.getGridCount()<luCount; i++)
+      outNbhProb.addGrid(); // Liste muss ein Raster fuer jeden LU-Typ enthalten
+    this.outActLU     = (WritableGrid)WA_outActLU.getValue();
+    this.outActLUHist = (WritableGrid)WA_outActLUHist.getValue();
+    MultiGrid outLUProb    = contManager.getLUProbabilities();
+    for (int i=0; outLUProb.getGridCount()<luCount; i++)
+      outLUProb.addGrid(); // Liste muss ein Raster fuer jeden LU-Typ enthalten
+
+    // PERFORMANZ A: Raster-Liste in lokale Arrays kopieren
+    this.outLUProbGrid  = new WritableGrid[luCount];
+    this.outNbhProbGrid = new WritableGrid[luCount];
+    for (int i=0; i<luCount; i++) {
+      outLUProbGrid[i]  = outLUProb.getGrid(i);
+      outNbhProbGrid[i] = outNbhProb.getGrid(i);
+    }
+//    // PERFORMANZ B
+//    this.outNbhProb = new float[luCount][areaWidth][areaHeight];
+//    this.outLUProb  = new float[luCount][areaWidth][areaHeight];
+
+    // PERFORMANZ E: Iterationsvariablen in lokalem Array
+//    this.outIter      = (ListPropertyWriteAccess)WA_outIter;
+//    // Lister der Iter-Variablen auf benoetigte Groesse auffuellen
+//    for (;outIter.getCount()<luCount;)
+//      outIter.addValue(0.0f);
+    this.outIter      = new float[luCount];
+
+    this.outStepLU    = contManager.getStepLUResults();
+
+    // Bei Toleranz-Art "prozentual" werden die Werte in Prozent
+    // angegeben (intern wird aber mit Abweichungen zwischen 0 und 1 gerechnet!)
+    if ( demandTolType == TOLTYPE_PCT ) {
+      this.demandTolSingle  /= 100.0f;
+      this.demandTolAverage /= 100.0f;
+    }
+
+    // Die Liste der dyn. DF ist blockweise nach DF grupperiert
+    // Es koennen mehr Zeitschritt-Raster angegeben werden, als simuliert
+    // werden.
+    // Im Array 'ddfStartIdx' wird fuer die dynamischen DF gespeichert, an
+    // welcher Stelle in der Liste der Block beginnt.
+    // -1 bedeutet, dass der DF ein statische DF ist!
+    this.ddfStartIdx = new int[dfCount];
+    for (int i=0; i<dfCount; i++)
+      ddfStartIdx[i] = - 1;
+    for (int i=0; i<ddfCount; i++)
+//      ddfStartIdx[i] = i*ddfGrids.getGridCount() / ddfCount; // PERFORMANZ C
+      ddfStartIdx[i] = i*ddfGrids.length / ddfCount;
+
+    // "Geschwindigkeit" fuer die Iterationsvariablen
+    this.iterSpeed = new float[luCount];
+
+    // Speichert die Flaechendeckung (in der Bedarfseinheit, z.B. ha)
+    // fuer die einzelnen LU-Typen zu jedem Zeitpunkt
+    // --> Die initialen Werte stehen in der 0-Zeile der Demand-Matrix
+    this.luCover   = new float[luCount][stepCount+1];
+    this.totCover = 0.0f;
+    statusOut.print("InitCover: ");
+    for (int lu=0; lu<luCount; lu++) {
+//      luCover[lu][0] = luDemand.getValueAsFloat(lu, 0); // ORIGINAL
+      luCover[lu][0] = luDemand[lu][0]; // PERFORMANZ F
+      totCover += luCover[lu][0]; // Gesamt-Flaeche des Untersuchungsgebiets
+      statusOut.print(luCover[lu][0]+"   ");
+    }
+    statusOut.println("   >> TotalCover "+totCover);
+
+    // Ausgabe-Raster leeren
+    for (int y=outActLU.getMinY(); y<outActLU.getMinY()+outActLU.getHeight(); y++)
+      for (int x=outActLU.getMinX(); x<outActLU.getMinX()+outActLU.getWidth(); x++)
+        outActLU.setRasterSample((float)Float.NaN,x,y);
+
+    LOG.info("========================================");
+    LOG.info("MODEL INITIALISED (Log-Level "+LOG.getLevel()+")");
+  }
+
+  /**
+   * Gibt die Lese/Schreibrechte auf das Ein- und Ausgaberaster wieder frei.
+   * Interne Ressourcen brauchen keine aus dem Speicher entfernt werden.
+   */
+  public void performModelDispose() {
+    // Ressourcen wieder freigeben
+    releaseAccess(RA_baseLU);
+    releaseAccess(RA_baseLUHist);
+    releaseAccess(RA_luConv);
+    releaseAccess(RA_luElas);
+    releaseAccess(RA_areaRestr);
+    releaseAccess(RA_luDemand);
+    releaseAccess(RA_sdfGrids);
+    releaseAccess(RA_ddfList);
+    releaseAccess(RA_ddfGrids);
+    releaseAccess(RA_regrRes);
+    releaseAccess(RA_nbhWeights);
+    releaseAccess(RA_nbhSettings);
+    releaseAccess(RA_nbhRegrRes);
+    releaseAccess(WA_outActLU);
+    releaseAccess(WA_outActLUHist);
+    releaseAccess(WA_outLUProb);
+    releaseAccess(WA_outNbhProb);
+    releaseAccess(WA_outIter);
+    releaseAccess(WA_outStepLU);
+    LOG.info("MODEL DISPOSED");
+    LOG.info("========================================");
+  }
+
+  /**
+   * Fuehrt einen Schritt des Modellablaufs durch.
+   * @param stepNo zu modellierender Schritt (beginnend bei 1!)
+   */
+  public void performModelStep(int stepNo) {
+    LOG.debug("Step "+stepNo+" started");
+    statusOut.println("Started step ".concat(String.valueOf(stepNo)));
+
+    // Raster festlegen, in dem die LU des vorangegangenen
+    // Schritts zu finden ist
+    WritableGrid lastLUGrid = (stepNo==1) ? baseLU : outStepLU.getGrid(stepNo-2);
+    // Raster festlegen, in dem die aktuelle LU History
+    // zu finden ist
+    WritableGrid luHistGrid = (stepNo==1) ? baseLUHist : outActLUHist;
+
+    // Merken, ob an einer Stelle bereits eine U-Zelle in einen anderen
+    // Typ gewechselt hat
+    boolean[] alreadyLUCCFromType = new boolean[luCount];
+    // Merken, ob an einer Stelle bereits eine U-Zelle neu entstanden ist
+    boolean[] alreadyLUCCToType = new boolean[luCount];
+
+    // LU-Wahrscheinlichkeiten berechnen
+    calculateLUProbabilities(stepNo);
+
+    // Nachbarschafts-Wahrscheinlichkeiten berechnen
+    calulateNeighborhoodProbabilities(stepNo,lastLUGrid);
+
+    // Randomizer fuer diesen Zeitschritt erzeugen
+    rand = new Random(System.currentTimeMillis());
+
+    int   iterNo     = 0;
+    int   x          = 0;
+    int   y          = 0;
+    int   lu         = 0;
+    int   lastLU     = 0;
+    int   bestLU     = 0;
+    float bestLUProb = 0.0f;
+    float baseProb   = 0.0f;
+    float nbhProb    = 0.0f;
+    float nbhWeight  = 0.0f;
+    float elas       = 0.0f;
+    float totalProb  = 0.0f;
+    Float lastLUC    = null;
+    Float actLUC     = null;
+
+    for (iterNo=1; !checkDemandCompliedAndCalculateIterVar(stepNo,iterNo); iterNo++) {
+      LOG.debug("Iter "+iterNo+" started");
+      this.fireModelEvent( new ModelIterationStepStartedEvent(this,stepNo,iterNo) );
+      // Arrays fuer Iterationsschritt initialisieren
+      for (lu = 0; lu < luCount; lu++) {
+        // noch kein Wechsel von einem LU-Typ
+        alreadyLUCCFromType[lu] = false;
+        // noch kein Wechsel zu einem LU-Typ
+        alreadyLUCCToType[lu] = false;
+        // Flaechen der LU-Typen fuer diesen Zeitschritt
+        luCover[lu][stepNo] = 0.0f;
+        // Speed fuer die Iterationsvariablen initialisieren
+        // --> liegt die Nachfrage bei weniger als 5% des U'gebiets
+        //     wird langsamer begonnen
+//        if ( luDemand.getValueAsFloat(lu,stepNo)/totCover < 0.05f ) // ORIGINAL
+        if ( luDemand[lu][stepNo]/totCover < 0.05f ) // PERFORMANZ F
+          iterSpeed[lu] = 0.01f;
+        else
+          iterSpeed[lu] = 0.05f;
+      }
+
+      // Fuer alle Zellen des Untersuchungsgebiets
+      for (y = areaMinY; y < areaMaxY; y++)
+        for (x = areaMinX; x < areaMaxX; x++) {
+          checkBreakingCommands();
+
+          // Rasterzellen ausserhalb des Untersuchungsgebiets komplett
+          // ignorieren
+          // Grund: NoData-Zellen (Float.NaN) werden beim Cast in int zu 0,
+          //        also zur Landnutzung 0!!
+          if ( checkNoData(x,y,baseLU) )
+            continue;
+
+          // Nutzungsdauern erhoehen
+          if (iterNo==1)
+            outActLUHist.setRasterSample(luHistGrid.getRasterSampleAsFloat(x, y) + 1, x, y);
+
+          // vorangegangene LU merken
+          lastLU = lastLUGrid.getRasterSampleAsInt(x, y);
+
+          // Beste gefundene LU wird mit aktueller LU initialisiert
+          bestLU = lastLU;
+          bestLUProb = 0.0f;
+
+          // Pruefen, ob Zelle die LU wechseln darf
+          if (checkLUCCGeneralAllowed(x, y, stepNo, lastLU, alreadyLUCCToType[lastLU])) {
+            // Alle LU-Typen auf Wechsel pruefen
+            for (lu = 0; lu < luCount; lu++) {
+              // Pruefen, ob Zelle in den betrachteten Typ wechseln darf
+              if (checkLUCCAllowed(x, y, stepNo, lastLU, lu, alreadyLUCCFromType[lu])) {
+                // Gesamt-Wahrscheinlichkeit berechnen
+                // a) DF-W'keit und Nachbarschaft-W'keit gehen anteilig ein
+                // b) Elastizitaet geht nur ein, wenn Zelle bereits fuer den
+                //    LU-Typ genutzt wird
+                // c) ITER geht negativ ein, da es auf Basis der Abweichung
+                //    luCover-luDemand berechnet wird. Ein negatives Iter
+                //    kennzeichnet also einen Mangel und muss die Gesamtw'keit
+                //    erhoehen
+//                baseProb  = outLUProb.getGrid(lu).getRasterSampleAsFloat(x, y); // ORIGINAL-VERSION
+//                nbhProb   = (nbhWeights == null) ? 0.0f : outNbhProb.getGrid(lu).getRasterSampleAsFloat(x, y); // ORIGINAL-VERSION
+                baseProb  = outLUProbGrid[lu].getRasterSampleAsFloat(x, y); // PERFORMANZ A
+                nbhProb   = (nbhWeights == null) ? 0.0f : outNbhProbGrid[lu].getRasterSampleAsFloat(x, y); // PERFORMANZ A
+//                baseProb  = outLUProb[lu][x][y]; // PERFORMANZ B
+//                nbhProb   = (nbhWeights == null) ? 0.0f : outNbhProb[lu][x][y]; // PERFORMANZ B
+//                nbhWeight = (nbhWeights == null) ? 0.0f : nbhWeights.getValueAsInt(lu); // ORIGINAL
+                nbhWeight = (nbhWeights == null) ? 0.0f : nbhWeights[lu]; // PERFORMANZ H
+//                elas      = (lu == lastLU && luElas.getValueAsFloat(lu) < 1) ? luElas.getValueAsFloat(lu) : 0.0f; // ORIGINAL-VERSION
+                elas      = (lu == lastLU && luElas[lu] < 1) ? luElas[lu] : 0.0f; // PERFORMANZ D
+                // LU-Wahrscheinlichkeit zusammensetzen
+                totalProb = baseProb * (1-nbhWeight)
+                          + nbhProb  * nbhWeight
+                          + elas
+//                          - outIter.getValueAsFloat(lu); // ORIGINAL-VERSION
+                          - outIter[lu]; // PERFORMANZ E
+
+                // betrachteter Typ ist geeigneter als der bisher beste
+                if (totalProb > bestLUProb) {
+                  bestLU = lu;
+                  bestLUProb = totalProb;
+                }
+              }
+            }
+            // Merken wenn wirklich ein Wechsel stattfindet
+            if (bestLU != lastLU) {
+              alreadyLUCCFromType[lastLU] = true;
+              alreadyLUCCToType[bestLU] = true;
+            }
+          }
+
+          // LU fuer diesen Iterationschritt setzen
+          outActLU.setRasterSample((float)bestLU, x, y);
+          // Flaechendeckung fuer LU-Typ erhoehen
+          luCover[bestLU][stepNo] += cellSize;
+        }
+      this.fireModelEvent( new ModelIterationStepFinishedEvent(this,stepNo,iterNo) );
+      LOG.debug("Iter "+iterNo+" finished");
+    }
+
+    // Liste der Zeitschritt-Ausgaberaster vergroessern
+    outStepLU.addGrid();
+
+    // LU in Ausgaberaster des Zeitschritts uebernehmen und ggf.
+    // Nutzungsdauer initialisieren
+    for (y=areaMinY; y<areaMaxY; y++)
+      for (x=areaMinX; x<areaMaxX; x++) {
+        checkBreakingCommands();
+        lastLUC = (Float)lastLUGrid.getRasterSample(x,y);
+        actLUC  = (Float)outActLU.getRasterSample(x,y);
+        // Wenn die Landnutzung gewechselt hat, wird die Historie zurueck
+        // gesetzt
+        if ( !actLUC.equals(lastLU) )
+          outActLUHist.setRasterSample((float)0,x,y);
+
+        // LU in Ausgabe-Raster des simulierten Schritts uebernehmen
+        outStepLU.getGrid(stepNo-1).setRasterSample(actLUC,x,y);
+      }
+    statusOut.println("Ended step ".concat(String.valueOf(stepNo)));
+    LOG.debug("Step "+stepNo+" finished");
+  }
+
+  //////////////////////////////////////////////////////////////////////
+  ////////////////////////   Clue-Methoden   ///////////////////////////
+  //////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob eine Rasterzelle mit <code>NoData</code> belegt ist
+   * @param x     Raster-Koordinate
+   * @param y     Raster-Koordinate
+   * @param grid  zu pruefendes Raster
+   */
+  protected static boolean checkNoData(int x, int y, WritableGrid grid) {
+    return Float.isNaN(grid.getRasterSampleAsFloat(x,y));
+  }
+
+  /**
+   * Berechnet die auf den Driving Forces basierenden
+   * Landnutzungs-Wahrscheinlichkeiten fuer einen Modell-Schritt und speichert
+   * diese in der Ressource "temp. Ausgaberaster fuer die LU-Wahrscheinlichkeiten".<br>
+   * Werden keine dynamischen Driving Forces verwendet, geschieht die Berechnung
+   * nur beim ersten Modellierungsschritt.
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   */
+  protected void calculateLUProbabilities(int stepNo) {
+    LOG.debug("LUC-Prop-Calc. started");
+    // Wenn keine dynamischen Driving Forces verwendet werden
+    // braucht die Berechnung nur fuer den ersten Schritt
+    // durchgefuehrt werden
+    if ( ddfCount == 0 && stepNo > 1 )
+      return;
+
+    statusOut.print("Calculate LU-Probabilities for step "+stepNo+"...");
+    int x            = 0;
+    int y            = 0;
+    int lu           = 0;
+    int df           = 0;
+    float betaSum    = 0.0f;
+    float expBetaSum = 0.0f;
+    float prob       = 0.0f;
+    // Fuer Zellen des Untersuchungsgebiets
+    for (y=areaMinY; y<areaMaxY; y++)
+      for (x=areaMinX; x<areaMaxX; x++)
+        // NotData-Bereich und Area Restrictions ignorieren
+        if ( !checkNoData(x,y,baseLU) && areaRestr.getRasterSampleAsFloat(x,y)==0 ) {
+          // Fuer alle LU-Typen
+          for (lu = 0; lu < luCount; lu++) {
+            betaSum = 0.0f;
+            // Fuer alle Driving Forces die Summe der Betas berechnen
+            for (df = 0; df < dfCount; df++) {
+              checkBreakingCommands();
+              // DF-Grid festlegen:
+              // Bei dynamischem DF das jew. Zeitschritt-Raster aus der Liste
+              // ansonsten das statische Raster
+              WritableGrid dfGrid = null;
+              if ( ddfStartIdx[df] >= 0 )
+//                dfGrid = this.ddfGrids.getGrid(ddfStartIdx[df]+stepNo-1); // ORIGINAL
+                  dfGrid = this.ddfGrids[ddfStartIdx[df]+stepNo-1]; // PERFORMANZ C
+              else
+//                dfGrid = this.sdfGrids.getGrid(df); // ORIGINAL
+                 dfGrid = this.sdfGrids[df]; // PERFORMANZ C
+              // Beim ersten Driving Force wird die Summe mit der
+              // Regressionskonstante initialisiert
+              if (df == 0)
+//                betaSum = regrRes.getValueAsFloat(0, lu); // ORIGINAL
+                betaSum = regrRes[0][lu]; // PERFORMANZ G
+              // betaSum = BETA0(U) + Sum( BETA(df+1,U) * DF(df,x,y) )
+//              betaSum += regrRes.getValueAsFloat(df + 1, lu) // ORIGINAL
+              betaSum += regrRes[df + 1][lu] // PERFORMANZ G
+                        * dfGrid.getRasterSampleAsFloat(x, y);
+            }
+            expBetaSum = (float)Math.exp(betaSum);
+            prob = expBetaSum / (1 + expBetaSum);
+            // errechnete W'keit im Raster speichern
+//            this.outLUProb.getGrid(lu).setRasterSample(prob, x, y); // ORIGINAL
+            this.outLUProbGrid[lu].setRasterSample(prob, x, y); // PERFORMANZ A
+//            this.outLUProb[lu][x][y] = prob; // PERFORMANZ B
+          }
+        }
+    statusOut.println(" done.");
+    LOG.debug("LUC-Prop-Calc. finished");
+  }
+
+  /**
+   * Berechnet die auf den Nachbarschaftsbeziehungen basierenden
+   * Landnutzungs-Wahrscheinlichkeiten fuer einen Modell-Schritt und speichert
+   * diese in der Ressource "temp. Ausgaberaster fuer die Nachbarschafts-Wahrscheinlichkeiten".<br>
+   * Da sich die Landnutzung mit jedem Zeitschritt aendert geschieht dies
+   * vor jedem Zeitschritt neu.<br>
+   * Diese Methode macht nichts, wenn ohne Nachbarschafts-W'keiten simuliert wird,
+   * also wenn keine Angabe fuer die "Neighborhood-Weights" gemacht wird.
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   * @param luGrid LU-Raster aus dem die Umgebung der jeweiligen Zellen
+   *               ermittelt werden
+   */
+  protected void calulateNeighborhoodProbabilities(int stepNo, WritableGrid luGrid) {
+    LOG.debug("NBH-Prop-Calc. started");
+    // Wenn ohne Nachbarschaftsbeziehungen simuliert wird
+    if ( nbhWeights == null )
+      return;
+
+    statusOut.print("Calculate Neighborhood-Probabilities for step "+stepNo+"...");
+
+    int      x            = 0;
+    int      y            = 0;
+    int      lu           = 0;
+    int      i            = 0;
+    int      dx           = 0;
+    int      dy           = 0;
+    int      totCellCount = 0;
+    float[]  luCellCount  = new float[luCount];
+    float    betaSum      = 0.0f;
+    float    beta         = 0.0f;
+    float    nbhFact      = 0.0f;
+    float    expBetaSum   = 0.0f;
+
+    // Fuer Zellen des Untersuchungsgebiets
+    for (y=areaMinY; y<areaMaxY; y++)
+      for (x=areaMinX; x<areaMaxX; x++)
+        // NoData-Bereich und Area Restrictions ignorieren
+        if ( !checkNoData(x,y,baseLU) && areaRestr.getRasterSampleAsFloat(x,y)==0 )
+          // Fuer alle LU-Typen
+          for (lu = 0; lu < luCount; lu++) {
+            checkBreakingCommands();
+
+            // Anzahl der Zellen in der Umgebung initialisieren
+            totCellCount = 0;
+            for (i=0; i<luCount; i++)
+              luCellCount[i] = 0.0f;
+
+            // Umgebung der Zelle betrachten
+            for (dy=-nbhRadiusY; dy<=nbhRadiusY; dy++)
+              if ( areaMinY <= y+dy && y+dy<areaMaxY )
+                for (dx=-nbhRadiusX; dx<=nbhRadiusX; dx++)
+                  if ( areaMinX <= x+dx && x+dx<areaMaxX ) {
+                    float luc = luGrid.getRasterSampleAsFloat(x+dx,y+dy);
+                    if ( !Float.isNaN(luc) /*!checkNoData(x+dx,y+dy,baseLU)*/ ) {
+                        // Alle Zellen in Umgebung zaehlen (jedoch nur diejenigen,
+                        // die potentiell auch in die Bewertung eingehen koennen!)
+//                        if ( nbhSettings.getValueAsFloat(dx+nbhRadiusX,dy+nbhRadiusY,lu) != 0.0f ) // ORIGINAL
+                        float setting = nbhSettings[dx+nbhRadiusX][dy+nbhRadiusY][lu];
+                        if ( setting != 0.0f ) { // PERFORMANZ H
+                          totCellCount++;
+                          // Anzahl der Zellen eines bestimmten Typs aufsummieren
+                          // (relativ zum in der Umgebung angegebenen Faktor)
+//                          luCellCount[ luGrid.getRasterSampleAsInt(x+dx,y+dy) ] += nbhSettings.getValueAsFloat(dx+nbhRadiusX,dy+nbhRadiusY,lu); // ORIGINAL
+//                          luCellCount[ luGrid.getRasterSampleAsInt(x+dx,y+dy) ] += setting ; // PERFORMANZ H
+                          luCellCount[ (int)luc ] += setting ; // PERFORMANZ H
+                        }
+                      }
+                    }
+              // Summe der Betas berechnen
+//              betaSum = nbhRegrRes.getValueAsFloat(0,lu); // Regr.Konstante // ORIGINAL
+              betaSum = nbhRegrRes[0][lu]; // Regr.Konstante // PERFORMANZ H
+              for (i=0; i<luCount; i++) {
+//                beta    = nbhRegrRes.getValueAsFloat(i + 1, lu); // ORIGINAL
+                beta    = nbhRegrRes[i + 1][lu]; // PERFORMANZ H
+                nbhFact = (luCellCount[i]/totCellCount) / (luCover[i][stepNo-1]/totCover);
+                betaSum += beta * nbhFact;
+              }
+              // Wahrscheinlichkeit berechnen
+              expBetaSum = (float)Math.exp(betaSum);
+//              outNbhProb.getGrid(lu).setRasterSample((float)(expBetaSum/(1 + expBetaSum)),x,y); // ORIGINAL
+              outNbhProbGrid[lu].setRasterSample((float)(expBetaSum/(1 + expBetaSum)),x,y); // PERFORMANZ A
+//              this.outNbhProb[lu][x][y] = (float)(expBetaSum/(1 + expBetaSum)); // PERFORMANZ B
+          }
+    statusOut.println(" done.");
+    LOG.debug("NBH-Prop-Calc. finished");
+  }
+
+
+  /**
+   * Prueft, ob ein genereller LU-Wechsel fuer eine Zelle erlaubt ist.
+   * <ul>
+   * <li>Schliessen die Area Restrictions einen Wechsel aus?<br>
+   *     > Rasterwert(x,y) != 0
+   *     </li>
+   * <li>Schliesst die Conversion Elasticity einen Wechsel aus (Elastizitaet 1
+   *     und steigende Bedarf)?<br>
+   *     > ELAS(lastLU) == 1 und DEMAND(lastLU,t) >= DEMAND(lastLU,t-1)
+   *     </li>
+   * </ul>
+   * @param x      Raster-Koordinate
+   * @param y      Raster-Koordinate
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   * @param lastLU Bedeckung von (x,y) zum Zeitpunkt stepNo-1
+   * @param alreadyLUCCToActualType Flag gibt an, ob in der laufenden Iteration
+   *                                bereits ein LU-Wechsel in den den aktuellen
+   *                                Typ der Zelle (lastLU) vorgenommen wurde.<br>
+   *                                <b>Dieses Flag wird zur Zeit nicht verwendet!</b>
+   */
+  protected boolean checkLUCCGeneralAllowed(int x, int y, int stepNo, int lastLU, boolean alreadyLUCCToActualType) {
+    // Area Restrictions checken
+    if ( areaRestr.getRasterSampleAsFloat(x,y) != 0 )
+      return false;
+// DER ERSTE TEIL IST KEINE ORIGINAL-CLUE-REGEL!
+//    // Conversion Elasticity checken
+//    // --> wenn Elasticity 1 und bereits an anderer Stelle eine Zelle des
+//    //     bisherigen Typs entstanden ist, darf sie nicht wechseln
+//    // --> wenn Elasticity 1 und Bedarf steigt, darf kein Wechsel
+//    //     stattfinden, denn dann muessten (um den Bedarf zu decken)
+//    //     an anderer Stelle neue entstehen
+//    if (  luElas.getValueAsFloat(lastLU) == 1.0f
+//       && ( alreadyLUCCToActualType ||
+//           luDemand.getValueAsFloat(lastLU,stepNo) >= luCover[lastLU][stepNo-1] ) )
+//      return false;
+
+    // Conversion Elasticity checken
+    // --> wenn Elasticity 1 und Bedarf steigt, darf kein Wechsel
+    //     stattfinden, denn dann muessten (um den Bedarf zu decken)
+    //     an anderer Stelle neue entstehen
+//    if (  luElas.getValueAsFloat(lastLU) == 1.0f && // PERFORMANZ D
+    if (  luElas[lastLU] == 1.0f &&
+//          luDemand.getValueAsFloat(lastLU,stepNo) >= luCover[lastLU][stepNo-1] ) // ALT
+//          luDemand.getValueAsFloat(lastLU,stepNo) >= luDemand.getValueAsFloat(lastLU,stepNo-1) ) // ORIGINAL
+          luDemand[lastLU][stepNo] >= luDemand[lastLU][stepNo-1] ) // PERFORMANZ F
+      return false;
+
+    return true;
+  }
+
+  /**
+   * Prueft, ob ein bestimmter LU-Wechsel fuer eine Zelle erlaubt ist.
+   * <ul>
+   * <li>Schliesst die Conversion Elasticity einen Wechsel aus (Elastizitaet des
+   *     potentiellen Wechseltyps 1 und sinkender Bedarf)?<br>
+   *     > lastLU != newLU und ELAS(newLU) == 1 und DEMAND(newLU,t) <= DEMAND(newLU,t-1)
+   *     </li>
+   * <li>Schliesst die Conversion Matrix einen Wechsel aus (generell oder ueber
+   *     Historie)?<br>
+   *     > CONV(lastLU,newLU) == 0 oder<br>
+   *     > CONV(lastLU,newLU) > 100 und HIST(x,y) < CONV(lastLU,newLU)-101 oder<br>
+   *     > CONV(lastLU,newLU) < -100 und HIST(x,y) > -CONV(lastLU,newLU)-101
+   *     </li>
+   * </ul>
+   * @param x      Raster-Koordinate
+   * @param y      Raster-Koordinate
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   * @param lastLU Bedeckung von (x,y) zum Zeitpunkt stepNo-1
+   * @param newLU  potentielle neue Bedeckung von (x,y)
+   * @param alreadyLUCCFromNewType  Flag gibt an, ob in der laufenden Iteration
+   *                                bereits ein LU-Wechsel vom potentiellen neuen
+   *                                Typ in einen anderen Typ vorgenommen wurde.<br>
+   *                                <b>Dieses Flag wird zur Zeit nicht verwendet!</b>
+   */
+  protected boolean checkLUCCAllowed(int x, int y, int stepNo, int lastLU, int newLU, boolean alreadyLUCCFromNewType) {
+// IST KEINE ORIGINAL-CLUE-REGEL!
+//    // LU-Conversion-Elasticity des neuen Typs checken
+//    // --> wenn Elasticity des neuen Typs 1 ist und an anderer Stelle bereits
+//    //     eine Zelle des dieses Typs "verloren" ging, darf er hier
+//    //     nicht entstehen
+//    if (  alreadyLUCCFromNewType && luElas.getValueAsFloat(newLU) == 1.0f )
+//      return false;
+
+    // Conversion Elasticity checken
+    // --> wenn Elasticity des neuen Typs "newLU" 1 und dessen Bedarf sinkt,
+    //     darf kein Wechsel in diesen Typ stattfinden, denn dann muessten (um
+    //     den Bedarf fuer "newLU" zu erreichen) an anderer Stelle newLU-Zellen
+    //     entfernt werden
+    if (  lastLU != newLU &&
+//          luElas.getValueAsFloat(newLU) == 1.0f && // ORIGINAL
+          luElas[newLU] == 1.0f && // PERFORMANZ D
+//          luDemand.getValueAsFloat(newLU,stepNo) <= luCover[newLU][stepNo-1] ) // ORIGINAL
+          luDemand[newLU][stepNo] <= luCover[newLU][stepNo-1] ) // PERFORMANZ F
+//          luDemand.getValueAsFloat(newLU,stepNo) <= luDemand.getValueAsFloat(newLU,stepNo-1) )
+      return false;
+
+    // Wert aus LU-Conversion-Matrix ermitteln
+    // Bemerke: "von" steht in den Zeilen (also Y, also Dim1)
+    //          "nach" steht in den Spalten (also X, also Dim2)
+//    int conv = luConv.getValueAsInt(newLU,lastLU); // ORIGINAL
+    int conv = luConv[newLU][lastLU]; // PERFORMANZ F
+    // 1 --> LUCC generell erlaubt
+    if ( conv == 1 )
+      return true;
+    // 0 --> LUCC generell verboten
+    if ( conv == 0 )
+      return false;
+
+    // 100+t --> Wechsel erst nach t Schritten der vorangegangenen
+    //           LU moeglich
+    if ( conv > 100 ) {
+//      int minLUHist = conv-100;
+//      int luHist    = outActLUHist.getRasterSampleAsInt(x,y);
+//      return luHist >= minLUHist;
+      int minLUHist = conv-101;
+      int luHist    = outActLUHist.getRasterSampleAsInt(x,y);
+      return luHist >= minLUHist;
+    }
+
+    // -100-t --> Wechsel nicht mehr moeglich, wenn Zelle bereits
+    //            t Schritte unter der vorangegangenen LU
+    if ( conv < -100 ) {
+//      int maxLUHist = -conv-100;
+//      int luHist    = outActLUHist.getRasterSampleAsInt(x,y);
+//      return luHist < maxLUHist;
+      int maxLUHist = -conv-101;
+      int luHist    = outActLUHist.getRasterSampleAsInt(x,y);
+      return luHist <= maxLUHist;
+    }
+
+    return true;
+  }
+
+  private float[] singleDevAbs = null;
+  private float[] singleDevPct = null;
+  /**
+   * Prueft, ob die aktuelle LU-Konfiguration die einzelenen Bedarfsanforderungen
+   * (bis auf eine Abweichung) erfuellt und berechnet die Iterationsvariablen
+   * neu.
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   * @param iterNo aktuelle Iteration (beginnend bei 1)
+   */
+  protected boolean checkDemandCompliedAndCalculateIterVar(int stepNo, int iterNo) {
+    LOG.debug("started\tIter-Recalc");
+    if ( singleDevAbs == null ) {
+      singleDevAbs = new float[luCount];
+      singleDevPct = new float[luCount];
+    }
+    boolean demandComplied = true;
+    // Abweichnungen berechnen
+    float   averageDevAbs = 0.0f;
+    float   averageDevPct = 0.0f;
+    float   totalDevAbs = 0.0f;
+    float   totalDevPct = 0.0f;
+    float   demand      = 0.0f;
+    float   singleDev   = 0.0f;
+    for (int lu = 0; lu < luCount; lu++) {
+      // ##### Einzelabweichungen #####
+      // Absolute Abweichung der Landbedeckung vom Bedarf berechnen
+//      demand = luDemand.getValueAsFloat(lu, stepNo); // ORIGINAL
+      demand = luDemand[lu][stepNo]; // PERFORMANZ F
+      singleDevAbs[lu]  = luCover[lu][stepNo] - demand;
+      // Prozentuale Einzel-Abweichnung relativ zum Bedarf
+      if (demand == 0)
+        // ist der Bedarf 0, aber auch die Bedeckung, ist die Abw. 0%
+        singleDevPct[lu] = luCover[lu][stepNo] == 0.0f ? 0.0f : 1.0f;
+      else
+        singleDevPct[lu] = singleDevAbs[lu] / demand;
+
+      // Abweichung ueber erlaubter Toleranz?
+      singleDev = (demandTolType == TOLTYPE_PCT) ? singleDevPct[lu] : singleDevAbs[lu];
+      if (Math.abs(singleDev) > demandTolSingle)
+        demandComplied = false;
+
+      // ##### Gesamtabweichungen aufsummieren #####
+      totalDevAbs += Math.abs(singleDevAbs[lu]);
+    }
+
+    // Prozentuale Gesamt-Abweichnung relativ zum Gesamt-Untersuchungsgebiet
+    totalDevPct = totalDevAbs / totCover;
+
+    // Durchschnittliche Abweichnung pro LU-Typ
+    averageDevAbs = totalDevAbs / luCount;
+
+    // Durchschnittliche Abweichnung pro LU-Typ relativ zum Gesamt-Untersuchungsgebiet
+    averageDevPct = averageDevAbs / totCover;
+
+    // Abweichung ueber erlaubter Toleranz?
+    float avgDev = (demandTolType == TOLTYPE_PCT) ? averageDevPct : averageDevAbs;
+    if ( Math.abs(avgDev) > demandTolAverage )
+      demandComplied = false;
+
+    // Iterationsvariablen neu berechnen
+    for (int lu = 0; lu < luCount; lu++) {
+      // Um Alternieren zwischen 2 Konfiguration zu verhindern
+      // eine kleine Zufallszahl hinzuaddieren (zwischen -0,005 und 0,005)
+      float randomValue = (rand.nextFloat()-0.5f)/100;
+
+      // --> Im ersten Schritt erhalten alle Iterationsvariablen den Wert 0,5
+//      float iter = outIter.getValueAsFloat(lu); // ORIGINAL-VERSION
+      float iter = outIter[lu]; // PERFORMANZ E
+      if (iterNo == 1)
+//        outIter.setValue(0.5f+randomValue, lu); // ORIGINAL-VERSION
+        iter = 0.5f+randomValue; // PERFORMANZ E
+//        iter = 0.5 + new float[] {0.002f,0,0.002f,0,0,-0.003f}[lu];
+//        iter = 0.5 + new float[] {0.002f,0,0.001f,0,0,-0.002f}[lu];
+      else {
+//        // Anteil der Einzelabweichnung an der Gesamtabweichnung
+////        float dev = (totalDevAbs!=0) ? singleDevAbs[lu] / totalDevAbs : 0.0f;
+//        float dev  = singleDevPct[lu];
+//        iter = outIter.getValueAsDouble(lu) // alter Iter-Wert
+//             + dev // Anteil der Abweichung zum Bedarf
+//             + randomValue;
+        /////////////////////////////////////////
+        // Original-Iter-Berechnung aus CLUE
+        iterSpeed[lu] += 0.00005f;
+        iter += (singleDevAbs[lu]/totCover)/(iterSpeed[lu]*(rand.nextInt(101)+1));
+
+        if (iter > 2)
+          iter = 0.5f;
+        if ( Math.abs(iter) < 0.001f )
+          iter = 0.01f * Math.signum(iter);
+        if (iter < -0.5f)
+          iter = -0.4f;
+        /////////////////////////////////////////
+      }
+      // Iter speichern
+//      outIter.setValue(iter, lu); // ORIGINAL-VERSION
+      outIter[lu] = iter; // PERFORMANZ E
+    }
+
+
+//    StringBuffer buffer = new StringBuffer();
+//    for (float v : outIter)
+//      buffer.append(v).append(" ");
+//    LOG.debug("finished\tIter-Recalc "+stepNo+"/"+iterNo+"   "+buffer.toString());
+    LOG.debug("finished\tIter-Recalc");
+    return demandComplied;
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/clue/ClueModel_Original.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/clue/ClueModel_Original.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/model/clue/ClueModel_Original.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,1525 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.model.clue;
+
+import java.awt.image.DataBuffer;
+import java.awt.Window;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.geom.AffineTransform;
+import javax.swing.BoxLayout;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JProgressBar;
+import javax.swing.BoundedRangeModel;
+import javax.swing.DefaultBoundedRangeModel;
+import javax.swing.JSlider;
+import javax.swing.SpringLayout;
+import javax.swing.BorderFactory;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.ChangeEvent;
+import java.util.Random;
+import java.text.NumberFormat;
+import java.text.DecimalFormat;
+
+import schmitzm.lang.LangUtil;
+
+import schmitzm.data.property.Access;
+import schmitzm.data.property.ValueProperty;
+import schmitzm.data.property.ValuePropertyType;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.ListPropertyReadAccess;
+import schmitzm.data.property.ListPropertyWriteAccess;
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.MatrixProperty;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.PropertyWriteAccess;
+import schmitzm.data.WritableGrid;
+
+import schmitzm.swing.SwingUtil;
+import schmitzm.swing.SpringUtilities;
+import schmitzm.swing.ExpansionBar;
+
+import edu.bonn.xulu.data.XuluDataException;
+import edu.bonn.xulu.model.AbstractStepModel;
+import edu.bonn.xulu.model.ModelContentManager;
+import edu.bonn.xulu.model.AbstractModelContentManager;
+import edu.bonn.xulu.model.ModelResource;
+import edu.bonn.xulu.model.AbstractModelResource;
+import edu.bonn.xulu.model.ValuePropertyResource;
+import edu.bonn.xulu.model.event.ModelIterationStepStartedEvent;
+import edu.bonn.xulu.model.event.ModelIterationStepFinishedEvent;
+
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+
+import schmitzm.temp.BaseTypeUtil;
+
+/**
+ * <b>BEI DIESER KLASSE HANDELT ES SICH UM DIE URSPRUENGLICHE XULU-IMPLEMENTIERUG
+ *    DES CLUE-MODELLS. DARIN KOMMEN NOCH KEINERLEI LAUFZEIT-OPTIMIERENDE TECHNIKEN
+ *    ZUM EINSATZ. FUER REALE MODELL-LAEUFE - INSBESONDERE AUF GROSSEN UNTERSUCHUNGSGEBIETEN -
+ *    WIRD EMPFOHLEN, DIE UM ETWA EINEN FAKTOR 10 SCHNELLERE IMPLEMENTIERUNG
+ *    {@link ClueModel} zu verwenden.</b>
+ * <br><br>
+ * Diese Klasse stellt eine Implementierung des
+ * <a href="http://www.dow.wau.nl/clue/" target="_blank">CLUE</a>-Modells dar
+ * (CLUE = The <b>C</b>onversion of <b>L</b>and <b>U</b>se and its <b>E</b>ffects).
+ * Dieses arbeitet mit Rasterdaten und berechnet die zeitliche
+ * Landnutzungsveraenderung (LUCC) in einem Untersuchungsgebiet iterativ auf
+ * Basis von statistischen Eingabeparametern und vorgegebenen Landnutzungsbedarfen.<br>
+ * Das CLUE-Modell benoetigt folgende Ressourcen, welche durch den
+ * {@link ClueModelContentManager} spezifiziert werden:
+ * <ol>
+ * <li><b>Modellparameter:</b>
+ *     <ul>
+ *     <li><i>n</i> = Anzahl modellierter LU-Typen (<b>implizit</b> durch die LU-Conversion-Matrix gegeben!)</li>
+ *     <li><i>m</i> = Anzahl an Driving Forces (<b>implizit</b> durch die Anzahl der Driving-Force-Raster gegeben!))</li>
+ *     <li><i>o</i> = Anzahl an dynamischen Driving Forces (<b>implizit</b> durch die Liste der dynamischen DF gegeben!))</li>
+ *     <li><i>t</i> = Anzahl zu simulierende Zeitschritte (Integer)</li>
+ *     <li><i>x</i> = Breite des Untersuchungsgebiets (<b>implizit</b> durch das Ausgangsszenario gegeben!)</li>
+ *     <li><i>y</i> = Anzahl zu simulierende Zeitschritte (<b>implizit</b> durch das Ausgangsszenario gegeben!)</li>
+ *     <li><i>a</i> = Erlaubte Durchschnitts-Abweichung zu den vorgegebenen LU-Bedarfen</li>
+ *     <li><i>s</i> = Erlaubte Abweichung eines jeden LU-Typs zum vorgegebenen LU-Bedarf</li>
+ *     <li><i>d</i> = Art der Abweichungsangaben (0=prozentual, 1=absolut in Bedarf-Einheit)</li>
+ *     <li><i>u</i> = Umrechnungsfaktor (z.B. 10000 bei ha), um von der (Flaechen-)Einheit der LU-Bedarfe in qm umzurechnen (Double)</li>
+ *     </ul></li>
+ * <li><b>Ein Ausgangsszenario ({@link WritableGrid})</b><br>
+ *     Stellt die Ausgangs-Landnutzung dar und muss Werte zwischen 0 und <i>n</i>
+ *     (sowie {@link Float#NaN} = NoData) enthalten.<br>
+ *     Dieses Raster bestimmt die Groesse (<i>x</i>, <i>y</i>) des
+ *     betrachteten Untersuchungsgebiets. Alle anderen Ein/Ausgabe-Raster muessen
+ *     dieser Dimension entsprechen.</li>
+ * <li><b>LU-History ({@link WritableGrid})</b><br>
+ *     Stellt die Vergangenheit des Ausgangsszenarios dar. Fuer jede Zelle
+ *     wird angegeben, wie lange die aktuelle Landnutzung bereits besteht.<br>
+ *     Das Raster muss dieselbe Dimension besitzen, wie das Ausgangsszenario.</li>
+ * <li><b>Eine LU-Conversion-Matrix ({@link MatrixProperty MatrixProperty[Integer]})</b><br>
+ *     Beschreibt ob und wie ein direkterWechsel zwischen den LU-Typen erlaubt
+ *     ist. Stellt eine <i>n</i>�<i>n</i>-Matrix dar und bestimmt somit,
+ *     wie viele LU-Typen modelliert werden.</li>
+ * <li><b>Conversion Elasticity ({@link ListProperty ListProperty[Double]})</b><br>
+ *     Beschreibt die Bestaendigkeit der LU-Typen und stellt so eine weitere
+ *     Einschraenkung an den LU-Wechsel dar. Die Liste muss fuer jeden LU-Typ
+ *     einen Wert zwischen 0 und 1 enthalten (also <i>n</i> Double-Werte).<br>
+ *     <ul>
+ *     <li><i>ELAS[U] = 1</i> bedeutet, dass wenn an einer Stelle eine U-Zelle "verschwindet",
+ *     an anderer Stelle im gleichen Zeitschritt keine Zelle vom Typ U entstehen darf.</li>
+ *     <li><i>ELAS[U] = 0</i> bedeutet, dass uneingeschraenkt an einer Stelle ein Wechsel von U
+ *         nach A und gleichzeitig an anderer Stelle von B nach U moeglich ist.</li>
+ *     <li><i>0 < ELAS[U] < 1</i> drueckt eine Tendenz zu einem der beiden Extremwerte 0 oder
+ *         1 aus.</li>
+ *     </ul></li>
+ * <li><b>Area Restrictions, Spatial policies ({@link WritableGrid})</b><br>
+ *     Beschreiben, an welchen Stellen des Untersuchungsgebiets ein LU-Wechsel generell
+ *     verboten ist (z.B. Schutzgebiete oder Bereiche, die nicht zum Untersuchungsgebiet
+ *     gehoeren).<br>
+ *     Das Raster muss dieselbe Dimension besitzen, wie das Ausgangsszenario.
+ *     Der Rasterwert NoData ({@link Float#NaN}) bedeutet, dass ein LU-Wechsel
+ *     verboten ist, jeder andere Wert erlaubt den Wechsel.</li>
+ * <li><b>Demand Scenario ({@link MatrixProperty MatrixProperty[Integer]})</b><br>
+ *     Beschreibt den LU-Bedarf (in Zellen!) fuer jeden LU-Typ zu jedem
+ *     modellierten Zeitschritt. Muss eine <i>n</i>�(<i>t</i>+1)-Matrix darstellen,
+ *     die Integer-Werte enthaelt.<br>
+ *     <u>Bemerke:</u><br>
+ *     Der "Bedarf" in der Zeile 0 stellt die Situation
+ *     des Ausgangsszenarios dar. Deshalb sind <i>t</i>+1 Zeilen anzugeben!</li>
+ * <li><b>Static Driving Forces ({@link MultiGrid})</b><br>
+ *     Beschreiben die Auspraegung der statischen Einflussfaktoren an jeder Stelle des
+ *     Untersuchungsgebiets. Zusammen mit den Regressionsparametern werden
+ *     hieraus die LU-Wahrscheinlichkeiten errechnet.<br>
+ *     Das MultiGrid muss mind. <i>m</i> numerische Raster enthalten, die alle dieselbe
+ *     Dimension besitzen, wie das Ausgangsszenario. Werden dynamische DF verwendet
+ *     werden die Elemente an deren Index <b>nicht</b> verwendet, sie muessen
+ *     jedoch vorhanden sein!</li>
+ * <li><b>Opt: Dynamic Driving Force Types ({@link ListProperty ListProperty[Integer]})</b><br>
+ *     Diese Liste enthaelt die Nummern der dynamischen Driving Forces. Die
+ *     Angabe ist optional, muss aber - wenn angegeben - Werte zwischen
+ *     0 und <i>m</i> enthalten.</li>
+ * <li><b>Opt: Dynamic Driving Forces ({@link MultiGrid})</b><br>
+ *     Beschreiben die Auspraegung der dynamischen Einflussfaktoren an jeder Stelle des
+ *     Untersuchungsgebiets ueber die Zeit. Zusammen mit den Regressionsparametern werden
+ *     hieraus die LU-Wahrscheinlichkeiten errechnet.<br>
+ *     Das MultiGrid muss mind. <i>t</i>*<i>o</i> numerische Raster enthalten,
+ *     die alle dieselbe Dimension besitzen, wie das Ausgangsszenario. Es koennen
+ *     aber auch mehr Raster angegeben werden. Bedingung ist aber, dass fuer alle
+ *     dyn. DF gleich viele Raster (=Zeitpunkte) angegeben werden! Die Grids
+ *     sind in der Liste gruppiert nach DF anzugeben, d.h. erst alle Grids
+ *     fuer den ersten dyn. DF, dann alle Grids fuer den zweiten, usw.</li>
+ * <li><b>Regression Results ({@link MatrixProperty MatrixProperty[Double]})</b><br>
+ *     Beschreiben die Einfluss-Staerke (Betas) der Driving Forces auf jeden einzelnen
+ *     LU-Typ. Muss eine (<i>m</i>+1)�<i>n</i>-Matrix darstellen,
+ *     die Double-Werte enthaelt.</li>
+ * <li><b>Opt: Neigborhood Weights ({@link ListProperty ListProperty[Double]})</b><br>
+ *     Diese (optionale) Liste enthaelt die Gewichte, wie stark der Nachbarschaftsfaktor
+ *     in die Berechnung der LU-Wahrscheinlichkeit fuer jeden LU-Typ eingeht.
+ *     Sie muss <i>n</i> Werte enthalten.</li>
+ * <li><b>Opt: Neighborhood Settings ({@link MatrixProperty MatrixProperty[Double]}})</b><br>
+ *     Beschreibt die Nachbarschaft, die fuer jeden LU-Typ betrachtet wird.
+ *     Muss eine <i>w</i>�<i>h</i>�<i>n</i>-Matrix darstellen, die Double-Werte enthaelt.
+ *     Dabei bestimmten <i>w</i> und <i>h</i> die Hoehe und Breit der betrachteten
+ *     Nachbarschaft. Werden Neighborhodd Weights angegeben, so werden auch die
+ *     Settings zu einer Pflicht-Angabe.
+ * <li><b>Opt: Neighborhood Regression Results ({@link MatrixProperty MatrixProperty[Double]}})</b><br>
+ *     Beschreibt die Einfluss-Staerke (Betas) eines jeden LU-Typs fuer den
+ *     Fall, dass er in der Nachbarschaft eines anderen LU-Typs auftritt.
+ *     Muss eine (<i>n</i>+1)�<i>n</i>-Matrix darstellen, die Double-Werte enthaelt.
+ *     Werden Neighborhodd Weights angegeben, so werden auch die Regression Results
+ *     zu einer Pflicht-Angabe.
+ * <li><b>Ein Ausgaberaster fuer die aktuelle LU ({@link WritableGrid})</b><br>
+ *     Hierin wird die aktuell modellierte LU-Konfiguration gespeichert.
+ *     Das Raster muss dieselbe Dimension besitzen, wie das Ausgangsszenario.</li>
+ * <li><b>Ein Ausgaberaster fuer die aktuelle LU Historie ({@link WritableGrid})</b><br>
+ *     Hierin wird die aktuelle Dauer gespeichert, fuer die eine Zelle
+ *     unter der aktuellen LU befindet.<br>
+ *     Das Raster muss dieselbe Dimension besitzen, wie das Ausgangsszenario.</li>
+ * <li><b>Ein temp. Ausgaberaster fuer die LU-Wahrscheinlichkeiten ({@link MultiGrid})</b><br>
+ *     Hierin werden die ueber die Driving Forces und Regression Results errechneten
+ *     LU-Wahrscheinlichkeiten gespeichert.
+ *     Das Raster muss dieselbe Dimension besitzen, wie das Ausgangsszenario.</li>
+ * <li><b>Ein temp. Ausgaberaster fuer die Nachbarschafts-Wahrscheinlichkeiten ({@link MultiGrid})</b><br>
+ *     Hierin werden die ueber die Nachbarschaftszellen und Nachbarschaftsregression errechneten
+ *     Wahrscheinlichkeiten gespeichert.
+ *     Das Raster muss dieselbe Dimension besitzen, wie das Ausgangsszenario.</li>
+ * <li><b>Ausgabeliste fuer die Iterations-Variablen ({@link ListProperty ListProperty[Double]})</b><br>
+ *     Speichert die aktuellen Werte der Iterationsvariablen ITER(U).</li>
+ * <li><b>Ausgaberaster fuer die LU zu jedem Zeitpunkt ({@link MultiGrid})</b><br>
+ *     Hierin wird die fuer jeden Zeitschritt modellierte LU-Konfiguration gespeichert.<br>
+ *     Das MultiGrid muss dieselbe Dimension besitzen, wie das Ausgangsszenario.</li>
+ * </ol>
+ * Die LU-Wahrscheinlichkeiten P1 (fuer Driving Forces) und P2 (fuer Nachbarschaft)
+ * werden jeweils ueber ein <i>Binary Logit Model</i> errechnet und gehen anteilig
+ * in die Gesamtwahrscheinlichkeit TPROB ein:
+ * <center>
+ *    TPROB(i,U) = P1(i,U) * (1-NBH_WEIGHT(U)) + P2(i,U) * NBH_WEIGHT + ELAS(U) - ITER(U)
+ * </center><br>
+ * Die Elastizitaet ELAS(U) wird nur eingerechnet, wenn sich die Zelle i im vorangegebenen
+ * Zeitschritt bereits unter der Landnutzung U befindet.
+ * In jedem Zeitschritt wird solgange iteriert, bis die vorgegebenen Bedarfe fuer
+ * jeden LU-Typ (bis auf die Abweichungen <i>a</i> und <i>s</i>) erfuellt sind.
+ * Nach jedem Iterationsschritt werden die ITER(U)-Variablen (einzige variable
+ * Groesse innerhalb einer Zeitschritt-Iteration!) auf Basis der
+ * Bedarfsabweichnung <i>DEMAND(U) - COVER(U)</i> angepasst, um die
+ * Gesamtwahrscheinlicheiten "in eine geeignete Richtung" zu lenken.
+ * <br><br>
+ * <b><u>BEACHTE</u>:</b><br>
+ * Zur Zeit werden folgende in CLUE integriert Regeln noch nicht unterstuetzt:
+ * <ul>
+ * <li>Area Restrictions fuer bestimmte Wechsel LU1 -> LU2 (Angabe ueber LU-Conversion
+ *     Matrix zusammen mit speziellen Eingabe-Rastern)</li>
+ * <li>Aufteilung des Untersuchungsgebiets in mehrere Regionen</li>
+ * </ul>
+ * @see ClueModelContentManager
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class ClueModel_Original extends AbstractStepModel {
+  /** Konstante fuer die Toleranz-Art "prozentual". */
+  public static final int TOLTYPE_PCT = 0;
+  /** Konstante fuer die Toleranz-Art "absolut in Bedarf-Einheit". */
+  public static final int TOLTYPE_ABS = 1;
+
+  /** Speichert den ContentManager fuer das Modell.
+   *  @see ClueModelContentManager */
+  protected ClueModelContentManager contManager;
+
+  private ClueModelGUI  modelGUI = new ClueModelGUI();
+
+  //********** Lese/Schreibrechte, die fuer den gesamten ***********
+  //********** Modellanlauf gehalten werden muessen      ***********
+  private PropertyReadAccess  RA_baseLU       = null; // Base Scenario
+  private PropertyReadAccess  RA_baseLUHist   = null; // Base LU History
+  private PropertyReadAccess  RA_luConv       = null; // LU-Conversion-Matrix
+  private PropertyReadAccess  RA_luElas       = null; // LU-Conversion-Elasticity
+  private PropertyReadAccess  RA_areaRestr    = null; // Area Restrictions
+  private PropertyReadAccess  RA_luDemand     = null; // LU-Bedarfe
+  private PropertyReadAccess  RA_sdfGrids     = null; // Static Driving Forces
+  private PropertyReadAccess  RA_ddfList      = null; // List of dynmic Driving Forces
+  private PropertyReadAccess  RA_ddfGrids     = null; // Dynamic Driving Forces
+  private PropertyReadAccess  RA_regrRes      = null; // Regression Results
+  private PropertyReadAccess  RA_nbhWeights   = null; // Gewichtung der Nachbarschaft pro LU-Typ
+  private PropertyReadAccess  RA_nbhSettings  = null; // Definition der Umgebung pro LU-Typ
+  private PropertyReadAccess  RA_nbhRegrRes   = null; // Regression Results fuer Nachbarschaft
+  private PropertyWriteAccess WA_outActLU     = null; // speichert die aktuell sim. LU
+  private PropertyWriteAccess WA_outActLUHist = null; // speichert die aktuell sim. LU Historie
+  private PropertyWriteAccess WA_outLUProb    = null; // speichert die LU-Wahrscheinlichkeiten
+  private PropertyWriteAccess WA_outNbhProb   = null; // speichert die Nachbarschafts-Wahrscheinlichkeiten
+  private PropertyWriteAccess WA_outIter      = null; // speichert die Iterationsvariablen
+  private PropertyWriteAccess WA_outStepLU    = null; // speichert die LU fuer jeden Zeitpunkt
+
+  //**************** Variablen mit denen gearbeitet wird *******************
+  // Modell-Parameter
+  private int    luCount    = 0;    // Anzahl an LU-Typen
+  private int    dfCount    = 0;    // Anzahl an Driving Forces
+  private int    ddfCount   = 0;    // Anzahl an dynamischen Driving Forces
+  private int    areaWidth  = 0;    // Breite des Untersuchungsgebiets (Rasterzellen)
+  private int    areaHeight = 0;    // Hoehe des Untersuchungsgebiets (Rasterzellen)
+  private int    areaMinX   = 0;    // Start-Index des Rasters in X-Richtung
+  private int    areaMinY   = 0;    // Start-Index des Rasters in Y-Richtung
+  private int    areaMaxX   = 0;    // End-Index des Rasters in X-Richtung (EXKLUSIVE!)
+  private int    areaMaxY   = 0;    // End-Index des Rasters in Y-Richtung (EXKLUSIVE!)
+  private int    demandTolType    = 0;    // Art der Abweichungsangaben
+  private double demandTolSingle  = 0.0;  // erlaubte Abweichung fuer jeden einzelnen LU-Typ vom Bedarf
+  private double demandTolAverage = 0.0;  // erlaubte Durchschnitts-Abweichung fuer das Untersuchungsgebiet
+  private double demandConv = 0.0;  // Umrechnungsfaktor Bedarfseingeit -> qm
+  private double cellSize   = 0;    // Flaeche einer Rasterzelle (in Bedarfseinheit)
+  // Eingabe-Daten, die ueber den gesamten Modellablauf benoetigt werden
+  private WritableGrid            baseLU       = null; // Base Scenario
+  private WritableGrid            baseLUHist   = null; // Base LU History
+  private PropertyReadAccess      luConv       = null; // LU-Conversion-Matrix
+  private ListPropertyReadAccess  luElas       = null; // LU-Conversion-Elasticity
+  private WritableGrid            areaRestr    = null; // Area Restrictions
+  private PropertyReadAccess      luDemand     = null; // LU-Bedarfe
+  private MultiGrid               sdfGrids     = null; // Static Driving Forces
+  private ListPropertyReadAccess  ddfList      = null; // Dynamic Driving Force Types
+  private MultiGrid               ddfGrids     = null; // Dynamic Driving Forces
+  private int[]                   ddfStartIdx  = null; // Listenindex an dem ein dyn. DF beginnt
+  private PropertyReadAccess      regrRes      = null; // LU-Bedarfe
+  private ListPropertyReadAccess  nbhWeights   = null; // Gewichtung der Nachbarschaft pro LU-Typ
+  private PropertyReadAccess      nbhSettings  = null; // Definition der Umgebung pro LU-Typ
+  private PropertyReadAccess      nbhRegrRes   = null; // Regression Results fuer Nachbarschaft
+  private int                     nbhRadiusX   = 0;    // horizontaler Radius der betrachteten Nachbarschaft
+  private int                     nbhRadiusY   = 0;    // vertikaler Radius der betrachteten Nachbarschaft
+  private double[][]              luCover      = null; // LU-Bedeckung der Typen ueber die Zeit in Bedarfseinheit
+  private double                  totCover     = 0;    // Gesamte Landbedeckungsflaeche (ohne NoData!)
+  private Random                  rand         = null; // Zufallsgenerator
+  private double[]                iterSpeed    = null; // Geschwindigkeit fuer die ITER-Variablen
+  // Ausgabe-Daten, die ueber den gesamten Modellablauf benoetigt werden
+  private WritableGrid            outActLU     = null; // speichert die aktuell sim. LU
+  private WritableGrid            outActLUHist = null; // speichert die aktuell sim. LU History
+  private MultiGrid               outLUProb    = null; // speichert die LU-Wahrscheinlichkeiten
+  private MultiGrid               outNbhProb   = null; // speichert die Nachbarschafts-Wahrscheinlichkeiten
+  private ListPropertyWriteAccess outIter      = null; // speichert die Iterationsvariablen
+  private MultiGrid               outStepLU    = null; // speichert die LU fuer jeden Zeitpunkt
+
+  /**
+   * Erzeugt eine neue Instanz des CLUE-Modells.
+   */
+  public ClueModel_Original() {
+    super( new ClueModelContentManager() );
+    contManager = (ClueModelContentManager)super.contManager;
+    // Iterations-Ereignisse der Event-Liste hinzufuegen
+    events.add(ModelIterationStepStartedEvent.class);
+    events.add(ModelIterationStepFinishedEvent.class);
+  }
+
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////   Implementierung von AbstractXuluModel   //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Initialisiert das Model, indem die Ressourcen aus dem ContentManager
+   * geladen werden und mit Lese/Schreib-Rechten versehen werden. Zudem
+   * werden Referenzen auf einen Teil der Ressourcen in lokalen Variablen
+   * gespeichert, um waehrend des Modellablaufs effizienter darauf zugreifen
+   * zu koennen.
+   */
+  public void performModelInit() {
+    if ( contManager == null )
+      return;
+    // Zugriffsrechte aus Ressourcen/Propertys holen
+    RA_baseLU       = contManager.getBaseScenario().getReadAccess(this);
+    RA_baseLUHist   = contManager.getLUHistory().getReadAccess(this);
+    RA_luConv       = contManager.getLUConversionMatrix().getReadAccess(this);
+    RA_luElas       = contManager.getConversionElasticity().getReadAccess(this);
+    RA_areaRestr    = contManager.getAreaRestrictions().getReadAccess(this);
+    RA_luDemand     = contManager.getDemandScenario().getReadAccess(this);
+    RA_sdfGrids     = ((ListProperty)contManager.getStaticDrivingForces().getProperty(MultiGrid.PROP_GRIDS)).getReadAccess(this);
+    if ( contManager.getDynamicDrivingForceTypes() != null ) {
+      RA_ddfList      = contManager.getDynamicDrivingForceTypes().getReadAccess(this);
+      RA_ddfGrids     = ((ListProperty)contManager.getDynamicDrivingForces().getProperty(MultiGrid.PROP_GRIDS)).getReadAccess(this);
+    } else {
+      RA_ddfList      = null;
+      RA_ddfGrids     = null;
+    }
+    RA_regrRes      = contManager.getRegressionResults().getReadAccess(this);
+    if ( contManager.getNeighborhoodWeights() != null ) {
+      RA_nbhWeights  = contManager.getNeighborhoodWeights().getReadAccess(this);
+      RA_nbhSettings = contManager.getNeighborhoodSettings().getReadAccess(this);
+      RA_nbhRegrRes  = contManager.getNeighborhoodRegression().getReadAccess(this);
+      WA_outNbhProb  = ((ListProperty)contManager.getNeighborhoodProbabilities().getProperty(MultiGrid.PROP_GRIDS)).getWriteAccess(this);
+    } else {
+      RA_nbhWeights  = null;
+      RA_nbhSettings = null;
+      RA_nbhRegrRes  = null;
+      WA_outNbhProb  = null;
+    }
+    WA_outActLU     = contManager.getActLUResult().getWriteAccess(this);
+    WA_outActLUHist = contManager.getActLUHistory().getWriteAccess(this);
+    WA_outLUProb    = ((ListProperty)contManager.getLUProbabilities().getProperty(MultiGrid.PROP_GRIDS)).getWriteAccess(this);
+    WA_outIter      = contManager.getIterationVariables().getWriteAccess(this);
+    WA_outStepLU    = ((ListProperty)contManager.getStepLUResults().getProperty(MultiGrid.PROP_GRIDS)).getWriteAccess(this);
+
+    // Variablen belegen mit denen gearbeitet wird
+    this.stepCount   = contManager.getStepCount().getOneTimeReadAccess().getValueAsInt(); // WICHTIG!!
+    this.dfCount     = contManager.getStaticDrivingForces().getGridCount();
+    this.demandTolType    = contManager.getDemandToleranceType().getOneTimeReadAccess().getValueAsInt();
+    this.demandTolSingle  = contManager.getSingleDemandTolerance().getOneTimeReadAccess().getValueAsDouble();
+    this.demandTolAverage = contManager.getAverageDemandTolerance().getOneTimeReadAccess().getValueAsDouble();
+    this.demandConv  = contManager.getConversionFactor().getOneTimeReadAccess().getValueAsDouble();
+    this.luCount     = contManager.getLUConversionMatrix().getSize(0);
+    this.baseLU      = (WritableGrid)RA_baseLU.getValue();
+    this.areaWidth   = baseLU.getWidth();
+    this.areaHeight  = baseLU.getHeight();
+    this.areaMinX    = baseLU.getMinX();
+    this.areaMinY    = baseLU.getMinY();
+    this.areaMaxX    = baseLU.getMinX() + areaWidth;
+    this.areaMaxY    = baseLU.getMinY() + areaHeight;
+    this.cellSize    = baseLU.getCellWidth() * baseLU.getCellHeight() / demandConv;
+    this.baseLUHist  = (WritableGrid)RA_baseLUHist.getValue();
+    this.luConv      = RA_luConv;
+    this.luElas      = (ListPropertyReadAccess)RA_luElas;
+    this.areaRestr   = (WritableGrid)RA_areaRestr.getValue();
+    this.luDemand    = RA_luDemand;
+    this.sdfGrids    = contManager.getStaticDrivingForces();
+    this.ddfList     = (RA_ddfList != null) ? (ListPropertyReadAccess)RA_ddfList : null;
+    this.ddfCount    = (ddfList != null)    ? ddfList.getCount() : 0;
+    this.ddfGrids    = (ddfList != null)    ? contManager.getDynamicDrivingForces() : null;
+    this.regrRes     = RA_regrRes;
+    this.nbhWeights  = (RA_nbhWeights != null) ? (ListPropertyReadAccess)RA_nbhWeights : null;
+    this.nbhSettings = (nbhWeights != null)    ? RA_nbhSettings : null;
+    this.nbhRadiusX  = (nbhWeights != null)    ? (contManager.getNeighborhoodSettings().getSize(0)-1)/2 : 0;
+    this.nbhRadiusY  = (nbhWeights != null)    ? (contManager.getNeighborhoodSettings().getSize(1)-1)/2 : 0;
+    this.nbhRegrRes  = (nbhWeights != null)    ? RA_nbhRegrRes : null;
+    this.outNbhProb  = (nbhWeights != null)    ? contManager.getNeighborhoodProbabilities() : null;
+    for (int i=0; outNbhProb!=null && outNbhProb.getGridCount()<luCount; i++)
+      outNbhProb.addGrid(); // Liste muss ein Raster fuer jeden LU-Typ enthalten
+    this.outActLU     = (WritableGrid)WA_outActLU.getValue();
+    this.outActLUHist = (WritableGrid)WA_outActLUHist.getValue();
+    this.outLUProb    = contManager.getLUProbabilities();
+    for (int i=0; outLUProb.getGridCount()<luCount; i++)
+      outLUProb.addGrid(); // Liste muss ein Raster fuer jeden LU-Typ enthalten
+
+    this.outIter      = (ListPropertyWriteAccess)WA_outIter;
+    // Lister der Iter-Variablen auf benoetigte Groesse auffuellen
+    for (;outIter.getCount()<luCount;)
+      outIter.addValue(0.0f);
+    this.outStepLU    = contManager.getStepLUResults();
+
+    // Bei Toleranz-Art "prozentual" werden die Werte in Prozent
+    // angegeben (intern wird aber mit Abweichungen zwischen 0 und 1 gerechnet!)
+    if ( demandTolType == TOLTYPE_PCT ) {
+      this.demandTolSingle  /= 100.0;
+      this.demandTolAverage /= 100.0;
+    }
+
+    // Die Liste der dyn. DF ist blockweise nach DF grupperiert
+    // Es koennen mehr Zeitschritt-Raster angegeben werden, als simuliert
+    // werden.
+    // Im Array 'ddfStartIdx' wird fuer die dynamischen DF gespeichert, an
+    // welcher Stelle in der Liste der Block beginnt.
+    // -1 bedeutet, dass der DF ein statische DF ist!
+    this.ddfStartIdx = new int[dfCount];
+    for (int i=0; i<dfCount; i++)
+      ddfStartIdx[i] = - 1;
+    for (int i=0; i<ddfCount; i++)
+      ddfStartIdx[i] = i*ddfGrids.getGridCount() / ddfCount;
+
+    // "Geschwindigkeit" fuer die Iterationsvariablen
+    this.iterSpeed = new double[luCount];
+
+    // Speichert die Flaechendeckung (in der Bedarfseinheit, z.B. ha)
+    // fuer die einzelnen LU-Typen zu jedem Zeitpunkt
+    // --> Die initialen Werte stehen in der 0-Zeile der Demand-Matrix
+    this.luCover   = new double[luCount][stepCount+1];
+    this.totCover = 0.0;
+    statusOut.print("InitCover: ");
+    for (int lu=0; lu<luCount; lu++) {
+      luCover[lu][0] = luDemand.getValueAsDouble(lu, 0);
+      totCover += luCover[lu][0]; // Gesamt-Flaeche des Untersuchungsgebiets
+      statusOut.print(luCover[lu][0]+"   ");
+    }
+    statusOut.println("   >> TotalCover "+totCover);
+
+    // Ausgabe-Raster leeren
+    for (int y=outActLU.getMinY(); y<outActLU.getMinY()+outActLU.getHeight(); y++)
+      for (int x=outActLU.getMinX(); x<outActLU.getMinX()+outActLU.getWidth(); x++)
+        outActLU.setRasterSample(Float.NaN,x,y);
+
+    // spezielle GUI initialisieren
+    modelGUI.init(this);
+  }
+
+  /**
+   * Gibt die Lese/Schreibrechte auf das Ein- und Ausgaberaster wieder frei.
+   * Interne Ressourcen brauchen keine aus dem Speicher entfernt werden.
+   */
+  public void performModelDispose() {
+    // Ressourcen wieder freigeben
+    releaseAccess(RA_baseLU);
+    releaseAccess(RA_baseLUHist);
+    releaseAccess(RA_luConv);
+    releaseAccess(RA_luElas);
+    releaseAccess(RA_areaRestr);
+    releaseAccess(RA_luDemand);
+    releaseAccess(RA_sdfGrids);
+    releaseAccess(RA_ddfList);
+    releaseAccess(RA_ddfGrids);
+    releaseAccess(RA_regrRes);
+    releaseAccess(RA_nbhWeights);
+    releaseAccess(RA_nbhSettings);
+    releaseAccess(RA_nbhRegrRes);
+    releaseAccess(WA_outActLU);
+    releaseAccess(WA_outActLUHist);
+    releaseAccess(WA_outLUProb);
+    releaseAccess(WA_outNbhProb);
+    releaseAccess(WA_outIter);
+    releaseAccess(WA_outStepLU);
+    closeLog();
+  }
+
+  /**
+   * Fuehrt einen Schritt des Modellablaufs durch.
+   * @param stepNo zu modellierender Schritt (beginnend bei 1!)
+   */
+  public void performModelStep(int stepNo) {
+    statusOut.println("Started step ".concat(String.valueOf(stepNo)));
+//    openLog(stepNo);
+
+    // Raster festlegen, in dem die LU des vorangegangenen
+    // Schritts zu finden ist
+    WritableGrid lastLUGrid = (stepNo==1) ? baseLU : outStepLU.getGrid(stepNo-2);
+    // Raster festlegen, in dem die aktuelle LU History
+    // zu finden ist
+    WritableGrid luHistGrid = (stepNo==1) ? baseLUHist : outActLUHist;
+
+    // Merken, ob an einer Stelle bereits eine U-Zelle in einen anderen
+    // Typ gewechselt hat
+    boolean[] alreadyLUCCFromType = new boolean[luCount];
+    // Merken, ob an einer Stelle bereits eine U-Zelle neu entstanden ist
+    boolean[] alreadyLUCCToType = new boolean[luCount];
+
+    // LU-Wahrscheinlichkeiten berechnen
+    calculateLUProbabilities(stepNo);
+
+    // Nachbarschafts-Wahrscheinlichkeiten berechnen
+    calulateNeighborhoodProbabilities(stepNo,lastLUGrid);
+
+    // Randomizer fuer diesen Zeitschritt erzeugen
+    rand = new Random(System.currentTimeMillis());
+
+    for (int iterNo=1; !checkDemandCompliedAndCalculateIterVar(stepNo,iterNo); iterNo++) {
+      this.fireModelEvent( new ModelIterationStepStartedEvent(this,stepNo,iterNo) );
+      if ( modelGUI != null )
+        modelGUI.setIterationNumber(stepNo+"/"+iterNo);
+      // Arrays fuer Iterationsschritt initialisieren
+      for (int lu = 0; lu < luCount; lu++) {
+        // noch kein Wechsel von einem LU-Typ
+        alreadyLUCCFromType[lu] = false;
+        // noch kein Wechsel zu einem LU-Typ
+        alreadyLUCCToType[lu] = false;
+        // Flaechen der LU-Typen fuer diesen Zeitschritt
+        luCover[lu][stepNo] = 0.0;
+        // Speed fuer die Iterationsvariablen initialisieren
+        // --> liegt die Nachfrage bei weniger als 5% des U'gebiets
+        //     wird langsamer begonnen
+        if ( luDemand.getValueAsDouble(lu,stepNo)/totCover < 0.05 )
+          iterSpeed[lu] = 0.01;
+        else
+          iterSpeed[lu] = 0.05;
+      }
+
+      // Fuer alle Zellen des Untersuchungsgebiets
+      for (int y = areaMinY; y < areaMaxY; y++)
+        for (int x = areaMinX; x < areaMaxX; x++) {
+          checkBreakingCommands();
+
+          // Rasterzellen ausserhalb des Untersuchungsgebiets komplett
+          // ignorieren
+          // Grund: NoData-Zellen (Float.NaN) werden beim Cast in int zu 0,
+          //        also zur Landnutzung 0!!
+          if ( checkNoData(x,y,areaRestr) || checkNoData(x,y,baseLU) )
+            continue;
+
+          // Nutzungsdauern erhoehen
+          if (iterNo==1)
+            outActLUHist.setRasterSample(luHistGrid.getRasterSampleAsFloat(x, y) + 1, x, y);
+
+          // vorangegangene LU merken
+          int lastLU = lastLUGrid.getRasterSampleAsInt(x, y);
+
+          // Beste gefundene LU wird mit aktueller LU initialisiert
+          int bestLU = lastLU;
+          double bestLUProb = 0.0;
+
+          // Pruefen, ob Zelle die LU wechseln darf
+          if (checkLUCCGeneralAllowed(x, y, stepNo, lastLU, alreadyLUCCToType[lastLU])) {
+            // Alle LU-Typen auf Wechsel pruefen
+            for (int lu = 0; lu < luCount; lu++) {
+              // Pruefen, ob Zelle in den betrachteten Typ wechseln darf
+              if (checkLUCCAllowed(x, y, stepNo, lastLU, lu, alreadyLUCCFromType[lu])) {
+                // Gesamt-Wahrscheinlichkeit berechnen
+                // a) DF-W'keit und Nachbarschaft-W'keit gehen anteilig ein
+                // b) Elastizitaet geht nur ein, wenn Zelle bereits fuer den
+                //    LU-Typ genutzt wird
+                // c) ITER geht negativ ein, da es auf Basis der Abweichung
+                //    luCover-luDemand berechnet wird. Ein negatives Iter
+                //    kennzeichnet also einen Mangel und muss die Gesamtw'keit
+                //    erhoehen
+                double baseProb  = outLUProb.getGrid(lu).getRasterSampleAsDouble(x, y);
+                double nbhProb   = (nbhWeights == null) ? 0.0 : outNbhProb.getGrid(lu).getRasterSampleAsDouble(x, y);
+                double nbhWeight = (nbhWeights == null) ? 0.0 : nbhWeights.getValueAsInt(lu);
+                double elas      = (lu == lastLU && luElas.getValueAsDouble(lu) < 1) ? luElas.getValueAsDouble(lu) : 0.0;
+                // LU-Wahrscheinlichkeit zusammensetzen
+                double totalProb = baseProb * (1-nbhWeight)
+                                 + nbhProb  * nbhWeight
+                                 + elas
+                                 - outIter.getValueAsFloat(lu);
+
+                // betrachteter Typ ist geeigneter als der bisher beste
+                if (totalProb > bestLUProb) {
+                  bestLU = lu;
+                  bestLUProb = totalProb;
+                }
+              }
+            }
+            // Merken wenn wirklich ein Wechsel stattfindet
+            if (bestLU != lastLU) {
+              alreadyLUCCFromType[lastLU] = true;
+              alreadyLUCCToType[bestLU] = true;
+            }
+          }
+
+          // LU fuer diesen Iterationschritt setzen
+          outActLU.setRasterSample( (float) bestLU, x, y);
+          // Flaechendeckung fuer LU-Typ erhoehen
+          luCover[bestLU][stepNo] += cellSize;
+        }
+      this.fireModelEvent( new ModelIterationStepFinishedEvent(this,stepNo,iterNo) );
+    }
+
+    // Liste der Zeitschritt-Ausgaberaster vergroessern
+    outStepLU.addGrid();
+
+    // LU in Ausgaberaster des Zeitschritts uebernehmen und ggf.
+    // Nutzungsdauer initialisieren
+    for (int y=areaMinY; y<areaMaxY; y++)
+      for (int x=areaMinX; x<areaMaxX; x++) {
+        checkBreakingCommands();
+        Float lastLU = (Float)lastLUGrid.getRasterSample(x,y);
+        Float actLU  = (Float)outActLU.getRasterSample(x,y);
+        // Wenn die Landnutzung gewechselt hat, wird die Historie zurueck
+        // gesetzt
+        if ( actLU != lastLU )
+          outActLUHist.setRasterSample((float)0,x,y);
+
+        // LU in Ausgabe-Raster des simulierten Schritts uebernehmen
+        outStepLU.getGrid(stepNo-1).setRasterSample(actLU,x,y);
+      }
+
+    statusOut.println("Ended step ".concat(String.valueOf(stepNo)));
+    closeLog();
+  }
+
+  /**
+   * Liefert eine CLUE-spezifische GUI, in der die Abweichungen waehrend der
+   * Iteration angezeigt werden und ueber die die Toleranzen eingestellt
+   * werden koennen
+   * @return Instannz von {@link ClueModelGUI}
+   */
+  public Component getModelSpecificGUI() {
+    return modelGUI;
+  }
+
+  //////////////////////////////////////////////////////////////////////
+  ////////////////////////   Clue-Methoden   ///////////////////////////
+  //////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob eine Rasterzelle mit <code>NoData</code> belegt ist
+   * @param x     Raster-Koordinate
+   * @param y     Raster-Koordinate
+   * @param grid  zu pruefendes Raster
+   */
+  protected static boolean checkNoData(int x, int y, WritableGrid grid) {
+    return Double.isNaN(grid.getRasterSampleAsDouble(x,y));
+  }
+
+  /**
+   * Berechnet die auf den Driving Forces basierenden
+   * Landnutzungs-Wahrscheinlichkeiten fuer einen Modell-Schritt und speichert
+   * diese in der Ressource "temp. Ausgaberaster fuer die LU-Wahrscheinlichkeiten".<br>
+   * Werden keine dynamischen Driving Forces verwendet, geschieht die Berechnung
+   * nur beim ersten Modellierungsschritt.
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   */
+  protected void calculateLUProbabilities(int stepNo) {
+    // Wenn keine dynamischen Driving Forces verwendet werden
+    // braucht die Berechnung nur fuer den ersten Schritt
+    // durchgefuehrt werden
+    if ( ddfCount == 0 && stepNo > 1 )
+      return;
+
+    statusOut.print("Calculate LU-Probabilities for step "+stepNo+"...");
+    // Fuer Zellen des Untersuchungsgebiets
+    for (int y=areaMinY; y<areaMaxY; y++)
+      for (int x=areaMinX; x<areaMaxX; x++)
+        // NotData-Bereich und Area Restrictions ignorieren
+        if ( !checkNoData(x,y,baseLU) && areaRestr.getRasterSampleAsFloat(x,y)==0 ) {
+          // Fuer alle LU-Typen
+          for (int lu = 0; lu < luCount; lu++) {
+            double betaSum = 0.0;
+            // Fuer alle Driving Forces die Summe der Betas berechnen
+            for (int df = 0; df < dfCount; df++) {
+              checkBreakingCommands();
+              // DF-Grid festlegen:
+              // Bei dynamischem DF das jew. Zeitschritt-Raster aus der Liste
+              // ansonsten das statische Raster
+              WritableGrid dfGrid = null;
+              if ( ddfStartIdx[df] >= 0 )
+                dfGrid = this.ddfGrids.getGrid(ddfStartIdx[df]+stepNo-1);
+              else
+                dfGrid = this.sdfGrids.getGrid(df);
+              // Beim ersten Driving Force wird die Summe mit der
+              // Regressionskonstante initialisiert
+              if (df == 0)
+                betaSum = regrRes.getValueAsDouble(0, lu);
+              // betaSum = BETA0(U) + Sum( BETA(df+1,U) * DF(df,x,y) )
+              betaSum += regrRes.getValueAsDouble(df + 1, lu)
+                        * dfGrid.getRasterSampleAsDouble(x, y);
+            }
+            double expBetaSum = Math.exp(betaSum);
+            double prob = expBetaSum / (1 + expBetaSum);
+            // errechnete W'keit im Raster speichern
+            this.outLUProb.getGrid(lu).setRasterSample( (float) prob, x, y);
+          }
+        }
+    statusOut.println(" done.");
+  }
+
+  /**
+   * Berechnet die auf den Nachbarschaftsbeziehungen basierenden
+   * Landnutzungs-Wahrscheinlichkeiten fuer einen Modell-Schritt und speichert
+   * diese in der Ressource "temp. Ausgaberaster fuer die Nachbarschafts-Wahrscheinlichkeiten".<br>
+   * Da sich die Landnutzung mit jedem Zeitschritt aendert geschieht dies
+   * vor jedem Zeitschritt neu.<br>
+   * Diese Methode macht nichts, wenn ohne Nachbarschafts-W'keiten simuliert wird,
+   * also wenn keine Angabe fuer die "Neighborhood-Weights" gemacht wird.
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   * @param luGrid LU-Raster aus dem die Umgebung der jeweiligen Zellen
+   *               ermittelt werden
+   */
+  protected void calulateNeighborhoodProbabilities(int stepNo, WritableGrid luGrid) {
+    // Wenn ohne Nachbarschaftsbeziehungen simuliert wird
+    if ( nbhWeights == null )
+      return;
+
+    statusOut.print("Calculate Neighborhood-Probabilities for step "+stepNo+"...");
+    // Fuer Zellen des Untersuchungsgebiets
+    for (int y=areaMinY; y<areaMaxY; y++)
+      for (int x=areaMinX; x<areaMaxX; x++)
+        // NoData-Bereich und Area Restrictions ignorieren
+        if ( !checkNoData(x,y,baseLU) && areaRestr.getRasterSampleAsFloat(x,y)==0 )
+          // Fuer alle LU-Typen
+          for (int lu = 0; lu < luCount; lu++) {
+            checkBreakingCommands();
+
+            // Anzahl der Zellen in der Umgebung initialisieren
+            int      totCellCount = 0;
+            double[] luCellCount  = new double[luCount];
+
+            // Umgebung der Zelle betrachten
+            for (int dy=-nbhRadiusY; dy<=nbhRadiusY; dy++)
+              if ( areaMinY <= y+dy && y+dy<areaMaxY )
+                for (int dx=-nbhRadiusX; dx<=nbhRadiusX; dx++)
+                  if ( areaMinX <= x+dx && x+dx<areaMaxX ) {
+                    double lucc = luGrid.getRasterSampleAsDouble(x+dx,y+dy); // PERFORMANZ > nur einmal den Zellen-Wert ermitteln
+//                    if ( !checkNoData(x+dx,y+dy,baseLU) ) {
+                    if ( !Double.isNaN(lucc) ) {
+                        // Alle Zellen in Umgebung zaehlen (jedoch nur diejenigen,
+                        // die potentiell auch in die Bewertung eingehen koennen!)
+                        double setting = nbhSettings.getValueAsDouble(dx+nbhRadiusX,dy+nbhRadiusY,lu);
+                        if ( setting != 0.0 ) {
+                          totCellCount++;
+                          // Anzahl der Zellen eines bestimmten Typs aufsummieren
+                          // (relativ zum in der Umgebung angegebenen Faktor)
+//                          luCellCount[ luGrid.getRasterSampleAsInt(x+dx,y+dy) ] += setting;
+                          luCellCount[ (int)lucc ] += setting;
+                        }
+                      }
+                    }
+              // Summe der Betas berechnen
+              double betaSum = nbhRegrRes.getValueAsDouble(0,lu); // Regr.Konstante
+              for (int i=0; i<luCount; i++) {
+                double beta    = nbhRegrRes.getValueAsDouble(i + 1, lu);
+                double nbhFact = (luCellCount[i]/totCellCount) / (luCover[i][stepNo-1]/totCover);
+                betaSum += beta * nbhFact;
+              }
+              // Wahrscheinlichkeit berechnen
+              double expBetaSum = Math.exp(betaSum);
+              outNbhProb.getGrid(lu).setRasterSample((float)(expBetaSum/(1 + expBetaSum)),x,y);
+          }
+    statusOut.println(" done.");
+  }
+
+
+  /**
+   * Prueft, ob ein genereller LU-Wechsel fuer eine Zelle erlaubt ist.
+   * <ul>
+   * <li>Schliessen die Area Restrictions einen Wechsel aus?<br>
+   *     > Rasterwert(x,y) != 0
+   *     </li>
+   * <li>Schliesst die Conversion Elasticity einen Wechsel aus (Elastizitaet 1
+   *     und steigende Bedarf)?<br>
+   *     > ELAS(lastLU) == 1 und DEMAND(lastLU,t) >= DEMAND(lastLU,t-1)
+   *     </li>
+   * </ul>
+   * @param x      Raster-Koordinate
+   * @param y      Raster-Koordinate
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   * @param lastLU Bedeckung von (x,y) zum Zeitpunkt stepNo-1
+   * @param alreadyLUCCToActualType Flag gibt an, ob in der laufenden Iteration
+   *                                bereits ein LU-Wechsel in den den aktuellen
+   *                                Typ der Zelle (lastLU) vorgenommen wurde.<br>
+   *                                <b>Dieses Flag wird zur Zeit nicht verwendet!</b>
+   */
+  protected boolean checkLUCCGeneralAllowed(int x, int y, int stepNo, int lastLU, boolean alreadyLUCCToActualType) {
+    // Area Restrictions checken
+    if ( areaRestr.getRasterSampleAsFloat(x,y) != 0 )
+      return false;
+// DER ERSTE TEIL IST KEINE ORIGINAL-CLUE-REGEL!
+//    // Conversion Elasticity checken
+//    // --> wenn Elasticity 1 und bereits an anderer Stelle eine Zelle des
+//    //     bisherigen Typs entstanden ist, darf sie nicht wechseln
+//    // --> wenn Elasticity 1 und Bedarf steigt, darf kein Wechsel
+//    //     stattfinden, denn dann muessten (um den Bedarf zu decken)
+//    //     an anderer Stelle neue entstehen
+//    if (  luElas.getValueAsDouble(lastLU) == 1.0
+//       && ( alreadyLUCCToActualType ||
+//           luDemand.getValueAsDouble(lastLU,stepNo) >= luCover[lastLU][stepNo-1] ) )
+//      return false;
+
+    // Conversion Elasticity checken
+    // --> wenn Elasticity 1 und Bedarf steigt, darf kein Wechsel
+    //     stattfinden, denn dann muessten (um den Bedarf zu decken)
+    //     an anderer Stelle neue entstehen
+    if (  luElas.getValueAsDouble(lastLU) == 1.0 &&
+//          luDemand.getValueAsDouble(lastLU,stepNo) >= luCover[lastLU][stepNo-1] )
+          luDemand.getValueAsDouble(lastLU,stepNo) >= luDemand.getValueAsDouble(lastLU,stepNo-1) )
+      return false;
+
+    return true;
+  }
+
+  /**
+   * Prueft, ob ein bestimmter LU-Wechsel fuer eine Zelle erlaubt ist.
+   * <ul>
+   * <li>Schliesst die Conversion Elasticity einen Wechsel aus (Elastizitaet des
+   *     potentiellen Wechseltyps 1 und sinkender Bedarf)?<br>
+   *     > lastLU != newLU und ELAS(newLU) == 1 und DEMAND(newLU,t) <= DEMAND(newLU,t-1)
+   *     </li>
+   * <li>Schliesst die Conversion Matrix einen Wechsel aus (generell oder ueber
+   *     Historie)?<br>
+   *     > CONV(lastLU,newLU) == 0 oder<br>
+   *     > CONV(lastLU,newLU) > 100 und HIST(x,y) < CONV(lastLU,newLU)-101 oder<br>
+   *     > CONV(lastLU,newLU) < -100 und HIST(x,y) > -CONV(lastLU,newLU)-101
+   *     </li>
+   * </ul>
+   * @param x      Raster-Koordinate
+   * @param y      Raster-Koordinate
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   * @param lastLU Bedeckung von (x,y) zum Zeitpunkt stepNo-1
+   * @param newLU  potentielle neue Bedeckung von (x,y)
+   * @param alreadyLUCCFromNewType  Flag gibt an, ob in der laufenden Iteration
+   *                                bereits ein LU-Wechsel vom potentiellen neuen
+   *                                Typ in einen anderen Typ vorgenommen wurde.<br>
+   *                                <b>Dieses Flag wird zur Zeit nicht verwendet!</b>
+   */
+  protected boolean checkLUCCAllowed(int x, int y, int stepNo, int lastLU, int newLU, boolean alreadyLUCCFromNewType) {
+// IST KEINE ORIGINAL-CLUE-REGEL!
+//    // LU-Conversion-Elasticity des neuen Typs checken
+//    // --> wenn Elasticity des neuen Typs 1 ist und an anderer Stelle bereits
+//    //     eine Zelle des dieses Typs "verloren" ging, darf er hier
+//    //     nicht entstehen
+//    if (  alreadyLUCCFromNewType && luElas.getValueAsDouble(newLU) == 1.0 )
+//      return false;
+
+    // Conversion Elasticity checken
+    // --> wenn Elasticity des neuen Typs "newLU" 1 und dessen Bedarf sinkt,
+    //     darf kein Wechsel in diesen Typ stattfinden, denn dann muessten (um
+    //     den Bedarf fuer "newLU" zu erreichen) an anderer Stelle newLU-Zellen
+    //     entfernt werden
+    if (  lastLU != newLU &&
+          luElas.getValueAsDouble(newLU) == 1.0 &&
+          luDemand.getValueAsDouble(newLU,stepNo) <= luCover[newLU][stepNo-1] )
+//          luDemand.getValueAsDouble(newLU,stepNo) <= luDemand.getValueAsDouble(newLU,stepNo-1) )
+      return false;
+
+    // Wert aus LU-Conversion-Matrix ermitteln
+    // Bemerke: "von" steht in den Zeilen (also Y, also Dim1)
+    //          "nach" steht in den Spalten (also X, also Dim2)
+    int conv = luConv.getValueAsInt(newLU,lastLU);
+    // 1 --> LUCC generell erlaubt
+    if ( conv == 1 )
+      return true;
+    // 0 --> LUCC generell verboten
+    if ( conv == 0 )
+      return false;
+
+    // 100+t --> Wechsel erst nach t Schritten der vorangegangenen
+    //           LU moeglich
+    if ( conv > 100 ) {
+//      int minLUHist = conv-100;
+//      int luHist    = outActLUHist.getRasterSampleAsInt(x,y);
+//      return luHist >= minLUHist;
+      int minLUHist = conv-101;
+      int luHist    = outActLUHist.getRasterSampleAsInt(x,y);
+      return luHist >= minLUHist;
+    }
+
+    // -100-t --> Wechsel nicht mehr moeglich, wenn Zelle bereits
+    //            t Schritte unter der vorangegangenen LU
+    if ( conv < -100 ) {
+//      int maxLUHist = -conv-100;
+//      int luHist    = outActLUHist.getRasterSampleAsInt(x,y);
+//      return luHist < maxLUHist;
+      int maxLUHist = -conv-101;
+      int luHist    = outActLUHist.getRasterSampleAsInt(x,y);
+      return luHist <= maxLUHist;
+    }
+
+    return true;
+  }
+
+  /**
+   * Prueft, ob die aktuelle LU-Konfiguration die einzelenen Bedarfsanforderungen
+   * (bis auf eine Abweichung) erfuellt und berechnet die Iterationsvariablen
+   * neu.
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   * @param iterNo aktuelle Iteration (beginnend bei 1)
+   */
+  protected boolean checkDemandCompliedAndCalculateIterVar(int stepNo, int iterNo) {
+    appendLog(iterNo);
+
+    boolean demandComplied = true;
+    // Abweichnungen berechnen
+    double[] singleDevAbs = new double[luCount];
+    double[] singleDevPct = new double[luCount];
+    double   averageDevAbs = 0.0;
+    double   averageDevPct = 0.0;
+    double   totalDevAbs = 0.0;
+    double   totalDevPct = 0.0;
+    for (int lu = 0; lu < luCount; lu++) {
+      // ##### Einzelabweichungen #####
+      // Absolute Abweichung der Landbedeckung vom Bedarf berechnen
+      double demand = luDemand.getValueAsDouble(lu, stepNo);
+      singleDevAbs[lu]  = luCover[lu][stepNo] - demand;
+      // Prozentuale Einzel-Abweichnung relativ zum Bedarf
+      if (demand == 0)
+        // ist der Bedarf 0, aber auch die Bedeckung, ist die Abw. 0%
+        singleDevPct[lu] = luCover[lu][stepNo] == 0.0 ? 0.0 : 1.0;
+      else
+        singleDevPct[lu] = singleDevAbs[lu] / demand;
+
+      // Abweichung ueber erlaubter Toleranz?
+      double singleDev = (demandTolType == TOLTYPE_PCT) ? singleDevPct[lu] : singleDevAbs[lu];
+      if (modelGUI!=null)
+        modelGUI.setDeviation(lu,singleDev);
+      if (Math.abs(singleDev) > demandTolSingle)
+        demandComplied = false;
+
+      // Abweichung des LU-Typs ausgeben
+      appendLog(singleDevAbs[lu],singleDevPct[lu],luDemand.getValueAsDouble(lu, stepNo),luCover[lu][stepNo]);
+
+      // ##### Gesamtabweichungen aufsummieren #####
+      totalDevAbs += Math.abs(singleDevAbs[lu]);
+    }
+
+    // Prozentuale Gesamt-Abweichnung relativ zum Gesamt-Untersuchungsgebiet
+    totalDevPct = totalDevAbs / totCover;
+    if (modelGUI!=null)
+      modelGUI.setDeviation(luCount,(demandTolType == TOLTYPE_PCT) ? totalDevPct : totalDevAbs);
+
+    // Durchschnittliche Abweichnung pro LU-Typ
+    averageDevAbs = totalDevAbs / luCount;
+
+    // Durchschnittliche Abweichnung pro LU-Typ relativ zum Gesamt-Untersuchungsgebiet
+    averageDevPct = averageDevAbs / totCover;
+
+    // Abweichung ueber erlaubter Toleranz?
+    double avgDev = (demandTolType == TOLTYPE_PCT) ? averageDevPct : averageDevAbs;
+    if (modelGUI!=null)
+      modelGUI.setDeviation(luCount+1,avgDev);
+    if ( Math.abs(avgDev) > demandTolAverage )
+      demandComplied = false;
+
+    appendLog(totalDevAbs,totalDevPct);
+
+    // Iterationsvariablen neu berechnen
+    for (int lu = 0; lu < luCount; lu++) {
+      // Um Alternieren zwischen 2 Konfiguration zu verhindern
+      // eine kleine Zufallszahl hinzuaddieren (zwischen -0,005 und 0,005)
+      float randomValue = (rand.nextFloat()-0.5f)/100;
+
+      // --> Im ersten Schritt erhalten alle Iterationsvariablen den Wert 0,5
+      double iter = outIter.getValueAsFloat(lu);
+      if (iterNo == 1)
+        iter = 0.5f+randomValue;
+//        iter = 0.5 + new float[] {0.002f,0f,0.002f,0f,0f,-0.003f}[lu];
+//        iter = 0.5 + new float[] {0.002f,0f,0.001f,0f,0f,-0.002f}[lu];
+      else {
+//        // Anteil der Einzelabweichnung an der Gesamtabweichnung
+////        double dev = (totalDevAbs!=0) ? singleDevAbs[lu] / totalDevAbs : 0.0;
+//        double dev  = singleDevPct[lu];
+//        iter = outIter.getValueAsFloat(lu) // alter Iter-Wert
+//             + dev // Anteil der Abweichung zum Bedarf
+//             + randomValue;
+        /////////////////////////////////////////
+        // Original-Iter-Berechnung aus CLUE
+        iterSpeed[lu] += 0.00005;
+        iter += (singleDevAbs[lu]/totCover)/(iterSpeed[lu]*(rand.nextInt(101)+1));
+
+        if (iter > 2f)
+          iter = 0.5f;
+        if ( Math.abs(iter) < 0.001 )
+          iter = 0.01f * Math.signum(iter);
+        if (iter < -0.5f)
+          iter = -0.4f;
+        /////////////////////////////////////////
+      }
+      // Iter speichern
+      outIter.setValue((float)iter, lu);
+      appendLog(outIter.getValueAsFloat(lu));
+    }
+
+    appendLog(" > Demand "+(demandComplied ? "" : "not ")+"complied");
+    appendLog("\n");
+    return demandComplied;
+  }
+
+  //////////////////////////////////////////////////////////////////////
+  /////////////////////   Clue-spezifische GUI   ///////////////////////
+  //////////////////////////////////////////////////////////////////////
+
+  /**
+   * Diese Klasse stellt eine modellspezifische GUI-Komponente fuer das
+   * {@link ClueModel CLUE-Modell} dar.
+   * In dieser wird fuer jeden modellierten LU-Typ ein {@linkplain ExpansionBar Status-Balken}
+   * fuer die Abweichnung vom geforderten Bedarf angezeigt. Sowie je ein Balken
+   * fuer die aktuelle Gesamt- und Durchschittsabweichung. Je nach gewaehlter
+   * Abweichungsart (prozentual oder absolute Angaben), werden Abweichungen
+   * von +/- 100% oder +/- 10000 Bedarfseinheiten angezeigt.<br>
+   * Darueber hinaus enthaelt sie je einen Regler, ueber den die maximal
+   * erlaubte Abweichung von den Bedarfen (Einzelabweichung der LU-Typen und
+   * Durchschnittsabweichung) eingestellt werden kann.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class ClueModelGUI extends JComponent {
+    private       double MIN = -1.0;
+    private       double MAX = 1.0;
+    private final double TOL = 0.2;
+    private       double SLIDER_FACT = 1000;
+    // Format fuer Wert-Anzeige des Sliders
+    private DecimalFormat sliderPctFormat = new DecimalFormat("0.0%");
+    private DecimalFormat sliderDecFormat = new DecimalFormat("0.0");
+    // Format fuer Wert-Anzeige im Balken
+    private DecimalFormat statusPctFormat = new DecimalFormat("0.0000%");
+    private DecimalFormat statusDecFormat = new DecimalFormat("0.0");
+    // Format fuer Wert-Anzeige unterhalb der Balken (Max/Min/Middle)
+    private DecimalFormat infoPctFormat   = new DecimalFormat("0.0%");
+    private DecimalFormat infoDecFormat   = new DecimalFormat("0.0");
+
+    private DeviationContainer  divCont          = null;
+    private JSlider             singleDivSlider  = null;
+    private JSlider             averageDivSlider = null;
+    private ClueModel_Original  model            = null;
+    private DeviationLabel      singleDivLabel   = new DeviationLabel("Erlaubte Bedarfsabweichung pro LU-Typ:",sliderPctFormat);
+    private DeviationLabel      averageDivLabel  = new DeviationLabel("Erlaubte durchschnittliche Bedarfsabweichung:",sliderPctFormat);
+    private Font                labelFont        = singleDivLabel.getFont().deriveFont(Font.BOLD | Font.CENTER_BASELINE);
+    private boolean             alreadyPacked    = false;
+    private JLabel              iterationLabel   = null;
+
+    /**
+     * Erzeugt eine neue Clue-GUI. Diese wird jedoch erst nach Aufruf
+     * der {@link #init(ClueModel_Original)}-Methode komplett erzeugt, da erst dann
+     * die Anzahl der angezeigten Balken (= Anzahl LU-Typen) feststeht.
+     */
+    public ClueModelGUI() {
+      super();
+      this.setLayout( new SpringLayout() );
+      // Label in dem die Iterationsnummer angezeigt wird
+      iterationLabel = new JLabel(" ");
+      iterationLabel.setBorder( BorderFactory.createLoweredBevelBorder() );
+      // Slider/Label fuer Abweichnug der einzelnen Typen
+      singleDivSlider  = new JSlider(JSlider.HORIZONTAL,0,(int)(SLIDER_FACT*MAX),(int)(SLIDER_FACT*TOL));
+      singleDivSlider.setPaintTicks(true);
+      singleDivSlider.setPaintLabels(true);
+      singleDivSlider.setPaintTrack(true);
+      singleDivSlider.setEnabled(false);
+      singleDivSlider.addChangeListener( new ChangeListener() {
+        public void stateChanged(ChangeEvent e) {
+          double tol = singleDivSlider.getValue() / SLIDER_FACT;
+          if ( model!=null )
+            model.demandTolSingle = tol;
+          if ( singleDivLabel!=null )
+            singleDivLabel.setValue(tol);
+          if ( divCont!=null )
+            divCont.setTolerance(tol);
+        }
+      });
+      singleDivLabel.setFont(labelFont);
+      singleDivLabel.setValue(singleDivSlider.getValue()/SLIDER_FACT);
+
+      // Slider/Label fuer Abweichnug der einzelnen Typen
+      averageDivSlider  = new JSlider(JSlider.HORIZONTAL,0,(int)(SLIDER_FACT*MAX),(int)(SLIDER_FACT*TOL));
+      averageDivSlider.setPaintTicks(true);
+      averageDivSlider.setPaintLabels(true);
+      averageDivSlider.setPaintTrack(true);
+      averageDivSlider.setEnabled(false);
+      averageDivSlider.addChangeListener( new ChangeListener() {
+        public void stateChanged(ChangeEvent e) {
+          double tol = averageDivSlider.getValue() / SLIDER_FACT;
+          if ( model!=null )
+            model.demandTolAverage = tol;
+          if ( averageDivLabel!=null )
+            averageDivLabel.setValue(tol);
+        }
+      });
+      averageDivLabel.setFont(labelFont);
+      averageDivLabel.setValue(averageDivSlider.getValue()/SLIDER_FACT);
+
+      this.add( averageDivLabel );
+      this.add( averageDivSlider );
+      this.add( singleDivLabel );
+      this.add( singleDivSlider );
+      this.add( iterationLabel );
+      SpringUtilities.makeCompactGrid(this,5,1,0,0,0,5);
+    }
+
+    /**
+     * Initialisiert die GUI fuer eine <b>initialisierte</b> Modell-Instanz.
+     * Wird zum Ende {@link ClueModel#performModelInit()} aufgerufen.
+     */
+    public void init(ClueModel_Original model) {
+      this.model = model;
+      if ( divCont != null )
+        remove(divCont);
+      SLIDER_FACT = (model.demandTolType == TOLTYPE_PCT) ? 1000.0 : 1.0;
+      MIN         = (model.demandTolType == TOLTYPE_PCT) ? -1.0 : -Math.pow(10,(int)Math.log10(model.totCover))/1000;
+      MAX         = (model.demandTolType == TOLTYPE_PCT) ?  1.0 : -MIN;
+      averageDivSlider.setMaximum((int)(MAX*SLIDER_FACT));
+      averageDivLabel.setNumberFormat( model.demandTolType == TOLTYPE_PCT ? sliderPctFormat : sliderDecFormat );
+      singleDivSlider.setMaximum((int)(MAX*SLIDER_FACT));
+      singleDivLabel.setNumberFormat( model.demandTolType == TOLTYPE_PCT ? sliderPctFormat : sliderDecFormat );
+
+      String[] divDesc = new String[model.luCount+2];
+      for (int i=0; i<model.luCount; i++)
+        divDesc[i] = String.valueOf(i);
+      divDesc[model.luCount]   = "Total";
+      divDesc[model.luCount+1] = "Average";
+
+      divCont = new DeviationContainer(
+                         divDesc.length,
+                         divDesc,
+                         MIN,
+                         MAX,
+                         0,
+                         model.demandTolSingle,
+                         model.demandTolType == TOLTYPE_PCT ? statusPctFormat : statusDecFormat,
+                         model.demandTolType == TOLTYPE_PCT ? infoPctFormat   : infoDecFormat
+      );
+      divCont.setBarDescHeader("LU-Typ");
+      divCont.setBarHeader("Aktuelle Bedarfsabweichung");
+      this.add(divCont,4);
+
+      // Wert des Balkens darf erst hier (nach Neu-Erstellung des
+      // Abweichungs-Containers) neu gesetzt werden, da beim Setzen
+      // des neuen Wertes automatisch die Toleranzen der Abweichungsbalken
+      // aktualisiert werden
+      setSingleTolerance(model.demandTolSingle);
+      setAverageTolerance(model.demandTolAverage);
+
+      SpringUtilities.makeCompactGrid(this,6,1,0,0,0,5);
+      if ( !alreadyPacked )
+        SwingUtil.packParentWindow(this);
+      else
+        this.validate();
+      alreadyPacked = true;
+      singleDivSlider.setEnabled( true );
+      averageDivSlider.setEnabled( true );
+    }
+
+    /**
+     * Setzt die in der GUI angezeigte Interationsnummer. Diese wird
+     * durch einen String repraesentiert, damit auch berliebige andere
+     * Informationen (anstelle der Nummer) dargestellt werden koennen (z.B.
+     * zusaetzlich noch die Schrittnummer).
+     * @param iterString dargestellte Iterationsnummer
+     */
+    public void setIterationNumber(String iterString) {
+      iterationLabel.setText("Iteration: "+iterString);
+    }
+
+    /**
+     * Stellt den Slider fuer die Einzelabweichung auf einen bestimmten Wert
+     * ein. Hierdurch wird automatisch auch der Wert fuer das Modell neu
+     * gesetzt.
+     */
+    public void setSingleTolerance(double tol) {
+      singleDivSlider.setValue((int)(tol*SLIDER_FACT));
+    }
+
+    /**
+     * Stellt den Slider fuer die Durchschnittsabweichung auf einen bestimmten Wert
+     * ein. Hierdurch wird automatisch auch der Wert fuer das Modell neu
+     * gesetzt.
+     */
+    public void setAverageTolerance(double tol) {
+      averageDivSlider.setValue((int)(tol*SLIDER_FACT));
+    }
+
+    /**
+     * Setzt die Abweichnungswerte fuer alle Statusbalken.
+     * @param value Array mit den Abweichungen
+     */
+    public void setDeviation(double[] value) {
+      if ( divCont!= null )
+        divCont.setExpansion(value);
+    }
+
+    /**
+     * Setzt den Abweichnungswert fuer einen Statusbalken.
+     * @param idx   Index eines Balkens
+     * @param value Array mit den Abweichungen
+     */
+    public void setDeviation(int idx, double value) {
+      if ( divCont!= null )
+        divCont.setExpansion(idx,value);
+    }
+
+    /**
+     * Diese Klasse stellt ein Label dar, in dem (hinter einem Basistext)
+     * ein numerischer Abweichungswert (z.B. erlaubte Maximalabweichung) angezeigt wird.
+     * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+     * @version 1.0
+     */
+    private static class DeviationLabel extends JLabel {
+      private String baseText        = "";
+      private double dev             = 0.0;
+      private NumberFormat numFormat = null;
+
+      /**
+       * Erzeugt ein neues leeres Label.
+       */
+      public DeviationLabel() {
+        this("");
+      }
+
+      /**
+       * Erzeugt ein neues Label. Der dargestellte Wert ist initial 0%.
+       * @param text      Basistext
+       */
+      public DeviationLabel(String text) {
+        this(text,new DecimalFormat("0.0%"));
+      }
+
+      /**
+       * Erzeugt ein neues Label. Der dargestellte Wert ist initial 0.
+       * @param text      Basistext
+       * @param numFormat Anzeigeformat fuer den dargestellten Abweichungswert
+       */
+      public DeviationLabel(String text, NumberFormat numFormat) {
+        this(text,numFormat,0.0);
+      }
+
+      /**
+       * Erzeugt ein neues Label.
+       * @param text      Basistext
+       * @param numFormat Anzeigeformat fuer den dargestellten Abweichungswert
+       * @param dev       initialer Wert fuer den Abweichungswert
+       */
+      public DeviationLabel(String text, NumberFormat numFormat, double dev) {
+        super();
+        this.baseText  = text;
+        this.dev    = dev;
+        setNumberFormat(numFormat);
+        setText(baseText);
+      }
+
+      /**
+       * Setzt den darzustellenden numerischen Abweichungswert.
+       */
+      public void setValue(double dev) {
+        this.dev = dev;
+        setText(baseText);
+      }
+
+      /**
+       * Setzt den Basistext des Labels.
+       */
+      public void setText(String text) {
+        this.baseText = text;
+        String displayText = baseText;
+        if ( numFormat != null )
+          displayText = displayText+" "+numFormat.format(this.dev);
+        super.setText(displayText);
+      }
+
+      /**
+       * Setzt das Darstellungsformat fuer den Abweichungswert.
+       */
+      public void setNumberFormat(NumberFormat format) {
+        this.numFormat = format;
+      }
+    }
+
+    /**
+     * Diese Klasse stellt einen Container dar, in dem vertikal eine Reihe von
+     * {@linkplain ExpansionBar Status-Balken} angezeigt werden. Alle Balken
+     * haben dieselben Extremwerte (Min, Max, Middle). Deshalb erhaelt nur
+     * der unterste Balken eine Info-Leiste mit diesen Extremwerten.
+     * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+     * @version 1.0
+     */
+    private static class DeviationContainer extends JComponent {
+      private static final NumberFormat NUM_FORMAT = new DecimalFormat("0.0%");
+      /** Konstante fuer eine vertikale Ausrichtung der Status-Balken */
+      public static final int VERTICAL   = ExpansionBar.VERTICAL;
+      /** Konstante fuer eine horizontale Ausrichtung der Status-Balken */
+      public static final int HORIZONTAL = ExpansionBar.HORIZONTAL;
+
+      private ExpansionBar[] expansionBar   = null;
+      private JLabel[]       expansionLabel = null;
+      private JLabel         typeLabel      = null;
+      private JLabel         divLabel       = null;
+      private Font           sampleFont     = new JLabel().getFont();
+
+      /**
+       * Erzeugt einen neuen Container. Die Balken stellen eine prozentuale
+       * Abweichung von +/- 100% um 0% dar. Die Balken erhalten keine Beschreibung,
+       * sondern werden durchnummeriert.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param tol      Toleranzwert fuer alle Balken (siehe {@link ExpansionBar})
+       */
+      public DeviationContainer(int count, double tol) {
+        this(count,-1,1,0,tol,NUM_FORMAT);
+      }
+
+      /**
+       * Erzeugt einen neuen Container. Als Mitte-Wert fuer die Balken wird
+       * 0 verwendet. Die Balken erhalten keine Beschreibung, sondern werden
+       * durchnummeriert.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param min      Minimum-Wert fuer die Balken
+       * @param max      Maximum-Wert fuer die Balken
+       * @param tol      Toleranzwert fuer alle Balken (siehe {@link ExpansionBar})
+       * @param form     Darstellungsformat fuer die Zahlen im Balken und in der
+       *                 Info-Leiste des untersten Balken
+       */
+      public DeviationContainer(int count, double min, double max, double tol, NumberFormat form) {
+        this(count,min,max,0,tol,form);
+      }
+
+      /**
+       * Erzeugt einen neuen Container. Die Balken werden durchnummeriert.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param min      Minimum-Wert fuer die Balken
+       * @param max      Maximum-Wert fuer die Balken
+       * @param mid      Mitte-Wert fuer die Balken
+       * @param tol      Toleranzwert fuer alle Balken (siehe {@link ExpansionBar})
+       * @param form     Darstellungsformat fuer die Zahlen im Balken und in der
+       *                 Info-Leiste des untersten Balken
+       */
+      public DeviationContainer(int count, double min, double max, double mid, double tol, NumberFormat form) {
+        this(count,null,min,max,mid,tol,form,form);
+      }
+
+      /**
+       * Erzeugt einen neuen Container.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param desc     Beschreibungen fuer die Balken (kann <code>null</code> sein!)
+       * @param min      Minimum-Wert fuer die Balken
+       * @param max      Maximum-Wert fuer die Balken
+       * @param mid      Mitte-Wert fuer die Balken
+       * @param tol      Toleranzwert fuer alle Balken (siehe {@link ExpansionBar})
+       * @param barForm  Darstellungsformat fuer die Zahlen im Balken
+       * @param infoForm Darstellungsformat fuer die Zahlen in der Info-Leiste
+       *                 des untersten Balken
+       */
+      public DeviationContainer(int count, String[] desc, double min, double max, double mid, double tol, NumberFormat barForm, NumberFormat infoForm) {
+        this(count,desc,min,max,mid,LangUtil.createArray(count,tol),barForm,infoForm);
+      }
+
+      /**
+       * Erzeugt einen neuen Container.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param desc     Beschreibungen fuer die Balken (kann <code>null</code> sein!)
+       * @param min      Minimum-Wert fuer die Balken
+       * @param max      Maximum-Wert fuer die Balken
+       * @param mid      Mitte-Wert fuer die Balken
+       * @param tol      Toleranzwert fuer jeden einzelnen Balken (siehe {@link ExpansionBar})
+       * @param barForm  Darstellungsformat fuer die Zahlen im Balken
+       * @param infoForm Darstellungsformat fuer die Zahlen in der Info-Leiste
+       *                 des untersten Balken
+       */
+      public DeviationContainer(int count, String[] desc, double min, double max, double mid, double[] tol, NumberFormat barForm, NumberFormat infoForm) {
+        super();
+        if ( count <= 0 )
+          throw new IllegalArgumentException("At least one divergence bar must specified!");
+        if ( desc!=null && desc.length < count )
+          throw new IllegalArgumentException("Less describtions specified!");
+
+        this.setLayout( new SpringLayout() );
+
+        // PROBLEME mit den Labels bei VERTICAL
+        // --> Label-Breite wird wohl zu 0
+        int orient = HORIZONTAL;
+
+        sampleFont = sampleFont.deriveFont(Font.BOLD);
+        if (orient == VERTICAL)
+          sampleFont = sampleFont.deriveFont( AffineTransform.getRotateInstance(Math.PI/2) );
+
+        // Label erzeugen
+        typeLabel = new JLabel("Type");
+        divLabel = new JLabel("Divergence");
+        typeLabel.setFont(sampleFont);
+        divLabel.setFont(sampleFont);
+
+        // Statusbalken erzeugen
+        this.expansionBar   = new ExpansionBar[count];
+        this.expansionLabel = new JLabel[count];
+        for (int i=0; i<count; i++) {
+          expansionBar[i]   = new ExpansionBar(orient,ExpansionBar.LINEAR,min,max,mid,-tol[i],tol[i],0,barForm,infoForm);
+          expansionLabel[i] = new JLabel( desc!=null && i<desc.length ? desc[i] : String.valueOf(i));
+          if ( orient == HORIZONTAL ) {
+            expansionLabel[i].setHorizontalAlignment(JLabel.CENTER);
+            expansionLabel[i].setVerticalAlignment(JLabel.TOP);
+          } else {
+            expansionLabel[i].setFont( expansionLabel[i].getFont().deriveFont( AffineTransform.getRotateInstance(Math.PI/2) ) );
+            expansionLabel[i].setHorizontalAlignment(JLabel.LEFT);
+            expansionLabel[i].setVerticalAlignment(JLabel.CENTER);
+          }
+        }
+        // beim untersten Balken sollen die Labels erscheinen
+        expansionBar[count-1].setValueLabelsPainted(true);
+
+        // Komponenten einfuegen und ausrichten
+        if ( orient == HORIZONTAL ) {
+          typeLabel.setHorizontalAlignment(JLabel.CENTER);
+          typeLabel.setVerticalAlignment(JLabel.BOTTOM);
+          divLabel.setHorizontalAlignment(JLabel.CENTER);
+          divLabel.setVerticalAlignment(JLabel.BOTTOM);
+          add( typeLabel );
+          add( divLabel );
+          for (int i=0; i<count; i++) {
+            add( expansionLabel[i] );
+            add( expansionBar[i] );
+          }
+          // Layout ausrichten
+          SpringUtilities.makeCompactGrid(this,getComponentCount()/2,2,0,0,10,0);
+        } else {
+          typeLabel.setHorizontalAlignment(JLabel.CENTER);
+          typeLabel.setVerticalAlignment(JLabel.CENTER);
+          divLabel.setHorizontalAlignment(JLabel.CENTER);
+          divLabel.setVerticalAlignment(JLabel.CENTER);
+          add( divLabel );
+          for (int i=0; i<count; i++)
+            add( expansionBar[i] );
+          add( typeLabel );
+          for (int i=0; i<count; i++)
+            add( expansionLabel[i] );
+          // Layout ausrichten
+          SpringUtilities.makeCompactGrid(this,2,getComponentCount()/2,0,0,10,0);
+        }
+      }
+
+      /**
+       * Setzt den Toleranzwert fuer alle Balken.
+       */
+      public void setTolerance(double tol) {
+        for (int i=0; i<expansionBar.length; i++) {
+          expansionBar[i].setMinimumTolerance( -tol );
+          expansionBar[i].setMaximumTolerance(  tol );
+        }
+      }
+
+      /**
+       * Setzt den Wert fuer alle Balken.
+       */
+      public void setExpansion(double[] value) {
+        for (int i=0; i<value.length; i++)
+          setExpansion(i,value[i]);
+      }
+
+      /**
+       * Setzt die Beschreibung fuer einen Balken.
+       */
+      public void setBarDesc(int idx, String text) {
+        expansionLabel[idx].setText(text);
+      }
+
+      /**
+       * Setzt den Wert fuer einen Balken.
+       */
+      public void setExpansion(int idx, double value) {
+        expansionBar[idx].setValue(value);
+      }
+
+      /**
+       * Setzt die Beschreibung die oberhalb der Balken-Beschreibungen steht.
+       */
+      public void setBarDescHeader(String text) {
+        typeLabel.setText(text);
+      }
+
+      /**
+       * Setzt die Beschreibung die oberhalb der Balken steht.
+       */
+      public void setBarHeader(String text) {
+        divLabel.setText(text);
+      }
+
+    }
+  }
+
+  ////////////////////////////////////////////////////////////////////////
+  ////////////////////   Nur zu temporaeren Zwecken   ////////////////////
+  ////////////////////////////////////////////////////////////////////////
+  private java.io.BufferedWriter logWriter = null;
+  private void openLog(int stepNo) {
+    if ( logWriter != null )
+      closeLog();
+    try {
+      logWriter = new java.io.BufferedWriter( new java.io.OutputStreamWriter( new java.io.FileOutputStream("Clue_"+stepNo+".log") ) );
+    } catch (Exception err) {
+      statusOut.println("Fehler beim Erzeugen des Log-Files!");
+    }
+  }
+
+  private void appendLog(Object... text) {
+    if ( logWriter!=null )
+      for (int i=0; i<text.length; i++)
+        try {
+          logWriter.write(text[i].toString());
+          if ( !text[i].equals("\n") )
+            logWriter.write("\t");
+        } catch (Exception err) {
+          statusOut.println("Fehler beim Schreiben in das Log-File!");
+        }
+  }
+
+  private void closeLog() {
+    try {
+      if ( logWriter != null ) {
+        logWriter.flush();
+        logWriter.close();
+        logWriter = null;
+      }
+    } catch (Exception err) {
+      statusOut.println("Fehler beim Schliessen des Log-Files!");
+    }
+  }
+  ////////////////////////////////////////////////////////////////////////
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueModelContentManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueModelContentManager.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueModelContentManager.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,796 @@
+package edu.bonn.xulu.plugin.model.parallel;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyReadAccess;
+import schmitzm.data.property.MatrixProperty;
+
+import schmitzm.temp.BaseTypeUtil;
+
+import edu.bonn.xulu.model.ModelResource;
+import edu.bonn.xulu.model.AbstractModelResource;
+import edu.bonn.xulu.model.ValuePropertyResource;
+import edu.bonn.xulu.model.AbstractModelContentManager;
+import edu.bonn.xulu.data.XuluDataException;
+
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+
+/**
+ * Diese Klasse verwaltet die Ressourcen fuer das {@linkplain ClueModelParallel Clue-Modell}
+ * und prueft diese auf Korrektheit.<br>
+ * Die Art der benoetigten Ressourcen ist der {@linkplain ClueModelParallel Model-Doku}
+ * zu entnehmen.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class ClueModelContentManager extends AbstractModelContentManager {
+    /** Ressource: Simulation step count */
+    public  static final int    MODELSTEPS  = 0; // Nummer der Ressource
+    private static final int    MODELSTEPS_MIN  = 1;
+    private static final int    MODELSTEPS_MAX  = 50;
+    private static final String MODELSTEPS_DESC = "Number of time steps (".concat(String.valueOf(MODELSTEPS_MIN)).concat("-").concat(String.valueOf(MODELSTEPS_MAX)).concat(")");
+    /** Ressource: Type of tolerance expression for demand compliance */
+    public  static final int    TOLERANCETYPE      = 1; // Nummer der Ressource
+    private static final String TOLERANCETYPE_DESC = "Type of tolerance expressions ["+ClueModelParallel.TOLTYPE_PCT+" = perc.; "+ClueModelParallel.TOLTYPE_ABS+" = abs.] (integer)";
+    /** Ressource: Tolerance for demand compliance for each lu type */
+    public  static final int    TOLERANCESINGLE      = 2; // Nummer der Ressource
+    private static final String TOLERANCESINGLE_DESC = "Demand tolerance for each single land use type (double)";
+    /** Ressource: Average tolerance for demand compliance */
+    public  static final int    TOLERANCEAVERAGE      = 3; // Nummer der Ressource
+    private static final String TOLERANCEAVERAGE_DESC = "Average tolerance for land use demand (double)";
+    /** Ressource: Toleranz fuer Bedarfe */
+    public  static final int    CONVFACTQM      = 4; // Nummer der Ressource
+    private static final String CONVFACTQM_DESC = "Conversion factor: demand unit to qm (double)";
+    /** Ressource: Base scenario */
+    public  static final int    BASESCENARIO      = 5; // Nummer der Ressource
+    private static final String BASESCENARIO_DESC = "Base scenatio (float-Grid)";
+    /** Ressource: Land use history of base scenario */
+    public  static final int    LUHISTORY      = 6; // Nummer der Ressource
+    private static final String LUHISTORY_DESC = "Land use history (float-Grid)";
+    /** Ressource: LU-Conversion-Matrix */
+    public  static final int    LUCONV      = 7; // Nummer der Ressource
+    private static final String LUCONV_DESC = "Land use conversion matrix (integer-Matrix)";
+    /** Ressource: Conversion elasticity */
+    public  static final int    ELASTICITY      = 8; // Nummer der Ressource
+    private static final String ELASTICITY_DESC = "Conversion elasticity (double-List)";
+    // Ressource: Area restrictions
+    public  static final int    AREARESTR      = 9; // Nummer der Ressource
+    private static final String AREARESTR_DESC = "Area restrictions (float-Grid)";
+    /** Ressource: Demand scenario */
+    public  static final int    DEMAND      = 10; // Nummer der Ressource
+    private static final String DEMAND_DESC = "Demand scenario (integer-Matrix)";
+    /** Ressource: Static driving forces */
+    public  static final int    STATDF      = 11; // Nummer der Ressource
+    private static final String STATDF_DESC = "Static driving forces (float-MultiGrid)";
+    /** Ressource: List of the dynamic driving force types */
+    public  static final int    DYNDFTYPES      = 12; // Nummer der Ressource
+    private static final String DYNDFTYPES_DESC = "Dynamic driving force types (int-List)";
+    /** Ressource: Dynamic driving forces */
+    public  static final int    DYNDF      = 13; // Nummer der Ressource
+    private static final String DYNDF_DESC = "Dynamic driving forces (float-MultiGrid)";
+    /** Ressource: Regression results */
+    public  static final int    REGRESSION      = 14; // Nummer der Ressource
+    private static final String REGRESSION_DESC = "Regression results (double-Matrix)";
+    /** Ressource: Gewichtung der Neighborhood-Regression results */
+    public  static final int    NBHWEIGHTS     = 15; // Nummer der Ressource
+    private static final String NBHWEIGHTS_DESC = "Weight of neighborhood (double-List)";
+    /** Ressource: Neighborhood-Settings */
+    public  static final int    NBHSETTINGS      = 16; // Nummer der Ressource
+    private static final String NBHSETTINGS_DESC = "Neighborhood settings (double-Matrix)";
+    /** Ressource: Neighborhood-Regression results */
+    public  static final int    NBHREGRESSION      = 17; // Nummer der Ressource
+    private static final String NBHREGRESSION_DESC = "Regression results for neighborhood (double-Matrix)";
+
+    /** Ressource: Temp-Raster for actual LU History */
+    public  static final int    ACTLUHISTORY      = 18; // Nummer der Ressource
+    private static final String ACTLUHISTORY_DESC = "Temp-Raster for actual land use history (float-Grid)";
+    /** Ressource: Temp-Raster for LU Probabilities */
+    public  static final int    LUPROB      = 19; // Nummer der Ressource
+    private static final String LUPROB_DESC = "Temp-Raster for land use probabilities (float-MultiGrid)";
+    /** Ressource: Temp-Raster for LU Probabilities */
+    public  static final int    NBHPROB      = 20; // Nummer der Ressource
+    private static final String NBHPROB_DESC = "Temp-Raster for neighborhood probabilities (float-MultiGrid)";
+    /** Ressource: Temp-List for iteration variables */
+    public  static final int    ITERVAR      = 21; // Nummer der Ressource
+//    private static final String ITERVAR_DESC = "Temp-List for iteration variables (double-List)";
+    private static final String ITERVAR_DESC = "Temp-List for iteration variables (float-List)";
+
+    /** Ressource: Temp-Raster for actual LU */
+    public  static final int    ACTLU      = 22; // Nummer der Ressource
+    private static final String ACTLU_DESC = "Temp-Raster for actual land use (float-Grid)";
+    /** Ressource: Out-Rasters for time step results */
+    public  static final int    STEPRESULTS      = 23; // Nummer der Ressource
+    private static final String STEPRESULTS_DESC = "Out-Rasters time step results (float-MultiGrid)";
+
+  /**
+   * Erzeugt einen neuen ContentManager fuer das {@linkplain ClueModelParallel ClueModelParallel}.
+   */
+  public ClueModelContentManager() {
+    super(24);
+    // Ressourcen festlegen
+    resource[MODELSTEPS]       = new ModelStepResource(ModelResource.CATEGORY_INPUT,MODELSTEPS_DESC,MODELSTEPS_MIN,MODELSTEPS_MAX);
+    resource[TOLERANCETYPE]    = new ToleranceTypeResource(ModelResource.CATEGORY_INPUT,TOLERANCETYPE_DESC);
+    resource[TOLERANCESINGLE]  = new SingleToleranceResource(ModelResource.CATEGORY_INPUT,TOLERANCESINGLE_DESC);
+    resource[TOLERANCEAVERAGE] = new AverageToleranceResource(ModelResource.CATEGORY_INPUT,TOLERANCEAVERAGE_DESC);
+    resource[CONVFACTQM]       = new ConversionFactorQMResource(ModelResource.CATEGORY_INPUT,CONVFACTQM_DESC);
+    resource[BASESCENARIO]     = new InitialScenarioResource(ModelResource.CATEGORY_INPUT,BASESCENARIO_DESC);
+    resource[LUHISTORY]        = new LUHistoryResource(ModelResource.CATEGORY_INPUT,LUHISTORY_DESC);
+    resource[LUCONV]           = new LUConversionMatrixResource(ModelResource.CATEGORY_INPUT,LUCONV_DESC);
+    resource[ELASTICITY]       = new ConversionElasticityResource(ModelResource.CATEGORY_INPUT,ELASTICITY_DESC);
+    resource[AREARESTR]        = new AreaRestrictionsResource(ModelResource.CATEGORY_INPUT,AREARESTR_DESC);
+    resource[DEMAND]           = new DemandScenarioResource(ModelResource.CATEGORY_INPUT,DEMAND_DESC);
+    resource[STATDF]           = new StaticDrivingForcesResource(ModelResource.CATEGORY_INPUT,STATDF_DESC);
+    resource[DYNDFTYPES]       = new DynamicDrivingForceTypesResource(ModelResource.CATEGORY_INPUT,DYNDFTYPES_DESC);
+    resource[DYNDF]            = new DynamicDrivingForcesResource(ModelResource.CATEGORY_INPUT,DYNDF_DESC);
+    resource[REGRESSION]       = new RegressionResultsResource(ModelResource.CATEGORY_INPUT,REGRESSION_DESC);
+    resource[NBHWEIGHTS]       = new NeighborhoodWeightsResource(ModelResource.CATEGORY_INPUT,NBHWEIGHTS_DESC);
+    resource[NBHSETTINGS]      = new NeighborhoodSettingsResource(ModelResource.CATEGORY_INPUT,NBHSETTINGS_DESC);
+    resource[NBHREGRESSION]    = new NeighborhoodRegressionResultsResource(ModelResource.CATEGORY_INPUT,NBHREGRESSION_DESC);
+    resource[ACTLU]            = new ActualLUResource(ModelResource.CATEGORY_OUTPUT,ACTLU_DESC);
+    resource[ACTLUHISTORY]     = new ActualLUHistoryResource(ModelResource.CATEGORY_TEMP,ACTLUHISTORY_DESC);
+    resource[LUPROB]           = new LUProbabilitiesResource(ModelResource.CATEGORY_TEMP,LUPROB_DESC);
+    resource[NBHPROB]          = new NeighborhoodProbabilitiesResource(ModelResource.CATEGORY_TEMP,NBHPROB_DESC);
+    resource[ITERVAR]          = new IterationVariablesResource(ModelResource.CATEGORY_TEMP,ITERVAR_DESC);
+    resource[STEPRESULTS]      = new StepResultsResource(ModelResource.CATEGORY_OUTPUT,STEPRESULTS_DESC);
+  }
+
+  /**
+   * Prueft alle Modell-Ressourcen auf Korrektheit.
+   * Neben den lokalen Bedingungen an die Ressourcen (die bereits durch
+   * die Methode der Oberklasse gechecked werden), prueft diese Methode, ob
+   * <ul>
+   * <li>ob die Raster alle dieselbe Groesse haben, wie das Base Scenario</li>
+   * <li>die MultiGrids genug Raster enthalten</li>
+   * <li>die Matrizen die passenden Groessen haben</li>
+   * </ul>
+   */
+  public void checkAndError() {
+    super.checkAndError();
+
+    // Parameter ermitteln, die fuer die Konsistenz relevant sind
+    int n = getLUConversionMatrix().getSize(0);
+    int m = getStaticDrivingForces().getGridCount();
+    int t = getStepCount().getOneTimeReadAccess().getValueAsInt();
+    WritableGrid baseGrid = (WritableGrid)getBaseScenario().getOneTimeReadAccess().getValue();
+    WritableGrid testGrid = null;
+
+    // Conversion Elasticity muss n Eintraege haben
+    int ceCount = getConversionElasticity().getOneTimeReadAccess().getCount();
+    if ( ceCount < n )
+      throw new XuluDataException("List for conversion elasticity must have at least "+n+" entries (one for each land use types)...");
+    // Area Restriction Raster muss dem Base Scenario entsprechen
+    testGrid = (WritableGrid)getAreaRestrictions().getOneTimeReadAccess().getValue();
+    checkRasterDim(baseGrid,BASESCENARIO_DESC,testGrid,AREARESTR_DESC);
+
+    // Demand Scenario muss (n,t)-Matrix sein
+    int[] dsSize = getDemandScenario().getSize();
+    if ( dsSize[0] < n )
+      throw new XuluDataException("Matrix for demand scenario must have "+n+" column (one for each land use type)...");
+    if ( dsSize[1] < t )
+      throw new XuluDataException("Matrix for demand scenario must have "+t+" rows (one for each time step)...");
+
+    // Driving Forces muessen m Raster, die dem Base Scenario entsprechen,
+    MultiGrid sdfGrid = getStaticDrivingForces();
+    if ( sdfGrid.getGridCount() < m )
+      throw new XuluDataException("MultiGrid for static driving forces must contain at leat "+m+" entries (one for each driving force)...");
+    // erstes befuelltes Raster checken
+    checkRasterDim(baseGrid,BASESCENARIO_DESC,sdfGrid.getFirstNotNullGrid(),STATDF_DESC);
+
+    // Liste der Dynamischen DF darf nur m Eintraege haben und Werte zwischen 0 und m enthalten
+    int ddfCount = 0;
+    if ( getDynamicDrivingForceTypes() != null ) {
+      ListPropertyReadAccess ddf = getDynamicDrivingForceTypes().getReadAccess(this);
+      ddfCount = ddf.getCount();
+      if ( ddfCount > m )
+        throw new XuluDataException("List of dynamic driving forces must not have more than "+m+" entries...");
+      for (int i=0; i<ddfCount; i++)
+        if ( ddf.getValueAsInt(i) < 0 || ddf.getValueAsInt(i) >= m )
+          throw new XuluDataException("Only values between 0 and "+(m-1)+" are allowed in list of dynamic driving forces...");
+      ddf.release();
+    }
+
+    // Werden dyn. DF verwendet, muessen auch Raster angegeben werden
+    MultiGrid ddfGrids = getDynamicDrivingForces();
+    if ( ddfCount > 0 && ddfGrids == null )
+      throw new XuluDataException("Dynamic Driving Forces are uses! Resource '"+DYNDF_DESC+"' is not allowed to be null...");
+    // Es muessen mind. t Raster fuer jeden dyn. DF angegeben werden
+    if ( ddfCount > 0 && ddfGrids.getGridCount() < ddfCount*t )
+      throw new XuluDataException("MultiGrid for dynamic driving forces must contain at leat "+(ddfCount*t)+" entries (one for each driving force at every time step)...");
+    // Fuer jeden DF muss dieselbe Anzahl an Grids enthalten sein
+    if ( ddfCount > 0 && ddfGrids.getGridCount() % ddfCount != 0 )
+      throw new XuluDataException("MultiGrid for dynamic driving forces must contain the same number of grids for all driving forces...");
+
+    // Regression Results muss (m+1,n)-Matrix sein
+    int[] rrSize = getRegressionResults().getSize();
+    if ( rrSize[0] < m+1 )
+      throw new XuluDataException("Matrix for regression results must have "+(m+1)+" columns (one for the constant and one for each driving force)...");
+    if ( rrSize[1] < n )
+      throw new XuluDataException("Matrix for regression results must have "+n+" rows (one for each land use type)...");
+
+    // Wenn angegeben, muss die Liste der Neighborhood Weights mind. n Eintraege haben
+    ListProperty nbhWeights = getNeighborhoodWeights();
+    if ( nbhWeights != null ) {
+      if ( nbhWeights.getOneTimeReadAccess().getCount() < n )
+        throw new XuluDataException("List of neighborhood weights must have at least "+n+" entries (one for each land use type)...");
+    }
+
+    // Wenn angegeben, muss die Matrix der Neighborhood Settings in der 3. Dimension
+    // die Groessen n haben
+    if ( nbhWeights != null ) {
+      if ( getNeighborhoodSettings() == null )
+        throw new XuluDataException("Neighborhood settings must be specified...");
+      int[] nbSize = getNeighborhoodSettings().getSize();
+      if ( nbSize[0]%2 == 0 || nbSize[1]%2 == 0 )
+        throw new XuluDataException("Neighborhood settings must be specified in matrix of uneven size in dimension 1 and 2 (the center is the considered cell)...");
+      if ( getNeighborhoodSettings().getSize(2) < n )
+        throw new XuluDataException(n+" neighborhood settings must be specified in matrix (one for each land use type)...");
+
+    }
+
+    // Wenn angegeben, muss die Matrix der Neighborhood Regression eine
+    // (n+1,n)-Matrix sein
+    if ( nbhWeights != null ) {
+      if ( getNeighborhoodRegression() == null )
+        throw new XuluDataException("Neighborhood regression must be specified...");
+      int[] nbSize = getNeighborhoodRegression().getSize();
+      if ( nbSize[0] < n+1 )
+        throw new XuluDataException("Matrix for neighborhood regression results must have "+(n+1)+" columns (one for the constant and one for each land use type)...");
+      if ( nbSize[1] < n )
+        throw new XuluDataException("Matrix for neighborhood regression results must have "+n+" rows (one for each land use type)...");
+    }
+
+    // Raster fuer die aktuelle LU muss dem Base Scenario entsprechen
+    testGrid = (WritableGrid)getActLUResult().getOneTimeReadAccess().getValue();
+    checkRasterDim(baseGrid,BASESCENARIO_DESC,testGrid,ACTLU_DESC);
+
+    // Raster fuer die aktuelle LU History muss dem Base Scenario entsprechen
+    testGrid = (WritableGrid)getActLUHistory().getOneTimeReadAccess().getValue();
+    checkRasterDim(baseGrid,BASESCENARIO_DESC,testGrid,ACTLUHISTORY_DESC);
+
+//    // MultiGrid fuer die LU-Wahrscheinlichkeiten muss n Raster enthalten,
+//    // die dem Base Scenario entsprechen
+//    MultiGrid luProbGrids = this.getLUProbabilities();
+//    if ( luProbGrids.getGridCount() < n )
+//      throw new XuluDataException("MultiGrid for land use probabilities must contain at leat "+n+" grids (one for each land use type)...");
+//    checkRasterDim(baseGrid,BASESCENARIO_DESC,luProbGrids.getGrid(0),LUPROB_DESC);
+    // MultiGrid fuer die LU-Wahrscheinlichkeiten muss dem Base Scenario entsprechen
+    // Die n Inhalt-Grids werden bei der Modell-Initialisierung dynamisch erzeugt!
+    MultiGrid luProbGrids = this.getLUProbabilities();
+    checkRasterDim(baseGrid,BASESCENARIO_DESC,luProbGrids.getTemplateGrid(),LUPROB_DESC);
+
+//    // MultiGrid fuer die Nachbarschafts-Wahrscheinlichkeiten muss n Raster enthalten,
+//    // die dem Base Scenario entsprechen
+//    if ( nbhWeights != null ) {
+//      MultiGrid nbhProbGrids = this.getNeighborhoodProbabilities();
+//      if ( nbhProbGrids == null )
+//        throw new XuluDataException("Temp. raster for neighborhood probabilities must be specified...");
+//      if ( nbhProbGrids.getGridCount() < n )
+//        throw new XuluDataException("MultiGrid for neighborhood probabilities must contain at leat "+n+" grids (one for each land use type)...");
+//      checkRasterDim(baseGrid,BASESCENARIO_DESC,nbhProbGrids.getGrid(0),LUPROB_DESC);
+//    }
+    // MultiGrid fuer die Nachbarschafts-Wahrscheinlichkeiten muss dem Base Scenario entsprechen
+    // Die n Inhalt-Grids werden bei der Modell-Initialisierung dynamisch erzeugt!
+    if ( nbhWeights != null ) {
+      MultiGrid nbhProbGrids = this.getNeighborhoodProbabilities();
+      if ( nbhProbGrids == null )
+        throw new XuluDataException("Temp. raster for neighborhood probabilities must be specified...");
+      checkRasterDim(baseGrid,BASESCENARIO_DESC,nbhProbGrids.getTemplateGrid(),LUPROB_DESC);
+    }
+
+//    // Wenn angegeben, muss das MultiGrid fuer die Zeitschritt-Ergebnisse
+//    // t Raster enthalten, die dem Base Scenario entsprechen
+//    MultiGrid resultGrids = this.getStepLUResults();
+//    if (resultGrids != null) {
+//      if ( resultGrids.getGridCount() < t )
+//        throw new XuluDataException("MultiGrid for time step results must contain at leat "+t+" grids (one for each time step)...");
+//      checkRasterDim(baseGrid, BASESCENARIO_DESC, resultGrids.getGrid(0),STEPRESULTS_DESC);
+//    }
+    // Das MultiGrid fuer die Zeitschritt-Ergebnisse dem Base Scenario entsprechen
+    // Die t Inhalt-Grids werden waehrend des Modellablaufs dynamisch erzeugt!
+    MultiGrid resultGrids = this.getStepLUResults();
+    checkRasterDim(baseGrid, BASESCENARIO_DESC, resultGrids.getTemplateGrid(),STEPRESULTS_DESC);
+  }
+
+  /**
+   * Vergleicht zwei Raster auf gleiche Struktur (Hoehe, Breite, Zell-Hoehe,
+   * Zell-Breite, Sample-Type).
+   */
+  private static void checkRasterDim(WritableGrid grid1, String desc1, WritableGrid grid2, String desc2) {
+    if ( grid1.getWidth() != grid2.getWidth() )
+      throw new XuluDataException(createCompareMessage("Grid width",desc1,desc2));
+    if ( grid1.getHeight() != grid2.getHeight() )
+      throw new XuluDataException(createCompareMessage("Grid height",desc1,desc2));
+    if ( grid1.getCellWidth() != grid2.getCellWidth() )
+      throw new XuluDataException(createCompareMessage("Cell width",desc1,desc2));
+    if ( grid1.getCellHeight() != grid2.getCellHeight() )
+      throw new XuluDataException(createCompareMessage("Cell height",desc1,desc2));
+    if ( grid1.getSampleType() != grid2.getSampleType() )
+      throw new XuluDataException(createCompareMessage("Grid sample-type",desc1,desc2));
+  }
+
+  /**
+   * Erzeugt eine Fehlermeldung fuer eine bestimmte inkompatible Raster-Struktur.
+   */
+  private static String createCompareMessage(String compType, String objDesc1, String objDesc2) {
+    return compType.concat(" of '").concat(objDesc1).concat("' is incompatible to '").concat(objDesc2).concat("'...");
+  }
+
+  //////////////////////////////////////////////////////////////////////
+  ///////   vereinfachende Zugriffsmethoden auf Ressourcen   ///////////
+  //////////////////////////////////////////////////////////////////////
+  /** Liefert Zugriff auf die Ressource "Time Steps". */
+  public ScalarProperty getStepCount() {
+    return (ScalarProperty)getResourceData(this.MODELSTEPS);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Art der Abweichungsangaben". */
+  public ScalarProperty getDemandToleranceType() {
+    return (ScalarProperty)getResourceData(this.TOLERANCETYPE);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Einzel-Abweichung von Bedarfen". */
+  public ScalarProperty getSingleDemandTolerance() {
+    return (ScalarProperty)getResourceData(this.TOLERANCESINGLE);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Durchschnitts-Abweichung von Bedarfen". */
+  public ScalarProperty getAverageDemandTolerance() {
+    return (ScalarProperty)getResourceData(this.TOLERANCEAVERAGE);
+  }
+
+
+  /** Liefert Zugriff auf die Ressource "Umrechnungsfaktor Bedarfseinheit -> qm". */
+  public ScalarProperty getConversionFactor() {
+    return (ScalarProperty)getResourceData(this.CONVFACTQM);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Base Scenario". */
+  public ScalarProperty getBaseScenario() {
+    return (ScalarProperty)getResourceData(this.BASESCENARIO);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Land use History". */
+  public ScalarProperty getLUHistory() {
+    return (ScalarProperty)getResourceData(this.LUHISTORY);
+  }
+
+  /** Liefert Zugriff auf die Ressource "LU Conversion Matrix". */
+  public MatrixProperty getLUConversionMatrix() {
+    return (MatrixProperty)getResourceData(this.LUCONV);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Conversion Elasticity". */
+ public ListProperty getConversionElasticity() {
+    return (ListProperty)getResourceData(this.ELASTICITY);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Area Restrictions". */
+  public ScalarProperty getAreaRestrictions() {
+    return (ScalarProperty)getResourceData(this.AREARESTR);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Demand Scenario". */
+  public MatrixProperty getDemandScenario() {
+    return (MatrixProperty)getResourceData(this.DEMAND);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Static Driving Forces". */
+  public MultiGrid getStaticDrivingForces() {
+    return (MultiGrid)getResourceData(this.STATDF);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Dynamic Driving Force Types". */
+ public ListProperty getDynamicDrivingForceTypes() {
+    return (ListProperty)getResourceData(this.DYNDFTYPES);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Dynamic Driving Forces". */
+ public MultiGrid getDynamicDrivingForces() {
+    return (MultiGrid)getResourceData(this.DYNDF);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Regression Results". */
+  public MatrixProperty getRegressionResults() {
+    return (MatrixProperty)getResourceData(this.REGRESSION);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Neighborhood Weights". */
+  public ListProperty getNeighborhoodWeights() {
+    return (ListProperty)getResourceData(this.NBHWEIGHTS);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Neighborhood Settings". */
+  public MatrixProperty getNeighborhoodSettings() {
+    return (MatrixProperty)getResourceData(this.NBHSETTINGS);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Neighborhood Regression Results". */
+  public MatrixProperty getNeighborhoodRegression() {
+    return (MatrixProperty)getResourceData(this.NBHREGRESSION);
+  }
+
+  /** Liefert Zugriff auf die Ausgabe-Ressource "Aktuelle Landnutzung". */
+  public ScalarProperty getActLUResult() {
+    return (ScalarProperty)getResourceData(this.ACTLU);
+  }
+
+  /** Liefert Zugriff auf die Ausgabe-Ressource "LU-Wahrscheinlichkeiten". */
+  public MultiGrid getLUProbabilities() {
+    return (MultiGrid)getResourceData(this.LUPROB);
+  }
+
+  /** Liefert Zugriff auf die Ausgabe-Ressource "Nachbarschafts-Wahrscheinlichkeiten". */
+  public MultiGrid getNeighborhoodProbabilities() {
+    return (MultiGrid)getResourceData(this.NBHPROB);
+  }
+
+  /** Liefert Zugriff auf die Ausgabe-Ressource "Iterationsvariablen". */
+  public ListProperty getIterationVariables() {
+    return (ListProperty)getResourceData(this.ITERVAR);
+  }
+
+  /** Liefert Zugriff auf die Ressource "Aktuelle Land use History". */
+  public ScalarProperty getActLUHistory() {
+    return (ScalarProperty)getResourceData(this.ACTLUHISTORY);
+  }
+
+  /** Liefert Zugriff auf die Ausgabe-Ressource "LU zu jedem Zeitschritt". */
+  public MultiGrid getStepLUResults() {
+    return (MultiGrid)getResourceData(this.STEPRESULTS);
+  }
+
+  //////////////////////////////////////////////////////////////////////
+  ///////////   Klassen fuer die benoetigten Ressourcen   //////////////
+  //////////////////////////////////////////////////////////////////////
+  /**
+   * Ressource fuer Simulationsschritte.
+   */
+  private class ModelStepResource extends ValuePropertyResource {
+    private int stepMin = 0;
+    private int stepMax = 0;
+
+    public ModelStepResource(int cat,String desc, int stepMin, int stepMax) {
+      super(cat,desc,ScalarProperty.class,Number.class,false);
+      this.stepMin = stepMin;
+      this.stepMax = stepMax;
+    }
+
+    public void checkTypeAndError(Object data) {
+      super.checkTypeAndError(data);
+      // muss als Datentyp Long oder Integer haben
+      if ( !BaseTypeUtil.isNumeric(((ScalarProperty)data).getType()) ||
+            BaseTypeUtil.isDecimal(((ScalarProperty)data).getType()) )
+        throwDataException("Long- or Integer-Property");
+    }
+
+    public void checkAndError(Object data) {
+      super.checkAndError(data);
+      // muss zwischen 1 und 20 liegen
+      checkRangeAndError(this,((ScalarProperty)data).getOneTimeReadAccess().getValueAsLong(),stepMin,stepMax);
+    }
+  }
+
+  /**
+   * Ressource fuer Art der Toleranz-Angaben (prozentual, absolut).
+   */
+  private class ToleranceTypeResource extends ValuePropertyResource {
+    public ToleranceTypeResource(int cat,String desc) {
+      super(cat,desc,ScalarProperty.class,Integer.class,false);
+    }
+    public void checkAndError(Object data) {
+      super.checkAndError(data);
+      // Flag muss 0 (prozentual) oder 1 (absolut) sein
+      checkRangeAndError(this,((ScalarProperty)data).getOneTimeReadAccess().getValueAsInt(),0,1);
+    }
+  }
+
+  /**
+   * Ressource fuer Toleranz der einzelnen Bedarfe.
+   */
+  private class SingleToleranceResource extends ValuePropertyResource {
+    public SingleToleranceResource(int cat,String desc) {
+      super(cat,desc,ScalarProperty.class,Number.class,false);
+    }
+    public void checkAndError(Object data) {
+      super.checkAndError(data);
+      // muss groesser 0 sein
+      checkRangeAndError(this,((ScalarProperty)data).getOneTimeReadAccess().getValueAsDouble(),0,Double.MAX_VALUE);
+    }
+  }
+
+  /**
+   * Ressource fuer Durchschnitts-Toleranz der einzelnen Bedarfe.
+   */
+  private class AverageToleranceResource extends ValuePropertyResource {
+    public AverageToleranceResource(int cat,String desc) {
+      super(cat,desc,ScalarProperty.class,Number.class,false);
+    }
+    public void checkAndError(Object data) {
+      super.checkAndError(data);
+      // muss groesser 0 sein
+      checkRangeAndError(this,((ScalarProperty)data).getOneTimeReadAccess().getValueAsDouble(),0,Double.MAX_VALUE);
+    }
+  }
+
+  /**
+   * Ressource fuer Umrechnungsfaktor Bedarfseinheit >> Quadratmeter.
+   */
+  private class ConversionFactorQMResource extends ValuePropertyResource {
+    public ConversionFactorQMResource(int cat,String desc) {
+      super(cat,desc,ScalarProperty.class,Double.class,false);
+    }
+  }
+
+  /**
+   * Ressource fuer Ausgangsszenario.
+   */
+  private class InitialScenarioResource extends ValuePropertyResource {
+    public InitialScenarioResource(int cat,String desc) {
+      super(cat,desc,ScalarProperty.class,WritableGrid.class,false);
+    }
+  }
+
+  /**
+   * Ressource fuer LU-History.
+   */
+  private class LUHistoryResource extends ValuePropertyResource {
+    public LUHistoryResource(int cat,String desc) {
+      super(cat,desc,ScalarProperty.class,WritableGrid.class,false);
+    }
+  }
+
+  /**
+   * Ressource fuer LU-Conversion-Matrix.
+   */
+  private class LUConversionMatrixResource extends ValuePropertyResource {
+    public LUConversionMatrixResource(int cat,String desc) {
+      super(cat,desc,MatrixProperty.class,Integer.class,false);
+    }
+    public void checkTypeAndError(Object data) {
+      super.checkTypeAndError(data);
+      // Matrix muss mindestens 2-dimensional sein
+      if ( ((MatrixProperty)data).getDimension() < 2 )
+        throwDataException("At least 2-dimensional Matrix");
+    }
+  }
+
+  /**
+   * Ressource fuer Conversion Elasticity.
+   */
+  private class ConversionElasticityResource extends ValuePropertyResource {
+    public ConversionElasticityResource(int cat,String desc) {
+      super(cat,desc,ListProperty.class,Double.class,false);
+    }
+
+    public void checkAndError(Object data) {
+      super.checkAndError(data);
+      // Alle Werte der Liste muessen zwischen 0 und 1 liegen
+      ListPropertyReadAccess a = ((ListProperty)data).getReadAccess(this);
+      for (int i=0; i<a.getCount(); i++) {
+        double v = a.getValueAsDouble(i);
+        if ( v < 0 || 1 < v ) {
+          a.release();
+          throwDataException("ListProperty with values between 0 and 1");
+        }
+      }
+      a.release();
+    }
+  }
+
+  /**
+   * Ressource fuer Area Restrictions.
+   */
+  private class AreaRestrictionsResource extends ValuePropertyResource {
+    public AreaRestrictionsResource(int cat,String desc) {
+      super(cat,desc,ScalarProperty.class,WritableGrid.class,false);
+    }
+  }
+
+  /**
+   * Ressource fuer Demand Scenario.
+   */
+  private class DemandScenarioResource extends ValuePropertyResource {
+    public DemandScenarioResource(int cat,String desc) {
+      super(cat,desc,MatrixProperty.class,Integer.class,false);
+    }
+
+    public void checkTypeAndError(Object data) {
+      super.checkTypeAndError(data);
+      // Matrix muss mindestens 2-dimensional sein
+      if ( ((MatrixProperty)data).getDimension() < 2 )
+        throwDataException("At least 2-dimensional Matrix");
+    }
+  }
+
+  /**
+   * Ressource fuer Static Driving Forces.
+   */
+  private class StaticDrivingForcesResource extends AbstractModelResource {
+    public StaticDrivingForcesResource(int cat,String desc) {
+      super(cat,desc,MultiGrid.class,false);
+    }
+
+    public void checkTypeAndError(Object data) {
+      if ( data!=null && !(data instanceof MultiGrid) ||
+           data==null && !nullable)
+        throwDataException("MultiGrid");
+    }
+
+    public void checkAndError(Object data) {
+      checkTypeAndError(data);
+    }
+  }
+
+  /**
+   * Ressource fuer Dynamic Driving Force Types.
+   */
+  private class DynamicDrivingForceTypesResource extends ValuePropertyResource {
+    public DynamicDrivingForceTypesResource(int cat,String desc) {
+      super(cat,desc,ListProperty.class,Integer.class,true);
+    }
+  }
+
+  /**
+   * Ressource fuer Dynamic Driving Forces.
+   */
+  private class DynamicDrivingForcesResource extends AbstractModelResource {
+    public DynamicDrivingForcesResource(int cat,String desc) {
+      super(cat,desc,MultiGrid.class,true);
+    }
+
+    public void checkTypeAndError(Object data) {
+      if ( data != null && !(data instanceof MultiGrid) ||
+           data == null && !nullable)
+        throwDataException("MultiGrid");
+    }
+
+    public void checkAndError(Object data) {
+      checkTypeAndError(data);
+    }
+  }
+
+  /**
+   * Ressource fuer Regression Results.
+   */
+  private class RegressionResultsResource extends ValuePropertyResource {
+    public RegressionResultsResource(int cat,String desc) {
+      super(cat,desc,MatrixProperty.class,Double.class,false);
+    }
+    public void checkTypeAndError(Object data) {
+      super.checkTypeAndError(data);
+      // Matrix muss mindestens 2-dimensional sein
+      if ( ((MatrixProperty)data).getDimension() < 2 )
+        throwDataException("At least 2-dimensional Matrix");
+    }
+  }
+
+  /**
+   * Ressource fuer Neighborhood Weight.
+   */
+  private class NeighborhoodWeightsResource extends ValuePropertyResource {
+    public NeighborhoodWeightsResource(int cat,String desc) {
+      super(cat,desc,ListProperty.class,Double.class,true);
+    }
+  }
+
+  /**
+   * Ressource fuer Neighborhood Settings.
+   */
+  private class NeighborhoodSettingsResource extends ValuePropertyResource {
+    public NeighborhoodSettingsResource(int cat,String desc) {
+      super(cat,desc,MatrixProperty.class,Double.class,true);
+    }
+    public void checkTypeAndError(Object data) {
+      super.checkTypeAndError(data);
+      // Matrix muss mindestens 3-dimensional sein
+      if ( data!=null && ((MatrixProperty)data).getDimension() < 3 )
+        throwDataException("At least 3-dimensional Matrix");
+    }
+  }
+
+  /**
+   * Ressource fuer Neighborhood Regression Results.
+   */
+  private class NeighborhoodRegressionResultsResource extends ValuePropertyResource {
+    public NeighborhoodRegressionResultsResource(int cat,String desc) {
+      super(cat,desc,MatrixProperty.class,Double.class,true);
+    }
+    public void checkTypeAndError(Object data) {
+      super.checkTypeAndError(data);
+      // Matrix muss mindestens 2-dimensional sein
+      if ( data!=null && ((MatrixProperty)data).getDimension() < 2 )
+        throwDataException("At least 2-dimensional Matrix");
+    }
+  }
+
+  /**
+   * Ressource fuer die simulierte LU.
+   */
+  private class ActualLUResource extends ValuePropertyResource {
+    public ActualLUResource(int cat,String desc) {
+      super(cat,desc,ScalarProperty.class,WritableGrid.class,false);
+    }
+  }
+
+  /**
+   * Ressource fuer aktuelle LU-History.
+   */
+  private class ActualLUHistoryResource extends ValuePropertyResource {
+    public ActualLUHistoryResource(int cat,String desc) {
+      super(cat,desc,ScalarProperty.class,WritableGrid.class,false);
+    }
+  }
+
+  /**
+   * Ressource fuer die errechneten LU-Wahrscheinlichkeiten.
+   */
+  private class LUProbabilitiesResource extends AbstractModelResource {
+    public LUProbabilitiesResource(int cat,String desc) {
+      super(cat,desc,MultiGrid.class,false);
+    }
+    public void checkTypeAndError(Object data) {
+      if ( data!=null && !(data instanceof MultiGrid) ||
+           data==null && !nullable )
+        throwDataException("MultiGrid");
+    }
+    public void checkAndError(Object object) {
+      checkTypeAndError(object);
+    }
+  }
+
+  /**
+   * Ressource fuer die errechneten Nachbarschafts-Wahrscheinlichkeiten.
+   */
+  private class NeighborhoodProbabilitiesResource extends AbstractModelResource {
+    public NeighborhoodProbabilitiesResource(int cat,String desc) {
+      super(cat,desc,MultiGrid.class,true);
+    }
+    public void checkTypeAndError(Object data) {
+      if ( data!=null && !(data instanceof MultiGrid) ||
+           data==null && !nullable )
+        throwDataException("MultiGrid");
+    }
+    public void checkAndError(Object object) {
+      checkTypeAndError(object);
+    }
+  }
+
+  /**
+   * Ressource fuer Iterationsvariablen.
+   */
+  private class IterationVariablesResource extends ValuePropertyResource {
+    public IterationVariablesResource(int cat,String desc) {
+//      super(cat,desc,ListProperty.class,Double.class,false);
+      super(cat,desc,ListProperty.class,Float.class,false);    }
+  }
+
+  /**
+   * Ressource fuer die einzelnen Zeit-Schritt-Ergebnisse.
+   */
+  private class StepResultsResource extends AbstractModelResource {
+    public StepResultsResource(int cat,String desc) {
+      super(cat,desc,MultiGrid.class,false);
+    }
+
+    public void checkTypeAndError(Object data) {
+      if ( data!=null && !(data instanceof MultiGrid) ||
+           data==null && !nullable )
+        throwDataException("MultiGrid");
+    }
+
+    public void checkAndError(Object object) {
+      checkTypeAndError(object);
+    }
+  }
+
+  /**
+   * Prueft, ob ein Wert in einem bestimmten Bereich liegt. Wenn nicht, wird
+   * fuer die angegebene Ressource eine Exception geworfen.
+   */
+  private static void checkRangeAndError(ModelResource r, double value, double min, double max) {
+    if ( value < min ||  max < value )
+     throw new XuluDataException("'".concat(r.getDesc()).concat("' nicht zul�ssig!"));
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueModelParallel.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueModelParallel.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueModelParallel.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,1386 @@
+package edu.bonn.xulu.plugin.model.parallel;
+
+import java.awt.image.DataBuffer;
+import java.awt.Window;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.geom.AffineTransform;
+import java.io.File;
+
+import javax.swing.BoxLayout;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JCheckBox;
+import javax.swing.JProgressBar;
+import javax.swing.BoundedRangeModel;
+import javax.swing.DefaultBoundedRangeModel;
+import javax.swing.JSlider;
+import javax.swing.SpringLayout;
+import javax.swing.BorderFactory;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.ChangeEvent;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+import java.text.NumberFormat;
+import java.text.DecimalFormat;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.LogManager;
+
+import appl.parallel.data.splittable.SplittableGridLLFactory;
+import appl.parallel.model.AbstractParallelStepModel;
+import appl.parallel.spmd.MultiDataObject;
+import appl.parallel.spmd.SPMDClientInterface;
+import appl.util.GeneralUtil;
+import appl.util.RasterUtil;
+
+import schmitzm.lang.LangUtil;
+
+import schmitzm.data.property.Access;
+import schmitzm.data.property.ValueProperty;
+import schmitzm.data.property.ValuePropertyType;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.ListPropertyReadAccess;
+import schmitzm.data.property.ListPropertyWriteAccess;
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.MatrixProperty;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.PropertyWriteAccess;
+import schmitzm.data.WritableGrid;
+
+import schmitzm.swing.SwingUtil;
+import schmitzm.swing.SpringUtilities;
+import schmitzm.swing.ExpansionBar;
+
+import edu.bonn.xulu.data.XuluDataException;
+import edu.bonn.xulu.model.AbstractStepModel;
+import edu.bonn.xulu.model.ModelContentManager;
+import edu.bonn.xulu.model.AbstractModelContentManager;
+import edu.bonn.xulu.model.ModelResource;
+import edu.bonn.xulu.model.AbstractModelResource;
+import edu.bonn.xulu.model.ValuePropertyResource;
+import edu.bonn.xulu.model.event.ModelIterationStepStartedEvent;
+import edu.bonn.xulu.model.event.ModelIterationStepFinishedEvent;
+
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+import edu.bonn.xulu.plugin.model.clue.ClueModel;
+import edu.bonn.xulu.plugin.model.clue.ClueModelContentManager;
+import edu.bonn.xulu.plugin.model.parallel.ClueTaskDefinition.Task;
+import edu.bonn.xulu.plugin.model.parallel.demo.AverageNeighborhoodParallelDemoModel;
+import edu.bonn.xulu.plugin.model.parallel.demo.AverageNeighborhoodSerialDemoModel;
+
+import schmitzm.temp.BaseTypeUtil;
+
+/**
+ * This class is a parallel version of the {@link ClueModel}. For details on
+ * the {@link ClueModel}, see its documentation. To understand the parallel
+ * module of Xulu please look at the demo algorithms
+ * {@link AverageNeighborhoodSerialDemoModel} and
+ * {@link AverageNeighborhoodParallelDemoModel}. The algorithm was splitted in
+ * the following way: Calculation of the LU-Probabilities, Neighborhood Bounds and
+ * the iteration were outsourced as a single Task named {@link ClueTask}. It is
+ * in general possible of course, to define them in different Tasks. <br>
+ * <br>
+ * Here the chain of actions:<br>
+ * 1.) In the init method, declare all variables which should be used on
+ * serverside are declared<br>
+ * 2.) In Run the LU-Probabilities on the on the Servers<br>
+ * 3.) If this not the first step: Update the neighborhood region<br>
+ * 4.) Calculate the neighborhood probabilities on the servers<br>
+ * 5.) Calculate (local!) the iterationvariable<br>
+ * 6.) Calculate the next Iteration on the servers<br>
+ * 7.) The servers will give back the distributed land cover<br>
+ * 8.) The sum of all distributed land cover (on every server) is calculated<br>
+ * 9.) Based on the sum: If demand is not met: Calculate new iterationvariable
+ * (goto 6.)<br>
+ * 10.) If the demand is met: Merge the outputGrids into the data-source in the
+ * datapool<br>
+ * </ul>
+ * <br>
+ * <br>
+ * Notice that the documentation of this file is a mixture of English and
+ * German. This is due to the fact that Xulu / V works so nicely that very much
+ * of Martin Schmitz' original German-commented {@link ClueModel}-code could be reused.
+ *
+ * @see ClueModelContentManager
+ * @author Dominik Appl
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of
+ *         Bonn/Germany) (original code)
+ * @version 1.0
+ */
+public class ClueModelParallel extends AbstractParallelStepModel {
+  /** Konstante fuer die Toleranz-Art "prozentual". */
+  public static final int TOLTYPE_PCT = 0;
+  /** Konstante fuer die Toleranz-Art "absolut in Bedarf-Einheit". */
+  public static final int TOLTYPE_ABS = 1;
+
+  /** Speichert den ContentManager fuer das Modell.
+   *  @see ClueModelContentManager */
+  protected ClueModelContentManager contManager;
+
+  private final ClueModelGUI  modelGUI = new ClueModelGUI();
+  private final Logger        LOG      = LogManager.getLogger(this.getClass().getName());
+
+  //********** Lese/Schreibrechte, die fuer den gesamten ***********
+  //********** Modellanlauf gehalten werden muessen      ***********
+  private PropertyReadAccess  RA_baseLU       = null; // Base Scenario
+  private PropertyReadAccess  RA_baseLUHist   = null; // Base LU History
+  private PropertyReadAccess  RA_luConv       = null; // LU-Conversion-Matrix
+  private PropertyReadAccess  RA_luElas       = null; // LU-Conversion-Elasticity
+  private PropertyReadAccess  RA_areaRestr    = null; // Area Restrictions
+  private PropertyReadAccess  RA_luDemand     = null; // LU-Bedarfe
+  private PropertyReadAccess  RA_sdfGrids     = null; // Static Driving Forces
+  private PropertyReadAccess  RA_ddfList      = null; // List of dynmic Driving Forces
+  private PropertyReadAccess  RA_ddfGrids     = null; // Dynamic Driving Forces
+  private PropertyReadAccess  RA_regrRes      = null; // Regression Results
+  private PropertyReadAccess  RA_nbhWeights   = null; // Gewichtung der Nachbarschaft pro LU-Typ
+  private PropertyReadAccess  RA_nbhSettings  = null; // Definition der Umgebung pro LU-Typ
+  private PropertyReadAccess  RA_nbhRegrRes   = null; // Regression Results fuer Nachbarschaft
+  private PropertyWriteAccess WA_outActLU     = null; // speichert die aktuell sim. LU
+  private PropertyWriteAccess WA_outActLUHist = null; // speichert die aktuell sim. LU Historie
+  private PropertyWriteAccess WA_outLUProb    = null; // speichert die LU-Wahrscheinlichkeiten
+  private PropertyWriteAccess WA_outNbhProb   = null; // speichert die Nachbarschafts-Wahrscheinlichkeiten
+  private PropertyWriteAccess WA_outStepLU    = null; // speichert die LU fuer jeden Zeitpunkt
+
+  //**************** Variablen mit denen gearbeitet wird *******************
+  // Modell-Parameter
+  private int    luCount    = 0;    // Anzahl an LU-Typen
+  private int    dfCount    = 0;    // Anzahl an Driving Forces
+  private int    ddfCount   = 0;    // Anzahl an dynamischen Driving Forces
+  private int    areaWidth  = 0;    // Breite des Untersuchungsgebiets (Rasterzellen)
+  private int    areaHeight = 0;    // Hoehe des Untersuchungsgebiets (Rasterzellen)
+  private int    areaMinX   = 0;    // Start-Index des Rasters in X-Richtung
+  private int    areaMinY   = 0;    // Start-Index des Rasters in Y-Richtung
+  private int    areaMaxX   = 0;    // End-Index des Rasters in X-Richtung (EXKLUSIVE!)
+  private int    areaMaxY   = 0;    // End-Index des Rasters in Y-Richtung (EXKLUSIVE!)
+  private int    demandTolType    = 0;  // Art der Abweichungsangaben
+  private float  demandTolSingle  = 0;  // erlaubte Abweichung fuer jeden einzelnen LU-Typ vom Bedarf
+  private float  demandTolAverage = 0;  // erlaubte Durchschnitts-Abweichung fuer das Untersuchungsgebiet
+  private float  demandConv = 0;    // Umrechnungsfaktor Bedarfseingeit -> qm
+  private float  cellSize   = 0;    // Flaeche einer Rasterzelle (in Bedarfseinheit)
+  // Eingabe-Daten, die ueber den gesamten Modellablauf benoetigt werden
+  private WritableGrid            baseLU        = null; // Base Scenario
+  private WritableGrid            baseLUHist    = null; // Base LU History
+  private int[][]                 luConv        = null; // LU-Conversion-Matrix
+  private float[]                 luElas        = null; // LU-Conversion-Elasticity
+  private WritableGrid            areaRestr     = null; // Area Restrictions
+  private float[][]               luDemand      = null; // LU-Bedarfe
+  private WritableGrid[]          sdfGrids      = null; // Static Driving Forces
+  private boolean                 CALC_WITH_DDF = false; // Flag, ob dynamische DF beruecksichtigt werden
+  private WritableGrid[]          ddfGrids      = null; // Dynamic Driving Forces
+  private int[]                   ddfStartIdx   = null; // Listenindex an dem ein dyn. DF beginnt
+  private float[][]               regrRes       = null; // Regression Results fuer LUCC
+  private boolean                 CALC_WITH_NBH = false; // Flag, ob Nachbarschaftsw'keit beruecksichtigt wird
+  private float[]                 nbhWeights    = null; // Gewichtung der Nachbarschaft pro LU-Typ
+  private float[][][]             nbhSettings   = null; // Definition der Umgebung pro LU-Typ
+  private float[][]               nbhRegrRes    = null; // Regression Results fuer Nachbarschaft
+  private int                     nbhRadiusX    = 0;    // horizontaler Radius der betrachteten Nachbarschaft
+  private int                     nbhRadiusY    = 0;    // vertikaler Radius der betrachteten Nachbarschaft
+  private float[][]               luCover       = null; // LU-Bedeckung der Typen ueber die Zeit in Bedarfseinheit
+  private float                   totCover      = 0;    // Gesamte Landbedeckungsflaeche (ohne NoData!)
+  private Random                  rand          = null; // Zufallsgenerator
+  private float[]                 iterSpeed     = null; // Geschwindigkeit fuer die ITER-Variablen
+  // Ausgabe-Daten, die ueber den gesamten Modellablauf benoetigt werden
+  private WritableGrid            outActLU      = null; // speichert die aktuell sim. LU
+  private WritableGrid            outActLUHist  = null; // speichert die aktuell sim. LU History
+  private WritableGrid[]          outLUProb     = null; // speichert die LU-Wahrscheinlichkeiten
+  private WritableGrid[]          outNbhProb    = null; // speichert die Nachbarschafts-Wahrscheinlichkeiten
+  private float[]                 outIter       = null; // speichert die Iterationsvariablen
+  private MultiGrid               outStepLU     = null; // speichert die LU fuer jeden Zeitpunkt
+  private MultiDataObject         outStepLUMultiData;
+
+  private Map<Float,Float> 		  luMap	        = new HashMap<Float,Float>(); // speichert das Mapping von LUCC-Typen im BAseScenario zu 0,1,2,...
+  private Map<Float,Float> 	  	  luMapReverse  = new HashMap<Float,Float>(); // speichert das Mapping von LUCC-Typen im BAseScenario zu 0,1,2,...
+
+  //Parallelisierungsvariablen:
+  private SPMDClientInterface clientController = null;
+  /**
+   * Erzeugt eine neue Instanz des CLUE-Modells.
+   */
+  public ClueModelParallel() {
+    super( new ClueModelContentManager() );
+    contManager = (ClueModelContentManager)super.contManager;
+    // In dieser optimierten Clue-Implementierung, werden die Iterationsvariablen
+    // lokal verwaltet und brauchen deshalb nicht als Ressource zur Verfuegung
+    // gestellt werden
+    contManager.getResource( contManager.ITERVAR ).setNullable(true);
+    // Iterations-Ereignisse der Event-Liste hinzufuegen
+    events.add(ModelIterationStepStartedEvent.class);
+    events.add(ModelIterationStepFinishedEvent.class);
+  }
+
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////   Implementierung von AbstractXuluModel   //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Initialisiert das Model, indem die Ressourcen aus dem ContentManager
+   * geladen werden und mit Lese/Schreib-Rechten versehen werden. Zudem
+   * werden Referenzen auf einen Teil der Ressourcen in lokalen Variablen
+   * gespeichert, um waehrend des Modellablaufs effizienter darauf zugreifen
+   * zu koennen.
+   */
+  public void performModelInit() {
+    if ( contManager == null )
+      return;
+    //######### Zugriffsrechte aus Ressourcen/Propertys holen #########
+    RA_baseLU       = contManager.getBaseScenario().getReadAccess(this);
+    RA_baseLUHist   = contManager.getLUHistory().getReadAccess(this);
+    MatrixProperty conversionMatrix = contManager.getLUConversionMatrix();
+	RA_luConv       = conversionMatrix.getReadAccess(this);
+    RA_luElas       = contManager.getConversionElasticity().getReadAccess(this);
+    RA_areaRestr    = contManager.getAreaRestrictions().getReadAccess(this);
+    RA_luDemand     = contManager.getDemandScenario().getReadAccess(this);
+    RA_regrRes      = contManager.getRegressionResults().getReadAccess(this);
+    RA_sdfGrids     = ((ListProperty)contManager.getStaticDrivingForces().getProperty(MultiGrid.PROP_GRIDS)).getReadAccess(this);
+    // Dynamische Driving Forces sind optional
+    CALC_WITH_DDF   = contManager.getDynamicDrivingForceTypes() != null;
+    if ( CALC_WITH_DDF ) {
+      RA_ddfList    = contManager.getDynamicDrivingForceTypes().getReadAccess(this);
+      RA_ddfGrids   = ((ListProperty)contManager.getDynamicDrivingForces().getProperty(MultiGrid.PROP_GRIDS)).getReadAccess(this);
+    } else {
+      RA_ddfList    = null;
+      RA_ddfGrids   = null;
+    }
+    // Nachbarschafts-W'keiten sind optional
+    CALC_WITH_NBH   = (contManager.getNeighborhoodWeights() != null);
+    if ( CALC_WITH_NBH ) {
+      RA_nbhWeights  = contManager.getNeighborhoodWeights().getReadAccess(this);
+      RA_nbhSettings = contManager.getNeighborhoodSettings().getReadAccess(this);
+      RA_nbhRegrRes  = contManager.getNeighborhoodRegression().getReadAccess(this);
+      WA_outNbhProb  = ((ListProperty)contManager.getNeighborhoodProbabilities().getProperty(MultiGrid.PROP_GRIDS)).getWriteAccess(this);
+    } else {
+      RA_nbhWeights  = null;
+      RA_nbhSettings = null;
+      RA_nbhRegrRes  = null;
+      WA_outNbhProb  = null;
+    }
+    WA_outActLU     = contManager.getActLUResult().getWriteAccess(this);
+    WA_outActLUHist = contManager.getActLUHistory().getWriteAccess(this);
+    WA_outLUProb    = ((ListProperty)contManager.getLUProbabilities().getProperty(MultiGrid.PROP_GRIDS)).getWriteAccess(this);
+    WA_outStepLU    = ((ListProperty)contManager.getStepLUResults().getProperty(MultiGrid.PROP_GRIDS)).getWriteAccess(this);
+
+    //#########  Variablen belegen mit denen gearbeitet wird  ###########
+    this.stepCount    = contManager.getStepCount().getOneTimeReadAccess().getValueAsInt(); // WICHTIG!!
+    this.dfCount      = contManager.getStaticDrivingForces().getGridCount();
+    this.demandTolType    = contManager.getDemandToleranceType().getOneTimeReadAccess().getValueAsInt();
+    this.demandTolSingle  = contManager.getSingleDemandTolerance().getOneTimeReadAccess().getValueAsFloat();
+    this.demandTolAverage = contManager.getAverageDemandTolerance().getOneTimeReadAccess().getValueAsFloat();
+    this.demandConv   = contManager.getConversionFactor().getOneTimeReadAccess().getValueAsFloat();
+    this.luCount      = conversionMatrix.getSize(0);
+    this.baseLU       = (WritableGrid)RA_baseLU.getValue();
+    this.areaWidth    = baseLU.getWidth();
+    this.areaHeight   = baseLU.getHeight();
+    this.areaMinX     = baseLU.getMinX();
+    this.areaMinY     = baseLU.getMinY();
+    this.areaMaxX     = baseLU.getMinX() + areaWidth;
+    this.areaMaxY     = baseLU.getMinY() + areaHeight;
+    this.cellSize     = ((float)(baseLU.getCellWidth() * baseLU.getCellHeight())) / demandConv;
+    this.baseLUHist   = (WritableGrid)RA_baseLUHist.getValue();
+    this.outActLU     = (WritableGrid)WA_outActLU.getValue();
+    this.outActLUHist = (WritableGrid)WA_outActLUHist.getValue();
+    this.outStepLU    = contManager.getStepLUResults();
+    this.outIter      = new float[luCount];
+
+    // LUCC-Conversion-Matrix in Array kopieren (PERFORMANZ!)
+    this.luConv      = new int[conversionMatrix.getSize(0)][conversionMatrix.getSize(1)];
+    for (int i=0; i<luConv.length; i++)
+      for (int j=0; j<luConv[i].length; j++)
+        luConv[i][j] = RA_luConv.getValueAsInt(i,j);
+    // LU-Demand-Matrix in Array kopieren (PERFORMANZ!)
+    this.luDemand    = new float[contManager.getDemandScenario().getSize(0)][contManager.getDemandScenario().getSize(1)];
+    for (int i=0; i<luDemand.length; i++)
+      for (int j=0; j<luDemand[i].length; j++)
+        luDemand[i][j] = RA_luDemand.getValueAsFloat(i,j);
+    // LUCC Elastizitaet in Array kopieren (PERFORMANZ!)
+    this.luElas      = new float[((ListPropertyReadAccess)RA_luElas).getCount()];
+    for (int i=0; i<luElas.length; i++)
+      this.luElas[i] = RA_luElas.getValueAsFloat(i);
+    this.areaRestr   = (WritableGrid)RA_areaRestr.getValue();
+    // Statische DF in Array kopieren (PERFORMANZ!)
+    this.sdfGrids    = new WritableGrid[contManager.getStaticDrivingForces().getGridCount()];
+    for (int i=0; i<sdfGrids.length; i++)
+      sdfGrids[i] = contManager.getStaticDrivingForces().getGrid(i);
+
+    // Variablen fuer dynamische Driving Forces nur belegen, wenn auch mit
+    // diesen gerechnet wird.
+    if ( CALC_WITH_DDF ) {
+      ListPropertyReadAccess ddfList = (ListPropertyReadAccess)RA_ddfList;
+      this.ddfCount    = ddfList.getCount();
+      // Raster mit dyn. DF in Array kopieren (PERFORMANZ!)
+      this.ddfGrids    = new WritableGrid[contManager.getDynamicDrivingForces().getGridCount()];
+      for (int i=0; i<ddfGrids.length; i++)
+        ddfGrids[i] = contManager.getDynamicDrivingForces().getGrid(i);
+    } else {
+      this.ddfCount = 0;
+      this.ddfGrids = null;
+    }
+
+    // Regression Results fuer LUCC-W'keiten in Array kopieren (PERFORMANZ!)
+    this.regrRes = new float[contManager.getRegressionResults().getSize(0)][contManager.getRegressionResults().getSize(1)];
+    for (int i=0; i<regrRes.length; i++)
+      for (int j=0; j<regrRes[i].length; j++)
+        this.regrRes[i][j] = RA_regrRes.getValueAsFloat(i,j);
+
+    // Ausgabe-Raster-Liste fuer LUC-W'keiten aus Ressource holen,
+    // auf benoetigte Groesse erweitern und in Array kopieren (PERFORMANZ!)
+    MultiGrid outLUProbTemp = contManager.getLUProbabilities();
+    for (int i=0; outLUProbTemp.getGridCount()<luCount; i++)
+      outLUProbTemp.addGrid(); // Liste muss ein Raster fuer jeden LU-Typ enthalten
+    this.outLUProb  = new WritableGrid[luCount];
+    for (int i=0; i<luCount; i++)
+      this.outLUProb[i]  = outLUProbTemp.getGrid(i);
+
+    // Variablen fuer Nachbarschaftsw'keiten nur belegen, wenn auch mit diesen
+    // gerechnet wird
+    if ( CALC_WITH_NBH ) {
+      this.nbhRadiusX  = (contManager.getNeighborhoodSettings().getSize(0)-1)/2;
+      this.nbhRadiusY  = (contManager.getNeighborhoodSettings().getSize(1)-1)/2;
+      // Nbh.-Gewichtungen in Array kopieren (PERFORMANZ!)
+      this.nbhWeights  = new float[((ListPropertyReadAccess)RA_nbhWeights).getCount()];
+      for (int i=0; i<nbhWeights.length; i++)
+        this.nbhWeights[i] = RA_nbhWeights.getValueAsFloat(i);
+      // Nbh.-Settings in Array kopieren (PERFORMANZ!)
+      this.nbhSettings = new float[contManager.getNeighborhoodSettings().getSize(0)][contManager.getNeighborhoodSettings().getSize(1)][contManager.getNeighborhoodSettings().getSize(2)];
+      for (int i=0; i<nbhSettings.length; i++)
+        for (int j=0; j<nbhSettings[i].length; j++)
+          for (int k=0; k<nbhSettings[i][j].length; k++)
+            this.nbhSettings[i][j][k] = RA_nbhSettings.getValueAsFloat(i,j,k);
+      // Regression Results fuer Nbh. in Array kopieren (PERFORMANZ!)
+      this.nbhRegrRes  = new float[contManager.getNeighborhoodRegression().getSize(0)][contManager.getNeighborhoodRegression().getSize(1)];
+      for (int i=0; i<nbhRegrRes.length; i++)
+        for (int j=0; j<nbhRegrRes[i].length; j++)
+          this.nbhRegrRes[i][j] = RA_nbhRegrRes.getValueAsFloat(i,j);
+      // Ausgabe-Raster-Liste fuer Nachbarschafts-W'keiten aus Ressource holen,
+      // auf benoetigte Groesse erweitern und in Array kopieren (PERFORMANZ)
+      MultiGrid outNbhProbTemp = contManager.getNeighborhoodProbabilities();
+      for (int i=0; outNbhProbTemp.getGridCount()<luCount; i++)
+        outNbhProbTemp.addGrid(); // Liste muss ein Raster fuer jeden LU-Typ enthalten
+      this.outNbhProb = new WritableGrid[luCount];
+      for (int i=0; i<luCount; i++)
+        this.outNbhProb[i] = outNbhProbTemp.getGrid(i);
+    } else {
+      this.nbhRadiusX  = 0;
+      this.nbhRadiusY  = 0;
+      this.nbhWeights  = null;
+      this.nbhSettings = null;
+      this.nbhRegrRes  = null;
+      this.outNbhProb  = null;
+    }
+
+
+    // Bei Toleranz-Art "prozentual" werden die Werte in Prozent
+    // angegeben (intern wird aber mit Abweichungen zwischen 0 und 1 gerechnet!)
+    if ( demandTolType == TOLTYPE_PCT ) {
+      this.demandTolSingle  /= 100.0;
+      this.demandTolAverage /= 100.0;
+    }
+
+    // Die Liste der dyn. DF ist blockweise nach DF grupperiert
+    // Es koennen mehr Zeitschritt-Raster angegeben werden, als simuliert
+    // werden.
+    // Im Array 'ddfStartIdx' wird fuer die dynamischen DF gespeichert, an
+    // welcher Stelle in der Liste der Block beginnt.
+    // -1 bedeutet, dass der DF ein statische DF ist!
+    this.ddfStartIdx = new int[dfCount];
+    for (int i=0; i<dfCount; i++)
+      ddfStartIdx[i] = - 1;
+    for (int i=0; i<ddfCount; i++)
+      ddfStartIdx[i] = i*ddfGrids.length / ddfCount;
+
+    // "Geschwindigkeit" fuer die Iterationsvariablen
+    this.iterSpeed = new float[luCount];
+
+    // Speichert die Flaechendeckung (in der Bedarfseinheit, z.B. ha)
+    // fuer die einzelnen LU-Typen zu jedem Zeitpunkt
+    // --> Die initialen Werte stehen in der 0-Zeile der Demand-Matrix
+    this.luCover  = new float[luCount][stepCount+1];
+    this.totCover = 0;
+    statusOut.print("InitCover: ");
+    for (int lu=0; lu<luCount; lu++) {
+      luCover[lu][0] = luDemand[lu][0];
+      totCover += luCover[lu][0]; // Gesamt-Flaeche des Untersuchungsgebiets
+      statusOut.print(luCover[lu][0]+"   ");
+    }
+    statusOut.println("   >> TotalCover "+totCover);
+
+//    // Ausgabe-Raster leeren
+//    for (int y=outActLU.getMinY(); y<outActLU.getMinY()+outActLU.getHeight(); y++)
+//      for (int x=outActLU.getMinX(); x<outActLU.getMinX()+outActLU.getWidth(); x++)
+//        outActLU.setRasterSample(Float.NaN,x,y);
+
+    // spezielle GUI initialisieren
+    if (modelGUI != null)
+      modelGUI.init(this);
+
+    LOG.info("Scanning for all LU-Values in the Base-Scenario and mapping to 0...");
+    // Alle Zellen des Untersuchungsgebiets...
+    Set<Float> luccs = new HashSet<Float>();
+
+    for (Integer y=0; y<this.areaHeight; y++)
+      for (Integer x=0; x<this.areaWidth; x++){
+    	  float rasterSampleAsFloat = (float)baseLU.getRasterSampleAsFloat(x,y);
+    	  if (! Float.isNaN(rasterSampleAsFloat) )
+    		 luccs.add( rasterSampleAsFloat );
+  	}
+    Object[] lmo = luccs.toArray() ;
+	Arrays.sort(lmo);
+	luMap.put(Float.NaN, Float.NaN );
+	luMapReverse.put(Float.NaN, Float.NaN );
+	for (Integer i = 0; i < lmo.length; i++ ){
+		luMap.put((Float) lmo[i], new Float(i) );
+		luMapReverse.put( new Float(i), (Float) lmo[i]);
+	}
+
+
+    LOG.info("========================================");
+    LOG.info("MODEL INITIALISED (Log-Level "+LOG.getLevel()+")");
+    // alles ist bereit: jetzt wird die Parallelisierung initialisiert
+    LOG.info("==== Parallelization: Add resources to split control ====");
+    long time = System.currentTimeMillis();
+    clientController = getSPMDController();
+    //setting the neighborhoodrange:
+    int neighborhoodrange = Math.max(nbhRadiusX, nbhRadiusY);
+    clientController.setNeighborhoodRange(neighborhoodrange);
+    statusOut.println("Setting neighborhoodrange to " + neighborhoodrange);
+    clientController.addToSplitControl(baseLU, "baseLU");
+    clientController.addToSplitControl(baseLUHist, "baseLUHist");
+    clientController.addToSplitControl(areaRestr, "areaRestr");
+    clientController.addToSplitControl(outActLUHist, "outActLUHist");
+    clientController.addToSplitControl(outActLU, "outActLU");
+
+    clientController.addToMultiDataSplitControl(sdfGrids, "sdfGrids");
+    clientController.addToMultiDataSplitControl(ddfGrids, "ddfGrids");
+    clientController.addToMultiDataSplitControl(outLUProb, "outLUProb");
+    clientController.addToMultiDataSplitControl(outNbhProb, "outNbhProb");
+    outStepLU.addGrid();
+
+	outStepLUMultiData = clientController.addToMultiDataSplitControl(outStepLU, "outStepLU");
+
+    clientController.addBaseParameter(luCount, "luCount");
+    clientController.addBaseParameter(dfCount, "dfCount");
+    clientController.addBaseParameter(ddfStartIdx, "ddfStartIdx");
+    clientController.addBaseParameter(regrRes, "regrRes");
+    clientController.addBaseParameter(nbhRadiusX, "nbhRadiusX");
+    clientController.addBaseParameter(nbhRadiusY, "nbhRadiusY");
+    clientController.addBaseParameter(nbhSettings, "nbhSettings");
+    clientController.addBaseParameter(nbhRegrRes, "nbhRegrRes");
+    //clientController.addBaseParameter(luCover, "luCover");
+    clientController.addBaseParameter(luDemand, "luDemand");
+    clientController.addBaseParameter(luElas, "luElas");
+    clientController.addBaseParameter(CALC_WITH_NBH, "CALC_WITH_NBH");
+    clientController.addBaseParameter(totCover, "totCover");
+    clientController.addBaseParameter(nbhWeights, "nbhWeights");
+    clientController.addBaseParameter(luConv, "luConv");
+    clientController.addBaseParameter(luMap, "luMap");
+    clientController.addBaseParameter(luMapReverse, "luMapReverse");
+
+    clientController.addBaseParameter(cellSize, "cellSize");
+
+
+    LOG.info("==== Parallelization: Add finished after " + (System.currentTimeMillis()-time)+ "ms ===");
+    //System.out.println("canonical name " + baseLU.getClass().);baseLU.getClass().get
+    // clientController.addToSplitControl(splittableResource, name)
+
+
+  }
+
+  /**
+   * Gibt die Lese/Schreibrechte auf das Ein- und Ausgaberaster wieder frei.
+   * Interne Ressourcen brauchen keine aus dem Speicher entfernt werden.
+   */
+  public void performModelDispose() {
+
+
+    // Ressourcen wieder freigeben
+    releaseAccess(RA_baseLU);
+    releaseAccess(RA_baseLUHist);
+    releaseAccess(RA_luConv);
+    releaseAccess(RA_luElas);
+    releaseAccess(RA_areaRestr);
+    releaseAccess(RA_luDemand);
+    releaseAccess(RA_sdfGrids);
+    releaseAccess(RA_ddfList);
+    releaseAccess(RA_ddfGrids);
+    releaseAccess(RA_regrRes);
+    releaseAccess(RA_nbhWeights);
+    releaseAccess(RA_nbhSettings);
+    releaseAccess(RA_nbhRegrRes);
+    releaseAccess(WA_outActLU);
+    releaseAccess(WA_outActLUHist);
+    releaseAccess(WA_outLUProb);
+    releaseAccess(WA_outNbhProb);
+    releaseAccess(WA_outStepLU);
+    LOG.info("MODEL DISPOSED");
+    LOG.info("========================================");
+  }
+
+  /**
+   * Fuehrt einen Schritt des Modellablaufs durch.
+   * @param stepNo zu modellierender Schritt (beginnend bei 1!)
+   */
+  public void performModelStep(int stepNo) {
+      statusOut.println("Started step ".concat(String.valueOf(stepNo)));
+      long time = System.currentTimeMillis();
+//    //Unloading no longer needed Data:
+//    if(stepNo>2)
+//      outStepLU.getGrid(stepNo-3).unloadData();
+
+
+
+    // Merken, ob an einer Stelle bereits eine U-Zelle in einen anderen
+    // Typ gewechselt hat
+    boolean[] alreadyLUCCFromType = new boolean[luCount];
+    // Merken, ob an einer Stelle bereits eine U-Zelle neu entstanden ist
+    boolean[] alreadyLUCCToType = new boolean[luCount];
+
+    // LU-Wahrscheinlichkeiten berechnen
+    calculateLUProbabilities(stepNo);
+
+    /********************* Update the neighborhood for this Step ********************/
+    if(stepNo>1){
+    	clientController.updateNeighborhood(outStepLUMultiData, stepNo-2);
+    }
+
+    // Nachbarschafts-Wahrscheinlichkeiten berechnen
+    calulateNeighborhoodProbabilities(stepNo);
+
+
+    // Randomizer fuer diesen Zeitschritt erzeugen
+    rand = new Random(0xCAFE);
+
+    int   iterNo     = 0;
+    int   x          = 0;
+    int   y          = 0;
+    int   lu         = 0;
+    float lastLUC    = 0;
+    float actLUC     = 0;
+
+    // the LUCover from the last step
+    float oldLUCover[] = new float[luCount];
+
+    for (lu = 0; lu < oldLUCover.length; lu++)
+	    oldLUCover[lu]=luCover[lu][stepNo-1];
+
+    for (iterNo=1; !checkDemandCompliedAndCalculateIterVar(stepNo,iterNo); iterNo++) {
+      this.fireModelEvent( new ModelIterationStepStartedEvent(this,stepNo,iterNo) );
+      if ( modelGUI != null /*&& modelGUI.isDeviationUpdateEnabled()*/ )
+    	  modelGUI.setIterationNumber(stepNo+"/"+iterNo);
+          checkBreakingCommands();
+         // Arrays fuer Iterationsschritt initialisieren
+          for (lu = 0; lu < luCount; lu++) {
+           // noch kein Wechsel von einem LU-Typ
+           alreadyLUCCFromType[lu] = false;
+           // noch kein Wechsel zu einem LU-Typ
+           alreadyLUCCToType[lu] = false;
+           // Flaechen der LU-Typen fuer diesen Zeitschritt
+           luCover[lu][stepNo] = 0;
+           // Speed fuer die Iterationsvariablen initialisieren
+           // --> liegt die Nachfrage bei weniger als 5% des U'gebiets
+           //     wird langsamer begonnen
+           if ( luDemand[lu][stepNo]/totCover < 0.05f )
+             iterSpeed[lu] = 0.01f;
+           else
+             iterSpeed[lu] = 0.05f;
+        }
+      try {
+    	  Object[] results = clientController.runSPMDModelTask(new ClueTask(),Task.CLUE_ITER, stepNo, iterNo, outIter,oldLUCover);
+		for (int i = 0; i < results.length; i++) {
+			float [] newCover = (float[]) results[i];
+			//add cover for each lu
+			for (lu = 0; lu < luCount; lu++) {
+				luCover[lu][stepNo] += newCover[lu];
+			}
+		}
+	} catch (Throwable e) {
+		// TODO Auto-generated catch block
+		e.printStackTrace();
+		throw new UnsupportedOperationException("An Exception occoured " + e.getMessage());
+	}
+	  /******************** Synchronize cover of each server **********************/
+
+
+	 this.fireModelEvent( new ModelIterationStepFinishedEvent(this,stepNo,iterNo) );
+    }
+
+//    clientController.mergePartition(lastLUGrid);
+//    clientController.mergePartition(outActLU);
+//    clientController.mergePartition(outActLUHist);
+    try {
+		clientController.runSPMDModelTask(new ClueTask(), Task.STEP_FINALIZATION,stepNo);
+	} catch (Throwable e) {
+		// TODO Auto-generated catch block
+		e.printStackTrace();
+	}
+	clientController.mergeMultiData(outStepLUMultiData,stepNo-1);
+    statusOut.println("Ended step ".concat(String.valueOf(stepNo)));
+//    WritableGrid sLU = (WritableGrid) GeneralUtil.readSerializedFrom(new File("L:/work/appl/outStepLUGrid" + stepNo));
+//	RasterUtil.checkEqual(sLU, (WritableGrid)outStepLUMultiData.getElement(stepNo-1), true);
+//
+//	WritableGrid sLU = (WritableGrid) GeneralUtil.readSerializedFrom(new File("./Temp/outStepLUGrid" + stepNo));
+//	RasterUtil.checkEqual(sLU, outStepLUGrid, true);
+//	WritableGrid actLU = (WritableGrid) GeneralUtil.readSerializedFrom(new File("./Temp/outActLU" + stepNo));
+//	RasterUtil.checkEqual(actLU, outActLU, true);
+//	WritableGrid LUHist = (WritableGrid) GeneralUtil.readSerializedFrom(new File("./Temp/outActLUHist" + stepNo));
+//	RasterUtil.checkEqual(LUHist, outActLUHist, true);
+  }
+
+  /**
+   * Liefert eine CLUE-spezifische GUI, in der die Abweichungen waehrend der
+   * Iteration angezeigt werden und ueber die die Toleranzen eingestellt
+   * werden koennen
+   * @return Instannz von {@link ClueModelGUI}
+   */
+  public Component getModelSpecificGUI() {
+    return modelGUI;
+  }
+
+  //////////////////////////////////////////////////////////////////////
+  ////////////////////////   Clue-Methoden   ///////////////////////////
+  //////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob eine Rasterzelle mit <code>NoData</code> belegt ist
+   * @param x     Raster-Koordinate
+   * @param y     Raster-Koordinate
+   * @param grid  zu pruefendes Raster
+   */
+  protected static boolean checkNoData(int x, int y, WritableGrid grid) {
+    return Float.isNaN(grid.getRasterSampleAsFloat(x,y));
+  }
+
+  /**
+   * Berechnet die auf den Driving Forces basierenden
+   * Landnutzungs-Wahrscheinlichkeiten fuer einen Modell-Schritt und speichert
+   * diese in der Ressource "temp. Ausgaberaster fuer die LU-Wahrscheinlichkeiten".<br>
+   * Werden keine dynamischen Driving Forces verwendet, geschieht die Berechnung
+   * nur beim ersten Modellierungsschritt.
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   */
+  protected void calculateLUProbabilities(int stepNo) {
+    // Wenn keine dynamischen Driving Forces verwendet werden
+    // braucht die Berechnung nur fuer den ersten Schritt
+    // durchgefuehrt werden
+    if ( ddfCount == 0 && stepNo > 1 )
+      return;
+
+    statusOut.print("Calculate LU-Probabilities for step "+stepNo+"...");
+
+    try {
+		clientController.runSPMDModelTask(new ClueTask(),Task.LU_PROB, stepNo);
+	} catch (Throwable e) {
+		// TODO Auto-generated catch block
+		e.printStackTrace();
+	}
+
+    //unloading no longer used ddfs to save memory (if supported by WritableGrid)
+    for (int df = 0; df < dfCount; df++) {
+        WritableGrid grid = null;
+        if ( ddfStartIdx[df] >= 0 )
+          grid = this.ddfGrids[ddfStartIdx[df]+stepNo-1];
+        if(grid!=null) grid.unloadData();
+     }
+
+    //*************************** Verify section *******************************
+
+//    for (int lu = 0; lu < luCount; lu++) {
+////    //Write out to disk
+////    if(outLUProb[lu]!=null)
+////	GeneralUtil.SerializeToFile(outLUProb[lu], new File("./Temp/" + lu + "outLUProb" + stepNo));
+////
+////    	WritableGrid LUprob = (WritableGrid) GeneralUtil.readSerializedFrom( new File("./Temp/" + lu + "outLUProb" + stepNo));
+////		RasterUtil.checkEqual(LUprob, outLUProb[lu], true);
+//
+//    }
+//    if (stepNo == 10) {
+//			statusOut.print("Trying to merge the data....");
+//			long time = System.currentTimeMillis();
+//			clientController.mergeMultiData("outLUProb");
+//			statusOut.println("finished after "
+//					+ (System.currentTimeMillis() - time) + " ms");
+//
+//			// check all partitions
+//			for (int lu = 0; lu < 1; lu++) {
+//				WritableGrid LUprob = (WritableGrid) GeneralUtil
+//						.readSerializedFrom(new File("./Temp/" + lu
+//								+ "outLUProb" + stepNo));
+//				RasterUtil.checkEqual(LUprob, outLUProb[lu], true);
+//				//RasterUtil.printGrid(outLUProb[lu]);
+//			}
+//
+//		}
+    statusOut.println(" done.");
+  }
+
+  /**
+   * Berechnet die auf den Nachbarschaftsbeziehungen basierenden
+   * Landnutzungs-Wahrscheinlichkeiten fuer einen Modell-Schritt und speichert
+   * diese in der Ressource "temp. Ausgaberaster fuer die Nachbarschafts-Wahrscheinlichkeiten".<br>
+   * Da sich die Landnutzung mit jedem Zeitschritt aendert geschieht dies
+   * vor jedem Zeitschritt neu.<br>
+   * Diese Methode macht nichts, wenn ohne Nachbarschafts-W'keiten simuliert wird,
+   * also wenn keine Angabe fuer die "Neighborhood-Weights" gemacht wird.
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   */
+  protected void calulateNeighborhoodProbabilities(int stepNo) {
+    // Wenn ohne Nachbarschaftsbeziehungen simuliert wird
+    if ( !CALC_WITH_NBH )
+      return;
+
+    //starte parallele Ausf�hrung:
+    statusOut.print("Calculate Neighborhood-Probabilities for step "+stepNo+"...");
+
+    try {
+		clientController.runSPMDModelTask(new ClueTask(),Task.NEIGHBORHOOD_PROB, stepNo, luCover);
+	} catch (Throwable e) {
+		// TODO Auto-generated catch block
+		e.printStackTrace();
+	}
+
+
+
+    /*************************** VERIFY SECTION ************************************/
+
+//    if (stepNo == 1) {
+//		statusOut.print("Trying to merge the data....");
+//		long time = System.currentTimeMillis();
+//		clientController.mergeMultiData("outNbhProb");
+//
+//		statusOut.println("finished after "
+//				+ (System.currentTimeMillis() - time) + " ms");
+//
+//		// check all partitions
+//
+//			WritableGrid LUprob[] = (WritableGrid[]) GeneralUtil
+//					.readSerializedFrom(new File("./Temp/" + 0
+//							+ "outNbhProb" + stepNo));
+//			for (int lu = 0; lu < luCount; lu++) {
+//			RasterUtil.checkEqual(LUprob[lu], outNbhProb[lu], true);
+//			//RasterUtil.printGrid(outLUProb[lu]);
+//		}
+//
+//	}
+//    //FileOutput!
+//	for (int j = 0; j < outNbhProb.length; j++) {
+//	  if(outNbhProb!=null)
+//	  GeneralUtil.SerializeToFile(outNbhProb, new File("./Temp/" + j + "outNbhProb" + stepNo));
+//	}
+    statusOut.println(" done.");
+  }
+
+
+
+
+
+
+  /**
+   * Prueft, ob die aktuelle LU-Konfiguration die einzelenen Bedarfsanforderungen
+   * (bis auf eine Abweichung) erfuellt und berechnet die Iterationsvariablen
+   * neu.
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   * @param iterNo aktuelle Iteration (beginnend bei 1)
+   */
+  protected boolean checkDemandCompliedAndCalculateIterVar(int stepNo, int iterNo) {
+    boolean updateEnabled  = (modelGUI!=null && modelGUI.isDeviationUpdateEnabled());
+    boolean demandComplied = true;
+    // Abweichnungen berechnen
+    float[] singleDevAbs = new float[luCount];
+    float[] singleDevPct = new float[luCount];
+    float   averageDevAbs = 0;
+    float   averageDevPct = 0;
+    float   totalDevAbs = 0;
+    float   totalDevPct = 0;
+    for (int lu = 0; lu < luCount; lu++) {
+      // ##### Einzelabweichungen #####
+      // Absolute Abweichung der Landbedeckung vom Bedarf berechnen
+      float demand = luDemand[lu][stepNo];
+      singleDevAbs[lu]  = luCover[lu][stepNo] - demand;
+      // Prozentuale Einzel-Abweichnung relativ zum Bedarf
+      if (demand == 0)
+        // ist der Bedarf 0, aber auch die Bedeckung, ist die Abw. 0%
+        singleDevPct[lu] = luCover[lu][stepNo] == 0 ? 0 : 1;
+      else
+        singleDevPct[lu] = singleDevAbs[lu] / demand;
+
+      // Abweichung ueber erlaubter Toleranz?
+      float singleDev = (demandTolType == TOLTYPE_PCT) ? singleDevPct[lu] : singleDevAbs[lu];
+      if ( updateEnabled )
+        modelGUI.setDeviation(lu,singleDev);
+      if (Math.abs(singleDev) > demandTolSingle)
+        demandComplied = false;
+
+//      // Abweichung des LU-Typs ausgeben
+//      appendLog(singleDevAbs[lu],singleDevPct[lu],luDemand.getValueAsFloat(lu, stepNo),luCover[lu][stepNo]);
+
+      // ##### Gesamtabweichungen aufsummieren #####
+      totalDevAbs += Math.abs(singleDevAbs[lu]);
+    }
+
+    // Prozentuale Gesamt-Abweichnung relativ zum Gesamt-Untersuchungsgebiet
+    totalDevPct = totalDevAbs / totCover;
+    if ( updateEnabled )
+      modelGUI.setDeviation(luCount,(demandTolType == TOLTYPE_PCT) ? totalDevPct : totalDevAbs);
+
+    // Durchschnittliche Abweichnung pro LU-Typ
+    averageDevAbs = totalDevAbs / luCount;
+
+    // Durchschnittliche Abweichnung pro LU-Typ relativ zum Gesamt-Untersuchungsgebiet
+    averageDevPct = averageDevAbs / totCover;
+
+    // Abweichung ueber erlaubter Toleranz?
+    float avgDev = (demandTolType == TOLTYPE_PCT) ? averageDevPct : averageDevAbs;
+    if ( updateEnabled )
+      modelGUI.setDeviation(luCount+1,avgDev);
+    if ( Math.abs(avgDev) > demandTolAverage )
+      demandComplied = false;
+
+    // Iterationsvariablen neu berechnen
+    for (int lu = 0; lu < luCount; lu++) {
+      // Um Alternieren zwischen 2 Konfiguration zu verhindern
+      // eine kleine Zufallszahl hinzuaddieren (zwischen -0,005 und 0,005)
+      float randomValue = (rand.nextFloat()-0.5f)/100;
+
+      // --> Im ersten Schritt erhalten alle Iterationsvariablen den Wert 0,5
+      float iter = outIter[lu];
+      if (iterNo == 1)
+        iter = 0.5f+randomValue;
+//        iter = 0.5 + new float[] {0.002f,0f,0.002f,0f,0f,-0.003f}[lu];
+//        iter = 0.5 + new float[] {0.002f,0f,0.001f,0f,0f,-0.002f}[lu];
+      else {
+//        // Anteil der Einzelabweichnung an der Gesamtabweichnung
+////        float dev = (totalDevAbs!=0) ? singleDevAbs[lu] / totalDevAbs : 0.0;
+//        float dev  = singleDevPct[lu];
+//        iter = outIter.getValueAsFloat(lu) // alter Iter-Wert
+//             + dev // Anteil der Abweichung zum Bedarf
+//             + randomValue;
+        /////////////////////////////////////////
+        // Original-Iter-Berechnung aus CLUE
+        iterSpeed[lu] += 0.00005;
+        iter += (singleDevAbs[lu]/totCover)/(iterSpeed[lu]*(rand.nextInt(101)+1));
+
+        if (iter > 2f)
+          iter = 0.5f;
+        if ( Math.abs(iter) < 0.001 )
+          iter = 0.01f * Math.signum(iter);
+        if (iter < -0.5f)
+          iter = -0.4f;
+        /////////////////////////////////////////
+      }
+      // Iter speichern
+      outIter[lu] = iter;
+    }
+    return demandComplied;
+  }
+
+  //////////////////////////////////////////////////////////////////////
+  /////////////////////   Clue-spezifische GUI   ///////////////////////
+  //////////////////////////////////////////////////////////////////////
+
+  /**
+   * Diese Klasse stellt eine modellspezifische GUI-Komponente fuer das
+   * {@link ClueModelParallel CLUE-Modell} dar.
+   * In dieser wird fuer jeden modellierten LU-Typ ein {@linkplain ExpansionBar Status-Balken}
+   * fuer die Abweichnung vom geforderten Bedarf angezeigt. Sowie je ein Balken
+   * fuer die aktuelle Gesamt- und Durchschittsabweichung. Je nach gewaehlter
+   * Abweichungsart (prozentual oder absolute Angaben), werden Abweichungen
+   * von +/- 100% oder +/- 10000 Bedarfseinheiten angezeigt.<br>
+   * Darueber hinaus enthaelt sie je einen Regler, ueber den die maximal
+   * erlaubte Abweichung von den Bedarfen (Einzelabweichung der LU-Typen und
+   * Durchschnittsabweichung) eingestellt werden kann.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class ClueModelGUI extends JComponent {
+    private       float MIN = -1;
+    private       float MAX = 1;
+    private final float TOL = 0.2f;
+    private       float SLIDER_FACT = 1000;
+    // Format fuer Wert-Anzeige des Sliders
+    private DecimalFormat sliderPctFormat = new DecimalFormat("0.0%");
+    private DecimalFormat sliderDecFormat = new DecimalFormat("0.0");
+    // Format fuer Wert-Anzeige im Balken
+    private DecimalFormat statusPctFormat = new DecimalFormat("0.0000%");
+    private DecimalFormat statusDecFormat = new DecimalFormat("0.0");
+    // Format fuer Wert-Anzeige unterhalb der Balken (Max/Min/Middle)
+    private DecimalFormat infoPctFormat   = new DecimalFormat("0.0%");
+    private DecimalFormat infoDecFormat   = new DecimalFormat("0.0");
+
+    private DeviationContainer  divCont          = null;
+    private JSlider             singleDivSlider  = null;
+    private JSlider             averageDivSlider = null;
+    private ClueModelParallel           model            = null;
+    private DeviationLabel      singleDivLabel   = new DeviationLabel("Erlaubte Bedarfsabweichung pro LU-Typ:",sliderPctFormat);
+    private DeviationLabel      averageDivLabel  = new DeviationLabel("Erlaubte durchschnittliche Bedarfsabweichung:",sliderPctFormat);
+    private Font                labelFont        = singleDivLabel.getFont().deriveFont(Font.BOLD | Font.CENTER_BASELINE);
+    private boolean             alreadyPacked    = false;
+    private JCheckBox           updateCheckBox   = null;
+    private JLabel              iterationLabel   = null;
+
+    /**
+     * Erzeugt eine neue Clue-GUI. Diese wird jedoch erst nach Aufruf
+     * der {@link #init(ClueModelParallel)}-Methode komplett erzeugt, da erst dann
+     * die Anzahl der angezeigten Balken (= Anzahl LU-Typen) feststeht.
+     */
+    public ClueModelGUI() {
+      super();
+      this.setLayout( new SpringLayout() );
+      // Label in dem die Iterationsnummer angezeigt wird
+      iterationLabel = new JLabel(" ");
+      iterationLabel.setBorder( BorderFactory.createLoweredBevelBorder() );
+      // Slider/Label fuer Abweichnug der einzelnen Typen
+      singleDivSlider  = new JSlider(JSlider.HORIZONTAL,0,(int)(SLIDER_FACT*MAX),(int)(SLIDER_FACT*TOL));
+      singleDivSlider.setPaintTicks(true);
+      singleDivSlider.setPaintLabels(true);
+      singleDivSlider.setPaintTrack(true);
+      singleDivSlider.setEnabled(false);
+      singleDivSlider.addChangeListener( new ChangeListener() {
+        public void stateChanged(ChangeEvent e) {
+          float tol = singleDivSlider.getValue() / SLIDER_FACT;
+          if ( model!=null )
+            model.demandTolSingle = tol;
+          if ( singleDivLabel!=null )
+            singleDivLabel.setValue(tol);
+          if ( divCont!=null )
+            divCont.setTolerance(tol);
+        }
+      });
+      singleDivLabel.setFont(labelFont);
+      singleDivLabel.setValue(singleDivSlider.getValue()/SLIDER_FACT);
+
+      // Slider/Label fuer Abweichnug der einzelnen Typen
+      averageDivSlider  = new JSlider(JSlider.HORIZONTAL,0,(int)(SLIDER_FACT*MAX),(int)(SLIDER_FACT*TOL));
+      averageDivSlider.setPaintTicks(true);
+      averageDivSlider.setPaintLabels(true);
+      averageDivSlider.setPaintTrack(true);
+      averageDivSlider.setEnabled(false);
+      averageDivSlider.addChangeListener( new ChangeListener() {
+        public void stateChanged(ChangeEvent e) {
+          float tol = averageDivSlider.getValue() / SLIDER_FACT;
+          if ( model!=null )
+            model.demandTolAverage = tol;
+          if ( averageDivLabel!=null )
+            averageDivLabel.setValue(tol);
+        }
+      });
+      averageDivLabel.setFont(labelFont);
+      averageDivLabel.setValue(averageDivSlider.getValue()/SLIDER_FACT);
+
+      // Checkbox zur (De)Aktivierung der Anzeige-Aktualisierung
+      updateCheckBox = new JCheckBox("Abweichungen autom. aktualisieren",true);
+
+      this.add( averageDivLabel );
+      this.add( averageDivSlider );
+      this.add( singleDivLabel );
+      this.add( singleDivSlider );
+      this.add( updateCheckBox );
+      this.add( iterationLabel );
+      SpringUtilities.makeCompactGrid(this,6,1,0,0,0,5);
+    }
+
+    /**
+     * Initialisiert die GUI fuer eine <b>initialisierte</b> Modell-Instanz.
+     * Wird zum Ende {@link ClueModelParallel#performModelInit()} aufgerufen.
+     */
+    public void init(ClueModelParallel model) {
+      this.model = model;
+      if ( divCont != null )
+        remove(divCont);
+      SLIDER_FACT = (model.demandTolType == TOLTYPE_PCT) ? 1000 : 1;
+      MIN         = (model.demandTolType == TOLTYPE_PCT) ? -1 : ((float)-Math.pow(10,(int)Math.log10(model.totCover)))/1000;
+      MAX         = (model.demandTolType == TOLTYPE_PCT) ?  1 : -MIN;
+      averageDivSlider.setMaximum((int)(MAX*SLIDER_FACT));
+      averageDivLabel.setNumberFormat( model.demandTolType == TOLTYPE_PCT ? sliderPctFormat : sliderDecFormat );
+      singleDivSlider.setMaximum((int)(MAX*SLIDER_FACT));
+      singleDivLabel.setNumberFormat( model.demandTolType == TOLTYPE_PCT ? sliderPctFormat : sliderDecFormat );
+
+      String[] divDesc = new String[model.luCount+2];
+      for (int i=0; i<model.luCount; i++)
+        divDesc[i] = String.valueOf(i);
+      divDesc[model.luCount]   = "Total";
+      divDesc[model.luCount+1] = "Average";
+
+      divCont = new DeviationContainer(
+                         divDesc.length,
+                         divDesc,
+                         MIN,
+                         MAX,
+                         0,
+                         model.demandTolSingle,
+                         model.demandTolType == TOLTYPE_PCT ? statusPctFormat : statusDecFormat,
+                         model.demandTolType == TOLTYPE_PCT ? infoPctFormat   : infoDecFormat
+      );
+      divCont.setBarDescHeader("LU-Typ");
+      divCont.setBarHeader("Aktuelle Bedarfsabweichung");
+      this.add(divCont,4);
+
+      // Wert des Balkens darf erst hier (nach Neu-Erstellung des
+      // Abweichungs-Containers) neu gesetzt werden, da beim Setzen
+      // des neuen Wertes automatisch die Toleranzen der Abweichungsbalken
+      // aktualisiert werden
+      setSingleTolerance(model.demandTolSingle);
+      setAverageTolerance(model.demandTolAverage);
+
+      SpringUtilities.makeCompactGrid(this,7,1,0,0,0,5);
+      if ( !alreadyPacked )
+        SwingUtil.packParentWindow(this);
+      else
+        this.validate();
+      alreadyPacked = true;
+      singleDivSlider.setEnabled( true );
+      averageDivSlider.setEnabled( true );
+    }
+
+    /**
+     * Setzt die in der GUI angezeigte Interationsnummer. Diese wird
+     * durch einen String repraesentiert, damit auch berliebige andere
+     * Informationen (anstelle der Nummer) dargestellt werden koennen (z.B.
+     * zusaetzlich noch die Schrittnummer).
+     * @param iterString dargestellte Iterationsnummer
+     */
+    public void setIterationNumber(String iterString) {
+      iterationLabel.setText("Iteration: "+iterString);
+    }
+
+    /**
+     * Stellt den Slider fuer die Einzelabweichung auf einen bestimmten Wert
+     * ein. Hierdurch wird automatisch auch der Wert fuer das Modell neu
+     * gesetzt.
+     */
+    public void setSingleTolerance(float tol) {
+      singleDivSlider.setValue((int)(tol*SLIDER_FACT));
+    }
+
+    /**
+     * Stellt den Slider fuer die Durchschnittsabweichung auf einen bestimmten Wert
+     * ein. Hierdurch wird automatisch auch der Wert fuer das Modell neu
+     * gesetzt.
+     */
+    public void setAverageTolerance(float tol) {
+      averageDivSlider.setValue((int)(tol*SLIDER_FACT));
+    }
+
+    /**
+     * Setzt die Abweichnungswerte fuer alle Statusbalken.
+     * @param value Array mit den Abweichungen
+     */
+    public void setDeviation(float[] value) {
+      if ( divCont!= null && isDeviationUpdateEnabled() )
+        divCont.setExpansion(value);
+    }
+
+    /**
+     * Setzt den Abweichnungswert fuer einen Statusbalken.
+     * @param idx   Index eines Balkens
+     * @param value Array mit den Abweichungen
+     */
+    public void setDeviation(int idx, float value) {
+      if ( divCont!= null && isDeviationUpdateEnabled() )
+        divCont.setExpansion(idx,value);
+    }
+
+    /**
+     * Aktiviert oder Deaktiviert die Aktualisierung der Abweichungsbalken.
+     */
+    public void setDeviationUpdateEnabled(boolean enabled) {
+      updateCheckBox.setSelected(enabled);
+    }
+
+    /**
+     * Aktiviert oder Deaktiviert die Aktualisierung der Abweichungsbalken.
+     */
+    public boolean isDeviationUpdateEnabled() {
+      return updateCheckBox.isSelected();
+    }
+
+    /**
+     * Diese Klasse stellt ein Label dar, in dem (hinter einem Basistext)
+     * ein numerischer Abweichungswert (z.B. erlaubte Maximalabweichung) angezeigt wird.
+     * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+     * @version 1.0
+     */
+    private static class DeviationLabel extends JLabel {
+      private String baseText        = "";
+      private float dev              = 0;
+      private NumberFormat numFormat = null;
+
+      /**
+       * Erzeugt ein neues leeres Label.
+       */
+      public DeviationLabel() {
+        this("");
+      }
+
+      /**
+       * Erzeugt ein neues Label. Der dargestellte Wert ist initial 0%.
+       * @param text      Basistext
+       */
+      public DeviationLabel(String text) {
+        this(text,new DecimalFormat("0.0%"));
+      }
+
+      /**
+       * Erzeugt ein neues Label. Der dargestellte Wert ist initial 0.
+       * @param text      Basistext
+       * @param numFormat Anzeigeformat fuer den dargestellten Abweichungswert
+       */
+      public DeviationLabel(String text, NumberFormat numFormat) {
+        this(text,numFormat,0);
+      }
+
+      /**
+       * Erzeugt ein neues Label.
+       * @param text      Basistext
+       * @param numFormat Anzeigeformat fuer den dargestellten Abweichungswert
+       * @param dev       initialer Wert fuer den Abweichungswert
+       */
+      public DeviationLabel(String text, NumberFormat numFormat, float dev) {
+        super();
+        this.baseText  = text;
+        this.dev    = dev;
+        setNumberFormat(numFormat);
+        setText(baseText);
+      }
+
+      /**
+       * Setzt den darzustellenden numerischen Abweichungswert.
+       */
+      public void setValue(float dev) {
+        this.dev = dev;
+        setText(baseText);
+      }
+
+      /**
+       * Setzt den Basistext des Labels.
+       */
+      public void setText(String text) {
+        this.baseText = text;
+        String displayText = baseText;
+        if ( numFormat != null )
+          displayText = displayText+" "+numFormat.format(this.dev);
+        super.setText(displayText);
+      }
+
+      /**
+       * Setzt das Darstellungsformat fuer den Abweichungswert.
+       */
+      public void setNumberFormat(NumberFormat format) {
+        this.numFormat = format;
+      }
+    }
+
+    /**
+     * Diese Klasse stellt einen Container dar, in dem vertikal eine Reihe von
+     * {@linkplain ExpansionBar Status-Balken} angezeigt werden. Alle Balken
+     * haben dieselben Extremwerte (Min, Max, Middle). Deshalb erhaelt nur
+     * der unterste Balken eine Info-Leiste mit diesen Extremwerten.
+     * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+     * @version 1.0
+     */
+    private static class DeviationContainer extends JComponent {
+      private static final NumberFormat NUM_FORMAT = new DecimalFormat("0.0%");
+      /** Konstante fuer eine vertikale Ausrichtung der Status-Balken */
+      public static final int VERTICAL   = ExpansionBar.VERTICAL;
+      /** Konstante fuer eine horizontale Ausrichtung der Status-Balken */
+      public static final int HORIZONTAL = ExpansionBar.HORIZONTAL;
+
+      private ExpansionBar[] expansionBar   = null;
+      private JLabel[]       expansionLabel = null;
+      private JLabel         typeLabel      = null;
+      private JLabel         divLabel       = null;
+      private Font           sampleFont     = new JLabel().getFont();
+
+      /**
+       * Erzeugt einen neuen Container. Die Balken stellen eine prozentuale
+       * Abweichung von +/- 100% um 0% dar. Die Balken erhalten keine Beschreibung,
+       * sondern werden durchnummeriert.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param tol      Toleranzwert fuer alle Balken (siehe {@link ExpansionBar})
+       */
+      public DeviationContainer(int count, float tol) {
+        this(count,-1,1,0,tol,NUM_FORMAT);
+      }
+
+      /**
+       * Erzeugt einen neuen Container. Als Mitte-Wert fuer die Balken wird
+       * 0 verwendet. Die Balken erhalten keine Beschreibung, sondern werden
+       * durchnummeriert.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param min      Minimum-Wert fuer die Balken
+       * @param max      Maximum-Wert fuer die Balken
+       * @param tol      Toleranzwert fuer alle Balken (siehe {@link ExpansionBar})
+       * @param form     Darstellungsformat fuer die Zahlen im Balken und in der
+       *                 Info-Leiste des untersten Balken
+       */
+      public DeviationContainer(int count, float min, float max, float tol, NumberFormat form) {
+        this(count,min,max,0,tol,form);
+      }
+
+      /**
+       * Erzeugt einen neuen Container. Die Balken werden durchnummeriert.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param min      Minimum-Wert fuer die Balken
+       * @param max      Maximum-Wert fuer die Balken
+       * @param mid      Mitte-Wert fuer die Balken
+       * @param tol      Toleranzwert fuer alle Balken (siehe {@link ExpansionBar})
+       * @param form     Darstellungsformat fuer die Zahlen im Balken und in der
+       *                 Info-Leiste des untersten Balken
+       */
+      public DeviationContainer(int count, float min, float max, float mid, float tol, NumberFormat form) {
+        this(count,null,min,max,mid,tol,form,form);
+      }
+
+      /**
+       * Erzeugt einen neuen Container.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param desc     Beschreibungen fuer die Balken (kann <code>null</code> sein!)
+       * @param min      Minimum-Wert fuer die Balken
+       * @param max      Maximum-Wert fuer die Balken
+       * @param mid      Mitte-Wert fuer die Balken
+       * @param tol      Toleranzwert fuer alle Balken (siehe {@link ExpansionBar})
+       * @param barForm  Darstellungsformat fuer die Zahlen im Balken
+       * @param infoForm Darstellungsformat fuer die Zahlen in der Info-Leiste
+       *                 des untersten Balken
+       */
+      public DeviationContainer(int count, String[] desc, float min, float max, float mid, float tol, NumberFormat barForm, NumberFormat infoForm) {
+        this(count,desc,min,max,mid,LangUtil.createArray(count,tol),barForm,infoForm);
+      }
+
+      /**
+       * Erzeugt einen neuen Container.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param desc     Beschreibungen fuer die Balken (kann <code>null</code> sein!)
+       * @param min      Minimum-Wert fuer die Balken
+       * @param max      Maximum-Wert fuer die Balken
+       * @param mid      Mitte-Wert fuer die Balken
+       * @param tol      Toleranzwert fuer jeden einzelnen Balken (siehe {@link ExpansionBar})
+       * @param barForm  Darstellungsformat fuer die Zahlen im Balken
+       * @param infoForm Darstellungsformat fuer die Zahlen in der Info-Leiste
+       *                 des untersten Balken
+       */
+      public DeviationContainer(int count, String[] desc, float min, float max, float mid, float[] tol, NumberFormat barForm, NumberFormat infoForm) {
+        super();
+        if ( count <= 0 )
+          throw new IllegalArgumentException("At least one divergence bar must specified!");
+        if ( desc!=null && desc.length < count )
+          throw new IllegalArgumentException("Less describtions specified!");
+
+        this.setLayout( new SpringLayout() );
+
+        // PROBLEME mit den Labels bei VERTICAL
+        // --> Label-Breite wird wohl zu 0
+        int orient = HORIZONTAL;
+
+        sampleFont = sampleFont.deriveFont(Font.BOLD);
+        if (orient == VERTICAL)
+          sampleFont = sampleFont.deriveFont( AffineTransform.getRotateInstance(Math.PI/2) );
+
+        // Label erzeugen
+        typeLabel = new JLabel("Type");
+        divLabel = new JLabel("Divergence");
+        typeLabel.setFont(sampleFont);
+        divLabel.setFont(sampleFont);
+
+        // Statusbalken erzeugen
+        this.expansionBar   = new ExpansionBar[count];
+        this.expansionLabel = new JLabel[count];
+        for (int i=0; i<count; i++) {
+          expansionBar[i]   = new ExpansionBar(orient,ExpansionBar.LINEAR,min,max,mid,-tol[i],tol[i],0,barForm,infoForm);
+          expansionLabel[i] = new JLabel( desc!=null && i<desc.length ? desc[i] : String.valueOf(i));
+          if ( orient == HORIZONTAL ) {
+            expansionLabel[i].setHorizontalAlignment(JLabel.CENTER);
+            expansionLabel[i].setVerticalAlignment(JLabel.TOP);
+          } else {
+            expansionLabel[i].setFont( expansionLabel[i].getFont().deriveFont( AffineTransform.getRotateInstance(Math.PI/2) ) );
+            expansionLabel[i].setHorizontalAlignment(JLabel.LEFT);
+            expansionLabel[i].setVerticalAlignment(JLabel.CENTER);
+          }
+        }
+        // beim untersten Balken sollen die Labels erscheinen
+        expansionBar[count-1].setValueLabelsPainted(true);
+
+        // Komponenten einfuegen und ausrichten
+        if ( orient == HORIZONTAL ) {
+          typeLabel.setHorizontalAlignment(JLabel.CENTER);
+          typeLabel.setVerticalAlignment(JLabel.BOTTOM);
+          divLabel.setHorizontalAlignment(JLabel.CENTER);
+          divLabel.setVerticalAlignment(JLabel.BOTTOM);
+          add( typeLabel );
+          add( divLabel );
+          for (int i=0; i<count; i++) {
+            add( expansionLabel[i] );
+            add( expansionBar[i] );
+          }
+          // Layout ausrichten
+          SpringUtilities.makeCompactGrid(this,getComponentCount()/2,2,0,0,10,0);
+        } else {
+          typeLabel.setHorizontalAlignment(JLabel.CENTER);
+          typeLabel.setVerticalAlignment(JLabel.CENTER);
+          divLabel.setHorizontalAlignment(JLabel.CENTER);
+          divLabel.setVerticalAlignment(JLabel.CENTER);
+          add( divLabel );
+          for (int i=0; i<count; i++)
+            add( expansionBar[i] );
+          add( typeLabel );
+          for (int i=0; i<count; i++)
+            add( expansionLabel[i] );
+          // Layout ausrichten
+          SpringUtilities.makeCompactGrid(this,2,getComponentCount()/2,0,0,10,0);
+        }
+      }
+
+      /**
+       * Setzt den Toleranzwert fuer alle Balken.
+       */
+      public void setTolerance(float tol) {
+        for (int i=0; i<expansionBar.length; i++) {
+          expansionBar[i].setMinimumTolerance( -tol );
+          expansionBar[i].setMaximumTolerance(  tol );
+        }
+      }
+
+      /**
+       * Setzt den Wert fuer alle Balken.
+       */
+      public void setExpansion(float[] value) {
+        for (int i=0; i<value.length; i++)
+          setExpansion(i,value[i]);
+      }
+
+      /**
+       * Setzt die Beschreibung fuer einen Balken.
+       */
+      public void setBarDesc(int idx, String text) {
+        expansionLabel[idx].setText(text);
+      }
+
+      /**
+       * Setzt den Wert fuer einen Balken.
+       */
+      public void setExpansion(int idx, float value) {
+        expansionBar[idx].setValue(value);
+      }
+
+      /**
+       * Setzt die Beschreibung die oberhalb der Balken-Beschreibungen steht.
+       */
+      public void setBarDescHeader(String text) {
+        typeLabel.setText(text);
+      }
+
+      /**
+       * Setzt die Beschreibung die oberhalb der Balken steht.
+       */
+      public void setBarHeader(String text) {
+        divLabel.setText(text);
+      }
+
+    }
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueModel_deterministic.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueModel_deterministic.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueModel_deterministic.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,1549 @@
+package edu.bonn.xulu.plugin.model.parallel;
+
+import java.awt.Component;
+import java.awt.Font;
+import java.awt.geom.AffineTransform;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+import java.util.Vector;
+
+import javax.swing.BorderFactory;
+import javax.swing.JCheckBox;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JSlider;
+import javax.swing.SpringLayout;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyReadAccess;
+import schmitzm.data.property.MatrixProperty;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.PropertyWriteAccess;
+import schmitzm.lang.LangUtil;
+import schmitzm.swing.ExpansionBar;
+import schmitzm.swing.SpringUtilities;
+import schmitzm.swing.SwingUtil;
+import edu.bonn.xulu.model.AbstractStepModel;
+import edu.bonn.xulu.model.event.ModelIterationStepFinishedEvent;
+import edu.bonn.xulu.model.event.ModelIterationStepStartedEvent;
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+import edu.bonn.xulu.plugin.model.clue.ClueModel;
+import edu.bonn.xulu.plugin.model.clue.ClueModelContentManager;
+
+/**
+ * This class can be used to verify parallel versions of the {@link ClueModel}. It
+ * is only slightly modified so that it no longer uses purely random numbers for
+ * the generation of the iteration variable, but uses random numbers seeded with
+ * 0xCAFE. This guarantees that every run with the same input uses the same number
+ * of iterations and produces exactly the same result.
+ *  *
+ * @see ClueModelContentManager
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @author Dominik Appl (only slightly modified)
+ * @version 1.0
+ */
+public class ClueModel_deterministic extends AbstractStepModel {
+  /** Konstante fuer die Toleranz-Art "prozentual". */
+  public static final int TOLTYPE_PCT = 0;
+  /** Konstante fuer die Toleranz-Art "absolut in Bedarf-Einheit". */
+  public static final int TOLTYPE_ABS = 1;
+
+  /** Speichert den ContentManager fuer das Modell.
+   *  @see ClueModelContentManager */
+  protected ClueModelContentManager contManager;
+
+  private final ClueModelGUI  modelGUI = new ClueModelGUI();
+  private final Logger        LOG      = LogManager.getLogger(this.getClass().getName());
+
+  //********** Lese/Schreibrechte, die fuer den gesamten ***********
+  //********** Modellanlauf gehalten werden muessen      ***********
+  private PropertyReadAccess  RA_baseLU       = null; // Base Scenario
+  private PropertyReadAccess  RA_baseLUHist   = null; // Base LU History
+  private PropertyReadAccess  RA_luConv       = null; // LU-Conversion-Matrix
+  private PropertyReadAccess  RA_luElas       = null; // LU-Conversion-Elasticity
+  private PropertyReadAccess  RA_areaRestr    = null; // Area Restrictions
+  private PropertyReadAccess  RA_luDemand     = null; // LU-Bedarfe
+  private PropertyReadAccess  RA_sdfGrids     = null; // Static Driving Forces
+  private PropertyReadAccess  RA_ddfList      = null; // List of dynmic Driving Forces
+  private PropertyReadAccess  RA_ddfGrids     = null; // Dynamic Driving Forces
+  private PropertyReadAccess  RA_regrRes      = null; // Regression Results
+  private PropertyReadAccess  RA_nbhWeights   = null; // Gewichtung der Nachbarschaft pro LU-Typ
+  private PropertyReadAccess  RA_nbhSettings  = null; // Definition der Umgebung pro LU-Typ
+  private PropertyReadAccess  RA_nbhRegrRes   = null; // Regression Results fuer Nachbarschaft
+  private PropertyWriteAccess WA_outActLU     = null; // speichert die aktuell sim. LU
+  private PropertyWriteAccess WA_outActLUHist = null; // speichert die aktuell sim. LU Historie
+  private PropertyWriteAccess WA_outLUProb    = null; // speichert die LU-Wahrscheinlichkeiten
+  private PropertyWriteAccess WA_outNbhProb   = null; // speichert die Nachbarschafts-Wahrscheinlichkeiten
+  private PropertyWriteAccess WA_outStepLU    = null; // speichert die LU fuer jeden Zeitpunkt
+
+  //**************** Variablen mit denen gearbeitet wird *******************
+  // Modell-Parameter
+  private int    luCount    = 0;    // Anzahl an LU-Typen
+  private int    dfCount    = 0;    // Anzahl an Driving Forces
+  private int    ddfCount   = 0;    // Anzahl an dynamischen Driving Forces
+  private int    areaWidth  = 0;    // Breite des Untersuchungsgebiets (Rasterzellen)
+  private int    areaHeight = 0;    // Hoehe des Untersuchungsgebiets (Rasterzellen)
+  private int    areaMinX   = 0;    // Start-Index des Rasters in X-Richtung
+  private int    areaMinY   = 0;    // Start-Index des Rasters in Y-Richtung
+  private int    areaMaxX   = 0;    // End-Index des Rasters in X-Richtung (EXKLUSIVE!)
+  private int    areaMaxY   = 0;    // End-Index des Rasters in Y-Richtung (EXKLUSIVE!)
+  private int    demandTolType    = 0;  // Art der Abweichungsangaben
+  private float  demandTolSingle  = 0;  // erlaubte Abweichung fuer jeden einzelnen LU-Typ vom Bedarf
+  private float  demandTolAverage = 0;  // erlaubte Durchschnitts-Abweichung fuer das Untersuchungsgebiet
+  private float  demandConv = 0;    // Umrechnungsfaktor Bedarfseingeit -> qm
+  private float  cellSize   = 0;    // Flaeche einer Rasterzelle (in Bedarfseinheit)
+  // Eingabe-Daten, die ueber den gesamten Modellablauf benoetigt werden
+  private WritableGrid            baseLU        = null; // Base Scenario
+  private WritableGrid            baseLUHist    = null; // Base LU History
+  private int[][]                 luConv        = null; // LU-Conversion-Matrix
+  private float[]                 luElas        = null; // LU-Conversion-Elasticity
+  private WritableGrid            areaRestr     = null; // Area Restrictions
+  private float[][]               luDemand      = null; // LU-Bedarfe
+  private WritableGrid[]          sdfGrids      = null; // Static Driving Forces
+  private boolean                 CALC_WITH_DDF = false; // Flag, ob dynamische DF beruecksichtigt werden
+  private WritableGrid[]          ddfGrids      = null; // Dynamic Driving Forces
+  private int[]                   ddfStartIdx   = null; // Listenindex an dem ein dyn. DF beginnt
+  private float[][]               regrRes       = null; // Regression Results fuer LUCC
+  private boolean                 CALC_WITH_NBH = false; // Flag, ob Nachbarschaftsw'keit beruecksichtigt wird
+  private float[]                 nbhWeights    = null; // Gewichtung der Nachbarschaft pro LU-Typ
+  private float[][][]             nbhSettings   = null; // Definition der Umgebung pro LU-Typ
+  private float[][]               nbhRegrRes    = null; // Regression Results fuer Nachbarschaft
+  private int                     nbhRadiusX    = 0;    // horizontaler Radius der betrachteten Nachbarschaft
+  private int                     nbhRadiusY    = 0;    // vertikaler Radius der betrachteten Nachbarschaft
+  private float[][]               luCover       = null; // LU-Bedeckung der Typen ueber die Zeit in Bedarfseinheit
+  private float                   totCover      = 0;    // Gesamte Landbedeckungsflaeche (ohne NoData!)
+  private Random                  rand          = null; // Zufallsgenerator
+  private float[]                 iterSpeed     = null; // Geschwindigkeit fuer die ITER-Variablen
+  // Ausgabe-Daten, die ueber den gesamten Modellablauf benoetigt werden
+  private WritableGrid            outActLU      = null; // speichert die aktuell sim. LU
+  private WritableGrid            outActLUHist  = null; // speichert die aktuell sim. LU History
+  private WritableGrid[]          outLUProb     = null; // speichert die LU-Wahrscheinlichkeiten
+  private WritableGrid[]          outNbhProb    = null; // speichert die Nachbarschafts-Wahrscheinlichkeiten
+  private float[]                 outIter       = null; // speichert die Iterationsvariablen
+  private MultiGrid               outStepLU     = null; // speichert die LU fuer jeden Zeitpunkt
+  private Map<Float,Float> 		  luMap	        = new HashMap<Float,Float>(); // speichert das Mapping von LUCC-Typen im BAseScenario zu 0,1,2,...
+  private Map<Float,Float> 	  	  luMapReverse  = new HashMap<Float,Float>(); // speichert das Mapping von LUCC-Typen im BAseScenario zu 0,1,2,...
+
+
+  /**
+   * Erzeugt eine neue Instanz des CLUE-Modells.
+   */
+  public ClueModel_deterministic() {
+    super( new ClueModelContentManager() );
+    contManager = (ClueModelContentManager)super.contManager;
+    // In dieser optimierten Clue-Implementierung, werden die Iterationsvariablen
+    // lokal verwaltet und brauchen deshalb nicht als Ressource zur Verfuegung
+    // gestellt werden
+    contManager.getResource( contManager.ITERVAR ).setNullable(true);
+    // Iterations-Ereignisse der Event-Liste hinzufuegen
+    events.add(ModelIterationStepStartedEvent.class);
+    events.add(ModelIterationStepFinishedEvent.class);
+  }
+
+
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////   Implementierung von AbstractXuluModel   //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Initialisiert das Model, indem die Ressourcen aus dem ContentManager
+   * geladen werden und mit Lese/Schreib-Rechten versehen werden. Zudem
+   * werden Referenzen auf einen Teil der Ressourcen in lokalen Variablen
+   * gespeichert, um waehrend des Modellablaufs effizienter darauf zugreifen
+   * zu koennen.
+   */
+  public void performModelInit() {
+    if ( contManager == null )
+      return;
+    //######### Zugriffsrechte aus Ressourcen/Propertys holen #########
+    RA_baseLU       = contManager.getBaseScenario().getReadAccess(this);
+    RA_baseLUHist   = contManager.getLUHistory().getReadAccess(this);
+    MatrixProperty conversionMatrix = contManager.getLUConversionMatrix();
+	RA_luConv       = conversionMatrix.getReadAccess(this);
+    RA_luElas       = contManager.getConversionElasticity().getReadAccess(this);
+    RA_areaRestr    = contManager.getAreaRestrictions().getReadAccess(this);
+    RA_luDemand     = contManager.getDemandScenario().getReadAccess(this);
+    RA_regrRes      = contManager.getRegressionResults().getReadAccess(this);
+    RA_sdfGrids     = ((ListProperty)contManager.getStaticDrivingForces().getProperty(MultiGrid.PROP_GRIDS)).getReadAccess(this);
+    // Dynamische Driving Forces sind optional
+    CALC_WITH_DDF   = contManager.getDynamicDrivingForceTypes() != null;
+    if ( CALC_WITH_DDF ) {
+      RA_ddfList    = contManager.getDynamicDrivingForceTypes().getReadAccess(this);
+      RA_ddfGrids   = ((ListProperty)contManager.getDynamicDrivingForces().getProperty(MultiGrid.PROP_GRIDS)).getReadAccess(this);
+    } else {
+      RA_ddfList    = null;
+      RA_ddfGrids   = null;
+    }
+    // Nachbarschafts-W'keiten sind optional
+    CALC_WITH_NBH   = (contManager.getNeighborhoodWeights() != null);
+    if ( CALC_WITH_NBH ) {
+      RA_nbhWeights  = contManager.getNeighborhoodWeights().getReadAccess(this);
+      RA_nbhSettings = contManager.getNeighborhoodSettings().getReadAccess(this);
+      RA_nbhRegrRes  = contManager.getNeighborhoodRegression().getReadAccess(this);
+      WA_outNbhProb  = ((ListProperty)contManager.getNeighborhoodProbabilities().getProperty(MultiGrid.PROP_GRIDS)).getWriteAccess(this);
+    } else {
+      RA_nbhWeights  = null;
+      RA_nbhSettings = null;
+      RA_nbhRegrRes  = null;
+      WA_outNbhProb  = null;
+    }
+    WA_outActLU     = contManager.getActLUResult().getWriteAccess(this);
+    WA_outActLUHist = contManager.getActLUHistory().getWriteAccess(this);
+    WA_outLUProb    = ((ListProperty)contManager.getLUProbabilities().getProperty(MultiGrid.PROP_GRIDS)).getWriteAccess(this);
+    WA_outStepLU    = ((ListProperty)contManager.getStepLUResults().getProperty(MultiGrid.PROP_GRIDS)).getWriteAccess(this);
+
+    //#########  Variablen belegen mit denen gearbeitet wird  ###########
+    this.stepCount    = contManager.getStepCount().getOneTimeReadAccess().getValueAsInt(); // WICHTIG!!
+    this.dfCount      = contManager.getStaticDrivingForces().getGridCount();
+    this.demandTolType    = contManager.getDemandToleranceType().getOneTimeReadAccess().getValueAsInt();
+    this.demandTolSingle  = contManager.getSingleDemandTolerance().getOneTimeReadAccess().getValueAsFloat();
+    this.demandTolAverage = contManager.getAverageDemandTolerance().getOneTimeReadAccess().getValueAsFloat();
+    this.demandConv   = contManager.getConversionFactor().getOneTimeReadAccess().getValueAsFloat();
+    this.luCount      = conversionMatrix.getSize(0);
+
+
+    this.baseLU       = (WritableGrid)RA_baseLU.getValue();
+    this.areaWidth    = baseLU.getWidth();
+    this.areaHeight   = baseLU.getHeight();
+    this.areaMinX     = baseLU.getMinX();
+    this.areaMinY     = baseLU.getMinY();
+    this.areaMaxX     = baseLU.getMinX() + areaWidth;
+    this.areaMaxY     = baseLU.getMinY() + areaHeight;
+    this.cellSize     = ((float)(baseLU.getCellWidth() * baseLU.getCellHeight())) / demandConv;
+    this.baseLUHist   = (WritableGrid)RA_baseLUHist.getValue();
+    this.outActLU     = (WritableGrid)WA_outActLU.getValue();
+    this.outActLUHist = (WritableGrid)WA_outActLUHist.getValue();
+    this.outStepLU    = contManager.getStepLUResults();
+    this.outIter      = new float[luCount];
+
+    // LUCC-Conversion-Matrix in Array kopieren (PERFORMANZ!)
+    this.luConv      = new int[conversionMatrix.getSize(0)][conversionMatrix.getSize(1)];
+    for (int i=0; i<luConv.length; i++)
+      for (int j=0; j<luConv[i].length; j++)
+        luConv[i][j] = RA_luConv.getValueAsInt(i,j);
+    // LU-Demand-Matrix in Array kopieren (PERFORMANZ!)
+    this.luDemand    = new float[contManager.getDemandScenario().getSize(0)][contManager.getDemandScenario().getSize(1)];
+    for (int i=0; i<luDemand.length; i++)
+      for (int j=0; j<luDemand[i].length; j++)
+        luDemand[i][j] = RA_luDemand.getValueAsFloat(i,j);
+    // LUCC Elastizitaet in Array kopieren (PERFORMANZ!)
+    this.luElas      = new float[((ListPropertyReadAccess)RA_luElas).getCount()];
+    for (int i=0; i<luElas.length; i++)
+      this.luElas[i] = RA_luElas.getValueAsFloat(i);
+    this.areaRestr   = (WritableGrid)RA_areaRestr.getValue();
+    // Statische DF in Array kopieren (PERFORMANZ!)
+    this.sdfGrids    = new WritableGrid[contManager.getStaticDrivingForces().getGridCount()];
+    for (int i=0; i<sdfGrids.length; i++)
+      sdfGrids[i] = contManager.getStaticDrivingForces().getGrid(i);
+
+    // Die Liste der dyn. DF ist blockweise nach DF grupperiert
+    // Es koennen mehr Zeitschritt-Raster angegeben werden, als simuliert
+    // werden.
+    // Im Array 'ddfStartIdx' wird fuer die dynamischen DF gespeichert, an
+    // welcher Stelle in der Liste der Block beginnt.
+    // -1 bedeutet, dass der DF ein statische DF ist!
+    this.ddfStartIdx = new int[dfCount];
+    for (int i=0; i<dfCount; i++)
+      ddfStartIdx[i] = - 1;
+
+    // Variablen fuer dynamische Driving Forces nur belegen, wenn auch mit
+    // diesen gerechnet wird.
+    if ( CALC_WITH_DDF ) {
+      ListPropertyReadAccess ddfList = (ListPropertyReadAccess)RA_ddfList;
+      this.ddfCount    = ddfList.getCount();
+      // Raster mit dyn. DF in Array kopieren (PERFORMANZ!)
+      this.ddfGrids    = new WritableGrid[contManager.getDynamicDrivingForces().getGridCount()];
+      for (int i=0; i<ddfGrids.length; i++)
+        ddfGrids[i] = contManager.getDynamicDrivingForces().getGrid(i);
+      // Start-Indizes der DDF in der Liste der DDF-Grids
+      for (int i=0; i<ddfCount; i++)
+        ddfStartIdx[ddfList.getValueAsInt(i)] = i * ddfGrids.length / ddfCount;
+    } else {
+      this.ddfCount = 0;
+      this.ddfGrids = null;
+    }
+
+    // Regression Results fuer LUCC-W'keiten in Array kopieren (PERFORMANZ!)
+    this.regrRes = new float[contManager.getRegressionResults().getSize(0)][contManager.getRegressionResults().getSize(1)];
+    for (int i=0; i<regrRes.length; i++)
+      for (int j=0; j<regrRes[i].length; j++)
+        this.regrRes[i][j] = RA_regrRes.getValueAsFloat(i,j);
+
+    // Ausgabe-Raster-Liste fuer LUC-W'keiten aus Ressource holen,
+    // auf benoetigte Groesse erweitern und in Array kopieren (PERFORMANZ!)
+    MultiGrid outLUProbTemp = contManager.getLUProbabilities();
+    for (int i=0; outLUProbTemp.getGridCount()<luCount; i++)
+      outLUProbTemp.addGrid(); // Liste muss ein Raster fuer jeden LU-Typ enthalten
+    this.outLUProb  = new WritableGrid[luCount];
+    for (int i=0; i<luCount; i++)
+      this.outLUProb[i]  = outLUProbTemp.getGrid(i);
+
+    // Variablen fuer Nachbarschaftsw'keiten nur belegen, wenn auch mit diesen
+    // gerechnet wird
+    if ( CALC_WITH_NBH ) {
+      this.nbhRadiusX  = (contManager.getNeighborhoodSettings().getSize(0)-1)/2;
+      this.nbhRadiusY  = (contManager.getNeighborhoodSettings().getSize(1)-1)/2;
+      // Nbh.-Gewichtungen in Array kopieren (PERFORMANZ!)
+      this.nbhWeights  = new float[((ListPropertyReadAccess)RA_nbhWeights).getCount()];
+      for (int i=0; i<nbhWeights.length; i++)
+        this.nbhWeights[i] = RA_nbhWeights.getValueAsFloat(i);
+      // Nbh.-Settings in Array kopieren (PERFORMANZ!)
+      this.nbhSettings = new float[contManager.getNeighborhoodSettings().getSize(0)][contManager.getNeighborhoodSettings().getSize(1)][contManager.getNeighborhoodSettings().getSize(2)];
+      for (int i=0; i<nbhSettings.length; i++)
+        for (int j=0; j<nbhSettings[i].length; j++)
+          for (int k=0; k<nbhSettings[i][j].length; k++)
+            this.nbhSettings[i][j][k] = RA_nbhSettings.getValueAsFloat(i,j,k);
+      // Regression Results fuer Nbh. in Array kopieren (PERFORMANZ!)
+      this.nbhRegrRes  = new float[contManager.getNeighborhoodRegression().getSize(0)][contManager.getNeighborhoodRegression().getSize(1)];
+      for (int i=0; i<nbhRegrRes.length; i++)
+        for (int j=0; j<nbhRegrRes[i].length; j++)
+          this.nbhRegrRes[i][j] = RA_nbhRegrRes.getValueAsFloat(i,j);
+      // Ausgabe-Raster-Liste fuer Nachbarschafts-W'keiten aus Ressource holen,
+      // auf benoetigte Groesse erweitern und in Array kopieren (PERFORMANZ)
+      MultiGrid outNbhProbTemp = contManager.getNeighborhoodProbabilities();
+      for (int i=0; outNbhProbTemp.getGridCount()<luCount; i++)
+        outNbhProbTemp.addGrid(); // Liste muss ein Raster fuer jeden LU-Typ enthalten
+      this.outNbhProb = new WritableGrid[luCount];
+      for (int i=0; i<luCount; i++)
+        this.outNbhProb[i] = outNbhProbTemp.getGrid(i);
+    } else {
+      this.nbhRadiusX  = 0;
+      this.nbhRadiusY  = 0;
+      this.nbhWeights  = null;
+      this.nbhSettings = null;
+      this.nbhRegrRes  = null;
+      this.outNbhProb  = null;
+    }
+
+
+    // Bei Toleranz-Art "prozentual" werden die Werte in Prozent
+    // angegeben (intern wird aber mit Abweichungen zwischen 0 und 1 gerechnet!)
+    if ( demandTolType == TOLTYPE_PCT ) {
+      this.demandTolSingle  /= 100.0;
+      this.demandTolAverage /= 100.0;
+    }
+
+    // "Geschwindigkeit" fuer die Iterationsvariablen
+    this.iterSpeed = new float[luCount];
+
+    // Speichert die Flaechendeckung (in der Bedarfseinheit, z.B. ha)
+    // fuer die einzelnen LU-Typen zu jedem Zeitpunkt
+    // --> Die initialen Werte stehen in der 0-Zeile der Demand-Matrix
+    this.luCover  = new float[luCount][stepCount+1];
+    this.totCover = 0;
+    statusOut.print("InitCover: ");
+    for (int lu=0; lu<luCount; lu++) {
+      luCover[lu][0] = luDemand[lu][0];
+      totCover += luCover[lu][0]; // Gesamt-Flaeche des Untersuchungsgebiets
+      statusOut.print(luCover[lu][0]+"   ");
+    }
+    statusOut.println("   >> TotalCover "+totCover);
+
+    // Ausgabe-Raster leeren
+    for (int y=outActLU.getMinY(); y<outActLU.getMinY()+outActLU.getHeight(); y++)
+      for (int x=outActLU.getMinX(); x<outActLU.getMinX()+outActLU.getWidth(); x++)
+        outActLU.setRasterSample(Float.NaN,x,y);
+    // Liste der Schritt-Resultate leeren (damit bei vorzeitigem Modellende
+    // nicht neue mit alten Daten vermischt werden)
+    while ( outStepLU.getGridCount() > 0 )
+      outStepLU.removeGrid(0);
+
+    // spezielle GUI initialisieren
+    if (modelGUI != null)
+      modelGUI.init(this);
+
+    LOG.info("Scannign for all LU-Values in the Base-Scenario and mapping to 0...");
+    // Alle Zellen des Untersuchungsgebiets...
+    Set<Float> luccs = new HashSet<Float>();
+
+    for (Integer y=0; y<this.areaHeight; y++)
+      for (Integer x=0; x<this.areaWidth; x++){
+    	  float rasterSampleAsFloat = (float)baseLU.getRasterSampleAsFloat(x,y);
+    	  if (! Float.isNaN(rasterSampleAsFloat) )
+    		 luccs.add( rasterSampleAsFloat );
+  	}
+    Object[] lmo = luccs.toArray() ;
+	Arrays.sort(lmo);
+	statusOut.println("List of all LUCC-Types in BaseScenario : ");
+	luMap.put(Float.NaN, Float.NaN );
+	luMapReverse.put(Float.NaN, Float.NaN );
+	for (Integer i = 0; i < lmo.length; i++ ){
+		luMap.put((Float) lmo[i], new Float(i) );
+		luMapReverse.put( new Float(i), (Float) lmo[i]);
+	}
+
+	LOG.info("========================================");
+    LOG.info("MODEL INITIALISED (Log-Level "+LOG.getLevel()+")");
+  }
+
+  /**
+   * Gibt die Lese/Schreibrechte auf das Ein- und Ausgaberaster wieder frei.
+   * Interne Ressourcen brauchen keine aus dem Speicher entfernt werden.
+   */
+  public void performModelDispose() {
+    // Ressourcen wieder freigeben
+    releaseAccess(RA_baseLU);
+    releaseAccess(RA_baseLUHist);
+    releaseAccess(RA_luConv);
+    releaseAccess(RA_luElas);
+    releaseAccess(RA_areaRestr);
+    releaseAccess(RA_luDemand);
+    releaseAccess(RA_sdfGrids);
+    releaseAccess(RA_ddfList);
+    releaseAccess(RA_ddfGrids);
+    releaseAccess(RA_regrRes);
+    releaseAccess(RA_nbhWeights);
+    releaseAccess(RA_nbhSettings);
+    releaseAccess(RA_nbhRegrRes);
+    releaseAccess(WA_outActLU);
+    releaseAccess(WA_outActLUHist);
+    releaseAccess(WA_outLUProb);
+    releaseAccess(WA_outNbhProb);
+    releaseAccess(WA_outStepLU);
+    LOG.info("MODEL DISPOSED");
+    LOG.info("========================================");
+  }
+
+  /**
+   * Fuehrt einen Schritt des Modellablaufs durch.
+   * @param stepNo zu modellierender Schritt (beginnend bei 1!)
+   */
+  public void performModelStep(int stepNo) {
+    statusOut.println("Started step ".concat(String.valueOf(stepNo)));
+	   long time = System.currentTimeMillis();
+    //Unloading no longer needed Data:
+    if(stepNo>2)
+      outStepLU.getGrid(stepNo-3).unloadData();
+
+    // Raster festlegen, in dem die LU des vorangegangenen
+    // Schritts zu finden ist
+    WritableGrid lastLUGrid = (stepNo==1) ? baseLU : outStepLU.getGrid(stepNo-2);
+    // Raster festlegen, in dem die aktuelle LU History
+    // zu finden ist
+    WritableGrid luHistGrid = (stepNo==1) ? baseLUHist : outActLUHist;
+
+    // Merken, ob an einer Stelle bereits eine U-Zelle in einen anderen
+    // Typ gewechselt hat
+    boolean[] alreadyLUCCFromType = new boolean[luCount];
+    // Merken, ob an einer Stelle bereits eine U-Zelle neu entstanden ist
+    boolean[] alreadyLUCCToType = new boolean[luCount];
+
+    long calcTime = System.currentTimeMillis();
+    // LU-Wahrscheinlichkeiten berechnen
+    calculateLUProbabilities(stepNo);
+	System.out.println(stepNo + ";" +"LUCalc" +";" + (System.currentTimeMillis()-calcTime) + ";");
+    // Nachbarschafts-Wahrscheinlichkeiten berechnen
+   calcTime = System.currentTimeMillis();
+    calulateNeighborhoodProbabilities(stepNo,lastLUGrid);
+	System.out.println(stepNo + ";" +"NbhCalc" +";" + (System.currentTimeMillis()-calcTime) + ";");
+    calcTime = System.currentTimeMillis();
+
+    // Randomizer fuer diesen Zeitschritt erzeugen
+    rand = new Random(0xCAFE);
+
+    int   iterNo     = 0;
+    int   x          = 0;
+    int   y          = 0;
+    int   lu         = 0;
+    int   lastLU     = 0;
+    int   bestLU     = 0;
+    float bestLUProb = 0;
+    float baseProb   = 0;
+    float nbhProb    = 0;
+    float nbhWeight  = 0;
+    float elas       = 0;
+    float totalProb  = 0;
+    float lastLUC    = 0;
+    float actLUC     = 0;
+    Vector<Long> times = new Vector<Long>(500);
+    for (iterNo=1; true; iterNo++) {
+      long itertime;
+      itertime = System.currentTimeMillis();
+      if(checkDemandCompliedAndCalculateIterVar(stepNo,iterNo))
+    	  break;
+      this.fireModelEvent( new ModelIterationStepStartedEvent(this,stepNo,iterNo) );
+      if ( modelGUI != null /*&& modelGUI.isDeviationUpdateEnabled()*/ )
+        modelGUI.setIterationNumber(stepNo+"/"+iterNo);
+      // Arrays fuer Iterationsschritt initialisieren
+      for (lu = 0; lu < luCount; lu++) {
+        // noch kein Wechsel von einem LU-Typ
+        alreadyLUCCFromType[lu] = false;
+        // noch kein Wechsel zu einem LU-Typ
+        alreadyLUCCToType[lu] = false;
+        // Flaechen der LU-Typen fuer diesen Zeitschritt
+        luCover[lu][stepNo] = 0;
+        // Speed fuer die Iterationsvariablen initialisieren
+        // --> liegt die Nachfrage bei weniger als 5% des U'gebiets
+        //     wird langsamer begonnen
+        if ( luDemand[lu][stepNo]/totCover < 0.05f )
+          iterSpeed[lu] = 0.01f;
+        else
+          iterSpeed[lu] = 0.05f;
+      }
+
+      // Fuer alle Zellen des Untersuchungsgebiets
+      for (y = areaMinY; y < areaMaxY; y++)
+        for (x = areaMinX; x < areaMaxX; x++) {
+          checkBreakingCommands();
+
+          // Rasterzellen ausserhalb des Untersuchungsgebiets komplett
+          // ignorieren
+          // Grund: NoData-Zellen (Float.NaN) werden beim Cast in int zu 0,
+          //        also zur Landnutzung 0!!
+          if ( checkNoData(x,y,areaRestr) || checkNoData(x,y,baseLU) )
+            continue;
+
+          // Nutzungsdauern erhoehen
+          if (iterNo==1)
+            outActLUHist.setRasterSample(luHistGrid.getRasterSampleAsFloat(x, y) + 1, x, y);
+
+          // vorangegangene LU merken.
+          // Diese steht im Raster nicht unbedingt 0-basiert
+          lastLU = luMap.get( new Float (lastLUGrid.getRasterSampleAsInt(x, y)) ).intValue();
+
+          // Beste gefundene LU wird mit aktueller LU initialisiert
+          bestLU = lastLU;
+          bestLUProb = 0;
+
+          // Pruefen, ob Zelle die LU wechseln darf
+          if (checkLUCCGeneralAllowed(x, y, stepNo, lastLU, alreadyLUCCToType[ lastLU ])) {
+            // Alle LU-Typen auf Wechsel pruefen
+            for (lu = 0; lu < luCount; lu++) {
+              // Pruefen, ob Zelle in den betrachteten Typ wechseln darf
+              if (checkLUCCAllowed(x, y, stepNo, lastLU, lu, alreadyLUCCFromType[lu])) {
+                // Gesamt-Wahrscheinlichkeit berechnen
+                // a) DF-W'keit und Nachbarschaft-W'keit gehen anteilig ein
+                // b) Elastizitaet geht nur ein, wenn Zelle bereits fuer den
+                //    LU-Typ genutzt wird
+                // c) ITER geht negativ ein, da es auf Basis der Abweichung
+                //    luCover-luDemand berechnet wird. Ein negatives Iter
+                //    kennzeichnet also einen Mangel und muss die Gesamtw'keit
+                //    erhoehen
+                baseProb  = outLUProb[lu].getRasterSampleAsFloat(x, y);
+                nbhProb   = !CALC_WITH_NBH ? 0 : outNbhProb[lu].getRasterSampleAsFloat(x, y);
+                nbhWeight = !CALC_WITH_NBH ? 0 : nbhWeights[lu];
+                elas      = (lu == lastLU && luElas[lu] < 1) ? luElas[lu] : 0;
+                // LU-Wahrscheinlichkeit zusammensetzen
+                totalProb = baseProb * (1-nbhWeight)
+                          + nbhProb  * nbhWeight
+                          + elas
+                          - outIter[lu];
+
+                // betrachteter Typ ist geeigneter als der bisher beste
+                if (totalProb > bestLUProb) {
+                  bestLU = lu;
+                  bestLUProb = totalProb;
+                }
+              }
+            }
+            // Merken wenn wirklich ein Wechsel stattfindet
+            if (bestLU != lastLU) {
+              alreadyLUCCFromType[ lastLU ] = true;
+              alreadyLUCCToType[ bestLU ] = true;
+            }
+          }
+
+          // LU fuer diesen Iterationschritt setzen
+          outActLU.setRasterSample( luMapReverse.get ( (float) bestLU) , x, y);
+          // Flaechendeckung fuer LU-Typ erhoehen
+          luCover[ bestLU ][stepNo] += cellSize;
+        }
+      itertime = System.currentTimeMillis()-itertime;
+      times.add(itertime);
+      this.fireModelEvent( new ModelIterationStepFinishedEvent(this,stepNo,iterNo) );
+    }
+    System.out.println();
+    int counter =0;
+    for (Iterator iter = times.iterator(); iter.hasNext();) {
+		System.out.print(iter.next() + " ; ");
+		counter++;
+		if(counter % 10==0)
+			System.out.println();
+	}
+    // Liste der Zeitschritt-Ausgaberaster vergroessern
+    if ( outStepLU.getGridCount() <= stepNo-1 )
+      outStepLU.addGrid();
+
+    // LU in Ausgaberaster des Zeitschritts uebernehmen und ggf.
+    // Nutzungsdauer initialisieren
+    WritableGrid outStepLUGrid = outStepLU.getGrid(stepNo-1);
+    for (y=areaMinY; y<areaMaxY; y++)
+      for (x=areaMinX; x<areaMaxX; x++) {
+        checkBreakingCommands();
+        lastLUC = luMap.get( lastLUGrid.getRasterSampleAsFloat(x,y) );
+        actLUC  = luMap.get( outActLU.getRasterSampleAsFloat(x,y) );
+        // Wenn die Landnutzung gewechselt hat, wird die Historie zurueck
+        // gesetzt
+        if ( actLUC != lastLUC )
+          outActLUHist.setRasterSample(0f,x,y);
+
+        // LU in Ausgabe-Raster des simulierten Schritts uebernehmen
+        // Die 0-basierten LU-Nummern werden wieder zurueckgemapped. (SK)
+        outStepLUGrid.setRasterSample( luMapReverse.get( actLUC) ,x,y);
+      }
+    System.out.println(stepNo + ";" +"IterationTime" +";" + (System.currentTimeMillis()-calcTime) + ";" + (iterNo-1));
+    System.out.println(stepNo + ";" +"StepTime" +";" + (System.currentTimeMillis()-time) + ";");
+//
+    statusOut.println("Ended step ".concat(String.valueOf(stepNo)));
+  }
+
+  /**
+   * Liefert eine CLUE-spezifische GUI, in der die Abweichungen waehrend der
+   * Iteration angezeigt werden und ueber die die Toleranzen eingestellt
+   * werden koennen
+   * @return Instannz von {@link ClueModelGUI}
+   */
+  public Component getModelSpecificGUI() {
+    return modelGUI;
+  }
+
+  //////////////////////////////////////////////////////////////////////
+  ////////////////////////   Clue-Methoden   ///////////////////////////
+  //////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob eine Rasterzelle mit <code>NoData</code> belegt ist
+   * @param x     Raster-Koordinate
+   * @param y     Raster-Koordinate
+   * @param grid  zu pruefendes Raster
+   */
+  protected static boolean checkNoData(int x, int y, WritableGrid grid) {
+    return Float.isNaN(grid.getRasterSampleAsFloat(x,y));
+  }
+
+  /**
+   * Berechnet die auf den Driving Forces basierenden
+   * Landnutzungs-Wahrscheinlichkeiten fuer einen Modell-Schritt und speichert
+   * diese in der Ressource "temp. Ausgaberaster fuer die LU-Wahrscheinlichkeiten".<br>
+   * Werden keine dynamischen Driving Forces verwendet, geschieht die Berechnung
+   * nur beim ersten Modellierungsschritt.
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   */
+  protected void calculateLUProbabilities(int stepNo) {
+    // Wenn keine dynamischen Driving Forces verwendet werden
+    // braucht die Berechnung nur fuer den ersten Schritt
+    // durchgefuehrt werden
+    if ( ddfCount == 0 && stepNo > 1 )
+      return;
+
+    statusOut.print("Calculate LU-Probabilities for step "+stepNo+"...");
+    int x            = 0;
+    int y            = 0;
+    int lu           = 0;
+    int df           = 0;
+    float betaSum    = 0;
+    float expBetaSum = 0;
+    float prob       = 0;
+
+    // Fuer Zellen des Untersuchungsgebiets
+    for (y=areaMinY; y<areaMaxY; y++)
+      for (x=areaMinX; x<areaMaxX; x++)
+        // NotData-Bereich und Area Restrictions ignorieren
+        if ( !checkNoData(x,y,baseLU) && areaRestr.getRasterSampleAsFloat(x,y)==0 ) {
+          // Fuer alle LU-Typen
+          for (lu = 0; lu < luCount; lu++) {
+            betaSum = 0;
+            // Fuer alle Driving Forces die Summe der Betas berechnen
+            for (df = 0; df < dfCount; df++) {
+              checkBreakingCommands();
+              // DF-Grid festlegen:
+              // Bei dynamischem DF das jew. Zeitschritt-Raster aus der Liste
+              // ansonsten das statische Raster
+              WritableGrid dfGrid = null;
+              if ( ddfStartIdx[df] >= 0 )
+                dfGrid = this.ddfGrids[ddfStartIdx[df]+stepNo-1];
+              else
+                dfGrid = this.sdfGrids[df];
+
+///
+//   if ( ddfStartIdx[df] >= 0 ) {
+//     if ( x == dfGrid.convertRealToRaster(379755.2,0) &&
+//          y == dfGrid.convertRealToRaster(1028214.7,1) ) {
+//       LOG.debug("Step "+stepNo+", LUC "+lu+", "+x+"/"+y+":  "+dfGrid.getGridSampleAsFloat(379755.2, 1028214.7)+"    "+dfGrid);
+//     }
+//   }
+///
+              // Beim ersten Driving Force wird die Summe mit der
+              // Regressionskonstante initialisiert
+              if (df == 0)
+                betaSum = regrRes[0][lu];
+              // betaSum = BETA0(U) + Sum( BETA(df+1,U) * DF(df,x,y) )
+              betaSum += regrRes[df + 1][lu]
+                       * dfGrid.getRasterSampleAsFloat(x, y);
+///
+//  if ( x == 184 && y == 396 )
+//    LOG.debug("Step "+stepNo+", LUC "+lu+", DF "+df+", "+x+"/"+y+":  beta = "+regrRes[df + 1][lu]+"     dfValue = "+dfGrid.getRasterSampleAsFloat(x, y)+"     mult = "+(regrRes[df + 1][lu] * dfGrid.getRasterSampleAsFloat(x, y))+"    BetaSum = "+betaSum);
+///
+            }
+            expBetaSum = (float)Math.exp(betaSum);
+            prob = expBetaSum / (1 + expBetaSum);
+            // errechnete W'keit im Raster speichern
+///
+//  if ( x == 184 && y == 396 )
+//    LOG.debug("Step "+stepNo+", LUC "+lu+", "+x+"/"+y+":  Prob = "+prob);
+///
+            this.outLUProb[lu].setRasterSample( (float) prob, x, y);
+          }
+        }
+    //unloading no longer used ddfs to save memory (if supported by WritableGrid)
+    for (df = 0; df < dfCount; df++) {
+        WritableGrid grid = null;
+        if ( ddfStartIdx[df] >= 0 )
+          grid = this.ddfGrids[ddfStartIdx[df]+stepNo-1];
+        if(grid!=null) grid.unloadData();
+     }
+
+    statusOut.println(" done.");
+  }
+
+  /**
+   * Berechnet die auf den Nachbarschaftsbeziehungen basierenden
+   * Landnutzungs-Wahrscheinlichkeiten fuer einen Modell-Schritt und speichert
+   * diese in der Ressource "temp. Ausgaberaster fuer die Nachbarschafts-Wahrscheinlichkeiten".<br>
+   * Da sich die Landnutzung mit jedem Zeitschritt aendert geschieht dies
+   * vor jedem Zeitschritt neu.<br>
+   * Diese Methode macht nichts, wenn ohne Nachbarschafts-W'keiten simuliert wird,
+   * also wenn keine Angabe fuer die "Neighborhood-Weights" gemacht wird.
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   * @param luGrid LU-Raster aus dem die Umgebung der jeweiligen Zellen
+   *               ermittelt werden
+   */
+  protected void calulateNeighborhoodProbabilities(int stepNo, WritableGrid luGrid) {
+    // Wenn ohne Nachbarschaftsbeziehungen simuliert wird
+    if ( !CALC_WITH_NBH )
+      return;
+
+    statusOut.print("Calculate Neighborhood-Probabilities for step "+stepNo+"...");
+
+    int      x            = 0;
+    int      y            = 0;
+    int      lu           = 0;
+    int      i            = 0;
+    int      dx           = 0;
+    int      dy           = 0;
+    int      totCellCount = 0;
+    float[]  luCellCount  = new float[luCount];
+    float    betaSum      = 0;
+    float    beta         = 0;
+    float    nbhFact      = 0;
+    float    expBetaSum   = 0;
+    float    lucc         = 0;
+    float    setting      = 0;
+    // Fuer Zellen des Untersuchungsgebiets
+    for (y=areaMinY; y<areaMaxY; y++)
+      for (x=areaMinX; x<areaMaxX; x++)
+        // NoData-Bereich und Area Restrictions ignorieren
+        if ( !checkNoData(x,y,baseLU) && areaRestr.getRasterSampleAsFloat(x,y)==0 )
+          // Fuer alle LU-Typen
+          for (lu = 0; lu < luCount; lu++) {
+            checkBreakingCommands();
+
+            // Anzahl der Zellen in der Umgebung initialisieren
+            totCellCount = 0;
+            for (i=0; i<luCount; i++)
+              luCellCount[i] = 0;
+
+            // Umgebung der Zelle betrachten
+            for (dy=-nbhRadiusY; dy<=nbhRadiusY; dy++)
+              if ( areaMinY <= y+dy && y+dy<areaMaxY )
+                for (dx=-nbhRadiusX; dx<=nbhRadiusX; dx++)
+                  if ( areaMinX <= x+dx && x+dx<areaMaxX ) {
+
+
+                    lucc = luGrid.getRasterSampleAsFloat(x+dx,y+dy); // PERFORMANZ > nur einmal den Zellen-Wert ermitteln
+                    if ( !Float.isNaN(lucc) /*!checkNoData(x+dx,y+dy,baseLU)*/ ) {
+                    	// Die LU-Typen stehen im Raster nicht 0-basiert, deshalb mapping
+                   		lucc = luMap.get( lucc );
+
+                        // Alle Zellen in Umgebung zaehlen (jedoch nur diejenigen,
+                        // die potentiell auch in die Bewertung eingehen koennen!)
+                        setting = nbhSettings[dx+nbhRadiusX][dy+nbhRadiusY][lu];
+                        if ( setting != 0.0 ) {
+                          totCellCount++;
+                          // Anzahl der Zellen eines bestimmten Typs aufsummieren
+                          // (relativ zum in der Umgebung angegebenen Faktor)
+//                          luCellCount[ luGrid.getRasterSampleAsInt(x+dx,y+dy) ] += setting;
+
+                          //TODO Bricht hier ab, wenn LUCC-Klassen nicht 0,1,2 ... zaehlen...
+//                         luCellCount[ (int)lucc ] += setting;
+
+                          luCellCount[ (int)lucc ] += setting;
+
+                        }
+                      }
+                    }
+              // Summe der Betas berechnen
+              betaSum = nbhRegrRes[0][lu]; // Regr.Konstante
+              for (i=0; i<luCount; i++) {
+                beta    = nbhRegrRes[i + 1][lu];
+                nbhFact = (luCellCount[i]/totCellCount) / (luCover[i][stepNo-1]/totCover);
+                betaSum += beta * nbhFact;
+              }
+              // Wahrscheinlichkeit berechnen
+              expBetaSum = (float)Math.exp(betaSum);
+              outNbhProb[lu].setRasterSample((float)(expBetaSum/(1 + expBetaSum)),x,y);
+          }
+    statusOut.println(" done.");
+  }
+
+
+  /**
+   * Prueft, ob ein genereller LU-Wechsel fuer eine Zelle erlaubt ist.
+   * <ul>
+   * <li>Schliessen die Area Restrictions einen Wechsel aus?<br>
+   *     > Rasterwert(x,y) != 0
+   *     </li>
+   * <li>Schliesst die Conversion Elasticity einen Wechsel aus (Elastizitaet 1
+   *     und steigende Bedarf)?<br>
+   *     > ELAS(lastLU) == 1 und DEMAND(lastLU,t) >= DEMAND(lastLU,t-1)
+   *     </li>
+   * </ul>
+   * @param x      Raster-Koordinate
+   * @param y      Raster-Koordinate
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   * @param lastLU Bedeckung von (x,y) zum Zeitpunkt stepNo-1
+   * @param alreadyLUCCToActualType Flag gibt an, ob in der laufenden Iteration
+   *                                bereits ein LU-Wechsel in den den aktuellen
+   *                                Typ der Zelle (lastLU) vorgenommen wurde.<br>
+   *                                <b>Dieses Flag wird zur Zeit nicht verwendet!</b>
+   */
+  protected boolean checkLUCCGeneralAllowed(int x, int y, int stepNo, int lastLU, boolean alreadyLUCCToActualType) {
+    // Area Restrictions checken
+    if ( areaRestr.getRasterSampleAsFloat(x,y) != 0 )
+      return false;
+// DER ERSTE TEIL IST KEINE ORIGINAL-CLUE-REGEL!
+//    // Conversion Elasticity checken
+//    // --> wenn Elasticity 1 und bereits an anderer Stelle eine Zelle des
+//    //     bisherigen Typs entstanden ist, darf sie nicht wechseln
+//    // --> wenn Elasticity 1 und Bedarf steigt, darf kein Wechsel
+//    //     stattfinden, denn dann muessten (um den Bedarf zu decken)
+//    //     an anderer Stelle neue entstehen
+//    if (  luElas.getValueAsFloat(lastLU) == 1.0
+//       && ( alreadyLUCCToActualType ||
+//           luDemand.getValueAsFloat(lastLU,stepNo) >= luCover[lastLU][stepNo-1] ) )
+//      return false;
+
+    // Conversion Elasticity checken
+    // --> wenn Elasticity 1 und Bedarf steigt, darf kein Wechsel
+    //     stattfinden, denn dann muessten (um den Bedarf zu decken)
+    //     an anderer Stelle neue entstehen
+    if (  luElas[ lastLU ] == 1.0 &&
+//          luDemand[lastLU][stepNo] >= luCover[lastLU][stepNo-1] )
+          luDemand[ lastLU ][stepNo] >= luDemand[ lastLU ][stepNo-1] )
+      return false;
+
+    return true;
+  }
+
+  /**
+   * Prueft, ob ein bestimmter LU-Wechsel fuer eine Zelle erlaubt ist.
+   * <ul>
+   * <li>Schliesst die Conversion Elasticity einen Wechsel aus (Elastizitaet des
+   *     potentiellen Wechseltyps 1 und sinkender Bedarf)?<br>
+   *     > lastLU != newLU und ELAS(newLU) == 1 und DEMAND(newLU,t) <= DEMAND(newLU,t-1)
+   *     </li>
+   * <li>Schliesst die Conversion Matrix einen Wechsel aus (generell oder ueber
+   *     Historie)?<br>
+   *     > CONV(lastLU,newLU) == 0 oder<br>
+   *     > CONV(lastLU,newLU) > 100 und HIST(x,y) < CONV(lastLU,newLU)-101 oder<br>
+   *     > CONV(lastLU,newLU) < -100 und HIST(x,y) > -CONV(lastLU,newLU)-101
+   *     </li>
+   * </ul>
+   * @param x      Raster-Koordinate
+   * @param y      Raster-Koordinate
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   * @param lastLU Bedeckung von (x,y) zum Zeitpunkt stepNo-1
+   * @param newLU  potentielle neue Bedeckung von (x,y)
+   * @param alreadyLUCCFromNewType  Flag gibt an, ob in der laufenden Iteration
+   *                                bereits ein LU-Wechsel vom potentiellen neuen
+   *                                Typ in einen anderen Typ vorgenommen wurde.<br>
+   *                                <b>Dieses Flag wird zur Zeit nicht verwendet!</b>
+   */
+  protected boolean checkLUCCAllowed(int x, int y, int stepNo, int lastLU, int newLU, boolean alreadyLUCCFromNewType) {
+// IST KEINE ORIGINAL-CLUE-REGEL!
+//    // LU-Conversion-Elasticity des neuen Typs checken
+//    // --> wenn Elasticity des neuen Typs 1 ist und an anderer Stelle bereits
+//    //     eine Zelle des dieses Typs "verloren" ging, darf er hier
+//    //     nicht entstehen
+//    if (  alreadyLUCCFromNewType && luElas.getValueAsFloat(newLU) == 1.0 )
+//      return false;
+
+    // Conversion Elasticity checken
+    // --> wenn Elasticity des neuen Typs "newLU" 1 und dessen Bedarf sinkt,
+    //     darf kein Wechsel in diesen Typ stattfinden, denn dann muessten (um
+    //     den Bedarf fuer "newLU" zu erreichen) an anderer Stelle newLU-Zellen
+    //     entfernt werden
+    if (  lastLU != newLU &&
+          luElas[ newLU ] == 1.0 &&
+          luDemand[ newLU ][stepNo] <= luCover[ newLU ][stepNo-1] )
+//          luDemand.getValueAsFloat(newLU,stepNo) <= luDemand.getValueAsFloat(newLU,stepNo-1) )
+      return false;
+
+    // Wert aus LU-Conversion-Matrix ermitteln
+    // Bemerke: "von" steht in den Zeilen (also Y, also Dim1)
+    //          "nach" steht in den Spalten (also X, also Dim2)
+    int conv = luConv[ newLU ][ lastLU ];
+    // 1 --> LUCC generell erlaubt
+    if ( conv == 1 )
+      return true;
+    // 0 --> LUCC generell verboten
+    if ( conv == 0 )
+      return false;
+
+    // 100+t --> Wechsel erst nach t Schritten der vorangegangenen
+    //           LU moeglich
+    if ( conv > 100 ) {
+//      int minLUHist = conv-100;
+//      int luHist    = outActLUHist.getRasterSampleAsInt(x,y);
+//      return luHist >= minLUHist;
+      int minLUHist = conv-101;
+      int luHist    = outActLUHist.getRasterSampleAsInt(x,y);
+      return luHist >= minLUHist;
+    }
+
+    // -100-t --> Wechsel nicht mehr moeglich, wenn Zelle bereits
+    //            t Schritte unter der vorangegangenen LU
+    if ( conv < -100 ) {
+//      int maxLUHist = -conv-100;
+//      int luHist    = outActLUHist.getRasterSampleAsInt(x,y);
+//      return luHist < maxLUHist;
+      int maxLUHist = -conv-101;
+      int luHist    = outActLUHist.getRasterSampleAsInt(x,y);
+      return luHist <= maxLUHist;
+    }
+
+    return true;
+  }
+
+  /**
+   * Prueft, ob die aktuelle LU-Konfiguration die einzelenen Bedarfsanforderungen
+   * (bis auf eine Abweichung) erfuellt und berechnet die Iterationsvariablen
+   * neu.
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   * @param iterNo aktuelle Iteration (beginnend bei 1)
+   */
+  protected boolean checkDemandCompliedAndCalculateIterVar(int stepNo, int iterNo) {
+    boolean updateEnabled  = (modelGUI!=null && modelGUI.isDeviationUpdateEnabled());
+    boolean demandComplied = true;
+    // Abweichnungen berechnen
+    float[] singleDevAbs = new float[luCount];
+    float[] singleDevPct = new float[luCount];
+    float   averageDevAbs = 0;
+    float   averageDevPct = 0;
+    float   totalDevAbs = 0;
+    float   totalDevPct = 0;
+    for (int lu = 0; lu < luCount; lu++) {
+      // ##### Einzelabweichungen #####
+      // Absolute Abweichung der Landbedeckung vom Bedarf berechnen
+      float demand = luDemand[lu][stepNo];
+      singleDevAbs[lu]  = luCover[lu][stepNo] - demand;
+      // Prozentuale Einzel-Abweichnung relativ zum Bedarf
+      if (demand == 0)
+        // ist der Bedarf 0, aber auch die Bedeckung, ist die Abw. 0%
+        singleDevPct[lu] = luCover[lu][stepNo] == 0 ? 0 : 1;
+      else
+        singleDevPct[lu] = singleDevAbs[lu] / demand;
+
+      // Abweichung ueber erlaubter Toleranz?
+      float singleDev = (demandTolType == TOLTYPE_PCT) ? singleDevPct[lu] : singleDevAbs[lu];
+      if ( updateEnabled )
+        modelGUI.setDeviation(lu,singleDev);
+      if (Math.abs(singleDev) > demandTolSingle)
+        demandComplied = false;
+
+//      // Abweichung des LU-Typs ausgeben
+//      appendLog(singleDevAbs[lu],singleDevPct[lu],luDemand.getValueAsFloat(lu, stepNo),luCover[lu][stepNo]);
+
+      // ##### Gesamtabweichungen aufsummieren #####
+      totalDevAbs += Math.abs(singleDevAbs[lu]);
+    }
+
+    // Prozentuale Gesamt-Abweichnung relativ zum Gesamt-Untersuchungsgebiet
+    totalDevPct = totalDevAbs / totCover;
+    if ( updateEnabled )
+      modelGUI.setDeviation(luCount,(demandTolType == TOLTYPE_PCT) ? totalDevPct : totalDevAbs);
+
+    // Durchschnittliche Abweichnung pro LU-Typ
+    averageDevAbs = totalDevAbs / luCount;
+
+    // Durchschnittliche Abweichnung pro LU-Typ relativ zum Gesamt-Untersuchungsgebiet
+    averageDevPct = averageDevAbs / totCover;
+
+    // Abweichung ueber erlaubter Toleranz?
+    float avgDev = (demandTolType == TOLTYPE_PCT) ? averageDevPct : averageDevAbs;
+    if ( updateEnabled )
+      modelGUI.setDeviation(luCount+1,avgDev);
+    if ( Math.abs(avgDev) > demandTolAverage )
+      demandComplied = false;
+
+    // Iterationsvariablen neu berechnen
+    for (int lu = 0; lu < luCount; lu++) {
+      // Um Alternieren zwischen 2 Konfiguration zu verhindern
+      // eine kleine Zufallszahl hinzuaddieren (zwischen -0,005 und 0,005)
+      float randomValue = (rand.nextFloat()-0.5f)/100;
+
+      // --> Im ersten Schritt erhalten alle Iterationsvariablen den Wert 0,5
+      float iter = outIter[lu];
+      if (iterNo == 1)
+        iter = 0.5f+randomValue;
+//        iter = 0.5 + new float[] {0.002f,0f,0.002f,0f,0f,-0.003f}[lu];
+//        iter = 0.5 + new float[] {0.002f,0f,0.001f,0f,0f,-0.002f}[lu];
+      else {
+//        // Anteil der Einzelabweichnung an der Gesamtabweichnung
+////        float dev = (totalDevAbs!=0) ? singleDevAbs[lu] / totalDevAbs : 0.0;
+//        float dev  = singleDevPct[lu];
+//        iter = outIter.getValueAsFloat(lu) // alter Iter-Wert
+//             + dev // Anteil der Abweichung zum Bedarf
+//             + randomValue;
+        /////////////////////////////////////////
+        // Original-Iter-Berechnung aus CLUE
+        iterSpeed[lu] += 0.00005;
+        iter += (singleDevAbs[lu]/totCover)/(iterSpeed[lu]*(rand.nextInt(101)+1));
+
+        if (iter > 2f)
+          iter = 0.5f;
+        if ( Math.abs(iter) < 0.001 )
+          iter = 0.01f * Math.signum(iter);
+        if (iter < -0.5f)
+          iter = -0.4f;
+        /////////////////////////////////////////
+      }
+      // Iter speichern
+      outIter[lu] = iter;
+    }
+
+    return demandComplied;
+  }
+
+  //////////////////////////////////////////////////////////////////////
+  /////////////////////   Clue-spezifische GUI   ///////////////////////
+  //////////////////////////////////////////////////////////////////////
+
+  /**
+   * Diese Klasse stellt eine modellspezifische GUI-Komponente fuer das
+   * {@link ClueModel CLUE-Modell} dar.
+   * In dieser wird fuer jeden modellierten LU-Typ ein {@linkplain ExpansionBar Status-Balken}
+   * fuer die Abweichnung vom geforderten Bedarf angezeigt. Sowie je ein Balken
+   * fuer die aktuelle Gesamt- und Durchschittsabweichung. Je nach gewaehlter
+   * Abweichungsart (prozentual oder absolute Angaben), werden Abweichungen
+   * von +/- 100% oder +/- 10000 Bedarfseinheiten angezeigt.<br>
+   * Darueber hinaus enthaelt sie je einen Regler, ueber den die maximal
+   * erlaubte Abweichung von den Bedarfen (Einzelabweichung der LU-Typen und
+   * Durchschnittsabweichung) eingestellt werden kann.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class ClueModelGUI extends JComponent {
+    private       float MIN = -1;
+    private       float MAX = 1;
+    private final float TOL = 0.2f;
+    private       float SLIDER_FACT = 1000;
+    // Format fuer Wert-Anzeige des Sliders
+    private DecimalFormat sliderPctFormat = new DecimalFormat("0.0%");
+    private DecimalFormat sliderDecFormat = new DecimalFormat("0.0");
+    // Format fuer Wert-Anzeige im Balken
+    private DecimalFormat statusPctFormat = new DecimalFormat("0.0000%");
+    private DecimalFormat statusDecFormat = new DecimalFormat("0.0");
+    // Format fuer Wert-Anzeige unterhalb der Balken (Max/Min/Middle)
+    private DecimalFormat infoPctFormat   = new DecimalFormat("0.0%");
+    private DecimalFormat infoDecFormat   = new DecimalFormat("0.0");
+
+    private DeviationContainer  divCont          = null;
+    private JSlider             singleDivSlider  = null;
+    private JSlider             averageDivSlider = null;
+    private ClueModel_deterministic           model            = null;
+    private DeviationLabel      singleDivLabel   = new DeviationLabel("Erlaubte Bedarfsabweichung pro LU-Typ:",sliderPctFormat);
+    private DeviationLabel      averageDivLabel  = new DeviationLabel("Erlaubte durchschnittliche Bedarfsabweichung:",sliderPctFormat);
+    private Font                labelFont        = singleDivLabel.getFont().deriveFont(Font.BOLD | Font.CENTER_BASELINE);
+    private boolean             alreadyPacked    = false;
+    private JCheckBox           updateCheckBox   = null;
+    private JLabel              iterationLabel   = null;
+
+    /**
+     * Erzeugt eine neue Clue-GUI. Diese wird jedoch erst nach Aufruf
+     * der {@link #init(ClueModel_deterministic)}-Methode komplett erzeugt, da erst dann
+     * die Anzahl der angezeigten Balken (= Anzahl LU-Typen) feststeht.
+     */
+    public ClueModelGUI() {
+      super();
+      this.setLayout( new SpringLayout() );
+      // Label in dem die Iterationsnummer angezeigt wird
+      iterationLabel = new JLabel(" ");
+      iterationLabel.setBorder( BorderFactory.createLoweredBevelBorder() );
+      // Slider/Label fuer Abweichnug der einzelnen Typen
+      singleDivSlider  = new JSlider(JSlider.HORIZONTAL,0,(int)(SLIDER_FACT*MAX),(int)(SLIDER_FACT*TOL));
+      singleDivSlider.setPaintTicks(true);
+      singleDivSlider.setPaintLabels(true);
+      singleDivSlider.setPaintTrack(true);
+      singleDivSlider.setEnabled(false);
+      singleDivSlider.addChangeListener( new ChangeListener() {
+        public void stateChanged(ChangeEvent e) {
+          float tol = singleDivSlider.getValue() / SLIDER_FACT;
+          if ( model!=null )
+            model.demandTolSingle = tol;
+          if ( singleDivLabel!=null )
+            singleDivLabel.setValue(tol);
+          if ( divCont!=null )
+            for (int i=0; i<divCont.getCount()-1; i++)
+              divCont.setTolerance(i,tol);
+        }
+      });
+      singleDivLabel.setFont(labelFont);
+      singleDivLabel.setValue(singleDivSlider.getValue()/SLIDER_FACT);
+
+      // Slider/Label fuer Abweichnug der einzelnen Typen
+      averageDivSlider  = new JSlider(JSlider.HORIZONTAL,0,(int)(SLIDER_FACT*MAX),(int)(SLIDER_FACT*TOL));
+      averageDivSlider.setPaintTicks(true);
+      averageDivSlider.setPaintLabels(true);
+      averageDivSlider.setPaintTrack(true);
+      averageDivSlider.setEnabled(false);
+      averageDivSlider.addChangeListener( new ChangeListener() {
+        public void stateChanged(ChangeEvent e) {
+          float tol = averageDivSlider.getValue() / SLIDER_FACT;
+          if ( model!=null )
+            model.demandTolAverage = tol;
+          if ( averageDivLabel!=null )
+            averageDivLabel.setValue(tol);
+          if ( divCont!=null )
+            divCont.setTolerance( divCont.getCount()-1, tol );
+        }
+      });
+      averageDivLabel.setFont(labelFont);
+      averageDivLabel.setValue(averageDivSlider.getValue()/SLIDER_FACT);
+
+      // Checkbox zur (De)Aktivierung der Anzeige-Aktualisierung
+      updateCheckBox = new JCheckBox("Abweichungen autom. aktualisieren",true);
+
+      this.add( averageDivLabel );
+      this.add( averageDivSlider );
+      this.add( singleDivLabel );
+      this.add( singleDivSlider );
+      this.add( updateCheckBox );
+      this.add( iterationLabel );
+      SpringUtilities.makeCompactGrid(this,6,1,0,0,0,5);
+    }
+
+    /**
+     * Initialisiert die GUI fuer eine <b>initialisierte</b> Modell-Instanz.
+     * Wird zum Ende {@link ClueModel#performModelInit()} aufgerufen.
+     */
+    public void init(ClueModel_deterministic model) {
+      this.model = model;
+      if ( divCont != null )
+        remove(divCont);
+      SLIDER_FACT = (model.demandTolType == TOLTYPE_PCT) ? 1000 : 1;
+      MIN         = (model.demandTolType == TOLTYPE_PCT) ? -1 : ((float)-Math.pow(10,(int)Math.log10(model.totCover)))/1000;
+      MAX         = (model.demandTolType == TOLTYPE_PCT) ?  1 : -MIN;
+      averageDivSlider.setMaximum((int)(MAX*SLIDER_FACT));
+      averageDivLabel.setNumberFormat( model.demandTolType == TOLTYPE_PCT ? sliderPctFormat : sliderDecFormat );
+      singleDivSlider.setMaximum((int)(MAX*SLIDER_FACT));
+      singleDivLabel.setNumberFormat( model.demandTolType == TOLTYPE_PCT ? sliderPctFormat : sliderDecFormat );
+
+      String[] divDesc = new String[model.luCount+2];
+      for (int i=0; i<model.luCount; i++)
+        divDesc[i] = String.valueOf(i);
+      divDesc[model.luCount]   = "Total";
+      divDesc[model.luCount+1] = "Average";
+
+      divCont = new DeviationContainer(
+                         divDesc.length,
+                         divDesc,
+                         MIN,
+                         MAX,
+                         0,
+                         model.demandTolSingle,
+                         model.demandTolType == TOLTYPE_PCT ? statusPctFormat : statusDecFormat,
+                         model.demandTolType == TOLTYPE_PCT ? infoPctFormat   : infoDecFormat
+      );
+      divCont.setBarDescHeader("LU-Typ");
+      divCont.setBarHeader("Aktuelle Bedarfsabweichung");
+      this.add(divCont,4);
+
+      // Wert des Balkens darf erst hier (nach Neu-Erstellung des
+      // Abweichungs-Containers) neu gesetzt werden, da beim Setzen
+      // des neuen Wertes automatisch die Toleranzen der Abweichungsbalken
+      // aktualisiert werden
+      setSingleTolerance(model.demandTolSingle);
+      setAverageTolerance(model.demandTolAverage);
+
+      SpringUtilities.makeCompactGrid(this,7,1,0,0,0,5);
+      if ( !alreadyPacked )
+        SwingUtil.packParentWindow(this);
+      else
+        this.validate();
+      alreadyPacked = true;
+      singleDivSlider.setEnabled( true );
+      averageDivSlider.setEnabled( true );
+    }
+
+    /**
+     * Setzt die in der GUI angezeigte Interationsnummer. Diese wird
+     * durch einen String repraesentiert, damit auch berliebige andere
+     * Informationen (anstelle der Nummer) dargestellt werden koennen (z.B.
+     * zusaetzlich noch die Schrittnummer).
+     * @param iterString dargestellte Iterationsnummer
+     */
+    public void setIterationNumber(String iterString) {
+      iterationLabel.setText("Iteration: "+iterString);
+    }
+
+    /**
+     * Stellt den Slider fuer die Einzelabweichung auf einen bestimmten Wert
+     * ein. Hierdurch wird automatisch auch der Wert fuer das Modell neu
+     * gesetzt.
+     */
+    public void setSingleTolerance(float tol) {
+      singleDivSlider.setValue((int)(tol*SLIDER_FACT));
+    }
+
+    /**
+     * Stellt den Slider fuer die Durchschnittsabweichung auf einen bestimmten Wert
+     * ein. Hierdurch wird automatisch auch der Wert fuer das Modell neu
+     * gesetzt.
+     */
+    public void setAverageTolerance(float tol) {
+      averageDivSlider.setValue((int)(tol*SLIDER_FACT));
+    }
+
+    /**
+     * Setzt die Abweichnungswerte fuer alle Statusbalken.
+     * @param value Array mit den Abweichungen
+     */
+    public void setDeviation(float[] value) {
+      if ( divCont!= null && isDeviationUpdateEnabled() )
+        divCont.setExpansion(value);
+    }
+
+    /**
+     * Setzt den Abweichnungswert fuer einen Statusbalken.
+     * @param idx   Index eines Balkens
+     * @param value Array mit den Abweichungen
+     */
+    public void setDeviation(int idx, float value) {
+      if ( divCont!= null && isDeviationUpdateEnabled() )
+        divCont.setExpansion(idx,value);
+    }
+
+    /**
+     * Aktiviert oder Deaktiviert die Aktualisierung der Abweichungsbalken.
+     */
+    public void setDeviationUpdateEnabled(boolean enabled) {
+      updateCheckBox.setSelected(enabled);
+    }
+
+    /**
+     * Aktiviert oder Deaktiviert die Aktualisierung der Abweichungsbalken.
+     */
+    public boolean isDeviationUpdateEnabled() {
+      return updateCheckBox.isSelected();
+    }
+
+    /**
+     * Diese Klasse stellt ein Label dar, in dem (hinter einem Basistext)
+     * ein numerischer Abweichungswert (z.B. erlaubte Maximalabweichung) angezeigt wird.
+     * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+     * @version 1.0
+     */
+    private static class DeviationLabel extends JLabel {
+      private String baseText        = "";
+      private float dev              = 0;
+      private NumberFormat numFormat = null;
+
+      /**
+       * Erzeugt ein neues leeres Label.
+       */
+      public DeviationLabel() {
+        this("");
+      }
+
+      /**
+       * Erzeugt ein neues Label. Der dargestellte Wert ist initial 0%.
+       * @param text      Basistext
+       */
+      public DeviationLabel(String text) {
+        this(text,new DecimalFormat("0.0%"));
+      }
+
+      /**
+       * Erzeugt ein neues Label. Der dargestellte Wert ist initial 0.
+       * @param text      Basistext
+       * @param numFormat Anzeigeformat fuer den dargestellten Abweichungswert
+       */
+      public DeviationLabel(String text, NumberFormat numFormat) {
+        this(text,numFormat,0);
+      }
+
+      /**
+       * Erzeugt ein neues Label.
+       * @param text      Basistext
+       * @param numFormat Anzeigeformat fuer den dargestellten Abweichungswert
+       * @param dev       initialer Wert fuer den Abweichungswert
+       */
+      public DeviationLabel(String text, NumberFormat numFormat, float dev) {
+        super();
+        this.baseText  = text;
+        this.dev    = dev;
+        setNumberFormat(numFormat);
+        setText(baseText);
+      }
+
+      /**
+       * Setzt den darzustellenden numerischen Abweichungswert.
+       */
+      public void setValue(float dev) {
+        this.dev = dev;
+        setText(baseText);
+      }
+
+      /**
+       * Setzt den Basistext des Labels.
+       */
+      public void setText(String text) {
+        this.baseText = text;
+        String displayText = baseText;
+        if ( numFormat != null )
+          displayText = displayText+" "+numFormat.format(this.dev);
+        super.setText(displayText);
+      }
+
+      /**
+       * Setzt das Darstellungsformat fuer den Abweichungswert.
+       */
+      public void setNumberFormat(NumberFormat format) {
+        this.numFormat = format;
+      }
+    }
+
+    /**
+     * Diese Klasse stellt einen Container dar, in dem vertikal eine Reihe von
+     * {@linkplain ExpansionBar Status-Balken} angezeigt werden. Alle Balken
+     * haben dieselben Extremwerte (Min, Max, Middle). Deshalb erhaelt nur
+     * der unterste Balken eine Info-Leiste mit diesen Extremwerten.
+     * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+     * @version 1.0
+     */
+    private static class DeviationContainer extends JComponent {
+      private static final NumberFormat NUM_FORMAT = new DecimalFormat("0.0%");
+      /** Konstante fuer eine vertikale Ausrichtung der Status-Balken */
+      public static final int VERTICAL   = ExpansionBar.VERTICAL;
+      /** Konstante fuer eine horizontale Ausrichtung der Status-Balken */
+      public static final int HORIZONTAL = ExpansionBar.HORIZONTAL;
+
+      private ExpansionBar[] expansionBar   = null;
+      private JLabel[]       expansionLabel = null;
+      private JLabel         typeLabel      = null;
+      private JLabel         divLabel       = null;
+      private Font           sampleFont     = new JLabel().getFont();
+
+      /**
+       * Erzeugt einen neuen Container. Die Balken stellen eine prozentuale
+       * Abweichung von +/- 100% um 0% dar. Die Balken erhalten keine Beschreibung,
+       * sondern werden durchnummeriert.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param tol      Toleranzwert fuer alle Balken (siehe {@link ExpansionBar})
+       */
+      public DeviationContainer(int count, float tol) {
+        this(count,-1,1,0,tol,NUM_FORMAT);
+      }
+
+      /**
+       * Erzeugt einen neuen Container. Als Mitte-Wert fuer die Balken wird
+       * 0 verwendet. Die Balken erhalten keine Beschreibung, sondern werden
+       * durchnummeriert.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param min      Minimum-Wert fuer die Balken
+       * @param max      Maximum-Wert fuer die Balken
+       * @param tol      Toleranzwert fuer alle Balken (siehe {@link ExpansionBar})
+       * @param form     Darstellungsformat fuer die Zahlen im Balken und in der
+       *                 Info-Leiste des untersten Balken
+       */
+      public DeviationContainer(int count, float min, float max, float tol, NumberFormat form) {
+        this(count,min,max,0,tol,form);
+      }
+
+      /**
+       * Erzeugt einen neuen Container. Die Balken werden durchnummeriert.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param min      Minimum-Wert fuer die Balken
+       * @param max      Maximum-Wert fuer die Balken
+       * @param mid      Mitte-Wert fuer die Balken
+       * @param tol      Toleranzwert fuer alle Balken (siehe {@link ExpansionBar})
+       * @param form     Darstellungsformat fuer die Zahlen im Balken und in der
+       *                 Info-Leiste des untersten Balken
+       */
+      public DeviationContainer(int count, float min, float max, float mid, float tol, NumberFormat form) {
+        this(count,null,min,max,mid,tol,form,form);
+      }
+
+      /**
+       * Erzeugt einen neuen Container.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param desc     Beschreibungen fuer die Balken (kann <code>null</code> sein!)
+       * @param min      Minimum-Wert fuer die Balken
+       * @param max      Maximum-Wert fuer die Balken
+       * @param mid      Mitte-Wert fuer die Balken
+       * @param tol      Toleranzwert fuer alle Balken (siehe {@link ExpansionBar})
+       * @param barForm  Darstellungsformat fuer die Zahlen im Balken
+       * @param infoForm Darstellungsformat fuer die Zahlen in der Info-Leiste
+       *                 des untersten Balken
+       */
+      public DeviationContainer(int count, String[] desc, float min, float max, float mid, float tol, NumberFormat barForm, NumberFormat infoForm) {
+        this(count,desc,min,max,mid,LangUtil.createArray(count,tol),barForm,infoForm);
+      }
+
+      /**
+       * Erzeugt einen neuen Container.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param desc     Beschreibungen fuer die Balken (kann <code>null</code> sein!)
+       * @param min      Minimum-Wert fuer die Balken
+       * @param max      Maximum-Wert fuer die Balken
+       * @param mid      Mitte-Wert fuer die Balken
+       * @param tol      Toleranzwert fuer jeden einzelnen Balken (siehe {@link ExpansionBar})
+       * @param barForm  Darstellungsformat fuer die Zahlen im Balken
+       * @param infoForm Darstellungsformat fuer die Zahlen in der Info-Leiste
+       *                 des untersten Balken
+       */
+      public DeviationContainer(int count, String[] desc, float min, float max, float mid, float[] tol, NumberFormat barForm, NumberFormat infoForm) {
+        super();
+        if ( count <= 0 )
+          throw new IllegalArgumentException("At least one divergence bar must specified!");
+        if ( desc!=null && desc.length < count )
+          throw new IllegalArgumentException("Less describtions specified!");
+
+        this.setLayout( new SpringLayout() );
+
+        // PROBLEME mit den Labels bei VERTICAL
+        // --> Label-Breite wird wohl zu 0
+        int orient = HORIZONTAL;
+
+        sampleFont = sampleFont.deriveFont(Font.BOLD);
+        if (orient == VERTICAL)
+          sampleFont = sampleFont.deriveFont( AffineTransform.getRotateInstance(Math.PI/2) );
+
+        // Label erzeugen
+        typeLabel = new JLabel("Type");
+        divLabel = new JLabel("Divergence");
+        typeLabel.setFont(sampleFont);
+        divLabel.setFont(sampleFont);
+
+        // Statusbalken erzeugen
+        this.expansionBar   = new ExpansionBar[count];
+        this.expansionLabel = new JLabel[count];
+        for (int i=0; i<count; i++) {
+          expansionBar[i]   = new ExpansionBar(orient,ExpansionBar.LINEAR,min,max,mid,-tol[i],tol[i],0,barForm,infoForm);
+          expansionLabel[i] = new JLabel( desc!=null && i<desc.length ? desc[i] : String.valueOf(i));
+          if ( orient == HORIZONTAL ) {
+            expansionLabel[i].setHorizontalAlignment(JLabel.CENTER);
+            expansionLabel[i].setVerticalAlignment(JLabel.TOP);
+          } else {
+            expansionLabel[i].setFont( expansionLabel[i].getFont().deriveFont( AffineTransform.getRotateInstance(Math.PI/2) ) );
+            expansionLabel[i].setHorizontalAlignment(JLabel.LEFT);
+            expansionLabel[i].setVerticalAlignment(JLabel.CENTER);
+          }
+        }
+        // beim untersten Balken sollen die Labels erscheinen
+        expansionBar[count-1].setValueLabelsPainted(true);
+
+        // Komponenten einfuegen und ausrichten
+        if ( orient == HORIZONTAL ) {
+          typeLabel.setHorizontalAlignment(JLabel.CENTER);
+          typeLabel.setVerticalAlignment(JLabel.BOTTOM);
+          divLabel.setHorizontalAlignment(JLabel.CENTER);
+          divLabel.setVerticalAlignment(JLabel.BOTTOM);
+          add( typeLabel );
+          add( divLabel );
+          for (int i=0; i<count; i++) {
+            add( expansionLabel[i] );
+            add( expansionBar[i] );
+          }
+          // Layout ausrichten
+          SpringUtilities.makeCompactGrid(this,getComponentCount()/2,2,0,0,10,0);
+        } else {
+          typeLabel.setHorizontalAlignment(JLabel.CENTER);
+          typeLabel.setVerticalAlignment(JLabel.CENTER);
+          divLabel.setHorizontalAlignment(JLabel.CENTER);
+          divLabel.setVerticalAlignment(JLabel.CENTER);
+          add( divLabel );
+          for (int i=0; i<count; i++)
+            add( expansionBar[i] );
+          add( typeLabel );
+          for (int i=0; i<count; i++)
+            add( expansionLabel[i] );
+          // Layout ausrichten
+          SpringUtilities.makeCompactGrid(this,2,getComponentCount()/2,0,0,10,0);
+        }
+      }
+
+      /**
+       * Liefert die Anzahl an Balken.
+       */
+      public int getCount() {
+        return expansionBar.length;
+      }
+
+      /**
+       * Setzt den Toleranzwert fuer alle Balken.
+       */
+      public void setTolerance(float tol) {
+        for (int i=0; i<expansionBar.length; i++)
+          setTolerance(i,tol);
+      }
+
+      /**
+       * Setzt den Toleranzwert fuer einen Balken.
+       */
+      public void setTolerance(int i, float tol) {
+        expansionBar[i].setMinimumTolerance( -tol );
+        expansionBar[i].setMaximumTolerance(  tol );
+      }
+
+      /**
+       * Setzt den Wert fuer alle Balken.
+       */
+      public void setExpansion(float[] value) {
+        for (int i=0; i<value.length; i++)
+          setExpansion(i,value[i]);
+      }
+
+      /**
+       * Setzt die Beschreibung fuer einen Balken.
+       */
+      public void setBarDesc(int idx, String text) {
+        expansionLabel[idx].setText(text);
+      }
+
+      /**
+       * Setzt den Wert fuer einen Balken.
+       */
+      public void setExpansion(int idx, float value) {
+        expansionBar[idx].setValue(value);
+      }
+
+      /**
+       * Setzt die Beschreibung die oberhalb der Balken-Beschreibungen steht.
+       */
+      public void setBarDescHeader(String text) {
+        typeLabel.setText(text);
+      }
+
+      /**
+       * Setzt die Beschreibung die oberhalb der Balken steht.
+       */
+      public void setBarHeader(String text) {
+        divLabel.setText(text);
+      }
+
+    }
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueParallelTuned.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueParallelTuned.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueParallelTuned.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,1375 @@
+package edu.bonn.xulu.plugin.model.parallel;
+
+import java.awt.image.DataBuffer;
+import java.awt.Window;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.geom.AffineTransform;
+import java.io.File;
+
+import javax.swing.BoxLayout;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JCheckBox;
+import javax.swing.JProgressBar;
+import javax.swing.BoundedRangeModel;
+import javax.swing.DefaultBoundedRangeModel;
+import javax.swing.JSlider;
+import javax.swing.SpringLayout;
+import javax.swing.BorderFactory;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.ChangeEvent;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+import java.text.NumberFormat;
+import java.text.DecimalFormat;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.LogManager;
+
+import appl.parallel.data.splittable.SplittableGridLLFactory;
+import appl.parallel.model.AbstractParallelStepModel;
+import appl.parallel.spmd.AdvancedSPMDClientInterface;
+import appl.parallel.spmd.MultiDataObject;
+import appl.parallel.spmd.SPMDClientInterface;
+import appl.parallel.spmd.SyncPoint;
+import appl.parallel.spmd.SyncPoint.Priority;
+import appl.util.GeneralUtil;
+import appl.util.RasterUtil;
+
+import schmitzm.lang.LangUtil;
+
+import schmitzm.data.property.Access;
+import schmitzm.data.property.ValueProperty;
+import schmitzm.data.property.ValuePropertyType;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.ListPropertyReadAccess;
+import schmitzm.data.property.ListPropertyWriteAccess;
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.MatrixProperty;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.PropertyWriteAccess;
+import schmitzm.data.WritableGrid;
+
+import schmitzm.swing.SwingUtil;
+import schmitzm.swing.SpringUtilities;
+import schmitzm.swing.ExpansionBar;
+
+import edu.bonn.xulu.data.XuluDataException;
+import edu.bonn.xulu.model.AbstractStepModel;
+import edu.bonn.xulu.model.ModelContentManager;
+import edu.bonn.xulu.model.AbstractModelContentManager;
+import edu.bonn.xulu.model.ModelResource;
+import edu.bonn.xulu.model.AbstractModelResource;
+import edu.bonn.xulu.model.ValuePropertyResource;
+import edu.bonn.xulu.model.event.ModelIterationStepStartedEvent;
+import edu.bonn.xulu.model.event.ModelIterationStepFinishedEvent;
+
+import edu.bonn.xulu.plugin.data.grid.MultiGrid;
+import edu.bonn.xulu.plugin.model.clue.ClueModelContentManager;
+import edu.bonn.xulu.plugin.model.parallel.ClueTaskDefinition.Task;
+
+import schmitzm.temp.BaseTypeUtil;
+
+/**
+ * Used for a better resource utilization in the associated task ({@link ClueTaskTuned}).
+ * Multithreading and preloading are used. See {@link ClueTaskTuned} for details. 
+ *
+ * @see ClueTaskTuned
+ * 
+ * @author Dominik Appl
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany) (original code)
+ * @version 1.0
+ */
+
+public class ClueParallelTuned extends AbstractParallelStepModel {
+  /** Konstante fuer die Toleranz-Art "prozentual". */
+  public static final int TOLTYPE_PCT = 0;
+  /** Konstante fuer die Toleranz-Art "absolut in Bedarf-Einheit". */
+  public static final int TOLTYPE_ABS = 1;
+
+  /** Speichert den ContentManager fuer das Modell.
+   *  @see ClueModelContentManager */
+  protected ClueModelContentManager contManager;
+
+  private final ClueModelGUI  modelGUI = new ClueModelGUI();
+  private final Logger        LOG      = LogManager.getLogger(this.getClass().getName());
+
+  //********** Lese/Schreibrechte, die fuer den gesamten ***********
+  //********** Modellanlauf gehalten werden muessen      ***********
+  private PropertyReadAccess  RA_baseLU       = null; // Base Scenario
+  private PropertyReadAccess  RA_baseLUHist   = null; // Base LU History
+  private PropertyReadAccess  RA_luConv       = null; // LU-Conversion-Matrix
+  private PropertyReadAccess  RA_luElas       = null; // LU-Conversion-Elasticity
+  private PropertyReadAccess  RA_areaRestr    = null; // Area Restrictions
+  private PropertyReadAccess  RA_luDemand     = null; // LU-Bedarfe
+  private PropertyReadAccess  RA_sdfGrids     = null; // Static Driving Forces
+  private PropertyReadAccess  RA_ddfList      = null; // List of dynmic Driving Forces
+  private PropertyReadAccess  RA_ddfGrids     = null; // Dynamic Driving Forces
+  private PropertyReadAccess  RA_regrRes      = null; // Regression Results
+  private PropertyReadAccess  RA_nbhWeights   = null; // Gewichtung der Nachbarschaft pro LU-Typ
+  private PropertyReadAccess  RA_nbhSettings  = null; // Definition der Umgebung pro LU-Typ
+  private PropertyReadAccess  RA_nbhRegrRes   = null; // Regression Results fuer Nachbarschaft
+  private PropertyWriteAccess WA_outActLU     = null; // speichert die aktuell sim. LU
+  private PropertyWriteAccess WA_outActLUHist = null; // speichert die aktuell sim. LU Historie
+  private PropertyWriteAccess WA_outLUProb    = null; // speichert die LU-Wahrscheinlichkeiten
+  private PropertyWriteAccess WA_outNbhProb   = null; // speichert die Nachbarschafts-Wahrscheinlichkeiten
+  private PropertyWriteAccess WA_outStepLU    = null; // speichert die LU fuer jeden Zeitpunkt
+
+  //**************** Variablen mit denen gearbeitet wird *******************
+  // Modell-Parameter
+  private int    luCount    = 0;    // Anzahl an LU-Typen
+  private int    dfCount    = 0;    // Anzahl an Driving Forces
+  private int    ddfCount   = 0;    // Anzahl an dynamischen Driving Forces
+  private int    areaWidth  = 0;    // Breite des Untersuchungsgebiets (Rasterzellen)
+  private int    areaHeight = 0;    // Hoehe des Untersuchungsgebiets (Rasterzellen)
+  private int    areaMinX   = 0;    // Start-Index des Rasters in X-Richtung
+  private int    areaMinY   = 0;    // Start-Index des Rasters in Y-Richtung
+  private int    areaMaxX   = 0;    // End-Index des Rasters in X-Richtung (EXKLUSIVE!)
+  private int    areaMaxY   = 0;    // End-Index des Rasters in Y-Richtung (EXKLUSIVE!)
+  private int    demandTolType    = 0;  // Art der Abweichungsangaben
+  private float  demandTolSingle  = 0;  // erlaubte Abweichung fuer jeden einzelnen LU-Typ vom Bedarf
+  private float  demandTolAverage = 0;  // erlaubte Durchschnitts-Abweichung fuer das Untersuchungsgebiet
+  private float  demandConv = 0;    // Umrechnungsfaktor Bedarfseingeit -> qm
+  private float  cellSize   = 0;    // Flaeche einer Rasterzelle (in Bedarfseinheit)
+  // Eingabe-Daten, die ueber den gesamten Modellablauf benoetigt werden
+  private WritableGrid            baseLU        = null; // Base Scenario
+  private WritableGrid            baseLUHist    = null; // Base LU History
+  private int[][]                 luConv        = null; // LU-Conversion-Matrix
+  private float[]                 luElas        = null; // LU-Conversion-Elasticity
+  private WritableGrid            areaRestr     = null; // Area Restrictions
+  private float[][]               luDemand      = null; // LU-Bedarfe
+  private WritableGrid[]          sdfGrids      = null; // Static Driving Forces
+  private boolean                 CALC_WITH_DDF = false; // Flag, ob dynamische DF beruecksichtigt werden
+  private WritableGrid[]          ddfGrids      = null; // Dynamic Driving Forces
+  private int[]                   ddfStartIdx   = null; // Listenindex an dem ein dyn. DF beginnt
+  private float[][]               regrRes       = null; // Regression Results fuer LUCC
+  private boolean                 CALC_WITH_NBH = false; // Flag, ob Nachbarschaftsw'keit beruecksichtigt wird
+  private float[]                 nbhWeights    = null; // Gewichtung der Nachbarschaft pro LU-Typ
+  private float[][][]             nbhSettings   = null; // Definition der Umgebung pro LU-Typ
+  private float[][]               nbhRegrRes    = null; // Regression Results fuer Nachbarschaft
+  private int                     nbhRadiusX    = 0;    // horizontaler Radius der betrachteten Nachbarschaft
+  private int                     nbhRadiusY    = 0;    // vertikaler Radius der betrachteten Nachbarschaft
+  private float[][]               luCover       = null; // LU-Bedeckung der Typen ueber die Zeit in Bedarfseinheit
+  private float                   totCover      = 0;    // Gesamte Landbedeckungsflaeche (ohne NoData!)
+  private Random                  rand          = null; // Zufallsgenerator
+  private float[]                 iterSpeed     = null; // Geschwindigkeit fuer die ITER-Variablen
+  // Ausgabe-Daten, die ueber den gesamten Modellablauf benoetigt werden
+  private WritableGrid            outActLU      = null; // speichert die aktuell sim. LU
+  private WritableGrid            outActLUHist  = null; // speichert die aktuell sim. LU History
+  private WritableGrid[]          outLUProb     = null; // speichert die LU-Wahrscheinlichkeiten
+  private WritableGrid[]          outNbhProb    = null; // speichert die Nachbarschafts-Wahrscheinlichkeiten
+  private float[]                 outIter       = null; // speichert die Iterationsvariablen
+  private MultiGrid               outStepLU     = null; // speichert die LU fuer jeden Zeitpunkt
+  private MultiDataObject         outStepLUMultiData;
+  
+  private Map<Float,Float> 		  luMap	        = new HashMap<Float,Float>(); // speichert das Mapping von LUCC-Typen im BAseScenario zu 0,1,2,...
+  private Map<Float,Float> 	  	  luMapReverse  = new HashMap<Float,Float>(); // speichert das Mapping von LUCC-Typen im BAseScenario zu 0,1,2,...
+  
+  //Parallelisierungsvariablen:
+  private AdvancedSPMDClientInterface clientController = null;
+private SyncPoint mergePoint;
+  /**
+   * Erzeugt eine neue Instanz des CLUE-Modells.
+   */
+  public ClueParallelTuned() {
+    super( new ClueModelContentManager() );
+    contManager = (ClueModelContentManager)super.contManager;
+    // In dieser optimierten Clue-Implementierung, werden die Iterationsvariablen
+    // lokal verwaltet und brauchen deshalb nicht als Ressource zur Verfuegung
+    // gestellt werden
+    contManager.getResource( contManager.ITERVAR ).setNullable(true);
+    // Iterations-Ereignisse der Event-Liste hinzufuegen
+    events.add(ModelIterationStepStartedEvent.class);
+    events.add(ModelIterationStepFinishedEvent.class);
+  }
+  
+   
+  ////////////////////////////////////////////////////////////////////////
+  ///////////////   Implementierung von AbstractXuluModel   //////////////
+  ////////////////////////////////////////////////////////////////////////
+  /**
+   * Initialisiert das Model, indem die Ressourcen aus dem ContentManager
+   * geladen werden und mit Lese/Schreib-Rechten versehen werden. Zudem
+   * werden Referenzen auf einen Teil der Ressourcen in lokalen Variablen
+   * gespeichert, um waehrend des Modellablaufs effizienter darauf zugreifen
+   * zu koennen.
+   */
+  public void performModelInit() {
+    if ( contManager == null )
+      return;
+    //######### Zugriffsrechte aus Ressourcen/Propertys holen #########
+    RA_baseLU       = contManager.getBaseScenario().getReadAccess(this);
+    RA_baseLUHist   = contManager.getLUHistory().getReadAccess(this);
+    MatrixProperty conversionMatrix = contManager.getLUConversionMatrix();
+	RA_luConv       = conversionMatrix.getReadAccess(this);
+    RA_luElas       = contManager.getConversionElasticity().getReadAccess(this);
+    RA_areaRestr    = contManager.getAreaRestrictions().getReadAccess(this);
+    RA_luDemand     = contManager.getDemandScenario().getReadAccess(this);
+    RA_regrRes      = contManager.getRegressionResults().getReadAccess(this);
+    RA_sdfGrids     = ((ListProperty)contManager.getStaticDrivingForces().getProperty(MultiGrid.PROP_GRIDS)).getReadAccess(this);
+    // Dynamische Driving Forces sind optional
+    CALC_WITH_DDF   = contManager.getDynamicDrivingForceTypes() != null;
+    if ( CALC_WITH_DDF ) {
+      RA_ddfList    = contManager.getDynamicDrivingForceTypes().getReadAccess(this);
+      RA_ddfGrids   = ((ListProperty)contManager.getDynamicDrivingForces().getProperty(MultiGrid.PROP_GRIDS)).getReadAccess(this);
+    } else {
+      RA_ddfList    = null;
+      RA_ddfGrids   = null;
+    }
+    // Nachbarschafts-W'keiten sind optional
+    CALC_WITH_NBH   = (contManager.getNeighborhoodWeights() != null);
+    if ( CALC_WITH_NBH ) {
+      RA_nbhWeights  = contManager.getNeighborhoodWeights().getReadAccess(this);
+      RA_nbhSettings = contManager.getNeighborhoodSettings().getReadAccess(this);
+      RA_nbhRegrRes  = contManager.getNeighborhoodRegression().getReadAccess(this);
+      WA_outNbhProb  = ((ListProperty)contManager.getNeighborhoodProbabilities().getProperty(MultiGrid.PROP_GRIDS)).getWriteAccess(this);
+    } else {
+      RA_nbhWeights  = null;
+      RA_nbhSettings = null; 
+      RA_nbhRegrRes  = null;
+      WA_outNbhProb  = null;
+    }
+    WA_outActLU     = contManager.getActLUResult().getWriteAccess(this);
+    WA_outActLUHist = contManager.getActLUHistory().getWriteAccess(this);
+    WA_outLUProb    = ((ListProperty)contManager.getLUProbabilities().getProperty(MultiGrid.PROP_GRIDS)).getWriteAccess(this);
+    WA_outStepLU    = ((ListProperty)contManager.getStepLUResults().getProperty(MultiGrid.PROP_GRIDS)).getWriteAccess(this);
+
+    //#########  Variablen belegen mit denen gearbeitet wird  ###########
+    this.stepCount    = contManager.getStepCount().getOneTimeReadAccess().getValueAsInt(); // WICHTIG!!
+    this.dfCount      = contManager.getStaticDrivingForces().getGridCount();
+    this.demandTolType    = contManager.getDemandToleranceType().getOneTimeReadAccess().getValueAsInt();
+    this.demandTolSingle  = contManager.getSingleDemandTolerance().getOneTimeReadAccess().getValueAsFloat();
+    this.demandTolAverage = contManager.getAverageDemandTolerance().getOneTimeReadAccess().getValueAsFloat();
+    this.demandConv   = contManager.getConversionFactor().getOneTimeReadAccess().getValueAsFloat();
+    this.luCount      = conversionMatrix.getSize(0);
+    this.baseLU       = (WritableGrid)RA_baseLU.getValue();
+    this.areaWidth    = baseLU.getWidth();
+    this.areaHeight   = baseLU.getHeight();
+    this.areaMinX     = baseLU.getMinX();
+    this.areaMinY     = baseLU.getMinY();
+    this.areaMaxX     = baseLU.getMinX() + areaWidth;
+    this.areaMaxY     = baseLU.getMinY() + areaHeight;
+    this.cellSize     = ((float)(baseLU.getCellWidth() * baseLU.getCellHeight())) / demandConv;
+    this.baseLUHist   = (WritableGrid)RA_baseLUHist.getValue();
+    this.outActLU     = (WritableGrid)WA_outActLU.getValue();
+    this.outActLUHist = (WritableGrid)WA_outActLUHist.getValue();
+    this.outStepLU    = contManager.getStepLUResults();
+    this.outIter      = new float[luCount];
+
+    // LUCC-Conversion-Matrix in Array kopieren (PERFORMANZ!)
+    this.luConv      = new int[conversionMatrix.getSize(0)][conversionMatrix.getSize(1)];
+    for (int i=0; i<luConv.length; i++)
+      for (int j=0; j<luConv[i].length; j++)
+        luConv[i][j] = RA_luConv.getValueAsInt(i,j);
+    // LU-Demand-Matrix in Array kopieren (PERFORMANZ!)
+    this.luDemand    = new float[contManager.getDemandScenario().getSize(0)][contManager.getDemandScenario().getSize(1)];
+    for (int i=0; i<luDemand.length; i++)
+      for (int j=0; j<luDemand[i].length; j++)
+        luDemand[i][j] = RA_luDemand.getValueAsFloat(i,j);
+    // LUCC Elastizitaet in Array kopieren (PERFORMANZ!)
+    this.luElas      = new float[((ListPropertyReadAccess)RA_luElas).getCount()];
+    for (int i=0; i<luElas.length; i++)
+      this.luElas[i] = RA_luElas.getValueAsFloat(i);
+    this.areaRestr   = (WritableGrid)RA_areaRestr.getValue();
+    // Statische DF in Array kopieren (PERFORMANZ!)
+    this.sdfGrids    = new WritableGrid[contManager.getStaticDrivingForces().getGridCount()];
+    for (int i=0; i<sdfGrids.length; i++)
+      sdfGrids[i] = contManager.getStaticDrivingForces().getGrid(i);
+
+    // Variablen fuer dynamische Driving Forces nur belegen, wenn auch mit
+    // diesen gerechnet wird.
+    if ( CALC_WITH_DDF ) {
+      ListPropertyReadAccess ddfList = (ListPropertyReadAccess)RA_ddfList;
+      this.ddfCount    = ddfList.getCount();
+      // Raster mit dyn. DF in Array kopieren (PERFORMANZ!)
+      this.ddfGrids    = new WritableGrid[contManager.getDynamicDrivingForces().getGridCount()];
+      for (int i=0; i<ddfGrids.length; i++)
+        ddfGrids[i] = contManager.getDynamicDrivingForces().getGrid(i);
+    } else {
+      this.ddfCount = 0;
+      this.ddfGrids = new WritableGrid[0];
+    }
+
+    // Regression Results fuer LUCC-W'keiten in Array kopieren (PERFORMANZ!)
+    this.regrRes = new float[contManager.getRegressionResults().getSize(0)][contManager.getRegressionResults().getSize(1)];
+    for (int i=0; i<regrRes.length; i++)
+      for (int j=0; j<regrRes[i].length; j++)
+        this.regrRes[i][j] = RA_regrRes.getValueAsFloat(i,j);
+
+    // Ausgabe-Raster-Liste fuer LUC-W'keiten aus Ressource holen,
+    // auf benoetigte Groesse erweitern und in Array kopieren (PERFORMANZ!)
+    MultiGrid outLUProbTemp = contManager.getLUProbabilities();
+    for (int i=0; outLUProbTemp.getGridCount()<luCount; i++)
+      outLUProbTemp.addGrid(); // Liste muss ein Raster fuer jeden LU-Typ enthalten
+    this.outLUProb  = new WritableGrid[luCount];
+    for (int i=0; i<luCount; i++)
+      this.outLUProb[i]  = outLUProbTemp.getGrid(i);
+
+    // Variablen fuer Nachbarschaftsw'keiten nur belegen, wenn auch mit diesen
+    // gerechnet wird
+    if ( CALC_WITH_NBH ) {
+      this.nbhRadiusX  = (contManager.getNeighborhoodSettings().getSize(0)-1)/2;
+      this.nbhRadiusY  = (contManager.getNeighborhoodSettings().getSize(1)-1)/2;
+      // Nbh.-Gewichtungen in Array kopieren (PERFORMANZ!)
+      this.nbhWeights  = new float[((ListPropertyReadAccess)RA_nbhWeights).getCount()];
+      for (int i=0; i<nbhWeights.length; i++)
+        this.nbhWeights[i] = RA_nbhWeights.getValueAsFloat(i);
+      // Nbh.-Settings in Array kopieren (PERFORMANZ!)
+      this.nbhSettings = new float[contManager.getNeighborhoodSettings().getSize(0)][contManager.getNeighborhoodSettings().getSize(1)][contManager.getNeighborhoodSettings().getSize(2)];
+      for (int i=0; i<nbhSettings.length; i++)
+        for (int j=0; j<nbhSettings[i].length; j++)
+          for (int k=0; k<nbhSettings[i][j].length; k++)
+            this.nbhSettings[i][j][k] = RA_nbhSettings.getValueAsFloat(i,j,k);
+      // Regression Results fuer Nbh. in Array kopieren (PERFORMANZ!)
+      this.nbhRegrRes  = new float[contManager.getNeighborhoodRegression().getSize(0)][contManager.getNeighborhoodRegression().getSize(1)];
+      for (int i=0; i<nbhRegrRes.length; i++)
+        for (int j=0; j<nbhRegrRes[i].length; j++)
+          this.nbhRegrRes[i][j] = RA_nbhRegrRes.getValueAsFloat(i,j);
+      // Ausgabe-Raster-Liste fuer Nachbarschafts-W'keiten aus Ressource holen,
+      // auf benoetigte Groesse erweitern und in Array kopieren (PERFORMANZ)
+      MultiGrid outNbhProbTemp = contManager.getNeighborhoodProbabilities();
+      for (int i=0; outNbhProbTemp.getGridCount()<luCount; i++)
+        outNbhProbTemp.addGrid(); // Liste muss ein Raster fuer jeden LU-Typ enthalten
+      this.outNbhProb = new WritableGrid[luCount];
+      for (int i=0; i<luCount; i++)
+        this.outNbhProb[i] = outNbhProbTemp.getGrid(i);
+    } else {
+      this.nbhRadiusX  = 0;
+      this.nbhRadiusY  = 0;
+      this.nbhWeights  = null;
+      this.nbhSettings = null;
+      this.nbhRegrRes  = null;
+      this.outNbhProb  = null;
+    }
+
+
+    // Bei Toleranz-Art "prozentual" werden die Werte in Prozent
+    // angegeben (intern wird aber mit Abweichungen zwischen 0 und 1 gerechnet!)
+    if ( demandTolType == TOLTYPE_PCT ) {
+      this.demandTolSingle  /= 100.0;
+      this.demandTolAverage /= 100.0;
+    }
+
+    // Die Liste der dyn. DF ist blockweise nach DF grupperiert
+    // Es koennen mehr Zeitschritt-Raster angegeben werden, als simuliert
+    // werden.
+    // Im Array 'ddfStartIdx' wird fuer die dynamischen DF gespeichert, an
+    // welcher Stelle in der Liste der Block beginnt.
+    // -1 bedeutet, dass der DF ein statische DF ist!
+    this.ddfStartIdx = new int[dfCount];
+    for (int i=0; i<dfCount; i++)
+      ddfStartIdx[i] = - 1;
+    for (int i=0; i<ddfCount; i++)
+      ddfStartIdx[i] = i*ddfGrids.length / ddfCount;
+
+    // "Geschwindigkeit" fuer die Iterationsvariablen
+    this.iterSpeed = new float[luCount];
+
+    // Speichert die Flaechendeckung (in der Bedarfseinheit, z.B. ha)
+    // fuer die einzelnen LU-Typen zu jedem Zeitpunkt
+    // --> Die initialen Werte stehen in der 0-Zeile der Demand-Matrix
+    this.luCover  = new float[luCount][stepCount+1];
+    this.totCover = 0;
+    statusOut.print("InitCover: ");
+    for (int lu=0; lu<luCount; lu++) {
+      luCover[lu][0] = luDemand[lu][0];
+      totCover += luCover[lu][0]; // Gesamt-Flaeche des Untersuchungsgebiets
+      statusOut.print(luCover[lu][0]+"   ");
+    }
+    statusOut.println("   >> TotalCover "+totCover);
+
+//    // Ausgabe-Raster leeren
+//    for (int y=outActLU.getMinY(); y<outActLU.getMinY()+outActLU.getHeight(); y++)
+//      for (int x=outActLU.getMinX(); x<outActLU.getMinX()+outActLU.getWidth(); x++)
+//        outActLU.setRasterSample(Float.NaN,x,y);
+
+    // spezielle GUI initialisieren
+    if (modelGUI != null)
+      modelGUI.init(this);
+    
+    LOG.info("Scanning for all LU-Values in the Base-Scenario and mapping to 0...");
+    // Alle Zellen des Untersuchungsgebiets...
+    Set<Float> luccs = new HashSet<Float>();
+
+    for (Integer y=0; y<this.areaHeight; y++)
+      for (Integer x=0; x<this.areaWidth; x++){
+    	  float rasterSampleAsFloat = (float)baseLU.getRasterSampleAsFloat(x,y);
+    	  if (! Float.isNaN(rasterSampleAsFloat) ) 
+    		 luccs.add( rasterSampleAsFloat );
+  	}
+    Object[] lmo = luccs.toArray() ;
+	Arrays.sort(lmo);
+	luMap.put(Float.NaN, Float.NaN );
+	luMapReverse.put(Float.NaN, Float.NaN );
+	for (Integer i = 0; i < lmo.length; i++ ){
+		luMap.put((Float) lmo[i], new Float(i) );
+		luMapReverse.put( new Float(i), (Float) lmo[i]);
+	}
+
+    
+    LOG.info("========================================");
+    LOG.info("MODEL INITIALISED (Log-Level "+LOG.getLevel()+")");
+    // alles ist bereit: jetzt wird die Parallelisierung initialisiert
+    LOG.info("==== Parallelization: Add resources to split control ====");
+    long time = System.currentTimeMillis();
+    clientController = getAdvancedSPMDController();
+    //setting the neighborhoodrange:
+    int neighborhoodrange = Math.max(nbhRadiusX, nbhRadiusY);
+    clientController.setNeighborhoodRange(neighborhoodrange);
+    statusOut.println("Setting neighborhoodrange to " + neighborhoodrange);
+    clientController.addToSplitControl(baseLU, "baseLU");
+    clientController.addToSplitControl(baseLUHist, "baseLUHist");
+    clientController.addToSplitControl(areaRestr, "areaRestr");
+    clientController.addToSplitControl(outActLUHist, "outActLUHist");
+    clientController.addToSplitControl(outActLU, "outActLU");
+    
+    clientController.addToMultiDataSplitControl(sdfGrids, "sdfGrids");
+    if(ddfGrids.length>0)
+    	clientController.addToMultiDataSplitControl(ddfGrids, "ddfGrids");
+    clientController.addToMultiDataSplitControl(outLUProb, "outLUProb");
+    clientController.addToMultiDataSplitControl(outNbhProb, "outNbhProb");
+    outStepLU.addGrid();
+    
+	outStepLUMultiData = clientController.addToMultiDataSplitControl(outStepLU, "outStepLU");
+  
+    clientController.addBaseParameter(luCount, "luCount");
+    clientController.addBaseParameter(dfCount, "dfCount");
+    clientController.addBaseParameter(ddfStartIdx, "ddfStartIdx");
+    clientController.addBaseParameter(regrRes, "regrRes");
+    clientController.addBaseParameter(nbhRadiusX, "nbhRadiusX");
+    clientController.addBaseParameter(nbhRadiusY, "nbhRadiusY");
+    clientController.addBaseParameter(nbhSettings, "nbhSettings");
+    clientController.addBaseParameter(nbhRegrRes, "nbhRegrRes");
+    //clientController.addBaseParameter(luCover, "luCover");
+    clientController.addBaseParameter(luDemand, "luDemand");
+    clientController.addBaseParameter(luElas, "luElas");
+    clientController.addBaseParameter(CALC_WITH_NBH, "CALC_WITH_NBH");
+    clientController.addBaseParameter(totCover, "totCover");
+    clientController.addBaseParameter(nbhWeights, "nbhWeights");
+    clientController.addBaseParameter(luConv, "luConv");
+    clientController.addBaseParameter(luMap, "luMap");
+    clientController.addBaseParameter(luMapReverse, "luMapReverse");
+    
+    clientController.addBaseParameter(cellSize, "cellSize");
+ 
+    
+    LOG.info("==== Parallelization: Add finished after " + (System.currentTimeMillis()-time)+ "ms ===");
+    //System.out.println("canonical name " + baseLU.getClass().);baseLU.getClass().get
+    // clientController.addToSplitControl(splittableResource, name)  
+
+    
+  }
+
+  /**
+   * Gibt die Lese/Schreibrechte auf das Ein- und Ausgaberaster wieder frei.
+   * Interne Ressourcen brauchen keine aus dem Speicher entfernt werden.
+   */
+  public void performModelDispose() {
+	 
+    
+    // Ressourcen wieder freigeben
+    releaseAccess(RA_baseLU);
+    releaseAccess(RA_baseLUHist);
+    releaseAccess(RA_luConv);
+    releaseAccess(RA_luElas);
+    releaseAccess(RA_areaRestr);
+    releaseAccess(RA_luDemand);
+    releaseAccess(RA_sdfGrids);
+    releaseAccess(RA_ddfList);
+    releaseAccess(RA_ddfGrids);
+    releaseAccess(RA_regrRes);
+    releaseAccess(RA_nbhWeights);
+    releaseAccess(RA_nbhSettings);
+    releaseAccess(RA_nbhRegrRes);
+    releaseAccess(WA_outActLU);
+    releaseAccess(WA_outActLUHist);
+    releaseAccess(WA_outLUProb);
+    releaseAccess(WA_outNbhProb);
+    releaseAccess(WA_outStepLU);
+    LOG.info("MODEL DISPOSED");
+    LOG.info("========================================");
+  }
+
+  /**
+   * Fuehrt einen Schritt des Modellablaufs durch.
+   * @param stepNo zu modellierender Schritt (beginnend bei 1!)
+   */
+  public void performModelStep(int stepNo) {
+      statusOut.println("Started step ".concat(String.valueOf(stepNo)));
+      long time = System.currentTimeMillis();   
+    //Unloading no longer needed Data:
+    if(stepNo>2)
+      outStepLU.getGrid(stepNo-3).unloadData();
+    
+    
+    // Merken, ob an einer Stelle bereits eine U-Zelle in einen anderen
+    // Typ gewechselt hat
+    boolean[] alreadyLUCCFromType = new boolean[luCount];
+    // Merken, ob an einer Stelle bereits eine U-Zelle neu entstanden ist
+    boolean[] alreadyLUCCToType = new boolean[luCount];
+    
+    this.checkBreakingCommands();
+    
+    long calcTime = System.currentTimeMillis();   
+    // LU-Wahrscheinlichkeiten berechnen
+    calculateLUProbabilities(stepNo);
+    
+    System.out.println(stepNo + ";" +"LUCalc" +";" + (System.currentTimeMillis()-calcTime) + ";");
+    /********************* Update the neighborhood for this Step ********************/
+    calcTime = System.currentTimeMillis();   
+    this.checkBreakingCommands();
+    if(stepNo>1){
+    	//merging of previous step must be finished before accessing outstepLU again (see end of this method)
+    	clientController.synchronizeToSyncPoint(mergePoint);
+    	clientController.updateNeighborhood(outStepLUMultiData, stepNo-2);
+    }
+    System.out.println(stepNo + ";" +"Update" +";" + (System.currentTimeMillis()-calcTime) + ";");  
+    
+    this.checkBreakingCommands();
+    
+    // Nachbarschafts-Wahrscheinlichkeiten berechnen
+    calcTime = System.currentTimeMillis();
+    calulateNeighborhoodProbabilities(stepNo);
+    System.out.println(stepNo + ";" +"NbhCalc" +";" + (System.currentTimeMillis()-calcTime) + ";");  
+    calcTime = System.currentTimeMillis();
+    
+    this.checkBreakingCommands();
+    
+    // Randomizer fuer diesen Zeitschritt erzeugen
+    rand = new Random(0xCAFE);
+   
+    int   iterNo     = 0;
+    int   lu         = 0;
+    
+    // the LUCover from the last step
+    float oldLUCover[] = new float[luCount];
+    
+    for (lu = 0; lu < oldLUCover.length; lu++) 
+	    oldLUCover[lu]=luCover[lu][stepNo-1];
+   
+    for (iterNo=1; !checkDemandCompliedAndCalculateIterVar(stepNo,iterNo); iterNo++) {
+      this.fireModelEvent( new ModelIterationStepStartedEvent(this,stepNo,iterNo) );
+      if ( modelGUI != null /*&& modelGUI.isDeviationUpdateEnabled()*/ )
+    	  modelGUI.setIterationNumber(stepNo+"/"+iterNo);
+          checkBreakingCommands();
+         // Arrays fuer Iterationsschritt initialisieren
+          for (lu = 0; lu < luCount; lu++) {
+           // noch kein Wechsel von einem LU-Typ
+           alreadyLUCCFromType[lu] = false;
+           // noch kein Wechsel zu einem LU-Typ
+           alreadyLUCCToType[lu] = false;
+           // Flaechen der LU-Typen fuer diesen Zeitschritt
+           luCover[lu][stepNo] = 0;
+           // Speed fuer die Iterationsvariablen initialisieren
+           // --> liegt die Nachfrage bei weniger als 5% des U'gebiets
+           //     wird langsamer begonnen
+           if ( luDemand[lu][stepNo]/totCover < 0.05f )
+             iterSpeed[lu] = 0.01f;
+           else
+             iterSpeed[lu] = 0.05f;
+        }
+      try {
+    	  
+    	  Object[] results = clientController.runSPMDModelTask(new ClueTaskTuned(),Task.CLUE_ITER, stepNo, iterNo, outIter,oldLUCover);
+		 /******************** Synchronize cover of each server **********************/
+		for (int i = 0; i < results.length; i++) {
+			float [] newCover = (float[]) results[i];
+			//add cover for each lu
+			for (lu = 0; lu < luCount; lu++) {
+				luCover[lu][stepNo] += newCover[lu];			
+			}
+		}
+	} catch (Throwable e) {
+		// TODO Auto-generated catch block
+		e.printStackTrace();
+		throw new UnsupportedOperationException("An Exception occoured " + e.getMessage());
+	}
+	 
+	 
+	 this.fireModelEvent( new ModelIterationStepFinishedEvent(this,stepNo,iterNo) );
+    }
+    
+    try {
+		clientController.runSPMDModelTask(new ClueTaskTuned(), Task.STEP_FINALIZATION,stepNo);
+	} catch (Throwable e) {
+		// TODO Auto-generated catch block
+		e.printStackTrace();
+	}
+	//merge multidata in a seperate Thread!
+	mergePoint = new SyncPoint(stepNo,Priority.BELOW_NORMAL);
+	clientController.mergeMultiData(outStepLUMultiData,stepNo-1,mergePoint,statusOut, "***** Finished Merging of OutStepLU step " + stepNo +"*****"	);
+    statusOut.println("Ended step ".concat(String.valueOf(stepNo).concat("  .. partition merging might be still in progress")));
+    System.out.println(stepNo + ";" +"IterationTime" +";" + (System.currentTimeMillis()-calcTime) + ";" + (iterNo-1));
+    System.out.println(stepNo + ";" +"StepTime" +";" + (System.currentTimeMillis()-time) + ";");
+//    WritableGrid sLU = (WritableGrid) GeneralUtil.readSerializedFrom(new File("L:/work/appl/outStepLUGrid" + stepNo));
+//	RasterUtil.checkEqual(sLU, (WritableGrid)outStepLUMultiData.getElement(stepNo-1), true);
+//    
+//	WritableGrid sLU = (WritableGrid) GeneralUtil.readSerializedFrom(new File("./Temp/outStepLUGrid" + stepNo));
+//	RasterUtil.checkEqual(sLU, outStepLUGrid, true);
+//	WritableGrid actLU = (WritableGrid) GeneralUtil.readSerializedFrom(new File("./Temp/outActLU" + stepNo));
+//	RasterUtil.checkEqual(actLU, outActLU, true);
+//	WritableGrid LUHist = (WritableGrid) GeneralUtil.readSerializedFrom(new File("./Temp/outActLUHist" + stepNo));
+//	RasterUtil.checkEqual(LUHist, outActLUHist, true);
+  }
+
+  /**
+   * Liefert eine CLUE-spezifische GUI, in der die Abweichungen waehrend der
+   * Iteration angezeigt werden und ueber die die Toleranzen eingestellt
+   * werden koennen
+   * @return Instannz von {@link ClueModelGUI}
+   */
+  public Component getModelSpecificGUI() {
+    return modelGUI;
+  }
+
+  //////////////////////////////////////////////////////////////////////
+  ////////////////////////   Clue-Methoden   ///////////////////////////
+  //////////////////////////////////////////////////////////////////////
+  /**
+   * Prueft, ob eine Rasterzelle mit <code>NoData</code> belegt ist
+   * @param x     Raster-Koordinate
+   * @param y     Raster-Koordinate
+   * @param grid  zu pruefendes Raster
+   */
+  protected static boolean checkNoData(int x, int y, WritableGrid grid) {
+    return Float.isNaN(grid.getRasterSampleAsFloat(x,y));
+  }
+
+  /**
+   * Berechnet die auf den Driving Forces basierenden
+   * Landnutzungs-Wahrscheinlichkeiten fuer einen Modell-Schritt und speichert
+   * diese in der Ressource "temp. Ausgaberaster fuer die LU-Wahrscheinlichkeiten".<br>
+   * Werden keine dynamischen Driving Forces verwendet, geschieht die Berechnung
+   * nur beim ersten Modellierungsschritt.
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   */
+  protected void calculateLUProbabilities(int stepNo) {
+    // Wenn keine dynamischen Driving Forces verwendet werden
+    // braucht die Berechnung nur fuer den ersten Schritt
+    // durchgefuehrt werden
+    if ( ddfCount == 0 && stepNo > 1 )
+      return;
+
+    statusOut.print("Calculate LU-Probabilities for step "+stepNo+"...");
+   
+    try {
+		clientController.runSPMDModelTask(new ClueTaskTuned(),Task.LU_PROB, stepNo);
+	} catch (Throwable e) {
+		// TODO Auto-generated catch block
+		e.printStackTrace();
+	}
+       
+    //unloading no longer used ddfs to save memory (if supported by WritableGrid)
+    for (int df = 0; df < dfCount; df++) {
+        WritableGrid grid = null;
+        if ( ddfStartIdx[df] >= 0 )
+          grid = this.ddfGrids[ddfStartIdx[df]+stepNo-1];
+        if(grid!=null) grid.unloadData();
+     }
+
+    //*************************** Verify section *******************************
+    
+//    for (int lu = 0; lu < luCount; lu++) {
+////    //Write out to disk
+////    if(outLUProb[lu]!=null)
+////	GeneralUtil.SerializeToFile(outLUProb[lu], new File("./Temp/" + lu + "outLUProb" + stepNo));
+////  
+////    	WritableGrid LUprob = (WritableGrid) GeneralUtil.readSerializedFrom( new File("./Temp/" + lu + "outLUProb" + stepNo));
+////		RasterUtil.checkEqual(LUprob, outLUProb[lu], true);
+//    	
+//    }
+//    if (stepNo == 10) {
+//			statusOut.print("Trying to merge the data....");
+//			long time = System.currentTimeMillis();
+//			clientController.mergeMultiData("outLUProb");
+//			statusOut.println("finished after "
+//					+ (System.currentTimeMillis() - time) + " ms");
+//
+//			// check all partitions
+//			for (int lu = 0; lu < 1; lu++) {
+//				WritableGrid LUprob = (WritableGrid) GeneralUtil
+//						.readSerializedFrom(new File("./Temp/" + lu
+//								+ "outLUProb" + stepNo));
+//				RasterUtil.checkEqual(LUprob, outLUProb[lu], true);
+//				//RasterUtil.printGrid(outLUProb[lu]);
+//			}
+//
+//		}
+    statusOut.println(" done.");
+  }
+
+  /**
+   * Berechnet die auf den Nachbarschaftsbeziehungen basierenden
+   * Landnutzungs-Wahrscheinlichkeiten fuer einen Modell-Schritt und speichert
+   * diese in der Ressource "temp. Ausgaberaster fuer die Nachbarschafts-Wahrscheinlichkeiten".<br>
+   * Da sich die Landnutzung mit jedem Zeitschritt aendert geschieht dies
+   * vor jedem Zeitschritt neu.<br>
+   * Diese Methode macht nichts, wenn ohne Nachbarschafts-W'keiten simuliert wird,
+   * also wenn keine Angabe fuer die "Neighborhood-Weights" gemacht wird.
+   * 
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   */
+  protected void calulateNeighborhoodProbabilities(int stepNo) {
+    // Wenn ohne Nachbarschaftsbeziehungen simuliert wird
+    if ( !CALC_WITH_NBH )
+      return;
+
+    //starte parallele Ausf�hrung:
+    statusOut.print("Calculate Neighborhood-Probabilities for step "+stepNo+"...");
+    
+    try {
+		clientController.runSPMDModelTask(new ClueTaskTuned(),Task.NEIGHBORHOOD_PROB, stepNo, luCover);
+	} catch (Throwable e) {
+		// TODO Auto-generated catch block
+		e.printStackTrace();
+	}
+    
+    
+   
+    /*************************** VERIFY SECTION ************************************/
+    
+//    if (stepNo == 1) {
+//		statusOut.print("Trying to merge the data....");
+//		long time = System.currentTimeMillis();
+//		clientController.mergeMultiData("outNbhProb");
+//
+//		statusOut.println("finished after "
+//				+ (System.currentTimeMillis() - time) + " ms");
+//
+//		// check all partitions
+//		
+//			WritableGrid LUprob[] = (WritableGrid[]) GeneralUtil
+//					.readSerializedFrom(new File("./Temp/" + 0
+//							+ "outNbhProb" + stepNo));
+//			for (int lu = 0; lu < luCount; lu++) {
+//			RasterUtil.checkEqual(LUprob[lu], outNbhProb[lu], true);
+//			//RasterUtil.printGrid(outLUProb[lu]);
+//		}
+//
+//	}
+//    //FileOutput!
+//	for (int j = 0; j < outNbhProb.length; j++) {
+//	  if(outNbhProb!=null)
+//	  GeneralUtil.SerializeToFile(outNbhProb, new File("./Temp/" + j + "outNbhProb" + stepNo));
+//	}
+    statusOut.println(" done.");
+  }
+
+
+ 
+
+ 
+
+  /**
+   * Prueft, ob die aktuelle LU-Konfiguration die einzelenen Bedarfsanforderungen
+   * (bis auf eine Abweichung) erfuellt und berechnet die Iterationsvariablen
+   * neu.
+   * @param stepNo modellierter Schritt (beginnend bei 1)
+   * @param iterNo aktuelle Iteration (beginnend bei 1)
+   */
+  protected boolean checkDemandCompliedAndCalculateIterVar(int stepNo, int iterNo) {
+    boolean updateEnabled  = (modelGUI!=null && modelGUI.isDeviationUpdateEnabled());
+    boolean demandComplied = true;
+    // Abweichnungen berechnen
+    float[] singleDevAbs = new float[luCount];
+    float[] singleDevPct = new float[luCount];
+    float   averageDevAbs = 0;
+    float   averageDevPct = 0;
+    float   totalDevAbs = 0;
+    float   totalDevPct = 0;
+    for (int lu = 0; lu < luCount; lu++) {
+      // ##### Einzelabweichungen #####
+      // Absolute Abweichung der Landbedeckung vom Bedarf berechnen
+      float demand = luDemand[lu][stepNo];
+      singleDevAbs[lu]  = luCover[lu][stepNo] - demand;
+      // Prozentuale Einzel-Abweichnung relativ zum Bedarf
+      if (demand == 0)
+        // ist der Bedarf 0, aber auch die Bedeckung, ist die Abw. 0%
+        singleDevPct[lu] = luCover[lu][stepNo] == 0 ? 0 : 1;
+      else
+        singleDevPct[lu] = singleDevAbs[lu] / demand;
+
+      // Abweichung ueber erlaubter Toleranz?
+      float singleDev = (demandTolType == TOLTYPE_PCT) ? singleDevPct[lu] : singleDevAbs[lu];
+      if ( updateEnabled )
+        modelGUI.setDeviation(lu,singleDev);
+      if (Math.abs(singleDev) > demandTolSingle)
+        demandComplied = false;
+
+//      // Abweichung des LU-Typs ausgeben
+//      appendLog(singleDevAbs[lu],singleDevPct[lu],luDemand.getValueAsFloat(lu, stepNo),luCover[lu][stepNo]);
+
+      // ##### Gesamtabweichungen aufsummieren #####
+      totalDevAbs += Math.abs(singleDevAbs[lu]);
+    }
+
+    // Prozentuale Gesamt-Abweichnung relativ zum Gesamt-Untersuchungsgebiet
+    totalDevPct = totalDevAbs / totCover;
+    if ( updateEnabled )
+      modelGUI.setDeviation(luCount,(demandTolType == TOLTYPE_PCT) ? totalDevPct : totalDevAbs);
+
+    // Durchschnittliche Abweichnung pro LU-Typ
+    averageDevAbs = totalDevAbs / luCount;
+
+    // Durchschnittliche Abweichnung pro LU-Typ relativ zum Gesamt-Untersuchungsgebiet
+    averageDevPct = averageDevAbs / totCover;
+
+    // Abweichung ueber erlaubter Toleranz?
+    float avgDev = (demandTolType == TOLTYPE_PCT) ? averageDevPct : averageDevAbs;
+    if ( updateEnabled )
+      modelGUI.setDeviation(luCount+1,avgDev);
+    if ( Math.abs(avgDev) > demandTolAverage )
+      demandComplied = false;
+
+    // Iterationsvariablen neu berechnen
+    for (int lu = 0; lu < luCount; lu++) {
+      // Um Alternieren zwischen 2 Konfiguration zu verhindern
+      // eine kleine Zufallszahl hinzuaddieren (zwischen -0,005 und 0,005)
+      float randomValue = (rand.nextFloat()-0.5f)/100;
+
+      // --> Im ersten Schritt erhalten alle Iterationsvariablen den Wert 0,5
+      float iter = outIter[lu];
+      if (iterNo == 1)
+        iter = 0.5f+randomValue;
+//        iter = 0.5 + new float[] {0.002f,0f,0.002f,0f,0f,-0.003f}[lu];
+//        iter = 0.5 + new float[] {0.002f,0f,0.001f,0f,0f,-0.002f}[lu];
+      else {
+//        // Anteil der Einzelabweichnung an der Gesamtabweichnung
+////        float dev = (totalDevAbs!=0) ? singleDevAbs[lu] / totalDevAbs : 0.0;
+//        float dev  = singleDevPct[lu];
+//        iter = outIter.getValueAsFloat(lu) // alter Iter-Wert
+//             + dev // Anteil der Abweichung zum Bedarf
+//             + randomValue;
+        /////////////////////////////////////////
+        // Original-Iter-Berechnung aus CLUE
+        iterSpeed[lu] += 0.00005;
+        iter += (singleDevAbs[lu]/totCover)/(iterSpeed[lu]*(rand.nextInt(101)+1));
+
+        if (iter > 2f)
+          iter = 0.5f;
+        if ( Math.abs(iter) < 0.001 )
+          iter = 0.01f * Math.signum(iter);
+        if (iter < -0.5f)
+          iter = -0.4f;
+        /////////////////////////////////////////
+      }
+      // Iter speichern
+      outIter[lu] = iter;
+    }
+    return demandComplied;
+  }
+
+  //////////////////////////////////////////////////////////////////////
+  /////////////////////   Clue-spezifische GUI   ///////////////////////
+  //////////////////////////////////////////////////////////////////////
+
+  /**
+   * Diese Klasse stellt eine modellspezifische GUI-Komponente fuer das
+   * {@link ClueParallelTuned CLUE-Modell} dar.
+   * In dieser wird fuer jeden modellierten LU-Typ ein {@linkplain ExpansionBar Status-Balken}
+   * fuer die Abweichnung vom geforderten Bedarf angezeigt. Sowie je ein Balken
+   * fuer die aktuelle Gesamt- und Durchschittsabweichung. Je nach gewaehlter
+   * Abweichungsart (prozentual oder absolute Angaben), werden Abweichungen
+   * von +/- 100% oder +/- 10000 Bedarfseinheiten angezeigt.<br>
+   * Darueber hinaus enthaelt sie je einen Regler, ueber den die maximal
+   * erlaubte Abweichung von den Bedarfen (Einzelabweichung der LU-Typen und
+   * Durchschnittsabweichung) eingestellt werden kann.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class ClueModelGUI extends JComponent {
+    private       float MIN = -1;
+    private       float MAX = 1;
+    private final float TOL = 0.2f;
+    private       float SLIDER_FACT = 1000;
+    // Format fuer Wert-Anzeige des Sliders
+    private DecimalFormat sliderPctFormat = new DecimalFormat("0.0%");
+    private DecimalFormat sliderDecFormat = new DecimalFormat("0.0");
+    // Format fuer Wert-Anzeige im Balken
+    private DecimalFormat statusPctFormat = new DecimalFormat("0.0000%");
+    private DecimalFormat statusDecFormat = new DecimalFormat("0.0");
+    // Format fuer Wert-Anzeige unterhalb der Balken (Max/Min/Middle)
+    private DecimalFormat infoPctFormat   = new DecimalFormat("0.0%");
+    private DecimalFormat infoDecFormat   = new DecimalFormat("0.0");
+
+    private DeviationContainer  divCont          = null;
+    private JSlider             singleDivSlider  = null;
+    private JSlider             averageDivSlider = null;
+    private ClueParallelTuned           model            = null;
+    private DeviationLabel      singleDivLabel   = new DeviationLabel("Erlaubte Bedarfsabweichung pro LU-Typ:",sliderPctFormat);
+    private DeviationLabel      averageDivLabel  = new DeviationLabel("Erlaubte durchschnittliche Bedarfsabweichung:",sliderPctFormat);
+    private Font                labelFont        = singleDivLabel.getFont().deriveFont(Font.BOLD | Font.CENTER_BASELINE);
+    private boolean             alreadyPacked    = false;
+    private JCheckBox           updateCheckBox   = null;
+    private JLabel              iterationLabel   = null;
+
+    /**
+     * Erzeugt eine neue Clue-GUI. Diese wird jedoch erst nach Aufruf
+     * der {@link #init(ClueParallelTuned)}-Methode komplett erzeugt, da erst dann
+     * die Anzahl der angezeigten Balken (= Anzahl LU-Typen) feststeht.
+     */
+    public ClueModelGUI() {
+      super();
+      this.setLayout( new SpringLayout() );
+      // Label in dem die Iterationsnummer angezeigt wird
+      iterationLabel = new JLabel(" ");
+      iterationLabel.setBorder( BorderFactory.createLoweredBevelBorder() );
+      // Slider/Label fuer Abweichnug der einzelnen Typen
+      singleDivSlider  = new JSlider(JSlider.HORIZONTAL,0,(int)(SLIDER_FACT*MAX),(int)(SLIDER_FACT*TOL));
+      singleDivSlider.setPaintTicks(true);
+      singleDivSlider.setPaintLabels(true);
+      singleDivSlider.setPaintTrack(true);
+      singleDivSlider.setEnabled(false);
+      singleDivSlider.addChangeListener( new ChangeListener() {
+        public void stateChanged(ChangeEvent e) {
+          float tol = singleDivSlider.getValue() / SLIDER_FACT;
+          if ( model!=null )
+            model.demandTolSingle = tol;
+          if ( singleDivLabel!=null )
+            singleDivLabel.setValue(tol);
+          if ( divCont!=null )
+            divCont.setTolerance(tol);
+        }
+      });
+      singleDivLabel.setFont(labelFont);
+      singleDivLabel.setValue(singleDivSlider.getValue()/SLIDER_FACT);
+
+      // Slider/Label fuer Abweichnug der einzelnen Typen
+      averageDivSlider  = new JSlider(JSlider.HORIZONTAL,0,(int)(SLIDER_FACT*MAX),(int)(SLIDER_FACT*TOL));
+      averageDivSlider.setPaintTicks(true);
+      averageDivSlider.setPaintLabels(true);
+      averageDivSlider.setPaintTrack(true);
+      averageDivSlider.setEnabled(false);
+      averageDivSlider.addChangeListener( new ChangeListener() {
+        public void stateChanged(ChangeEvent e) {
+          float tol = averageDivSlider.getValue() / SLIDER_FACT;
+          if ( model!=null )
+            model.demandTolAverage = tol;
+          if ( averageDivLabel!=null )
+            averageDivLabel.setValue(tol);
+        }
+      });
+      averageDivLabel.setFont(labelFont);
+      averageDivLabel.setValue(averageDivSlider.getValue()/SLIDER_FACT);
+
+      // Checkbox zur (De)Aktivierung der Anzeige-Aktualisierung
+      updateCheckBox = new JCheckBox("Abweichungen autom. aktualisieren",true);
+
+      this.add( averageDivLabel );
+      this.add( averageDivSlider );
+      this.add( singleDivLabel );
+      this.add( singleDivSlider );
+      this.add( updateCheckBox );
+      this.add( iterationLabel );
+      SpringUtilities.makeCompactGrid(this,6,1,0,0,0,5);
+    }
+
+    /**
+     * Initialisiert die GUI fuer eine <b>initialisierte</b> Modell-Instanz.
+     * Wird zum Ende {@link ClueParallelTuned#performModelInit()} aufgerufen.
+     */
+    public void init(ClueParallelTuned model) {
+      this.model = model;
+      if ( divCont != null )
+        remove(divCont);
+      SLIDER_FACT = (model.demandTolType == TOLTYPE_PCT) ? 1000 : 1;
+      MIN         = (model.demandTolType == TOLTYPE_PCT) ? -1 : ((float)-Math.pow(10,(int)Math.log10(model.totCover)))/1000;
+      MAX         = (model.demandTolType == TOLTYPE_PCT) ?  1 : -MIN;
+      averageDivSlider.setMaximum((int)(MAX*SLIDER_FACT));
+      averageDivLabel.setNumberFormat( model.demandTolType == TOLTYPE_PCT ? sliderPctFormat : sliderDecFormat );
+      singleDivSlider.setMaximum((int)(MAX*SLIDER_FACT));
+      singleDivLabel.setNumberFormat( model.demandTolType == TOLTYPE_PCT ? sliderPctFormat : sliderDecFormat );
+
+      String[] divDesc = new String[model.luCount+2];
+      for (int i=0; i<model.luCount; i++)
+        divDesc[i] = String.valueOf(i);
+      divDesc[model.luCount]   = "Total";
+      divDesc[model.luCount+1] = "Average";
+
+      divCont = new DeviationContainer(
+                         divDesc.length,
+                         divDesc,
+                         MIN,
+                         MAX,
+                         0,
+                         model.demandTolSingle,
+                         model.demandTolType == TOLTYPE_PCT ? statusPctFormat : statusDecFormat,
+                         model.demandTolType == TOLTYPE_PCT ? infoPctFormat   : infoDecFormat
+      );
+      divCont.setBarDescHeader("LU-Typ");
+      divCont.setBarHeader("Aktuelle Bedarfsabweichung");
+      this.add(divCont,4);
+
+      // Wert des Balkens darf erst hier (nach Neu-Erstellung des
+      // Abweichungs-Containers) neu gesetzt werden, da beim Setzen
+      // des neuen Wertes automatisch die Toleranzen der Abweichungsbalken
+      // aktualisiert werden
+      setSingleTolerance(model.demandTolSingle);
+      setAverageTolerance(model.demandTolAverage);
+
+      SpringUtilities.makeCompactGrid(this,7,1,0,0,0,5);
+      if ( !alreadyPacked )
+        SwingUtil.packParentWindow(this);
+      else
+        this.validate();
+      alreadyPacked = true;
+      singleDivSlider.setEnabled( true );
+      averageDivSlider.setEnabled( true );
+    }
+
+    /**
+     * Setzt die in der GUI angezeigte Interationsnummer. Diese wird
+     * durch einen String repraesentiert, damit auch berliebige andere
+     * Informationen (anstelle der Nummer) dargestellt werden koennen (z.B.
+     * zusaetzlich noch die Schrittnummer).
+     * @param iterString dargestellte Iterationsnummer
+     */
+    public void setIterationNumber(String iterString) {
+      iterationLabel.setText("Iteration: "+iterString);
+    }
+
+    /**
+     * Stellt den Slider fuer die Einzelabweichung auf einen bestimmten Wert
+     * ein. Hierdurch wird automatisch auch der Wert fuer das Modell neu
+     * gesetzt.
+     */
+    public void setSingleTolerance(float tol) {
+      singleDivSlider.setValue((int)(tol*SLIDER_FACT));
+    }
+
+    /**
+     * Stellt den Slider fuer die Durchschnittsabweichung auf einen bestimmten Wert
+     * ein. Hierdurch wird automatisch auch der Wert fuer das Modell neu
+     * gesetzt.
+     */
+    public void setAverageTolerance(float tol) {
+      averageDivSlider.setValue((int)(tol*SLIDER_FACT));
+    }
+
+    /**
+     * Setzt die Abweichnungswerte fuer alle Statusbalken.
+     * @param value Array mit den Abweichungen
+     */
+    public void setDeviation(float[] value) {
+      if ( divCont!= null && isDeviationUpdateEnabled() )
+        divCont.setExpansion(value);
+    }
+
+    /**
+     * Setzt den Abweichnungswert fuer einen Statusbalken.
+     * @param idx   Index eines Balkens
+     * @param value Array mit den Abweichungen
+     */
+    public void setDeviation(int idx, float value) {
+      if ( divCont!= null && isDeviationUpdateEnabled() )
+        divCont.setExpansion(idx,value);
+    }
+
+    /**
+     * Aktiviert oder Deaktiviert die Aktualisierung der Abweichungsbalken.
+     */
+    public void setDeviationUpdateEnabled(boolean enabled) {
+      updateCheckBox.setSelected(enabled);
+    }
+
+    /**
+     * Aktiviert oder Deaktiviert die Aktualisierung der Abweichungsbalken.
+     */
+    public boolean isDeviationUpdateEnabled() {
+      return updateCheckBox.isSelected();
+    }
+
+    /**
+     * Diese Klasse stellt ein Label dar, in dem (hinter einem Basistext)
+     * ein numerischer Abweichungswert (z.B. erlaubte Maximalabweichung) angezeigt wird.
+     * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+     * @version 1.0
+     */
+    private static class DeviationLabel extends JLabel {
+      private String baseText        = "";
+      private float dev              = 0;
+      private NumberFormat numFormat = null;
+
+      /**
+       * Erzeugt ein neues leeres Label.
+       */
+      public DeviationLabel() {
+        this("");
+      }
+
+      /**
+       * Erzeugt ein neues Label. Der dargestellte Wert ist initial 0%.
+       * @param text      Basistext
+       */
+      public DeviationLabel(String text) {
+        this(text,new DecimalFormat("0.0%"));
+      }
+
+      /**
+       * Erzeugt ein neues Label. Der dargestellte Wert ist initial 0.
+       * @param text      Basistext
+       * @param numFormat Anzeigeformat fuer den dargestellten Abweichungswert
+       */
+      public DeviationLabel(String text, NumberFormat numFormat) {
+        this(text,numFormat,0);
+      }
+
+      /**
+       * Erzeugt ein neues Label.
+       * @param text      Basistext
+       * @param numFormat Anzeigeformat fuer den dargestellten Abweichungswert
+       * @param dev       initialer Wert fuer den Abweichungswert
+       */
+      public DeviationLabel(String text, NumberFormat numFormat, float dev) {
+        super();
+        this.baseText  = text;
+        this.dev    = dev;
+        setNumberFormat(numFormat);
+        setText(baseText);
+      }
+
+      /**
+       * Setzt den darzustellenden numerischen Abweichungswert.
+       */
+      public void setValue(float dev) {
+        this.dev = dev;
+        setText(baseText);
+      }
+
+      /**
+       * Setzt den Basistext des Labels.
+       */
+      public void setText(String text) {
+        this.baseText = text;
+        String displayText = baseText;
+        if ( numFormat != null )
+          displayText = displayText+" "+numFormat.format(this.dev);
+        super.setText(displayText);
+      }
+
+      /**
+       * Setzt das Darstellungsformat fuer den Abweichungswert.
+       */
+      public void setNumberFormat(NumberFormat format) {
+        this.numFormat = format;
+      }
+    }
+
+    /**
+     * Diese Klasse stellt einen Container dar, in dem vertikal eine Reihe von
+     * {@linkplain ExpansionBar Status-Balken} angezeigt werden. Alle Balken
+     * haben dieselben Extremwerte (Min, Max, Middle). Deshalb erhaelt nur
+     * der unterste Balken eine Info-Leiste mit diesen Extremwerten.
+     * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+     * @version 1.0
+     */
+    private static class DeviationContainer extends JComponent {
+      private static final NumberFormat NUM_FORMAT = new DecimalFormat("0.0%");
+      /** Konstante fuer eine vertikale Ausrichtung der Status-Balken */
+      public static final int VERTICAL   = ExpansionBar.VERTICAL;
+      /** Konstante fuer eine horizontale Ausrichtung der Status-Balken */
+      public static final int HORIZONTAL = ExpansionBar.HORIZONTAL;
+
+      private ExpansionBar[] expansionBar   = null;
+      private JLabel[]       expansionLabel = null;
+      private JLabel         typeLabel      = null;
+      private JLabel         divLabel       = null;
+      private Font           sampleFont     = new JLabel().getFont();
+
+      /**
+       * Erzeugt einen neuen Container. Die Balken stellen eine prozentuale
+       * Abweichung von +/- 100% um 0% dar. Die Balken erhalten keine Beschreibung,
+       * sondern werden durchnummeriert.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param tol      Toleranzwert fuer alle Balken (siehe {@link ExpansionBar})
+       */
+      public DeviationContainer(int count, float tol) {
+        this(count,-1,1,0,tol,NUM_FORMAT);
+      }
+
+      /**
+       * Erzeugt einen neuen Container. Als Mitte-Wert fuer die Balken wird
+       * 0 verwendet. Die Balken erhalten keine Beschreibung, sondern werden
+       * durchnummeriert.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param min      Minimum-Wert fuer die Balken
+       * @param max      Maximum-Wert fuer die Balken
+       * @param tol      Toleranzwert fuer alle Balken (siehe {@link ExpansionBar})
+       * @param form     Darstellungsformat fuer die Zahlen im Balken und in der
+       *                 Info-Leiste des untersten Balken
+       */
+      public DeviationContainer(int count, float min, float max, float tol, NumberFormat form) {
+        this(count,min,max,0,tol,form);
+      }
+
+      /**
+       * Erzeugt einen neuen Container. Die Balken werden durchnummeriert.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param min      Minimum-Wert fuer die Balken
+       * @param max      Maximum-Wert fuer die Balken
+       * @param mid      Mitte-Wert fuer die Balken
+       * @param tol      Toleranzwert fuer alle Balken (siehe {@link ExpansionBar})
+       * @param form     Darstellungsformat fuer die Zahlen im Balken und in der
+       *                 Info-Leiste des untersten Balken
+       */
+      public DeviationContainer(int count, float min, float max, float mid, float tol, NumberFormat form) {
+        this(count,null,min,max,mid,tol,form,form);
+      }
+
+      /**
+       * Erzeugt einen neuen Container.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param desc     Beschreibungen fuer die Balken (kann <code>null</code> sein!)
+       * @param min      Minimum-Wert fuer die Balken
+       * @param max      Maximum-Wert fuer die Balken
+       * @param mid      Mitte-Wert fuer die Balken
+       * @param tol      Toleranzwert fuer alle Balken (siehe {@link ExpansionBar})
+       * @param barForm  Darstellungsformat fuer die Zahlen im Balken
+       * @param infoForm Darstellungsformat fuer die Zahlen in der Info-Leiste
+       *                 des untersten Balken
+       */
+      public DeviationContainer(int count, String[] desc, float min, float max, float mid, float tol, NumberFormat barForm, NumberFormat infoForm) {
+        this(count,desc,min,max,mid,LangUtil.createArray(count,tol),barForm,infoForm);
+      }
+
+      /**
+       * Erzeugt einen neuen Container.
+       * @param count    Anzahl an Statusbalken im Conatiner
+       * @param desc     Beschreibungen fuer die Balken (kann <code>null</code> sein!)
+       * @param min      Minimum-Wert fuer die Balken
+       * @param max      Maximum-Wert fuer die Balken
+       * @param mid      Mitte-Wert fuer die Balken
+       * @param tol      Toleranzwert fuer jeden einzelnen Balken (siehe {@link ExpansionBar})
+       * @param barForm  Darstellungsformat fuer die Zahlen im Balken
+       * @param infoForm Darstellungsformat fuer die Zahlen in der Info-Leiste
+       *                 des untersten Balken
+       */
+      public DeviationContainer(int count, String[] desc, float min, float max, float mid, float[] tol, NumberFormat barForm, NumberFormat infoForm) {
+        super();
+        if ( count <= 0 )
+          throw new IllegalArgumentException("At least one divergence bar must specified!");
+        if ( desc!=null && desc.length < count )
+          throw new IllegalArgumentException("Less describtions specified!");
+
+        this.setLayout( new SpringLayout() );
+
+        // PROBLEME mit den Labels bei VERTICAL
+        // --> Label-Breite wird wohl zu 0
+        int orient = HORIZONTAL;
+
+        sampleFont = sampleFont.deriveFont(Font.BOLD);
+        if (orient == VERTICAL)
+          sampleFont = sampleFont.deriveFont( AffineTransform.getRotateInstance(Math.PI/2) );
+
+        // Label erzeugen
+        typeLabel = new JLabel("Type");
+        divLabel = new JLabel("Divergence");
+        typeLabel.setFont(sampleFont);
+        divLabel.setFont(sampleFont);
+
+        // Statusbalken erzeugen
+        this.expansionBar   = new ExpansionBar[count];
+        this.expansionLabel = new JLabel[count];
+        for (int i=0; i<count; i++) {
+          expansionBar[i]   = new ExpansionBar(orient,ExpansionBar.LINEAR,min,max,mid,-tol[i],tol[i],0,barForm,infoForm);
+          expansionLabel[i] = new JLabel( desc!=null && i<desc.length ? desc[i] : String.valueOf(i));
+          if ( orient == HORIZONTAL ) {
+            expansionLabel[i].setHorizontalAlignment(JLabel.CENTER);
+            expansionLabel[i].setVerticalAlignment(JLabel.TOP);
+          } else {
+            expansionLabel[i].setFont( expansionLabel[i].getFont().deriveFont( AffineTransform.getRotateInstance(Math.PI/2) ) );
+            expansionLabel[i].setHorizontalAlignment(JLabel.LEFT);
+            expansionLabel[i].setVerticalAlignment(JLabel.CENTER);
+          }
+        }
+        // beim untersten Balken sollen die Labels erscheinen
+        expansionBar[count-1].setValueLabelsPainted(true);
+
+        // Komponenten einfuegen und ausrichten
+        if ( orient == HORIZONTAL ) {
+          typeLabel.setHorizontalAlignment(JLabel.CENTER);
+          typeLabel.setVerticalAlignment(JLabel.BOTTOM);
+          divLabel.setHorizontalAlignment(JLabel.CENTER);
+          divLabel.setVerticalAlignment(JLabel.BOTTOM);
+          add( typeLabel );
+          add( divLabel );
+          for (int i=0; i<count; i++) {
+            add( expansionLabel[i] );
+            add( expansionBar[i] );
+          }
+          // Layout ausrichten
+          SpringUtilities.makeCompactGrid(this,getComponentCount()/2,2,0,0,10,0);
+        } else {
+          typeLabel.setHorizontalAlignment(JLabel.CENTER);
+          typeLabel.setVerticalAlignment(JLabel.CENTER);
+          divLabel.setHorizontalAlignment(JLabel.CENTER);
+          divLabel.setVerticalAlignment(JLabel.CENTER);
+          add( divLabel );
+          for (int i=0; i<count; i++)
+            add( expansionBar[i] );
+          add( typeLabel );
+          for (int i=0; i<count; i++)
+            add( expansionLabel[i] );
+          // Layout ausrichten
+          SpringUtilities.makeCompactGrid(this,2,getComponentCount()/2,0,0,10,0);
+        }
+      }
+
+      /**
+       * Setzt den Toleranzwert fuer alle Balken.
+       */
+      public void setTolerance(float tol) {
+        for (int i=0; i<expansionBar.length; i++) {
+          expansionBar[i].setMinimumTolerance( -tol );
+          expansionBar[i].setMaximumTolerance(  tol );
+        }
+      }
+
+      /**
+       * Setzt den Wert fuer alle Balken.
+       */
+      public void setExpansion(float[] value) {
+        for (int i=0; i<value.length; i++)
+          setExpansion(i,value[i]);
+      }
+
+      /**
+       * Setzt die Beschreibung fuer einen Balken.
+       */
+      public void setBarDesc(int idx, String text) {
+        expansionLabel[idx].setText(text);
+      }
+
+      /**
+       * Setzt den Wert fuer einen Balken.
+       */
+      public void setExpansion(int idx, float value) {
+        expansionBar[idx].setValue(value);
+      }
+
+      /**
+       * Setzt die Beschreibung die oberhalb der Balken-Beschreibungen steht.
+       */
+      public void setBarDescHeader(String text) {
+        typeLabel.setText(text);
+      }
+
+      /**
+       * Setzt die Beschreibung die oberhalb der Balken steht.
+       */
+      public void setBarHeader(String text) {
+        divLabel.setText(text);
+      }
+
+    }
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueTask.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueTask.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueTask.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,751 @@
+package edu.bonn.xulu.plugin.model.parallel;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import edu.bonn.xulu.plugin.model.clue.ClueModel;
+import edu.bonn.xulu.plugin.model.parallel.ClueTaskDefinition.Task;
+
+import schmitzm.data.WritableGrid;
+import appl.parallel.spmd.AbstractSPMDTask;
+import appl.parallel.spmd.MultiDataObject;
+import appl.parallel.spmd.SPMDServerInterface;
+
+/**
+ * This is the task class for the parallel computation of the {@link ClueModel},
+ * originally developed by Peter Verburg at Wageningen University and adapted
+ * for Xulu by Martin Schmitz. <br>
+ * This class is send to the servers. It has three
+ * main modules: the {@link #calculateLUProbabilities(Object...) LU-Calculation},
+ * the
+ * {@link #calulateNeighborhoodProbabilities(Object...) neighborhood probabilities calculation}
+ * and the calculation of the {@link #clue_iter(Object...) CLUE iteration}. The
+ * modules are largely independent and could theoretically be defined in
+ * Separate classes. Because the {@link ClueModel original implementation} uses
+ * only one class, this principle is not changed here. It makes sense because
+ * some functions are used by all modules and class loading using JINI is
+ * simplified.<br>
+ * 
+ * Notice that the documentation of this file is a mixture of English and
+ * German. This is due to the fact that Xulu / V works so nicely that very much 
+ * of Martin Schmitz' original German-commented {@link ClueModel}-code could be reused.
+ * @author Dominik Appl
+ */
+public class ClueTask extends AbstractSPMDTask {
+
+	private WritableGrid baseLU;
+
+	private SPMDServerInterface controller;
+
+	private int luCount;
+
+	private int dfCount;
+
+	private int[] ddfStartIdx;
+
+	private float[][] regrRes;
+
+	private int areaMinY;
+
+	private int areaMinX;
+
+	private int areaMaxY;
+
+	private int areaMaxX;
+
+	private WritableGrid[] outLUProb;
+
+	private WritableGrid areaRestr;
+
+	private int nbhRadiusX;
+
+	private int nbhRadiusY;
+
+	private float[][][] nbhSettings;
+
+	private float[][] nbhRegrRes;
+
+	private float totCover;
+
+	private int localMinX;
+
+	private int localMinY;
+
+	private int localMaxX;
+
+	private int localMaxY;
+
+	private WritableGrid[] outNbhProb;
+
+	private WritableGrid outActLUHist;
+
+	private float[][] luDemand;
+
+	private float[] luElas;
+
+	private int[][] luConv;
+
+	private float[] oldLUCover;
+
+	private WritableGrid outActLU;
+
+	private boolean CALC_WITH_NBH;
+
+	private float[] nbhWeights;
+
+	private float cellSize;
+
+	private WritableGrid baseLUHist;
+
+	private MultiDataObject outStepLU;
+
+	private static Object monitor = new Object();
+
+	private Map<Float, Float> luMap = new HashMap<Float, Float>(); // speichert
+
+	// das
+	// Mapping
+	// von
+	// LUCC-Typen
+	// im
+	// BAseScenario
+	// zu
+	// 0,1,2,...
+
+	private Map<Float, Float> luMapReverse = new HashMap<Float, Float>(); // speichert
+
+	// das
+	// Mapping
+	// von
+	// LUCC-Typen
+	// im
+	// BAseScenario
+	// zu
+	// 0,1,2,...
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.spmd.AbstractSPMDTask#init()
+	 */
+	@Override
+	public void init() {
+		controller = getSPMDServerController();
+		long time = System.currentTimeMillis();
+		// initalize partitions
+		outActLU = (WritableGrid) controller.getPartition("outActLU");
+		outActLUHist = (WritableGrid) controller.getPartition("outActLUHist");
+		baseLUHist = (WritableGrid) controller.getPartition("baseLUHist");
+		baseLU = (WritableGrid) controller.getPartition("baseLU");
+		areaRestr = (WritableGrid) controller.getPartition("areaRestr");
+
+		// initialize base Parameters
+		nbhRadiusX = (Integer) controller.getBaseParameter("nbhRadiusX");
+		nbhRadiusY = (Integer) controller.getBaseParameter("nbhRadiusY");
+		nbhSettings = (float[][][]) controller.getBaseParameter("nbhSettings");
+		nbhRegrRes = (float[][]) controller.getBaseParameter("nbhRegrRes");
+		totCover = (Float) controller.getBaseParameter("totCover");
+		luCount = (Integer) controller.getBaseParameter("luCount");
+		dfCount = (Integer) controller.getBaseParameter("dfCount");
+		ddfStartIdx = (int[]) controller.getBaseParameter("ddfStartIdx");
+		regrRes = (float[][]) controller.getBaseParameter("regrRes");
+		CALC_WITH_NBH = (Boolean) controller.getBaseParameter("CALC_WITH_NBH");
+		nbhWeights = (float[]) controller.getBaseParameter("nbhWeights");
+		cellSize = (Float) controller.getBaseParameter("cellSize");
+		luConv = (int[][]) controller.getBaseParameter("luConv");
+		luDemand = (float[][]) controller.getBaseParameter("luDemand");
+		luElas = (float[]) controller.getBaseParameter("luElas");
+		luMap = (Map<Float, Float>) controller.getBaseParameter("luMap");
+		luMapReverse = (Map<Float, Float>) controller
+				.getBaseParameter("luMapReverse");
+
+		areaMinY = controller.getLocalCalcMinY();
+		areaMinX = controller.getLocalCalcMinX();
+		// +1 because Clue is programmed that area-MaxCoordinates are exclusive!
+		areaMaxY = controller.getLocalCalcMaxY() + 1;
+		areaMaxX = controller.getLocalCalcMaxX() + 1;
+
+		// the bounds of all the available data (including neighborhood)
+
+		localMinX = (int) controller.getLocalBounds().getMinX();
+		localMinY = (int) controller.getLocalBounds().getMinY();
+		localMaxX = (int) controller.getLocalBounds().getMaxX();
+		localMaxY = (int) controller.getLocalBounds().getMaxY();
+
+		outLUProb = new WritableGrid[luCount];
+		for (int i = 0; i < outLUProb.length; i++) {
+			outLUProb[i] = (WritableGrid) controller.getMultiPartition(
+					"outLUProb", i);
+		}
+
+		// initialize outNbhProb
+		outNbhProb = new WritableGrid[luCount];
+		for (int i = 0; i < outNbhProb.length; i++) {
+			outNbhProb[i] = (WritableGrid) controller.getMultiPartition(
+					"outNbhProb", i);
+		}
+		outStepLU = controller.getMultiData("outStepLU");
+
+		// leere Ausgaberaster
+		for (int y = localMinY; y < localMaxY; y++)
+			for (int x = localMinX; x < localMaxX; x++)
+
+				outActLU.setRasterSample(Float.NaN, x, y);
+		System.out.println("Finished init of CLUE_TASK in "
+				+ (System.currentTimeMillis() - time) + " ms");
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.spmd.AbstractSPMDTask#run()
+	 */
+	@Override
+	public Object run(Object... parameters) {
+		controller = this.getSPMDServerController();
+
+		Task task = (Task) parameters[0];
+		switch (task) {
+		case LU_PROB:
+			calculateLUProbabilities(parameters);
+			break;
+		case NEIGHBORHOOD_PROB:
+			calulateNeighborhoodProbabilities(parameters);
+			break;
+		case CLUE_ITER:
+			return clue_iter(parameters);
+
+		case STEP_FINALIZATION:
+			finalizeStep(parameters);
+			break;
+		}
+		return null;
+
+	}
+
+	private void finalizeStep(Object... parameters) {
+
+		WritableGrid outStepLUGrid, lastLUGrid;
+		synchronized (monitor) {
+			// initialize step count StepCount
+			int stepNo = (Integer) parameters[1];
+
+			// Liste der Zeitschritt-Ausgaberaster vergroessern
+			if (outStepLU.getCount() <= stepNo - 1)
+				outStepLU.addElement();
+			// Raster festlegen, in dem die LU des vorangegangenen
+			// Schritts zu finden ist
+			if (stepNo == 1)
+
+				lastLUGrid = baseLU;
+			else
+				lastLUGrid = (WritableGrid) controller.getMultiPartition(
+						"outStepLU", stepNo - 2);
+			// LU in Ausgaberaster des Zeitschritts uebernehmen und ggf.
+			// Nutzungsdauer initialisieren
+			outStepLUGrid = (WritableGrid) outStepLU.getElement(stepNo - 1);
+		}
+		float lastLUC;
+		float actLUC;
+		for (int y = areaMinY; y < areaMaxY; y++)
+			for (int x = areaMinX; x < areaMaxX; x++) {
+				// checkBreakingCommands();
+				lastLUC = luMap.get(lastLUGrid.getRasterSampleAsFloat(x, y));
+				actLUC = luMap.get(outActLU.getRasterSampleAsFloat(x, y));
+				// Wenn die Landnutzung gewechselt hat, wird die Historie
+				// zurueck
+				// gesetzt
+				if (actLUC != lastLUC)
+					outActLUHist.setRasterSample(0f, x, y);
+
+				// LU in Ausgabe-Raster des simulierten Schritts uebernehmen
+				// Die 0-basierten LU-Nummern werden wieder zurueckgemapped.
+				// (SK)
+				outStepLUGrid.setRasterSample(luMapReverse.get(actLUC), x, y);
+			}
+	}
+
+	/**
+	 * 
+	 */
+	private void calculateLUProbabilities(Object... parameters) {
+		// initialisiere Parameter
+		int stepNo = (Integer) parameters[1];
+
+		// /************************* START CALCULATION
+		// *********************************/
+		// System.out.println("Local Area:" + controller.getLocalBounds());
+		int x = 0;
+		int y = 0;
+		int lu = 0;
+		int df = 0;
+		float betaSum = 0;
+		float expBetaSum = 0;
+		float prob = 0;
+		// Fuer Zellen des Untersuchungsgebiets
+		for (y = areaMinY; y < areaMaxY; y++)
+			for (x = areaMinX; x < areaMaxX; x++)
+				// NotData-Bereich und Area Restrictions ignorieren
+				if (!checkNoData(x, y, baseLU)
+						&& areaRestr.getRasterSampleAsFloat(x, y) == 0) {
+					// Fuer alle LU-Typen
+					for (lu = 0; lu < luCount; lu++) {
+						betaSum = 0;
+						// Fuer alle Driving Forces die Summe der Betas
+						// berechnen
+						for (df = 0; df < dfCount; df++) {
+							// /****checkBreakingCommands();
+							// DF-Grid festlegen:
+							// Bei dynamischem DF das jew. Zeitschritt-Raster
+							// aus der Liste
+							// ansonsten das statische Raster
+							WritableGrid dfGrid = null;
+							if (ddfStartIdx[df] >= 0)
+								dfGrid = (WritableGrid) controller
+										.getMultiPartition("ddfGrids",
+												ddfStartIdx[df] + (stepNo - 1));
+							else
+								dfGrid = (WritableGrid) controller
+										.getMultiPartition("sdfGrids", df);
+							// Beim ersten Driving Force wird die Summe mit der
+							// Regressionskonstante initialisiert
+							if (df == 0)
+								betaSum = regrRes[0][lu];
+							// betaSum = BETA0(U) + Sum( BETA(df+1,U) *
+							// DF(df,x,y) )
+							betaSum += regrRes[df + 1][lu]
+									* dfGrid.getRasterSampleAsFloat(x, y);
+						}
+						expBetaSum = (float) Math.exp(betaSum);
+						prob = expBetaSum / (1 + expBetaSum);
+						// errechnete W'keit im Raster speichern
+						outLUProb[lu].setRasterSample((float) prob, x, y);
+					}
+				}
+		// destroy no longer used ddfs to save memory
+		for (df = 0; df < dfCount; df++) {
+			WritableGrid grid = null;
+			if (ddfStartIdx[df] >= 0)
+				controller.destroyMultiPartition("ddfGrids", ddfStartIdx[df]
+						+ stepNo - 1);
+		}
+
+	}
+
+	public void calulateNeighborhoodProbabilities(Object... parameters) {
+		// initialize parameters
+		int stepNo = (Integer) parameters[1];
+		float[][] luCover = (float[][]) parameters[2];
+
+		/***********************************************************************
+		 * Parallel Computation *************************** The following code
+		 * is near a copy&paste from Martin Schmitz Clue - code. The 2 lines
+		 * changed are indicated with '*P*'. About the adjustment: The change
+		 * was necessary because of the neighborhood region the algorithm looks
+		 * at. It is wasted computing time to try to calculate the probabilities
+		 * for this overlapping region, but on the other hand the algorithm must
+		 * be aware of the additional data for the calculation of the inner
+		 * bounds.
+		 **********************************************************************/
+
+		// Raster festlegen, in dem die LU des vorangegangenen
+		// Schritts zu finden ist
+		WritableGrid luGrid;
+		if (stepNo == 1)
+			luGrid = (WritableGrid) controller.getPartition("baseLU");
+		else
+			luGrid = (WritableGrid) controller.getMultiPartition("outStepLU",
+					stepNo - 2);
+
+		int x = 0;
+		int y = 0;
+		int lu = 0;
+		int i = 0;
+		int dx = 0;
+		int dy = 0;
+		int totCellCount = 0;
+		float[] luCellCount = new float[luCount];
+		float betaSum = 0;
+		float beta = 0;
+		float nbhFact = 0;
+		float expBetaSum = 0;
+		float lucc = 0;
+		float setting = 0;
+		System.out.println("ClueTask - Calc Area min/max X: " + areaMinX + "/"
+				+ areaMaxX + "  Y: " + areaMinY + "/" + areaMaxY);
+		// Fuer Zellen des Untersuchungsgebiets
+		for (y = areaMinY; y < areaMaxY; y++)
+			for (x = areaMinX; x < areaMaxX; x++)
+				// NoData-Bereich und Area Restrictions ignorieren
+				if (!checkNoData(x, y, baseLU)
+						&& areaRestr.getRasterSampleAsFloat(x, y) == 0)
+					// Fuer alle LU-Typen
+					for (lu = 0; lu < luCount; lu++) {
+						// checkBreakingCommands();
+
+						// Anzahl der Zellen in der Umgebung initialisieren
+						totCellCount = 0;
+						for (i = 0; i < luCount; i++)
+							luCellCount[i] = 0;
+						// Umgebung der Zelle betrachten
+						for (dy = -nbhRadiusY; dy <= nbhRadiusY; dy++)
+							/* P */if (localMinY <= y + dy
+									&& y + dy < localMaxY)
+								for (dx = -nbhRadiusX; dx <= nbhRadiusX; dx++)
+									/* P */if (localMinX <= x + dx
+											&& x + dx < localMaxX) {
+										lucc = luGrid.getRasterSampleAsFloat(x
+												+ dx, y + dy); // PERFORMANZ >
+										// nur einmal
+										// den
+										// Zellen-Wert
+										// ermitteln
+										if (!Float.isNaN(lucc) /* !checkNoData(x+dx,y+dy,baseLU) */) {
+											// Die LU-Typen stehen im Raster
+											// nicht 0-basiert, deshalb mapping
+											lucc = luMap.get(lucc);
+
+											// Alle Zellen in Umgebung zaehlen
+											// (jedoch nur diejenigen,
+											// die potentiell auch in die
+											// Bewertung eingehen koennen!)
+											setting = nbhSettings[dx
+													+ nbhRadiusX][dy
+													+ nbhRadiusY][lu];
+											if (setting != 0.0) {
+												totCellCount++;
+												// Anzahl der Zellen eines
+												// bestimmten Typs aufsummieren
+												// (relativ zum in der Umgebung
+												// angegebenen Faktor)
+												// luCellCount[
+												// luGrid.getRasterSampleAsInt(x+dx,y+dy)
+												// ] += setting;
+												// TODO Bricht hier ab, wenn
+												// LUCC-Klassen nicht 0,1,2 ...
+												// zaehlen...
+												// luCellCount[ (int)lucc ] +=
+												// setting;
+
+												luCellCount[(int) lucc] += setting;
+											}
+										}
+									}
+						// Summe der Betas berechnen
+						betaSum = nbhRegrRes[0][lu]; // Regr.Konstante
+						for (i = 0; i < luCount; i++) {
+							beta = nbhRegrRes[i + 1][lu];
+							nbhFact = (luCellCount[i] / totCellCount)
+									/ (luCover[i][stepNo - 1] / totCover);
+							betaSum += beta * nbhFact;
+						}
+						// Wahrscheinlichkeit berechnen
+						expBetaSum = (float) Math.exp(betaSum);
+						outNbhProb[lu].setRasterSample(
+								(float) (expBetaSum / (1 + expBetaSum)), x, y);
+					}
+	}
+
+	public Object clue_iter(Object... parameters) {
+		// initialize parameters
+		int stepNo = (Integer) parameters[1];
+		int iterNo = (Integer) parameters[2];
+		float[] outIter = (float[]) parameters[3];
+		oldLUCover = (float[]) parameters[4];
+
+		/**
+		 * saves the new, additional lu for each step (needed for
+		 * synchronisation
+		 */
+		float[] newLUCover = new float[luCount];
+
+		WritableGrid luHistGrid;
+		if (stepNo == 1)
+			luHistGrid = baseLUHist;
+		else
+			luHistGrid = outActLUHist;
+
+		// Raster festlegen, in dem die LU des vorangegangenen
+		// Schritts zu finden ist
+		WritableGrid lastLUGrid;
+		if (stepNo == 1)
+			lastLUGrid = baseLU;
+		else
+			lastLUGrid = (WritableGrid) controller.getMultiPartition(
+					"outStepLU", stepNo - 2);
+		int x = 0;
+		int y = 0;
+		int lu = 0;
+		int lastLU = 0;
+		int bestLU = 0;
+		float bestLUProb = 0;
+		float baseProb = 0;
+		float nbhProb = 0;
+		float nbhWeight = 0;
+		float elas = 0;
+		float totalProb = 0;
+		// float lastLUC = 0;
+		// float actLUC = 0;
+		// Merken, ob an einer Stelle bereits eine U-Zelle in einen anderen
+		// Typ gewechselt hat
+		boolean[] alreadyLUCCFromType = new boolean[luCount];
+		// Merken, ob an einer Stelle bereits eine U-Zelle neu entstanden ist
+		boolean[] alreadyLUCCToType = new boolean[luCount];
+		float[] iterSpeed = new float[luCount];
+		// Arrays fuer Iterationsschritt initialisieren
+		for (lu = 0; lu < luCount; lu++) {
+			// noch kein Wechsel von einem LU-Typ
+			alreadyLUCCFromType[lu] = false;
+			// noch kein Wechsel zu einem LU-Typ
+			alreadyLUCCToType[lu] = false;
+			// Flaechen der LU-Typen fuer diesen Zeitschritt
+			newLUCover[lu] = 0;
+
+			// Speed fuer die Iterationsvariablen initialisieren
+			// --> liegt die Nachfrage bei weniger als 5% des U'gebiets
+			// wird langsamer begonnen
+			if (luDemand[lu][stepNo] / totCover < 0.05f)
+				iterSpeed[lu] = 0.01f;
+			else
+				iterSpeed[lu] = 0.05f;
+		}
+		// Fuer alle Zellen des Untersuchungsgebiets
+		for (y = areaMinY; y < areaMaxY; y++)
+			for (x = areaMinX; x < areaMaxX; x++) {
+				// ******checkBreakingCommands();
+
+				// Rasterzellen ausserhalb des Untersuchungsgebiets komplett
+				// ignorieren
+				// Grund: NoData-Zellen (Float.NaN) werden beim Cast in int zu
+				// 0,
+				// also zur Landnutzung 0!!
+				if (checkNoData(x, y, areaRestr) || checkNoData(x, y, baseLU))
+					continue;
+
+				// Nutzungsdauern erhoehen
+				if (iterNo == 1)
+					outActLUHist.setRasterSample(luHistGrid
+							.getRasterSampleAsFloat(x, y) + 1, x, y);
+
+				// vorangegangene LU merken.
+				// Diese steht im Raster nicht unbedingt 0-basiert
+				lastLU = luMap.get(
+						new Float(lastLUGrid.getRasterSampleAsInt(x, y)))
+						.intValue();
+
+				// Beste gefundene LU wird mit aktueller LU initialisiert
+				bestLU = lastLU;
+				bestLUProb = 0;
+
+				// Pruefen, ob Zelle die LU wechseln darf
+				if (checkLUCCGeneralAllowed(x, y, stepNo, lastLU,
+						alreadyLUCCToType[lastLU])) {
+					// Alle LU-Typen auf Wechsel pruefen
+					for (lu = 0; lu < luCount; lu++) {
+						// Pruefen, ob Zelle in den betrachteten Typ wechseln
+						// darf
+						if (checkLUCCAllowed(x, y, stepNo, lastLU, lu,
+								alreadyLUCCFromType[lu])) {
+							// Gesamt-Wahrscheinlichkeit berechnen
+							// a) DF-W'keit und Nachbarschaft-W'keit gehen
+							// anteilig ein
+							// b) Elastizitaet geht nur ein, wenn Zelle bereits
+							// fuer den
+							// LU-Typ genutzt wird
+							// c) ITER geht negativ ein, da es auf Basis der
+							// Abweichung
+							// luCover-luDemand berechnet wird. Ein negatives
+							// Iter
+							// kennzeichnet also einen Mangel und muss die
+							// Gesamtw'keit
+							// erhoehen
+							baseProb = outLUProb[lu].getRasterSampleAsFloat(x,
+									y);
+							nbhProb = !CALC_WITH_NBH ? 0 : outNbhProb[lu]
+									.getRasterSampleAsFloat(x, y);
+							nbhWeight = !CALC_WITH_NBH ? 0 : nbhWeights[lu];
+							elas = (lu == lastLU && luElas[lu] < 1) ? luElas[lu]
+									: 0;
+							// LU-Wahrscheinlichkeit zusammensetzen
+							totalProb = baseProb * (1 - nbhWeight) + nbhProb
+									* nbhWeight + elas - outIter[lu];
+
+							// betrachteter Typ ist geeigneter als der bisher
+							// beste
+							if (totalProb > bestLUProb) {
+								bestLU = lu;
+								bestLUProb = totalProb;
+							}
+						}
+					}
+					// Merken wenn wirklich ein Wechsel stattfindet
+					if (bestLU != lastLU) {
+						alreadyLUCCFromType[lastLU] = true;
+						alreadyLUCCToType[bestLU] = true;
+					}
+				}
+				// LU fuer diesen Iterationschritt setzen
+				outActLU
+						.setRasterSample(luMapReverse.get((float) bestLU), x, y);
+				// Flaechendeckung fuer LU-Typ erhoehen
+				/* P */newLUCover[bestLU] += cellSize;
+
+			}
+		/* P */return newLUCover;
+	}
+
+	/**
+	 * Prueft, ob ein genereller LU-Wechsel fuer eine Zelle erlaubt ist.
+	 * <ul>
+	 * <li>Schliessen die Area Restrictions einen Wechsel aus?<br> >
+	 * Rasterwert(x,y) != 0 </li>
+	 * <li>Schliesst die Conversion Elasticity einen Wechsel aus (Elastizitaet
+	 * 1 und steigende Bedarf)?<br> > ELAS(lastLU) == 1 und DEMAND(lastLU,t) >=
+	 * DEMAND(lastLU,t-1) </li>
+	 * </ul>
+	 * 
+	 * @param x
+	 *            Raster-Koordinate
+	 * @param y
+	 *            Raster-Koordinate
+	 * @param stepNo
+	 *            modellierter Schritt (beginnend bei 1)
+	 * @param lastLU
+	 *            Bedeckung von (x,y) zum Zeitpunkt stepNo-1
+	 * @param alreadyLUCCToActualType
+	 *            Flag gibt an, ob in der laufenden Iteration bereits ein
+	 *            LU-Wechsel in den den aktuellen Typ der Zelle (lastLU)
+	 *            vorgenommen wurde.<br>
+	 *            <b>Dieses Flag wird zur Zeit nicht verwendet!</b>
+	 */
+	protected boolean checkLUCCGeneralAllowed(int x, int y, int stepNo,
+			int lastLU, boolean alreadyLUCCToActualType) {
+		// Area Restrictions checken
+		if (areaRestr.getRasterSampleAsFloat(x, y) != 0)
+			return false;
+		// DER ERSTE TEIL IST KEINE ORIGINAL-CLUE-REGEL!
+		// // Conversion Elasticity checken
+		// // --> wenn Elasticity 1 und bereits an anderer Stelle eine Zelle des
+		// // bisherigen Typs entstanden ist, darf sie nicht wechseln
+		// // --> wenn Elasticity 1 und Bedarf steigt, darf kein Wechsel
+		// // stattfinden, denn dann muessten (um den Bedarf zu decken)
+		// // an anderer Stelle neue entstehen
+		// if ( luElas.getValueAsFloat(lastLU) == 1.0
+		// && ( alreadyLUCCToActualType ||
+		// luDemand.getValueAsFloat(lastLU,stepNo) >= luCover[lastLU][stepNo-1]
+		// ) )
+		// return false;
+
+		// Conversion Elasticity checken
+		// --> wenn Elasticity 1 und Bedarf steigt, darf kein Wechsel
+		// stattfinden, denn dann muessten (um den Bedarf zu decken)
+		// an anderer Stelle neue entstehen
+		if (luElas[lastLU] == 1.0 &&
+		// luDemand[lastLU][stepNo] >= luCover[lastLU][stepNo-1] )
+				luDemand[lastLU][stepNo] >= luDemand[lastLU][stepNo - 1])
+			return false;
+
+		return true;
+	}
+
+	/**
+	 * Prueft, ob ein bestimmter LU-Wechsel fuer eine Zelle erlaubt ist.
+	 * <ul>
+	 * <li>Schliesst die Conversion Elasticity einen Wechsel aus (Elastizitaet
+	 * des potentiellen Wechseltyps 1 und sinkender Bedarf)?<br> > lastLU !=
+	 * newLU und ELAS(newLU) == 1 und DEMAND(newLU,t) <= DEMAND(newLU,t-1) </li>
+	 * <li>Schliesst die Conversion Matrix einen Wechsel aus (generell oder
+	 * ueber Historie)?<br> > CONV(lastLU,newLU) == 0 oder<br> >
+	 * CONV(lastLU,newLU) > 100 und HIST(x,y) < CONV(lastLU,newLU)-101 oder<br> >
+	 * CONV(lastLU,newLU) < -100 und HIST(x,y) > -CONV(lastLU,newLU)-101 </li>
+	 * </ul>
+	 * 
+	 * @param x
+	 *            Raster-Koordinate
+	 * @param y
+	 *            Raster-Koordinate
+	 * @param stepNo
+	 *            modellierter Schritt (beginnend bei 1)
+	 * @param lastLU
+	 *            Bedeckung von (x,y) zum Zeitpunkt stepNo-1
+	 * @param newLU
+	 *            potentielle neue Bedeckung von (x,y)
+	 * @param alreadyLUCCFromNewType
+	 *            Flag gibt an, ob in der laufenden Iteration bereits ein
+	 *            LU-Wechsel vom potentiellen neuen Typ in einen anderen Typ
+	 *            vorgenommen wurde.<br>
+	 *            <b>Dieses Flag wird zur Zeit nicht verwendet!</b>
+	 */
+	protected boolean checkLUCCAllowed(int x, int y, int stepNo, int lastLU,
+			int newLU, boolean alreadyLUCCFromNewType) {
+		// IST KEINE ORIGINAL-CLUE-REGEL!
+		// // LU-Conversion-Elasticity des neuen Typs checken
+		// // --> wenn Elasticity des neuen Typs 1 ist und an anderer Stelle
+		// bereits
+		// // eine Zelle des dieses Typs "verloren" ging, darf er hier
+		// // nicht entstehen
+		// if ( alreadyLUCCFromNewType && luElas.getValueAsFloat(newLU) == 1.0 )
+		// return false;
+
+		// Conversion Elasticity checken
+		// --> wenn Elasticity des neuen Typs "newLU" 1 und dessen Bedarf sinkt,
+		// darf kein Wechsel in diesen Typ stattfinden, denn dann muessten (um
+		// den Bedarf fuer "newLU" zu erreichen) an anderer Stelle newLU-Zellen
+		// entfernt werden
+		if (lastLU != newLU && luElas[newLU] == 1.0
+				&& luDemand[newLU][stepNo] <= oldLUCover[newLU])
+			// luDemand.getValueAsFloat(newLU,stepNo) <=
+			// luDemand.getValueAsFloat(newLU,stepNo-1) )
+			return false;
+
+		// Wert aus LU-Conversion-Matrix ermitteln
+		// Bemerke: "von" steht in den Zeilen (also Y, also Dim1)
+		// "nach" steht in den Spalten (also X, also Dim2)
+		int conv = luConv[newLU][lastLU];
+		// 1 --> LUCC generell erlaubt
+		if (conv == 1)
+			return true;
+		// 0 --> LUCC generell verboten
+		if (conv == 0)
+			return false;
+
+		// 100+t --> Wechsel erst nach t Schritten der vorangegangenen
+		// LU moeglich
+		if (conv > 100) {
+			// int minLUHist = conv-100;
+			// int luHist = outActLUHist.getRasterSampleAsInt(x,y);
+			// return luHist >= minLUHist;
+			int minLUHist = conv - 101;
+			int luHist = outActLUHist.getRasterSampleAsInt(x, y);
+			return luHist >= minLUHist;
+		}
+
+		// -100-t --> Wechsel nicht mehr moeglich, wenn Zelle bereits
+		// t Schritte unter der vorangegangenen LU
+		if (conv < -100) {
+			// int maxLUHist = -conv-100;
+			// int luHist = outActLUHist.getRasterSampleAsInt(x,y);
+			// return luHist < maxLUHist;
+			int maxLUHist = -conv - 101;
+			int luHist = outActLUHist.getRasterSampleAsInt(x, y);
+			return luHist <= maxLUHist;
+		}
+
+		return true;
+	}
+
+	/**
+	 * Prueft, ob eine Rasterzelle mit <code>NoData</code> belegt ist
+	 * 
+	 * @param x
+	 *            Raster-Koordinate
+	 * @param y
+	 *            Raster-Koordinate
+	 * @param grid
+	 *            zu pruefendes Raster
+	 */
+	protected static boolean checkNoData(int x, int y, WritableGrid grid) {
+		return Float.isNaN(grid.getRasterSampleAsFloat(x, y));
+	}
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueTaskDefinition.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueTaskDefinition.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueTaskDefinition.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,26 @@
+package edu.bonn.xulu.plugin.model.parallel;
+
+/**
+ * Defines which clue task to execute.
+ * @author Dominik Appl
+ */
+public class ClueTaskDefinition {
+	public enum Task{
+		/**
+		 * Task: Calculate the LU-probabilities
+		 */
+		LU_PROB,
+		/**
+		 *Task: Calculate the neighborhood-probabilties 
+		 */
+		NEIGHBORHOOD_PROB,
+		/**
+		 *Task: Calculate a iteration 
+		 */
+		CLUE_ITER, 
+		/**
+		 *Task: Finalize the step (prepare for next step execution)
+		 */
+		STEP_FINALIZATION
+	}
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueTaskTuned.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueTaskTuned.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/model/parallel/ClueTaskTuned.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,682 @@
+package edu.bonn.xulu.plugin.model.parallel;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import edu.bonn.xulu.plugin.model.parallel.ClueTaskDefinition.Task;
+
+import schmitzm.data.WritableGrid;
+import appl.parallel.spmd.AbstractSPMDTask;
+import appl.parallel.spmd.AdvancedSPMDServerInterface;
+import appl.parallel.spmd.MultiDataObject;
+import appl.parallel.spmd.SPMDServerInterface;
+import appl.parallel.spmd.SyncPoint;
+import appl.parallel.spmd.SyncPoint.Priority;
+
+/**
+ * This is a tuned version of the {@link ClueTask}. Preloading and multithreading are
+ * used for a better resource utilization.
+ * 
+ * @author Dominik Appl
+ */
+public class ClueTaskTuned extends AbstractSPMDTask {
+
+	private WritableGrid baseLU;
+	private AdvancedSPMDServerInterface controller;
+	private int luCount;
+	private int dfCount;
+	private int[] ddfStartIdx;
+	private float[][] regrRes;
+	private int areaMinY;
+	private int areaMinX;
+	private int areaMaxY;
+	private int areaMaxX;
+	private WritableGrid[] outLUProb;
+	private WritableGrid areaRestr;
+	private int nbhRadiusX;
+	private int nbhRadiusY;
+	private float[][][] nbhSettings;
+	private float[][] nbhRegrRes;
+	private float totCover;
+	private int localMinX;
+	private int localMinY;
+	private int localMaxX;
+	private int localMaxY;
+	private WritableGrid[] outNbhProb;
+	private WritableGrid outActLUHist;
+	private float[][] luDemand;
+	private float[] luElas;
+	private int[][]	luConv;
+	private float[] oldLUCover;
+	private WritableGrid outActLU;
+	private boolean CALC_WITH_NBH;
+	private float[] nbhWeights;
+	private float cellSize;
+	private WritableGrid baseLUHist;
+	private MultiDataObject outStepLU;
+	private SyncPoint drivingForcesSync;
+	
+	private static Object monitor = new Object();
+	private Map<Float,Float> 		  luMap	        = new HashMap<Float,Float>(); // speichert das Mapping von LUCC-Typen im BAseScenario zu 0,1,2,...
+	private Map<Float,Float> 	  	  luMapReverse  = new HashMap<Float,Float>(); // speichert das Mapping von LUCC-Typen im BAseScenario zu 0,1,2,...
+	  
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.AbstractSPMDTask#supportsMultiThreading()
+	 */
+	@Override
+	public boolean supportsMultiThreading() {
+		return true;
+	}
+	
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.AbstractSPMDTask#init()
+	 */
+	@Override
+	public void init() {
+		controller = getAdvancedSPMDServerController();
+        
+		luCount = (Integer) controller.getBaseParameter("luCount");
+		dfCount = (Integer) controller.getBaseParameter("dfCount");
+		ddfStartIdx = (int[]) controller.getBaseParameter("ddfStartIdx");
+		
+		long time = System.currentTimeMillis();
+        SyncPoint loadPoint = new SyncPoint(0,Priority.HIGH);
+        
+        /**  
+         * load all data at the same time (uses heavy multithreading!)
+         * might cause problems with many participating servers, because
+         * the client might be overloaded with get-threads
+         */
+		controller.preloadPartition("outActLU",loadPoint);
+		controller.preloadPartition("outActLUHist",loadPoint);
+		controller.preloadPartition("baseLUHist",loadPoint);
+		controller.preloadPartition("baseLU",loadPoint);
+		controller.preloadPartition("areaRestr",loadPoint);
+				
+		
+		for (int i = 0; i < luCount; i++) {
+			controller.preloadMultiPartition("outLUProb",i, loadPoint);
+			controller.preloadMultiPartition("outNbhProb",i, loadPoint);
+		}
+		//wait on the loading to finish
+		controller.synchronizeToSyncPoint(loadPoint);
+		//after loading the basedata we can start preloading the static or dynamic 
+		//DrivingForces which will be needed when calculating the LUProbabilities
+		preloadData(1);
+		
+		/******************* end of preloading section ***********************/
+		
+		// initalize partitions
+		outActLU = (WritableGrid) controller.getPartition("outActLU");
+		outActLUHist = (WritableGrid) controller.getPartition("outActLUHist");
+		baseLUHist = (WritableGrid) controller.getPartition("baseLUHist");
+		baseLU = (WritableGrid) controller.getPartition("baseLU");
+		areaRestr = (WritableGrid) controller.getPartition("areaRestr");
+		
+		//initialize base Parameters
+		nbhRadiusX = (Integer) controller.getBaseParameter("nbhRadiusX");
+		nbhRadiusY = (Integer) controller.getBaseParameter("nbhRadiusY");
+		nbhSettings = (float[][][]) controller.getBaseParameter("nbhSettings");
+		nbhRegrRes = (float[][]) controller.getBaseParameter("nbhRegrRes");
+		totCover = (Float) controller.getBaseParameter("totCover");
+		
+		regrRes = (float[][]) controller.getBaseParameter("regrRes");
+		CALC_WITH_NBH = (Boolean)    controller.getBaseParameter("CALC_WITH_NBH");
+		nbhWeights = (float[])    controller.getBaseParameter("nbhWeights");
+		cellSize = (Float)      controller.getBaseParameter("cellSize");
+		luConv			         = (int[][])    controller.getBaseParameter("luConv");
+		luDemand 				 = (float[][])  controller.getBaseParameter("luDemand");
+		luElas  				 = (float[])    controller.getBaseParameter("luElas"); 
+		luMap = (Map<Float, Float>) controller.getBaseParameter("luMap");
+		luMapReverse = (Map<Float, Float>) controller.getBaseParameter("luMapReverse");
+		
+		
+		areaMinY = controller.getLocalCalcMinY();
+		areaMinX = controller.getLocalCalcMinX();
+//		+1 because Clue is programmed that area-MaxCoordinates are exclusive!
+		areaMaxY = controller.getLocalCalcMaxY()+1;
+		areaMaxX = controller.getLocalCalcMaxX()+1;
+		
+//		the bounds of the available data (including neighborhood)
+
+		localMinX = (int)controller.getLocalBounds().getMinX();
+		localMinY = (int)controller.getLocalBounds().getMinY();
+		localMaxX = (int)controller.getLocalBounds().getMaxX();
+		localMaxY = (int)controller.getLocalBounds().getMaxY();
+		
+				outLUProb = new WritableGrid[luCount];
+		for (int i = 0; i < outLUProb.length; i++) {
+			outLUProb[i] = (WritableGrid) controller.getMultiPartition("outLUProb",i);
+		}
+
+		//initialize outNbhProb
+		outNbhProb = new WritableGrid[luCount];
+		for (int i = 0; i < outNbhProb.length; i++) {
+			outNbhProb[i] = (WritableGrid) controller.getMultiPartition("outNbhProb",i);
+		}
+		outStepLU = controller.getMultiData("outStepLU");
+		
+		// clear output data (only done one for primary thread
+		if (controller.isMasterThread())
+			for (int y = localMinY; y < localMaxY; y++)
+				for (int x = localMinX; x < localMaxX; x++)
+					outActLU.setRasterSample(Float.NaN, x, y);
+		
+		System.out.println("Finished init of CLUE_TASK_TUNED in "
+				+ (System.currentTimeMillis() - time) + " ms");
+	}
+
+	
+	/**
+	 * Preloads the static or dynamic driving forces which will be needed for the given step no
+	 * 
+	 * @param stepNo the stepNo
+	 */
+	private void preloadData(int stepNo) {
+		//do not forget to reinitialize the syncPoint
+		drivingForcesSync = new SyncPoint(stepNo,Priority.HIGH);
+		for (int df = 0; df < dfCount; df++) { 
+		if ( ddfStartIdx[df] >= 0 )
+             controller.preloadMultiPartition("ddfGrids",ddfStartIdx[df]+(stepNo-1),drivingForcesSync);
+           else
+             controller.preloadMultiPartition("sdfGrids",df,drivingForcesSync);
+		 }
+	}
+
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.AbstractSPMDTask#run()
+	 */
+	@Override
+	public Object run(Object... parameters) {
+		controller = this.getAdvancedSPMDServerController();
+		
+		Task task = (Task) parameters[0]; 
+		switch(task){
+		case LU_PROB:
+			calculateLUProbabilities(parameters);
+			break;
+		case NEIGHBORHOOD_PROB:
+			calulateNeighborhoodProbabilities(parameters);
+			break;
+		case CLUE_ITER:
+			return clue_iter(parameters);
+		case STEP_FINALIZATION:
+			finalizeStep(parameters);
+			break;
+		}
+		return null;
+	}
+	
+	private void finalizeStep(Object... parameters){
+		
+		WritableGrid outStepLUGrid, lastLUGrid;
+		//it is import to synchronize the #addElement because this method is not
+		//thread-safe. Two threads Thread access the method at the same time
+		//two new grids would be created, each thread would use its own grid
+		//and at last only one of the two grids would have been added to the multi grid.
+		synchronized (monitor) {
+			// initialisiere StepCount
+			int stepNo = (Integer) parameters[1];
+
+			// Liste der Zeitschritt-Ausgaberaster vergroessern
+			if (outStepLU.getCount() <= stepNo - 1)
+				outStepLU.addElement();
+			// Raster festlegen, in dem die LU des vorangegangenen
+			// Schritts zu finden ist
+			if (stepNo == 1)
+				lastLUGrid = baseLU;
+			else
+				lastLUGrid = (WritableGrid) controller.getMultiPartition(
+						"outStepLU", stepNo - 2);
+
+			// LU in Ausgaberaster des Zeitschritts uebernehmen und ggf.
+			// Nutzungsdauer initialisieren
+			outStepLUGrid = (WritableGrid) outStepLU.getElement(stepNo - 1);
+		}
+	    float lastLUC;
+	    float actLUC;
+	    for (int y=areaMinY; y<areaMaxY; y++)
+	      for (int x=areaMinX; x<areaMaxX; x++) {
+	        //checkBreakingCommands();
+	    	  lastLUC = luMap.get( lastLUGrid.getRasterSampleAsFloat(x,y) );
+	          actLUC  = luMap.get( outActLU.getRasterSampleAsFloat(x,y) );
+	        // Wenn die Landnutzung gewechselt hat, wird die Historie zurueck
+	        // gesetzt
+	        if ( actLUC != lastLUC )
+	          outActLUHist.setRasterSample(0f,x,y);
+
+	        // LU in Ausgabe-Raster des simulierten Schritts uebernehmen
+	        // Die 0-basierten LU-Nummern werden wieder zurueckgemapped. (SK)
+	        outStepLUGrid.setRasterSample( luMapReverse.get( actLUC) ,x,y);
+	      }
+	  }
+	
+	
+	 /**
+	 * 
+	 */
+	private void calculateLUProbabilities(Object... parameters) {
+		//wait on the preloading to finish
+/*P*/	controller.synchronizeToSyncPoint(drivingForcesSync);
+		//		initialisiere Parameter
+		int	stepNo = (Integer) parameters[1];
+		
+				
+		///************************* START CALCULATION *********************************/
+//	    System.out.println("Local Area:" + controller.getLocalBounds());
+		int x            = 0;
+	    int y            = 0;
+	    int lu           = 0;
+	    int df           = 0;
+	    float betaSum    = 0;
+	    float expBetaSum = 0;
+	    float prob       = 0;
+	    // Fuer Zellen des Untersuchungsgebiets
+	    for (y=areaMinY; y<areaMaxY; y++)
+	        for (x=areaMinX; x<areaMaxX; x++)
+	        // NotData-Bereich und Area Restrictions ignorieren
+	        if ( !checkNoData(x,y,baseLU) && areaRestr.getRasterSampleAsFloat(x,y)==0 ) {
+	          // Fuer alle LU-Typen
+	          for (lu = 0; lu < luCount; lu++) {
+	            betaSum = 0;
+	            // Fuer alle Driving Forces die Summe der Betas berechnen
+	            for (df = 0; df < dfCount; df++) {
+	              ///****checkBreakingCommands();
+	              // DF-Grid festlegen:
+	              // Bei dynamischem DF das jew. Zeitschritt-Raster aus der Liste
+	              // ansonsten das statische Raster
+	              WritableGrid dfGrid = null;
+	              if ( ddfStartIdx[df] >= 0 )
+	                dfGrid = (WritableGrid) controller.getMultiPartition("ddfGrids",ddfStartIdx[df]+(stepNo-1));
+	              else
+	                dfGrid = (WritableGrid) controller.getMultiPartition("sdfGrids",df);
+	              // Beim ersten Driving Force wird die Summe mit der
+	              // Regressionskonstante initialisiert
+	              if (df == 0)
+	                betaSum = regrRes[0][lu];
+	              // betaSum = BETA0(U) + Sum( BETA(df+1,U) * DF(df,x,y) )
+	              betaSum += regrRes[df + 1][lu]
+	                       * dfGrid.getRasterSampleAsFloat(x, y);
+	            }
+	            expBetaSum = (float)Math.exp(betaSum);
+	            prob = expBetaSum / (1 + expBetaSum);
+	            // errechnete W'keit im Raster speichern
+	            outLUProb[lu].setRasterSample( (float) prob, x, y);
+	          }
+	        }
+	    	//start preloading the values for the next step
+/*P*/	    preloadData(stepNo+1);
+	    
+			// destroy no longer used ddfs to save memory
+			for (df = 0; df < dfCount; df++) {
+			if (ddfStartIdx[df] >= 0)
+				controller.destroyMultiPartition("ddfGrids", ddfStartIdx[df]
+						+ stepNo - 1);
+		}
+		
+	}
+
+	
+	public void calulateNeighborhoodProbabilities(Object... parameters) {
+		//initialize parameters
+		int	stepNo = (Integer) parameters[1]; 
+		float[][] luCover =  (float[][]) parameters[2];
+		
+				
+		/***************************** Parallel Computation *********************************
+		 * The following code is near a copy&paste from Martin Schmitz Clue - code. The 2 lines 
+		 * changed are indicated with '*P*'.
+		 * 
+		 * About the adjustment:
+		 * The change was necessary because of the neighborhood region the algorithm
+		 * looks at. It is wasted computing time to try to calculate the  probabilities 
+		 * for this overlapping region, but on the other hand the algorithm must be aware
+		 * of the additional data for the calculation of the inner bounds.  
+		 **********************************************************************************/
+		
+		// Raster festlegen, in dem die LU des vorangegangenen
+	    // Schritts zu finden ist
+		WritableGrid luGrid;
+		if(stepNo==1)
+			luGrid = (WritableGrid) controller.getPartition("baseLU");
+		else 
+			luGrid = (WritableGrid) controller.getMultiPartition("outStepLU", stepNo-2);
+
+		int      x            = 0;
+	    int      y            = 0;
+	    int      lu           = 0;
+	    int      i            = 0;
+	    int      dx           = 0;
+	    int      dy           = 0;
+	    int      totCellCount = 0;
+	    float[]  luCellCount  = new float[luCount];
+	    float    betaSum      = 0;
+	    float    beta         = 0;
+	    float    nbhFact      = 0;
+	    float    expBetaSum   = 0;
+	    float    lucc         = 0;
+	    float    setting      = 0;
+	    System.out.println("ClueTask - Calc Area min/max X: " + areaMinX + "/" + areaMaxX + "  Y: " + areaMinY + "/" + areaMaxY);
+	    // Fuer Zellen des Untersuchungsgebiets
+	    for (y=areaMinY; y<areaMaxY; y++)
+	      for (x=areaMinX; x<areaMaxX; x++)
+	        // NoData-Bereich und Area Restrictions ignorieren
+	        if ( !checkNoData(x,y,baseLU) && areaRestr.getRasterSampleAsFloat(x,y)==0 )
+	          // Fuer alle LU-Typen
+	          for (lu = 0; lu < luCount; lu++) {
+	            //checkBreakingCommands();
+
+	            // Anzahl der Zellen in der Umgebung initialisieren
+	            totCellCount = 0;
+	            for (i=0; i<luCount; i++)
+	              luCellCount[i] = 0;
+	           // Umgebung der Zelle betrachten
+	            for (dy=-nbhRadiusY; dy<=nbhRadiusY; dy++)
+/*P*/ 	           if ( localMinY <= y+dy && y+dy<localMaxY )
+	                for (dx=-nbhRadiusX; dx<=nbhRadiusX; dx++)
+/*P*/                  if ( localMinX <= x+dx && x+dx<localMaxX ) {
+	                    lucc = luGrid.getRasterSampleAsFloat(x+dx,y+dy); // PERFORMANZ > nur einmal den Zellen-Wert ermitteln
+	                    if ( !Float.isNaN(lucc) /*!checkNoData(x+dx,y+dy,baseLU)*/ ) {
+//	                    	 Die LU-Typen stehen im Raster nicht 0-basiert, deshalb mapping
+	                   		lucc = luMap.get( lucc );
+	                   		
+	                    	// Alle Zellen in Umgebung zaehlen (jedoch nur diejenigen,
+	                        // die potentiell auch in die Bewertung eingehen koennen!)
+	                        setting = nbhSettings[dx+nbhRadiusX][dy+nbhRadiusY][lu];
+	                        if ( setting != 0.0 ) {
+	                          totCellCount++;
+	                          // Anzahl der Zellen eines bestimmten Typs aufsummieren
+	                          // (relativ zum in der Umgebung angegebenen Faktor)
+	                          // luCellCount[ luGrid.getRasterSampleAsInt(x+dx,y+dy) ] += setting;
+//	                        TODO Bricht hier ab, wenn LUCC-Klassen nicht 0,1,2 ... zaehlen...
+//	                         luCellCount[ (int)lucc ] += setting;
+	                          
+	                          luCellCount[ (int)lucc ] += setting;
+	                        }
+	                      }
+	                    }
+	              // Summe der Betas berechnen
+	              betaSum = nbhRegrRes[0][lu]; // Regr.Konstante
+	              for (i=0; i<luCount; i++) {
+	                beta    = nbhRegrRes[i + 1][lu];
+	                nbhFact = (luCellCount[i]/totCellCount) / (luCover[i][stepNo-1]/totCover);
+	                betaSum += beta * nbhFact;
+	              }
+	              // Wahrscheinlichkeit berechnen
+	              expBetaSum = (float)Math.exp(betaSum);
+	              outNbhProb[lu].setRasterSample((float)(expBetaSum/(1 + expBetaSum)),x,y);
+	          }
+	}
+	
+	
+	public Object clue_iter(Object... parameters) {
+		// initialize parameters
+		int stepNo        = (Integer) parameters[1];
+		int iterNo        = (Integer) parameters[2];
+		float[] outIter   = (float[]) parameters[3];
+		oldLUCover = (float[]) parameters[4];
+		
+		/** saves the new, additional lu for each step (needed for synchronisation */
+		float[] newLUCover = new float[luCount]; 
+
+		WritableGrid luHistGrid;
+		if(stepNo==1)
+			luHistGrid = baseLUHist;
+		else 
+			luHistGrid = outActLUHist;
+		
+		// Raster festlegen, in dem die LU des vorangegangenen
+	    // Schritts zu finden ist
+		WritableGrid lastLUGrid;
+		if(stepNo==1)
+			lastLUGrid = baseLU;
+		else 
+			lastLUGrid = (WritableGrid) controller.getMultiPartition("outStepLU", stepNo-2);
+		int x = 0;
+		int y = 0;
+		int lu = 0;
+		int lastLU = 0;
+		int bestLU = 0;
+		float bestLUProb = 0;
+		float baseProb = 0;
+		float nbhProb = 0;
+		float nbhWeight = 0;
+		float elas = 0;
+		float totalProb = 0;
+//		float lastLUC = 0;
+//		float actLUC = 0;
+		 // Merken, ob an einer Stelle bereits eine U-Zelle in einen anderen
+	    // Typ gewechselt hat
+	    boolean[] alreadyLUCCFromType = new boolean[luCount];
+	    // Merken, ob an einer Stelle bereits eine U-Zelle neu entstanden ist
+	    boolean[] alreadyLUCCToType = new boolean[luCount];
+	    float[] iterSpeed = new float[luCount];
+		// Arrays fuer Iterationsschritt initialisieren
+	      for (lu = 0; lu < luCount; lu++) {
+	        // noch kein Wechsel von einem LU-Typ
+	        alreadyLUCCFromType[lu] = false;
+	        // noch kein Wechsel zu einem LU-Typ
+	        alreadyLUCCToType[lu] = false;
+	        // Flaechen der LU-Typen fuer diesen Zeitschritt
+	        newLUCover[lu] = 0;
+	       
+			// Speed fuer die Iterationsvariablen initialisieren
+	        // --> liegt die Nachfrage bei weniger als 5% des U'gebiets
+	        //     wird langsamer begonnen
+	        if ( luDemand[lu][stepNo]/totCover < 0.05f )
+	          iterSpeed[lu] = 0.01f;
+	        else
+	          iterSpeed[lu] = 0.05f;
+	      }
+		  // Fuer alle Zellen des Untersuchungsgebiets
+	      for (y = areaMinY; y < areaMaxY; y++)
+	        for (x = areaMinX; x < areaMaxX; x++) {
+	          //******checkBreakingCommands();
+
+	          // Rasterzellen ausserhalb des Untersuchungsgebiets komplett
+	          // ignorieren
+	          // Grund: NoData-Zellen (Float.NaN) werden beim Cast in int zu 0,
+	          //        also zur Landnutzung 0!!
+	          if ( checkNoData(x,y,areaRestr) || checkNoData(x,y,baseLU) )
+	            continue;
+
+	          // Nutzungsdauern erhoehen
+	          if (iterNo==1)
+	            outActLUHist.setRasterSample(luHistGrid.getRasterSampleAsFloat(x, y) + 1, x, y);
+
+	          // vorangegangene LU merken. 
+	          // Diese steht im Raster nicht unbedingt 0-basiert
+	          lastLU = luMap.get( new Float (lastLUGrid.getRasterSampleAsInt(x, y)) ).intValue();
+
+	          // Beste gefundene LU wird mit aktueller LU initialisiert
+	          bestLU = lastLU;
+	          bestLUProb = 0;
+
+	          // Pruefen, ob Zelle die LU wechseln darf
+	          if (checkLUCCGeneralAllowed(x, y, stepNo, lastLU, alreadyLUCCToType[lastLU])) {
+	            // Alle LU-Typen auf Wechsel pruefen
+	            for (lu = 0; lu < luCount; lu++) {
+	              // Pruefen, ob Zelle in den betrachteten Typ wechseln darf
+	              if (checkLUCCAllowed(x, y, stepNo, lastLU, lu, alreadyLUCCFromType[lu])) {
+	                // Gesamt-Wahrscheinlichkeit berechnen
+	                // a) DF-W'keit und Nachbarschaft-W'keit gehen anteilig ein
+	                // b) Elastizitaet geht nur ein, wenn Zelle bereits fuer den
+	                //    LU-Typ genutzt wird
+	                // c) ITER geht negativ ein, da es auf Basis der Abweichung
+	                //    luCover-luDemand berechnet wird. Ein negatives Iter
+	                //    kennzeichnet also einen Mangel und muss die Gesamtw'keit
+	                //    erhoehen
+	                 	baseProb  =  outLUProb[lu].getRasterSampleAsFloat(x, y);
+	                nbhProb   = !CALC_WITH_NBH ? 0 : outNbhProb[lu].getRasterSampleAsFloat(x, y);
+	                nbhWeight = !CALC_WITH_NBH ? 0 : nbhWeights[lu];
+	                elas      = (lu == lastLU && luElas[lu] < 1) ? luElas[lu] : 0;
+	                // LU-Wahrscheinlichkeit zusammensetzen
+	                totalProb = baseProb * (1-nbhWeight)
+	                          + nbhProb  * nbhWeight
+	                          + elas
+	                          - outIter[lu];
+
+	                // betrachteter Typ ist geeigneter als der bisher beste
+	                if (totalProb > bestLUProb) {
+	                  bestLU = lu;
+	                  bestLUProb = totalProb;
+	                }
+	              }
+	            }
+	            // Merken wenn wirklich ein Wechsel stattfindet
+	            if (bestLU != lastLU) {
+	              alreadyLUCCFromType[lastLU] = true;
+	              alreadyLUCCToType[bestLU] = true;
+	            }
+	          }
+	          // LU fuer diesen Iterationschritt setzen
+	          outActLU.setRasterSample( luMapReverse.get ( (float) bestLU) , x, y);
+	          // Flaechendeckung fuer LU-Typ erhoehen
+/*P*/	          newLUCover[bestLU] += cellSize;
+
+	        }
+/*P*/	      return newLUCover;
+	 }
+	
+	
+	  /**
+	   * Prueft, ob ein genereller LU-Wechsel fuer eine Zelle erlaubt ist.
+	   * <ul>
+	   * <li>Schliessen die Area Restrictions einen Wechsel aus?<br>
+	   *     > Rasterwert(x,y) != 0
+	   *     </li>
+	   * <li>Schliesst die Conversion Elasticity einen Wechsel aus (Elastizitaet 1
+	   *     und steigende Bedarf)?<br>
+	   *     > ELAS(lastLU) == 1 und DEMAND(lastLU,t) >= DEMAND(lastLU,t-1)
+	   *     </li>
+	   * </ul>
+	   * @param x      Raster-Koordinate
+	   * @param y      Raster-Koordinate
+	   * @param stepNo modellierter Schritt (beginnend bei 1)
+	   * @param lastLU Bedeckung von (x,y) zum Zeitpunkt stepNo-1
+	   * @param alreadyLUCCToActualType Flag gibt an, ob in der laufenden Iteration
+	   *                                bereits ein LU-Wechsel in den den aktuellen
+	   *                                Typ der Zelle (lastLU) vorgenommen wurde.<br>
+	   *                                <b>Dieses Flag wird zur Zeit nicht verwendet!</b>
+	   */
+	  protected boolean checkLUCCGeneralAllowed(int x, int y, int stepNo, int lastLU, boolean alreadyLUCCToActualType) {
+	    // Area Restrictions checken
+	    if ( areaRestr.getRasterSampleAsFloat(x,y) != 0 )
+	      return false;
+//	 DER ERSTE TEIL IST KEINE ORIGINAL-CLUE-REGEL!
+//	    // Conversion Elasticity checken
+//	    // --> wenn Elasticity 1 und bereits an anderer Stelle eine Zelle des
+//	    //     bisherigen Typs entstanden ist, darf sie nicht wechseln
+//	    // --> wenn Elasticity 1 und Bedarf steigt, darf kein Wechsel
+//	    //     stattfinden, denn dann muessten (um den Bedarf zu decken)
+//	    //     an anderer Stelle neue entstehen
+//	    if (  luElas.getValueAsFloat(lastLU) == 1.0
+//	       && ( alreadyLUCCToActualType ||
+//	           luDemand.getValueAsFloat(lastLU,stepNo) >= luCover[lastLU][stepNo-1] ) )
+//	      return false;
+
+	    // Conversion Elasticity checken
+	    // --> wenn Elasticity 1 und Bedarf steigt, darf kein Wechsel
+	    //     stattfinden, denn dann muessten (um den Bedarf zu decken)
+	    //     an anderer Stelle neue entstehen
+	    if (  luElas[lastLU] == 1.0 &&
+//	          luDemand[lastLU][stepNo] >= luCover[lastLU][stepNo-1] )
+	          luDemand[lastLU][stepNo] >= luDemand[lastLU][stepNo-1] )
+	      return false;
+
+	    return true;
+	  }
+	  
+	  /**
+	   * Prueft, ob ein bestimmter LU-Wechsel fuer eine Zelle erlaubt ist.
+	   * <ul>
+	   * <li>Schliesst die Conversion Elasticity einen Wechsel aus (Elastizitaet des
+	   *     potentiellen Wechseltyps 1 und sinkender Bedarf)?<br>
+	   *     > lastLU != newLU und ELAS(newLU) == 1 und DEMAND(newLU,t) <= DEMAND(newLU,t-1)
+	   *     </li>
+	   * <li>Schliesst die Conversion Matrix einen Wechsel aus (generell oder ueber
+	   *     Historie)?<br>
+	   *     > CONV(lastLU,newLU) == 0 oder<br>
+	   *     > CONV(lastLU,newLU) > 100 und HIST(x,y) < CONV(lastLU,newLU)-101 oder<br>
+	   *     > CONV(lastLU,newLU) < -100 und HIST(x,y) > -CONV(lastLU,newLU)-101
+	   *     </li>
+	   * </ul>
+	   * @param x      Raster-Koordinate
+	   * @param y      Raster-Koordinate
+	   * @param stepNo modellierter Schritt (beginnend bei 1)
+	   * @param lastLU Bedeckung von (x,y) zum Zeitpunkt stepNo-1
+	   * @param newLU  potentielle neue Bedeckung von (x,y)
+	   * @param alreadyLUCCFromNewType  Flag gibt an, ob in der laufenden Iteration
+	   *                                bereits ein LU-Wechsel vom potentiellen neuen
+	   *                                Typ in einen anderen Typ vorgenommen wurde.<br>
+	   *                                <b>Dieses Flag wird zur Zeit nicht verwendet!</b>
+	   */
+	  protected boolean checkLUCCAllowed(int x, int y, int stepNo, int lastLU, int newLU, boolean alreadyLUCCFromNewType) {
+//	 IST KEINE ORIGINAL-CLUE-REGEL!
+//	    // LU-Conversion-Elasticity des neuen Typs checken
+//	    // --> wenn Elasticity des neuen Typs 1 ist und an anderer Stelle bereits
+//	    //     eine Zelle des dieses Typs "verloren" ging, darf er hier
+//	    //     nicht entstehen
+//	    if (  alreadyLUCCFromNewType && luElas.getValueAsFloat(newLU) == 1.0 )
+//	      return false;
+
+	    // Conversion Elasticity checken
+	    // --> wenn Elasticity des neuen Typs "newLU" 1 und dessen Bedarf sinkt,
+	    //     darf kein Wechsel in diesen Typ stattfinden, denn dann muessten (um
+	    //     den Bedarf fuer "newLU" zu erreichen) an anderer Stelle newLU-Zellen
+	    //     entfernt werden
+	    if (  lastLU != newLU &&
+	          luElas[newLU] == 1.0 &&
+	          luDemand[newLU][stepNo] <= oldLUCover[newLU] )
+//	          luDemand.getValueAsFloat(newLU,stepNo) <= luDemand.getValueAsFloat(newLU,stepNo-1) )
+	      return false;
+
+	    // Wert aus LU-Conversion-Matrix ermitteln
+	    // Bemerke: "von" steht in den Zeilen (also Y, also Dim1)
+	    //          "nach" steht in den Spalten (also X, also Dim2)
+	    int conv = luConv[newLU][lastLU];
+	    // 1 --> LUCC generell erlaubt
+	    if ( conv == 1 )
+	      return true;
+	    // 0 --> LUCC generell verboten
+	    if ( conv == 0 )
+	      return false;
+
+	    // 100+t --> Wechsel erst nach t Schritten der vorangegangenen
+	    //           LU moeglich
+	    if ( conv > 100 ) {
+//	      int minLUHist = conv-100;
+//	      int luHist    = outActLUHist.getRasterSampleAsInt(x,y);
+//	      return luHist >= minLUHist;
+	      int minLUHist = conv-101;
+	      int luHist    = outActLUHist.getRasterSampleAsInt(x,y);
+	      return luHist >= minLUHist;
+	    }
+
+	    // -100-t --> Wechsel nicht mehr moeglich, wenn Zelle bereits
+	    //            t Schritte unter der vorangegangenen LU
+	    if ( conv < -100 ) {
+//	      int maxLUHist = -conv-100;
+//	      int luHist    = outActLUHist.getRasterSampleAsInt(x,y);
+//	      return luHist < maxLUHist;
+	      int maxLUHist = -conv-101;
+	      int luHist    = outActLUHist.getRasterSampleAsInt(x,y);
+	      return luHist <= maxLUHist;
+	    }
+
+	    return true;
+	  }
+	
+		
+	/**
+	   * Prueft, ob eine Rasterzelle mit <code>NoData</code> belegt ist
+	   * @param x     Raster-Koordinate
+	   * @param y     Raster-Koordinate
+	   * @param grid  zu pruefendes Raster
+	   */
+	  protected static boolean checkNoData(int x, int y, WritableGrid grid) {
+	    return Float.isNaN(grid.getRasterSampleAsFloat(x,y));
+	  }
+	  
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/AVNTask.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/AVNTask.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/AVNTask.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,108 @@
+package edu.bonn.xulu.plugin.model.parallel.demo;
+
+import java.awt.Rectangle;
+
+import schmitzm.data.WritableGrid;
+import appl.parallel.spmd.AbstractSPMDTask;
+import appl.parallel.spmd.AdvancedSPMDServerInterface;
+import appl.parallel.spmd.SPMDServerInterface;
+import appl.parallel.spmd.SPMDTask;
+import appl.parallel.spmd.SyncPoint;
+import appl.util.RasterUtil;
+
+/**
+ * This is the {@link SPMDTask} which will be executed on server side by the
+ * parallel model {@link AverageNeighborhoodParallelDemoModel}. There are only
+ * very little changes to the serial code you have seen in
+ * {@link AverageNeighborhoodSerialDemoModel}. Basically you have to retrieve
+ * the partitions you have submitted to Xulu / V control on client side and use
+ * the copy paste the sequential code. One important change has to be made
+ * though: you now must iterate over the so called calculation area of the
+ * partition. This becomes even more important when use multithreading to
+ * calculate on many calculation areas at once.
+ * <p/>
+ * <strong>Multithreading is disabled!</strong>
+ * 
+ * @see SPMDTask
+ * @see AverageNeighborhoodParallelDemoModel
+ * @see AVNTuned
+ * @author Dominik Appl
+ */
+public class AVNTask extends AbstractSPMDTask {
+
+	private static final long serialVersionUID = 13L;
+
+	AdvancedSPMDServerInterface controller;
+
+	int neighborhoodRange;
+
+	WritableGrid gridOutput;
+
+	WritableGrid gridInput;
+
+	/*
+	 * The init method is executed excactly one time per task class
+	 * 
+	 * @see appl.parallel.spmd.AbstractSPMDTask#init()
+	 */
+	@Override
+	public void init() {
+		// get the server controller for Xulu / V access
+		controller = getAdvancedSPMDServerController();
+		// get the partitions from Xulu / V control
+		gridInput = (WritableGrid) controller.getPartition("inputGrid");
+		gridOutput = (WritableGrid) controller.getPartition("outputGrid");
+	}
+
+	/*
+	 * In the run method you specifiy the main execution code
+	 * 
+	 * @see appl.parallel.spmd.SPMDTask#run()
+	 */
+	public Object run(Object... parameters) {
+
+		// neighborhood range is given as a parameter
+		neighborhoodRange = (Integer) parameters[0];
+
+		/***********************************************************************
+		 * START REMOTE ALGORITHM Notice that only the outer loop variables have
+		 * changed to the serial version!!!
+		 **********************************************************************/
+		float overallSum = 0;
+		Rectangle partition = controller.getLocalBounds();
+		// iterate over all cells
+		for (int y = controller.getLocalCalcMinY(); y < controller
+				.getLocalCalcMaxY() + 1; y++)
+			for (int x = controller.getLocalCalcMinX(); x < controller
+					.getLocalCalcMaxX() + 1; x++) {
+				float tmp = gridInput.getRasterSampleAsFloat(x, y);
+				if (!Float.isNaN(tmp))
+					overallSum += tmp;
+				// the local sum is simply the sum over all elements in the
+				// neighborhood
+				float localSum = 0;
+				// number of cells over which the sum is calculated
+				int noOfCells = 0;
+				// for each cell: calculate the sum of all neighbors
+				for (int y2 = y - neighborhoodRange; y2 <= y
+						+ neighborhoodRange; y2++)
+					for (int x2 = x - neighborhoodRange; x2 <= x
+							+ neighborhoodRange; x2++)
+						// check if the coordinates are valid (inside the grid
+						// and not NaN)
+						if (partition.contains(x2, y2))
+							if (!Float.isNaN(gridInput.getRasterSampleAsFloat(
+									x2, y2))) {
+								localSum += gridInput.getRasterSampleAsFloat(
+										x2, y2);
+								noOfCells++;
+							}
+				gridOutput
+						.setRasterSample(localSum / (float) (noOfCells), x, y);
+
+			}
+		// copy values into results from output to input (for next step)
+		RasterUtil.copyInto(gridOutput, gridInput);
+		return overallSum;
+	}
+}
\ No newline at end of file

Added: trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/AVNTuned.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/AVNTuned.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/AVNTuned.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,167 @@
+package edu.bonn.xulu.plugin.model.parallel.demo;
+
+import java.awt.Rectangle;
+
+import appl.parallel.model.AbstractParallelStepModel;
+import appl.parallel.spmd.AdvancedSPMDClientInterface;
+import appl.parallel.spmd.SPMDClientInterface;
+import appl.parallel.spmd.SyncPoint;
+import appl.util.RasterUtil;
+import edu.bonn.xulu.model.AbstractStepModel;
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.PropertyWriteAccess;
+import schmitzm.data.property.ScalarProperty;
+
+/**
+ *This is a tuned version of the {@link AverageNeighborhoodParallelDemoModel}, which uses
+ *multithreading and preloading. 
+ * <ol>
+ * <li><b>Input Grid ({@code inputGrid}):</b> A grid with input values </li>
+ * <li><b>Output Grid ({@code outputGrid}):</b> A grid where the output is
+ * stored </li>
+ * <li><b>Number of steps ({@code steps}):</b> the number of steps to
+ * compute. </li>
+ * </ol>
+ * @see AverageNeighborhoodContentManager
+ * @author Dominik Appl
+ * @version 1.0
+ */
+public class AVNTuned extends
+		AbstractParallelStepModel {
+
+	private int neighborhoodRange = 6;
+
+	/** Speichert den ContentManager fuer das Modell.
+	 *  @see AverageNeighborhoodContentManager */
+	protected AverageNeighborhoodContentManager contManager;
+
+	//********** Lese/Schreibrechte, die fuer den gesamten ***********
+	//********** Modellanlauf gehalten werden muessen      ***********
+	private PropertyReadAccess RA_inputGrid = null; // Input Grid
+
+	private PropertyWriteAccess WA_outputGrid = null; // Output Grid
+
+	private PropertyReadAccess RA_steps = null; // Number of steps
+
+	//**************** Variablen mit denen gearbeitet wird *******************
+	private WritableGrid inputGrid = null; // Input Grid
+
+	private WritableGrid outputGrid = null; // Output Grid
+
+	private PropertyReadAccess steps = null; // Number of steps
+
+	AdvancedSPMDClientInterface clientController = null;
+
+	/**
+	 * Erzeugt eine neue Instanz des Modells.
+	 */
+	public AVNTuned() {
+		super(new AverageNeighborhoodContentManager());
+		this.contManager = (AverageNeighborhoodContentManager) super.contManager;
+	}
+
+	////////////////////////////////////////////////////////////////////////
+	///////////////   Implementierung von AbstractXuluModel   //////////////
+	////////////////////////////////////////////////////////////////////////
+	/**
+	 * Initialisiert das Model, indem die Ressourcen aus dem ContentManager
+	 * geladen werden und mit Lese/Schreib-Rechten versehen werden. Zudem
+	 * werden Referenzen auf die Ressourcen in lokalen Variablen
+	 * gespeichert, um waehrend des Modellablaufs effizienter darauf zugreifen
+	 * zu koennen.
+	 */
+	public void performModelInit() {
+		clientController = getAdvancedSPMDController();
+		if (contManager == null)
+			return;
+		// Zugriffsrechte aus Ressourcen/Propertys holen
+		RA_inputGrid = null;
+		if (contManager.getResource(0).getData() != null)
+			RA_inputGrid = ((ScalarProperty) contManager.getResource(0)
+					.getData()).getReadAccess(this);
+		WA_outputGrid = null;
+		if (contManager.getResource(1).getData() != null)
+			WA_outputGrid = ((ScalarProperty) contManager.getResource(1)
+					.getData()).getWriteAccess(this);
+		RA_steps = null;
+		if (contManager.getResource(2).getData() != null)
+			RA_steps = ((ScalarProperty) contManager.getResource(2).getData())
+					.getReadAccess(this);
+
+		// Variablen belegen mit denen gearbeitet wird
+		inputGrid = (WritableGrid) RA_inputGrid.getValue();
+		outputGrid = (WritableGrid) WA_outputGrid.getValue();
+		steps = RA_steps;
+
+		this.stepCount = steps.getValueAsInt();
+
+		//****  Initialize parallelization ********////
+		long remoteStartTime = System.currentTimeMillis();
+		clientController.setNeighborhoodRange(neighborhoodRange);
+		clientController.addToSplitControl(inputGrid, "inputGrid");
+		clientController.addToSplitControl(outputGrid, "outputGrid");
+		System.out.println("After "
+				+ ((System.currentTimeMillis() - remoteStartTime))
+				+ "ms: finished with adding to splitcontrol");
+	}
+
+	/**
+	 * Gibt die Lese/Schreibrechte auf das Ein- und Ausgaberaster wieder frei.
+	 * Interne Ressourcen brauchen keine aus dem Speicher entfernt werden.
+	 */
+	public void performModelDispose() {
+
+		// Ressourcen wieder freigeben
+		releaseAccess(RA_inputGrid);
+		releaseAccess(WA_outputGrid);
+		releaseAccess(RA_steps);
+	}
+
+	/**
+	 * Fuehrt einen Schritt des Modellablaufs durch.
+	 * @param stepNo zu modellierender Schritt (beginnend bei 1!)
+	 */
+	public void performModelStep(int stepNo) {
+		long remoteStartTime = System.currentTimeMillis();
+		
+		statusOut.println("Starting step " + stepNo + "...");
+		/***********************************************************************
+		 * 						START REMOTE ALGORITHM
+		 //***********************************************************************/
+		if (stepNo > 1)
+			clientController.updateNeighborhood(inputGrid);
+		try {
+			Object[] sum = clientController.runSPMDModelTask(new AVNTunedTask(),
+					neighborhoodRange);
+			float overallSum = 0;
+			for (int i = 0; i < sum.length; i++)
+				overallSum += (Float) sum[i];
+			System.out.println("finished step " + (stepNo) + " in "
+					+ ((System.currentTimeMillis() - remoteStartTime)) + "ms "
+					+ " with sum " + +overallSum);
+			remoteStartTime = System.currentTimeMillis();
+		} catch (Throwable e) {
+			e.printStackTrace();
+		}
+
+		//***************** END STEP CONTROL *****************************
+		//After last step: Merge the grids back to the client data pool
+		if (stepNo == stepCount) {
+			//After execution:
+			// merge partitions and check if the local and remotely calculated
+			// versions are equal
+			remoteStartTime = System.currentTimeMillis();
+			
+			//in this algorithm we tune the merging by allowing the merge in a separate Thread
+			//this normally makes sense especially if you have to merge after every step!
+			
+			clientController.mergePartition(outputGrid,new SyncPoint(),statusOut,"Finished merging!");
+			System.out.println("Merging is done in a separate thread, so this took only "
+					+ ((System.currentTimeMillis() - remoteStartTime)) + "ms");
+			// Thread.currentThread().sleep(10000);
+			if (inputGrid.getWidth() < 20)
+				RasterUtil.printGrid(outputGrid, 5, 1, "Remote Output");
+		}
+	}
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/AVNTunedTask.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/AVNTunedTask.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/AVNTunedTask.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,135 @@
+package edu.bonn.xulu.plugin.model.parallel.demo;
+
+import java.awt.Rectangle;
+
+import schmitzm.data.WritableGrid;
+import appl.parallel.spmd.AbstractSPMDTask;
+import appl.parallel.spmd.AdvancedSPMDServerInterface;
+import appl.parallel.spmd.SPMDServerInterface;
+import appl.parallel.spmd.SPMDTask;
+import appl.parallel.spmd.SyncPoint;
+import appl.util.RasterUtil;
+
+/**
+ * This is the {@link SPMDTask} which will be executed on server side by
+ * the parallel model {@link AverageNeighborhoodParallelDemoModel}. There are
+ * only very little changes to the serial code you have seen in
+ * {@link AverageNeighborhoodSerialDemoModel}. Basically you have to retrieve
+ * the partitions you have submitted to Xulu / V control on client side and use
+ * the copy paste the sequential code. One important change has to be made
+ * though: you now must iterate over the so called calculation area of the
+ * partition. This becomes even more important when use multithreading to
+ * calculate on many calculation areas at once.
+ * <p/>
+ * <strong>Multithreading is enabled!</strong>
+ * <p>
+ * Preloading is also used, but the effect is in this case very small (because data is 
+ * only loaded once and not every step).
+ * 
+ * @see SPMDTask
+ * @see AverageNeighborhoodParallelDemoModel
+ * @see AVNTuned
+ * @author Dominik Appl
+ */
+public class AVNTunedTask extends AbstractSPMDTask {
+
+	private static final long serialVersionUID = 13L;
+
+	AdvancedSPMDServerInterface controller;
+
+	int neighborhoodRange;
+
+	WritableGrid gridOutput;
+
+	WritableGrid gridInput;
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.spmd.AbstractSPMDTask#init()
+	 */
+	@Override
+	public void init() {
+		//get the server controller for Xulu / V access
+		controller = getAdvancedSPMDServerController();
+
+		/***********************************************************************
+		 * TUNING: we can load the grids concurrently using syncPoints. Of
+		 * course in case of this simple algorithm with only two grids this will
+		 * not make much difference. Normaly you would use SyncPoints when you
+		 * have many grids or want to preload data for the NEXT step. 
+		 * Look at the parallel Clue model for an example.
+		 **********************************************************************/
+		SyncPoint loadPoint = new SyncPoint(1, SyncPoint.Priority.HIGH);
+		controller.preloadPartition("inputGrid", loadPoint);
+		controller.preloadPartition("outputGrid", loadPoint);
+		// wait for the loading to be finished
+		controller.synchronizeToSyncPoint(loadPoint);
+
+		// Now the data is loaded and the following 2 assignments are no-time
+		// operations
+		gridInput = (WritableGrid) controller.getPartition("inputGrid");
+		gridOutput = (WritableGrid) controller.getPartition("outputGrid");
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see appl.parallel.spmd.SPMDTask#run()
+	 */
+	public Object run(Object... parameters) {
+
+		//neighborhood range is given as a parameter
+		neighborhoodRange = (Integer) parameters[0];
+
+		/***********************************************************************
+		 * START REMOTE ALGORITHM 
+		 * Notice that only the outer loop variables have changed to the serial version!!!
+		 **********************************************************************/
+		float overallSum = 0;
+		Rectangle partition = controller.getLocalBounds();
+		//iterate over all cells
+		for (int y = controller.getLocalCalcMinY(); y < controller
+				.getLocalCalcMaxY() + 1; y++)
+			for (int x = controller.getLocalCalcMinX(); x < controller
+					.getLocalCalcMaxX() + 1; x++) {
+				float tmp = gridInput.getRasterSampleAsFloat(x, y);
+				if (!Float.isNaN(tmp))
+					overallSum += tmp;
+				// the local sum is simply the sum over all elements in the
+				// neighborhood
+				float localSum = 0;
+				// number of cells over which the sum is calculated
+				int noOfCells = 0;
+				// for each cell: calculate the sum of all neighbors
+				for (int y2 = y - neighborhoodRange; y2 <= y
+						+ neighborhoodRange; y2++)
+					for (int x2 = x - neighborhoodRange; x2 <= x
+							+ neighborhoodRange; x2++)
+						// check if the coordinates are valid (inside the grid
+						// and not NaN)
+						if (partition.contains(x2, y2))
+							if (!Float.isNaN(gridInput.getRasterSampleAsFloat(
+									x2, y2))) {
+								localSum += gridInput.getRasterSampleAsFloat(
+										x2, y2);
+								noOfCells++;
+							}
+				gridOutput
+						.setRasterSample(localSum / (float) (noOfCells), x, y);
+
+			}
+		// copy values into results from output to input (for next step)
+		RasterUtil.copyInto(gridOutput, gridInput);
+		return overallSum;
+	}
+
+	/* (non-Javadoc)
+	 * @see appl.parallel.spmd.AbstractSPMDTask#supportsMultiThreading()
+	 */
+	@Override
+	public boolean supportsMultiThreading() {
+		return true;
+	}
+
+}
\ No newline at end of file

Added: trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/AverageNeighborhoodContentManager.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/AverageNeighborhoodContentManager.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/AverageNeighborhoodContentManager.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,38 @@
+package edu.bonn.xulu.plugin.model.parallel.demo;
+
+import edu.bonn.xulu.model.AbstractModelContentManager;
+import edu.bonn.xulu.model.ModelResource;
+import edu.bonn.xulu.model.PropertiesResource;
+import edu.bonn.xulu.model.ValuePropertyResource;
+import edu.bonn.xulu.plugin.model.clue.ClueModelContentManager;
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.ScalarProperty;
+
+
+/**
+ * This class defines and handle the three resources for the models
+ * <ol> 
+ * <li><b> </li>
+ * <li><b> {@link AverageNeighborhoodSerialDemoModel}</b></li>
+ * <li><b> {@link AverageNeighborhoodParallelDemoModel}</b></li>
+ * <li><b> {@link AVNTuned}</b></li>
+ * </ol>
+ * @see ClueModelContentManager
+ * @author automatically generated using {@link edu.bonn.xulu.plugin.appl.GeoModelCodeGenerator}
+ * @version 1.0
+ */
+public class AverageNeighborhoodContentManager extends AbstractModelContentManager {
+
+  /**
+   * Erzeugt einen neuen ContentManager fuer das Modell {@linkplain AverageNeighborhoodParallelDemoModel}.
+   */
+  public AverageNeighborhoodContentManager() {
+    super(3);
+    // Input Grid
+    resource[0] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Input Grid",ScalarProperty.class,WritableGrid.class,false);
+    // Output Grid
+    resource[1] = new ValuePropertyResource(ModelResource.CATEGORY_OUTPUT,"Output Grid",ScalarProperty.class,WritableGrid.class,false);
+    // Number of steps
+    resource[2] = new ValuePropertyResource(ModelResource.CATEGORY_INPUT,"Number of steps",ScalarProperty.class,Integer.class,false);
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/AverageNeighborhoodParallelDemoModel.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/AverageNeighborhoodParallelDemoModel.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/AverageNeighborhoodParallelDemoModel.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,153 @@
+package edu.bonn.xulu.plugin.model.parallel.demo;
+
+import java.awt.Rectangle;
+
+import appl.parallel.model.AbstractParallelStepModel;
+import appl.parallel.spmd.SPMDClientInterface;
+import appl.util.RasterUtil;
+import edu.bonn.xulu.model.AbstractStepModel;
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.PropertyWriteAccess;
+import schmitzm.data.property.ScalarProperty;
+
+/**
+ * This class is a simple demo algorithm for the usage of Xulu / V. It
+ * implements exactly the same functionality as the
+ * {@link AverageNeighborhoodSerialDemoModel serial counterpart}, but makes
+ * heavy use of parallel computations. See
+ * {@link AverageNeighborhoodSerialDemoModel} for details about the model
+ * semantics. The Model needs three resources, which are specified using the
+ * {@linkplain AverageNeighborhoodContentManager}:
+ * <ol>
+ * <li><b>Input Grid ({@code inputGrid}):</b> A grid with input values </li>
+ * <li><b>Output Grid ({@code outputGrid}):</b> A grid where the output is
+ * stored </li>
+ * <li><b>Number of steps ({@code steps}):</b> the number of steps to
+ * compute. </li>
+ * </ol>
+ * 
+ * @see AverageNeighborhoodContentManager
+ * @author Dominik Appl
+ * @version 1.0
+ */
+public class AverageNeighborhoodParallelDemoModel extends
+		AbstractParallelStepModel {
+
+	/** specifies which neighborhood range to use */
+	private int neighborhoodRange = 6;
+
+	/**Speichert den ContentManager fuer das Modell.
+	 * @see AverageNeighborhoodContentManager*/
+	protected AverageNeighborhoodContentManager contManager;
+
+	// ********** Read and Write access ***********
+	private PropertyReadAccess RA_inputGrid = null; // Input Grid
+	private PropertyWriteAccess WA_outputGrid = null; // Output Grid
+	private PropertyReadAccess RA_steps = null; // Number of steps
+
+	// **************** working variables  *******************
+	private WritableGrid inputGrid = null; // Input Grid
+	private WritableGrid outputGrid = null; // Output Grid
+	private PropertyReadAccess steps = null; // Number of steps
+
+	SPMDClientInterface clientController = null;
+
+	/** Creates a new instance. */
+	public AverageNeighborhoodParallelDemoModel() {
+		super(new AverageNeighborhoodContentManager());
+		this.contManager = (AverageNeighborhoodContentManager) super.contManager;
+	}
+
+	/**
+	 * Performes the initalization. In addition to the work in the serial version
+	 * here the {@link SPMDClientInterface} is retrieved. The neighborhood range is 
+	 * set and the two grids are submitted to Xulu / V - control. 
+	 */
+	public void performModelInit() {
+		clientController = getSPMDController();
+		if (contManager == null)
+			return;
+		// Zugriffsrechte aus Ressourcen/Propertys holen
+		RA_inputGrid = null;
+		if (contManager.getResource(0).getData() != null)
+			RA_inputGrid = ((ScalarProperty) contManager.getResource(0)
+					.getData()).getReadAccess(this);
+		WA_outputGrid = null;
+		if (contManager.getResource(1).getData() != null)
+			WA_outputGrid = ((ScalarProperty) contManager.getResource(1)
+					.getData()).getWriteAccess(this);
+		RA_steps = null;
+		if (contManager.getResource(2).getData() != null)
+			RA_steps = ((ScalarProperty) contManager.getResource(2).getData())
+					.getReadAccess(this);
+
+		// Variablen belegen mit denen gearbeitet wird
+		inputGrid = (WritableGrid) RA_inputGrid.getValue();
+		outputGrid = (WritableGrid) WA_outputGrid.getValue();
+		steps = RA_steps;
+
+		this.stepCount = steps.getValueAsInt();
+
+		// **** Initialize parallelization ********////
+		long remoteStartTime = System.currentTimeMillis();
+		clientController.setNeighborhoodRange(neighborhoodRange);
+		clientController.addToSplitControl(inputGrid, "inputGrid");
+		clientController.addToSplitControl(outputGrid, "outputGrid");
+		System.out.println("After "
+				+ ((System.currentTimeMillis() - remoteStartTime))
+				+ "ms: finished with adding to splitcontrol");
+	}
+
+	/**
+	 * frees read / write access
+	 */
+	public void performModelDispose() {
+
+		// Ressourcen wieder freigeben
+		releaseAccess(RA_inputGrid);
+		releaseAccess(WA_outputGrid);
+		releaseAccess(RA_steps);
+	}
+
+	/** Executes one model step:	 */
+	public void performModelStep(int stepNo) {
+		long remoteStartTime = System.currentTimeMillis();
+		statusOut.println("Starting step " + stepNo + "...");
+
+		/***********************************************************************
+		 * START REMOTE ALGORITHM //********************** START STEP CONTROL
+		 **********************************************************************/
+
+		if (stepNo > 1)
+			clientController.updateNeighborhood(inputGrid);
+
+		try {
+			Object[] sum = clientController.runSPMDModelTask(new AVNTask(),
+					neighborhoodRange);
+			float overallSum = 0;
+			for (int i = 0; i < sum.length; i++)
+				overallSum += (Float) sum[i];
+			System.out.println("finished step " + (stepNo) + " in "
+					+ ((System.currentTimeMillis() - remoteStartTime)) + "ms "
+					+ " with sum " + +overallSum);
+			remoteStartTime = System.currentTimeMillis();
+		} catch (Throwable e) {
+			e.printStackTrace();
+		}
+
+		// ***************** END STEP CONTROL *****************************
+		if (stepNo == stepCount) {
+			// After execution:
+			// merge partitions and check if the local and remotely calculated
+			// versions are equal
+			remoteStartTime = System.currentTimeMillis();
+			clientController.mergePartition(outputGrid);
+			System.out.println("Merging took another "
+					+ ((System.currentTimeMillis() - remoteStartTime)) + "ms");
+			// Thread.currentThread().sleep(10000);
+			if (inputGrid.getWidth() < 20)
+				RasterUtil.printGrid(outputGrid, 5, 1, "Remote Output");
+		}
+	}
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/AverageNeighborhoodSerialDemoModel.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/AverageNeighborhoodSerialDemoModel.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/model/parallel/demo/AverageNeighborhoodSerialDemoModel.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,169 @@
+package edu.bonn.xulu.plugin.model.parallel.demo;
+
+import java.awt.Rectangle;
+
+import appl.util.RasterUtil;
+import edu.bonn.xulu.model.AbstractStepModel;
+import edu.bonn.xulu.model.XuluModel;
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.property.PropertyWriteAccess;
+import schmitzm.data.property.ScalarProperty;
+
+/**
+ *  This very simple model looks at every grid cell and takes the average 
+ *  over a the surrounding cells in a specified neighborhood. It was implemented
+ *  as demonstration of the Xulu / V functionality. You can see the parallel version
+ *  of this model in {@link AverageNeighborhoodParallelDemoModel} and also a tuned
+ *  version using late-merging support in {@link AVNTuned}. 
+ * <ol>
+ * <li><b>Input Grid ({@code inputGrid}):</b> A grid with input values </li>
+ * <li><b>Output Grid ({@code outputGrid}):</b> A grid where the output is
+ * stored </li>
+ * <li><b>Number of steps ({@code steps}):</b> the number of steps to
+ * compute. </li>
+ * </ol>
+ * 
+ * @see AverageNeighborhoodContentManager
+ * @author Dominik Appl
+ * @version 1.0
+ */
+public class AverageNeighborhoodSerialDemoModel extends AbstractStepModel {
+
+	/**
+	 * the width/height of the neighborhood region over which the algorithm takes 
+	 * the average
+	 */
+	private int neighborhoodRange = 6;
+
+	/**
+	 * Speichert den ContentManager fuer das Modell.
+	 * 
+	 * @see AverageNeighborhoodContentManager
+	 */
+	protected AverageNeighborhoodContentManager contManager;
+
+	// ********** Lese/Schreibrechte, die fuer den gesamten ***********
+	// ********** Modellanlauf gehalten werden muessen ***********
+	private PropertyReadAccess RA_inputGrid = null; // Input Grid
+
+	private PropertyWriteAccess WA_outputGrid = null; // Output Grid
+
+	private PropertyReadAccess RA_steps = null; // Number of steps
+
+	// **************** Variablen mit denen gearbeitet wird *******************
+	private WritableGrid inputGrid = null; // Input Grid
+
+	private WritableGrid outputGrid = null; // Output Grid
+
+	private PropertyReadAccess steps = null; // Number of steps
+
+	/**
+	 * Erzeugt eine neue Instanz des Modells.
+	 */
+	public AverageNeighborhoodSerialDemoModel() {
+		super(new AverageNeighborhoodContentManager());
+		this.contManager = (AverageNeighborhoodContentManager) super.contManager;
+	}
+
+	
+	/**
+	 * Initializes the model. Like in the init method of every {@link XuluModel}
+	 * the resources are initalized. 
+	 */
+	public void performModelInit() {
+		if (contManager == null)
+			return;
+		// Zugriffsrechte aus Ressourcen/Propertys holen
+		RA_inputGrid = null;
+		if (contManager.getResource(0).getData() != null)
+			RA_inputGrid = ((ScalarProperty) contManager.getResource(0)
+					.getData()).getReadAccess(this);
+		WA_outputGrid = null;
+		if (contManager.getResource(1).getData() != null)
+			WA_outputGrid = ((ScalarProperty) contManager.getResource(1)
+					.getData()).getWriteAccess(this);
+		RA_steps = null;
+		if (contManager.getResource(2).getData() != null)
+			RA_steps = ((ScalarProperty) contManager.getResource(2).getData())
+					.getReadAccess(this);
+
+		// Variablen belegen mit denen gearbeitet wird
+		inputGrid = (WritableGrid) RA_inputGrid.getValue();
+		outputGrid = (WritableGrid) WA_outputGrid.getValue();
+		steps = RA_steps;
+
+		this.stepCount = steps.getValueAsInt();
+
+	}
+
+	/**
+	* like in every model: frees the resources
+	 */
+	public void performModelDispose() {
+
+		// Ressourcen wieder freigeben
+		releaseAccess(RA_inputGrid);
+		releaseAccess(WA_outputGrid);
+		releaseAccess(RA_steps);
+	}
+
+	/**
+	 * This very simple model looks at every grid cell and takes the average
+	 * over a the surrounding cells in a specified neighborhood.
+	 * 
+	 * @param stepNo
+	 *            zu modellierender Schritt (beginnend bei 1!)
+	 */
+	public void performModelStep(int stepNo) {
+		
+		statusOut.println("Starting step " + stepNo + "...");
+		//this rectangle is only used to check if values are outside the grid (see below)
+		Rectangle gridBounds = new Rectangle(0, 0, inputGrid.getWidth(),
+				inputGrid.getHeight());
+
+		/***********************************************************************
+		 * the overallsum is simply the sum over ALL grid elements. it can be used to
+		 * compare the result of this model with e.g. the parallel version of
+		 * this algorithm.
+		 **********************************************************************/ 
+		float overallSum = 0f;
+		long localStartTime = System.currentTimeMillis();
+		//iterate over all cells
+		for (int y = 0; y < inputGrid.getHeight(); y++)
+			for (int x = 0; x < inputGrid.getWidth(); x++) {
+				float tmp = inputGrid.getRasterSampleAsFloat(x, y);
+				if (!Float.isNaN(tmp))
+					overallSum += tmp;
+				// the local sum is simply the sum over all elements in the
+				// neighborhood
+				float localSum = 0;
+				// number of cells over which the sum is calculated
+				int noOfCells = 0;
+				// for each cell: calculate the sum of all neighbors
+				for (int y2 = y - neighborhoodRange; y2 <= y
+						+ neighborhoodRange; y2++)
+					for (int x2 = x - neighborhoodRange; x2 <= x
+							+ neighborhoodRange; x2++)
+						// check if the coordinates are valid (inside the
+						// grid and not NaN)
+						if (gridBounds.contains(x2, y2))
+							if (!Float.isNaN(inputGrid.getRasterSampleAsFloat(
+									x2, y2))) {
+								localSum += inputGrid.getRasterSampleAsFloat(
+										x2, y2);
+								noOfCells++;
+							}
+				//after calculation: Set the grid sample
+				outputGrid
+						.setRasterSample(localSum / (float) (noOfCells), x, y);
+			}
+
+		System.out.print("Finished step " + (stepNo) + " in "
+				+ ((System.currentTimeMillis() - localStartTime)) + " ms");
+		localStartTime = System.currentTimeMillis();
+		System.out.println(" with sum (local calculated): " + overallSum);
+		// copy values into results from output to input (for next step)
+		RasterUtil.copyInto(outputGrid, inputGrid);
+	}
+}

Added: trunk/src/edu/bonn/xulu/plugin/model/test/TestModel.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/model/test/TestModel.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/model/test/TestModel.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,277 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.model.test;
+
+import java.awt.image.DataBuffer;
+
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.data.property.PropertyReadAccess;
+import schmitzm.data.WritableGrid;
+import edu.bonn.xulu.data.XuluDataException;
+import edu.bonn.xulu.model.AbstractStepModel;
+import edu.bonn.xulu.model.ModelContentManager;
+import edu.bonn.xulu.model.AbstractModelContentManager;
+import edu.bonn.xulu.model.PropertiesResource;
+
+import schmitzm.temp.BaseTypeUtil;
+
+/**
+ * Diese Klasse stellt ein Test-Modell dar, dass eigentlich gar nichts macht.
+ * Es benoetigt 3 Ressourcen:
+ * <ol>
+ * <li>Eine Ganzzahl, welche die Anzahl der durchzufuehrenden Modellierungsschritte
+ *     festlegt</li>
+ * <li>Ein diskretes Double-Raster als Eingabe ({@link WritableGrid})</li>
+ * <li>Ein entsprechendes diskretes Double-Raster als Ausgabe ({@link WritableGrid})</li>
+ * </ol>
+ * In jedem Zeitschritt t werden alle Rasterzellen r des Eingabe-Rasters und deren
+ * t-Umgebung betrachtet. Ist der Wert von r groesser als der Durchschnitt der
+ * Umgebungswerte, wird die entsprechende Zelle im Ausgabe-Raster auf 1 gesetzt,
+ * ansonsten auf 0.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class TestModel extends AbstractStepModel {
+
+  /** Speichert den ContentManager fuer das Modell.
+   *  @see TestModel.ContentManager */
+  protected ContentManager contManager;
+
+  private WritableGrid inGrid    = null;
+  private WritableGrid outGrid   = null;
+
+
+  // ZUM TESTEN: Referenz auf Property des Ausgaberasters
+  ScalarProperty outRasterProp = null;
+
+  /**
+   * Erzeugt ein neues Test-Modell.
+   */
+  public TestModel() {
+    super( new ContentManager() );
+    contManager = (ContentManager)super.contManager;
+  }
+
+  /**
+   * Initialisiert das Model, indem die Ressourcen aus dem ContentManager
+   * geladen werden (Lese/Schreib-Rechte).
+   */
+  public void performModelInit() {
+    if ( contManager == null )
+      return;
+
+//    /////////////////////////
+//    // ZUM TESTEN: die VisualisationUpdateListener des Ausgaberaster auf ein
+//    //             ChangeEvent reagieren lassen
+//    outRasterProp = (ScalarProperty)contManager.getResource(2).getData();
+//    schmitzm.data.event.ObjectListener[] listener = outRasterProp.getObjectListener(edu.bonn.xulu.appl.VisualisationUpdateListener.class);
+//    for (int i=0; i<listener.length; i++)
+//      ((edu.bonn.xulu.appl.VisualisationUpdateListener)listener[i]).setAutoRefresh(true);
+//    /////////////////////////
+
+    // Ressourcen aus dem ContentManager referenzieren (Lese/Schreib-Rechte
+    // erzeugen)
+    this.stepCount = contManager.getStepCount();
+    inGrid         = contManager.getInRaster();
+    outGrid        = contManager.getOutRaster();
+    // Ausgabe-Raster leeren
+    for (int y=outGrid.getMinY(); y<outGrid.getHeight(); y++)
+      for (int x=outGrid.getMinX(); x<outGrid.getWidth(); x++)
+        outGrid.setRasterSample(Float.NaN,x,y);
+
+//    // ZUM TESTEN: Aenderung des Ausgaberasters propagieren
+//    outRasterProp.fireGeneralEvent();
+  }
+
+  /**
+   * Fuehrt einen Schritt des Modellablaufs durch.
+   */
+  public void performModelStep(int stepNo) {
+    statusOut.println("Started step ".concat(String.valueOf(stepNo)));
+    for (int y=inGrid.getMinY(); y<inGrid.getHeight(); y++)
+      for (int x=inGrid.getMinX(); x<inGrid.getWidth(); x++) {
+        // Wert des Eingabe-Rasters
+        float  inValue = (Float)inGrid.getRasterSample(x,y);
+        // Durchschnitt der Umgebung berechnen
+        int    cellCount = 0;
+        float  cellSum   = 0.0f;
+        for (int r=0; r<stepNo; r++)
+          for (int uy=y-r; uy<=y+r; uy++)
+            if ( uy >= inGrid.getMinY() && uy < inGrid.getMinY()+inGrid.getHeight() )
+              for (int ux=x-r; ux<=x+r; ux++)
+                if ( ux >= inGrid.getMinX() && ux < inGrid.getMinX()+inGrid.getWidth() ) {
+                  cellCount++;
+                  cellSum += (Float)inGrid.getRasterSample(ux,uy);
+                  checkBreakingCommands();
+                }
+        // Wenn Wert groesser dem Durchschnitt, Ausgabe auf 1 setzten, sonst
+        // auf 0
+        int outValue = ( inValue > cellSum/cellCount ) ? 1 : 0;
+        outGrid.setRasterSample((float)outValue,x,y);
+      }
+//    // ZUM TESTEN: Aenderung des Ausgaberasters propagieren
+//    outRasterProp.fireGeneralEvent();
+
+    statusOut.println("Ended step ".concat(String.valueOf(stepNo)));
+  }
+
+  /**
+   * Gibt die Lese/Schreibrechte auf das Ein- und Ausgaberaster wieder frei.
+   * Interne Ressourcen brauchen keine aus dem Speicher entfernt werden.
+   */
+  public void performModelDispose() {
+    contManager.releaseInRaster();
+    contManager.releaseOutRaster();
+  }
+
+
+  /**
+   * Diese Klasse verwaltet die Ressourcen fuer das {@linkplain TestModel TestModel}
+   * und prueft diese auf Korrektheit.<br>
+   * Die Art der benoetigten Ressourcen ist der {@linkplain TestModel Model-Doku}
+   * zu entnehmen.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  public static class ContentManager extends AbstractModelContentManager {
+    // Ressource 0: Anzahl an Modellschritten
+    private static final int    STEP_MIN = 1;
+    private static final int    STEP_MAX = 100;
+    private static final String DESC0 = "Anzahl an Modellschritten (".concat(String.valueOf(STEP_MIN)).concat("-").concat(String.valueOf(STEP_MAX)).concat(")");
+    private PropertyReadAccess stepAccess = null;
+    // Ressource 1: Eingabe-Raster
+    private static final String DESC1 = "Eingabe-Raster (double-Raster)";
+    private PropertyReadAccess inRasterAccess = null;
+    // Ressource 2: Ausgabe-Raster
+    private static final String DESC2 = "Ausgabe-Raster (double-Raster)";
+    private PropertyReadAccess outRasterAccess = null;
+
+    /**
+     * Erzeugt einen neuen ContentManager fuer das {@linkplain TestModel TestModel}.
+     */
+    public ContentManager() {
+      super(3);
+      // Ressource 0: Anzahl an Modellschritten
+      resource[0] = new PropertiesResource(DESC0,ScalarProperty.class,false) {
+        public void checkTypeAndError(Object data) {
+          super.checkTypeAndError(data);
+          // muss als Datentyp Long oder Integer haben
+          if ( !BaseTypeUtil.isNumeric(((ScalarProperty)data).getType()) ||
+                BaseTypeUtil.isDecimal(((ScalarProperty)data).getType()) )
+            throw new XuluDataException("Long- oder Integer-Property erforderlich fuer '".concat(this.getDesc()).concat("'"));
+        }
+        public void checkAndError(Object data) {
+          super.checkAndError(data);
+          // muss zwischen 1 und 20 liegen
+          int value = ((ScalarProperty)data).getOneTimeReadAccess().getValueAsInt();
+          if ( value < STEP_MIN ||  STEP_MAX < value )
+            throw new XuluDataException("'".concat(this.getDesc()).concat("' nicht zul�ssig!"));
+        }
+      };
+
+      // Ressource 1: Eingabe-Raster
+      resource[1] = new PropertiesResource(DESC1,ScalarProperty.class,false) {
+        public void checkTypeAndError(Object data) {
+          super.checkTypeAndError(data);
+          // muss als Datentyp ein WritableGrid haben
+          if ( !WritableGrid.class.isAssignableFrom(((ScalarProperty)data).getType()) )
+            throw new XuluDataException("WritableGrid-Property erforderlich fuer '".concat(this.getDesc()).concat("'"));
+        }
+        public void checkAndError(Object data) {
+          super.checkAndError(data);
+          // das Raster muss Double-Werte liefern
+          WritableGrid value = (WritableGrid)((ScalarProperty)data).getOneTimeReadAccess().getValue();
+          if ( value.getSampleType() != DataBuffer.TYPE_FLOAT )
+            throw new XuluDataException("Das Eingabe-Raster muss double-Werte liefern!");
+        }
+      };
+
+      // Ressource 2: Ausgabe-Raster
+      resource[2] = new PropertiesResource(DESC2,ScalarProperty.class,false) {
+        public void checkTypeAndError(Object data) {
+          super.checkTypeAndError(data);
+          // muss als Datentyp ein WritableGrid haben
+          if ( !WritableGrid.class.isAssignableFrom(((ScalarProperty)data).getType()) )
+            throw new XuluDataException("WritableGrid-Property erforderlich fuer '".concat(this.getDesc()).concat("'"));
+        }
+        public void checkAndError(Object data) {
+          super.checkAndError(data);
+          // das Raster muss Integer aufnehmen koennen
+          WritableGrid value = (WritableGrid)((ScalarProperty)data).getOneTimeReadAccess().getValue();
+          if ( value.getSampleType() != DataBuffer.TYPE_FLOAT )
+            throw new XuluDataException("Das Ausgabe-Raster muss double-Werte aufnehmen koennen!");
+        }
+      };
+    }
+
+    /**
+     * Prueft alle Modell-Ressourcen auf Korrektheit.
+     * Neben den lokalen Bedingungen an die Ressourcen (die bereits durch
+     * die Methode der Oberklasse gechecked werden), prueft diese Methode,
+     * ob das Ausgabe-Raster dieselbe Groesse hat, wie das Eingabe-Raster.
+     */
+    public void checkAndError() {
+      super.checkAndError();
+      WritableGrid in = this.getInRaster();
+      WritableGrid out = this.getOutRaster();
+      if ( in.getWidth() != out.getWidth() || in.getHeight() != out.getHeight() ) {
+        releaseInRaster();
+        releaseOutRaster();
+        throw new XuluDataException("Das Ausgabe-Raster muss dieselbe Groesse haben, wie das Eingabe-Raster");
+      }
+      releaseInRaster();
+      releaseOutRaster();
+    }
+
+    /**
+     * Liefert die Anzahl an Schritten, die das Modell laufen soll.
+     */
+    public int getStepCount() {
+      return ((ScalarProperty)resource[0].getData()).getOneTimeReadAccess().getValueAsInt();
+    }
+
+    /**
+     * Liefert das Raster, das die Modell-Ausgaben aufnimmt.
+     */
+    public WritableGrid getInRaster() {
+      releaseInRaster();
+      inRasterAccess = ((ScalarProperty)resource[1].getData()).getReadAccess(this);
+      return (WritableGrid)inRasterAccess.getValue();
+    }
+
+    /**
+     * Gibt das Leserecht auf das Eingabe-Raster wieder frei.
+     */
+    public void releaseInRaster() {
+      if ( inRasterAccess != null )
+        inRasterAccess.release();
+    }
+
+    /**
+     * Liefert das Raster, das dem Modell als Eingabe dient.
+     */
+    public WritableGrid getOutRaster() {
+      releaseOutRaster();
+      outRasterAccess = ((ScalarProperty)resource[2].getData()).getReadAccess(this);
+      return (WritableGrid)outRasterAccess.getValue();
+    }
+
+    /**
+     * Gibt das Leserecht auf das Eingabe-Raster wieder frei.
+     */
+    public void releaseOutRaster() {
+      if ( outRasterAccess != null )
+        outRasterAccess.release();
+    }
+
+  }
+}

Added: trunk/src/edu/bonn/xulu/plugin/package.html
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,5 @@
+<html>
+<body>
+	Base package for classes created by Dominik Appl
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/edu/bonn/xulu/plugin/vis/GTEditorTool.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/vis/GTEditorTool.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/vis/GTEditorTool.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,135 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.vis;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import org.geotools.feature.FeatureCollection;
+import org.geotools.map.MapLayer;
+import org.geotools.styling.Style;
+
+import schmitzm.data.property.ValueProperty;
+import schmitzm.geotools.gui.GeoMapPane;
+import schmitzm.geotools.gui.JEditorPane;
+import schmitzm.geotools.gui.LayeredEditorFrame;
+import schmitzm.geotools.gui.LayeredMapPane;
+import schmitzm.geotools.map.event.JMapPaneEvent;
+import schmitzm.geotools.map.event.JMapPaneListener;
+import schmitzm.geotools.map.event.LayerEditFinishedEvent;
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.DataPool;
+import edu.bonn.xulu.appl.XuluConstants;
+import edu.bonn.xulu.data.XuluDataException;
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.gui.XuluGUIMessages;
+import edu.bonn.xulu.io.InstantiationFactory;
+import edu.bonn.xulu.plugin.data.feature.SingleFeatureCollection;
+
+/**
+ * Diese Klasse stellt einen Editor fuer geografische Vektor-Daten dar.
+ * Neben Vektor-Daten koennen auch Raster angezeigt werden.
+ * Gesteuert wird der Editor durch eine {@linkplain MapEditorToolBar Button-Leiste}.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class GTEditorTool extends GTVisualisationTool implements JMapPaneListener {
+  /** Xulu-Instanz fuer die der Editor erstellt wurde. */ 
+  protected XuluModellingPlatform appl = null;
+  
+  /**
+   * Erstellt ein neues Tool. Erweitert das Fenster um eine Button-Leiste
+   * zur Steuerung des Editors. 
+   */
+  public GTEditorTool() {
+    super( new LayeredEditorFrame(
+                new LayeredMapPane(
+                    new GeoMapPane(
+                        new JEditorPane(),
+                        null,
+                        null,
+                        null
+                    )
+                )
+           ),
+           XuluConstants.XULU_VIS_RES.getString("GTEditorTool.FrameTitle")
+    );
+    // set listener to recognize new layers
+    ((JEditorPane)this.layeredMapPane.getMapPane()).addMapPaneListener(this);
+  }
+  
+  /**
+   * Speichert die Xulu-Instanz, um in den Datenpool die neu erstellten
+   * Objekte einzufuegen.
+   * @param appl Xulu-Instanz
+   */
+  public void initialize(XuluModellingPlatform appl) {
+    super.initialize(appl);
+    this.appl = appl;
+  }
+
+  /**
+   * Lauscht auf das {@link JEditorPane}, um nach Beendigung eines Layers,
+   * dieses in den Xulu-Datenpool einzufuegen. 
+   */
+  public void performMapPaneEvent(JMapPaneEvent e) {
+    try {
+      if ( e instanceof LayerEditFinishedEvent ) {
+        LayerEditFinishedEvent lefe   = (LayerEditFinishedEvent)e;
+        JEditorPane            editor = (JEditorPane)lefe.getSource();
+        JEditorPane.EditorMode mode   = editor.getEditorMode();
+        // neues Objekt im Xulu-Datenpool nur, wenn komplett neues Layer
+        // erstellt wurde
+        if ( JEditorPane.EditorMode.New_Point.equals(mode) ||
+             JEditorPane.EditorMode.New_Line.equals(mode) ||
+             JEditorPane.EditorMode.New_Polygon.equals(mode) )
+          createNewXuluObjectInDatapool(editor);
+      }
+    } catch (Exception err) {
+      XuluGUIMessages.showError(layeredMapPane, err);
+    }
+  }
+    
+  /**
+   * Erstellt eine {@link SingleFeatureCollection} fuer eine {@link FeatureCollection}
+   * und fuegt es in den {@linkplain DataPool Xulu-Datenpool} ein.
+   * @param name Bezeichnung fuer das neue Objekt im Datenpool
+   * @param fc   neue {@link FeatureCollection}   
+   */
+  protected void createNewXuluObjectInDatapool(JEditorPane editor) throws Exception {
+    FeatureCollection  fc    = editor.getEditorFeatureCollection();
+    MapLayer           layer = editor.getEditorLayer();
+    String             title = layer.getTitle();
+    Style              style = layer.getStyle();
+    
+    // Xulu-Objekt erstellen und mit FeatureCollection befuellen
+    InstantiationFactory fac = appl.getRegistry().getDefaultFactory( SingleFeatureCollection.class );
+    if ( fac == null )
+      throw new UnsupportedOperationException("No factory registered in XuluRegistry for type SingleFeatureCollection");
+    SingleFeatureCollection sfc = (SingleFeatureCollection)fac.newInstance(false);
+    sfc.setFeatureCollection(fc);
+    sfc.setDescription( appl.getDataPool().createUniqueDescription(title) );
+    ((ValueProperty)sfc.getProperty( SingleFeatureCollection.PROP_STYLE )).getOneTimeWriteAccess().setValue(style);
+
+    // Objekt in den Datenpool einfuegen
+    appl.getDataPool().addObject(sfc);
+    
+    // Damit Layer auf Datenpool-Aktionen (z.B. Loeschen)
+    // reagiert, muessen diverse Listener gesetzt werden
+    // -> Editor-Layer entfernen
+    // -> neues Layer als Xulu-Objekt neu in GTEditorTool
+    //    einfuegen
+    editor.getContext().removeLayer( layer );
+    this.add(sfc, sfc.getDescription());
+  }
+  
+}

Added: trunk/src/edu/bonn/xulu/plugin/vis/GTVisualisationTool.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/vis/GTVisualisationTool.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/vis/GTVisualisationTool.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,706 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.vis;
+
+import java.util.Vector;
+import java.awt.Color;
+import java.awt.Point;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+import java.awt.image.DataBufferFloat;
+import java.awt.image.ComponentSampleModel;
+import javax.media.jai.RasterFactory;
+
+import schmitzm.lang.LangUtil;
+import schmitzm.data.WritableGrid;
+import schmitzm.data.WritableGridArray;
+import schmitzm.data.property.Property;
+import schmitzm.data.property.Properties;
+import schmitzm.data.property.DynamicProperties;
+import schmitzm.data.property.ValueProperty;
+import schmitzm.data.property.ScalarProperty;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyReadAccess;
+import schmitzm.data.event.ObjectTraceable;
+import schmitzm.data.event.ObjectListener;
+import schmitzm.data.event.ObjectEvent;
+import schmitzm.data.event.ObjectChangeEvent;
+import schmitzm.data.event.NameChangeEvent;
+import schmitzm.geotools.GTUtil;
+import schmitzm.geotools.gui.LayeredMapFrame;
+import schmitzm.geotools.gui.LayeredMapPane;
+import schmitzm.geotools.grid.WritableGridCoverage;
+import schmitzm.geotools.grid.GridUtil;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.VisualisationTool;
+import edu.bonn.xulu.appl.VisualisationUpdateListener;
+import edu.bonn.xulu.data.XuluObject;
+import edu.bonn.xulu.appl.XuluConstants;
+
+import org.geotools.map.MapContext;
+import org.geotools.map.MapLayer;
+import org.geotools.coverage.grid.GridCoverageFactory;
+import org.geotools.coverage.grid.GridCoverage2D;
+import org.geotools.feature.FeatureCollection;
+import org.geotools.geometry.Envelope2D;
+import org.geotools.geometry.GeneralEnvelope;
+import org.geotools.coverage.GridSampleDimension;
+import org.geotools.coverage.Category;
+import org.geotools.styling.Style;
+
+import appl.data.DataProxy;
+import appl.data.LateLoadingProxy;
+import appl.data.LoadingException;
+
+// nur fuer Doku
+import schmitzm.data.WritableGridRaster;
+import skrueger.geotools.StyledMapStyle;
+
+/**
+ * Diese Klasse stellt ein Visualisierungstool fuer geografische Raster- und
+ * Vektor-Daten dar. Es basiert auf {@link LayeredMapFrame} und kann Layer fuer
+ * folgende Datentypen darstellen:
+ * <ul>
+ *   <li>{@link GridCoverage2D org.geotools.coverage.grid.GridCoverage2D}</li>
+ *   <li>{@link FeatureCollection org.geotools.feature.FeatureCollection}</li>
+ *   <li><u>gleichzeitig</u> {@link WritableRaster java.awt.image.WritableRaster}
+ *       und {@link WritableGrid schmitzm.data.WritableGrid} (z.B. {@link WritableGridRaster})</li>
+ *   <li>{@linkplain Property Xulu-Properties}, die einen der obigen Typen
+ *       beinhalten.</li>
+ *   <li>{@linkplain XuluObject Xulu-Objekte}, die mindestens eine Property
+ *       der obigen Typen besitzen.</li>
+ * </ul>
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class GTVisualisationTool /*extends LayeredMapFrame*/ implements VisualisationTool {
+  /** Zaehlt die Instanzen (nur fuer den Titel) */
+  protected static int instanceCount = 1;
+  /** Speichert die verteilten UpdateListener */
+  protected Vector<VisualisationUpdateListener> updateListener = new Vector<VisualisationUpdateListener>();
+  
+  /** Fenster mit Kartenbereich und Layer-Liste */
+  protected LayeredMapFrame mapFrame = null;
+  /** Kartenbereich und Layer-Liste */
+  protected LayeredMapPane  layeredMapPane = null;
+
+  /**
+   * Erzeugt ein neues <code>GTVisualisationTool</code>-Fenster.
+   */
+  protected GTVisualisationTool(LayeredMapFrame frame, String title) {
+    super();
+    this.mapFrame       = frame != null ? frame : new LayeredMapFrame();
+    this.layeredMapPane = mapFrame.getLayeredMapPane();
+    this.mapFrame.setIconImage( XuluConstants.XULU_ICON.getImage() );
+    setTitle(title+" (".concat(String.valueOf(instanceCount++)).concat(")"));
+  }
+
+  /**
+   * Erzeugt ein neues <code>GTVisualisationTool</code>-Fenster.
+   */
+  public GTVisualisationTool() {
+    this( null, XuluConstants.XULU_VIS_RES.getString("GTVisualisationTool.FrameTitle") );
+  }
+  
+  /**
+   * Macht nichts, da die Xulu-Applikation nicht fuer die Visualisierung
+   * benoetigt wird.
+   */
+  public void initialize(XuluModellingPlatform appl) {
+  }
+
+  /**
+   * Verbirgt das <code>GTVisualisationTool</code>-Fenster, entfernt alle (durch
+   * <code>UpdateListener</code>) damit verbundenen Layer und "vernichtet"
+   * anschliessend das Fenster mit {@link #dispose()}.
+   */
+  public void close() {
+    // Fenster unsichtbar machen
+    setVisible(false);
+    // Alle Layer schliessen
+    for (int i=0; i<updateListener.size(); i++)
+      ((VisualisationUpdateListener)updateListener.elementAt(i)).close();
+    // Frame "vernichten"
+    mapFrame.dispose();
+  }
+  
+  /**
+   * Zeigt oder verbirgt das Fenster.
+   */
+  public void setVisible(boolean visible) {
+    mapFrame.setVisible( visible );
+  }
+
+  /**
+   * Prueft, ob das Fenster angezeigt wird.
+   */
+  public boolean isVisible() {
+    return mapFrame.isVisible();
+  }
+  
+  /**
+   * Setzt den Titel des Fensters.
+   */
+  public void setTitle(String title) {
+    mapFrame.setTitle(title);
+  }
+
+  /**
+   * Liefert den Titel des Fensters.
+   */
+  public String getTitle() {
+    return mapFrame.getTitle();
+  }
+  
+  /**
+   * Liefert das Visualisierungsfenster.
+   */
+  public LayeredMapFrame getLayeredMapFrame() {
+    return mapFrame;
+  }
+
+  /**
+   * Prueft, ob Instanzen einer bestimmten Klasse visualisiert werden koennen.
+   * Neben den direkt von der Oberklasse {@link LayeredMapPane#isVisualisable(Class) LayeredMapPane}
+   * darstellbaren Klassen, kann das <code>GTVisualisationTool</code> Instanzen
+   * folgende Klassen visualisieren:
+   * <ul>
+   *   <li><u>gleichzeitig</u> {@link WritableRaster} und {@link WritableGrid} (z.B. {@link WritableGridRaster})</li>
+   *   <li>{@link WritableGridArray}</li>
+   * </ul>
+   */
+  public boolean isVisualisable(Class c) {
+    return layeredMapPane.isVisualisable( c ) ||
+           // Aus einem Objekt, das WritableGrid und WritableRaster implementiert
+           // kann ein GridCoverage2D erzeugt werden
+           WritableRaster.class.isAssignableFrom( c ) && WritableGrid.class.isAssignableFrom( c ) ||
+           // Aus einem Objekt, das WritableGridArray implementiert
+           // kann ein GridCoverage2D erzeugt werden
+           WritableGridArray.class.isAssignableFrom( c );
+  }
+
+  /**
+   * Ermittelt alle darstellbaren Eigenschaften eines aus Properties
+   * bestehenden Objekts.
+   */
+  private Vector<ValueProperty> determineVisualisableProperties(Properties obj) {
+    Vector visProp = new Vector<ValueProperty> ();
+    // Alle skalaren Propertys ermitteln
+    Property[] allProp = (Property[]) obj.getProperties(ScalarProperty.class).getProperties();
+    // Alle darstellbaren skalaren Propertys ermitteln
+    for (int i = 0; i < allProp.length; i++)
+      if ( /*super.*/isVisualisable( ( (ScalarProperty) allProp[i]).getOneTimeReadAccess().getValue()))
+        visProp.add(allProp[i]);
+
+    // Alle Listen ermitteln
+    allProp = (Property[]) obj.getProperties(ListProperty.class).getProperties();
+    // Alle darstellbaren Listen-Properties ermitteln
+    for (int i = 0; i < allProp.length; i++)
+// Bei Listen haengt die Darstellbarkeit vom jeweiligen Element ab. Sie kann
+// nicht ueber den allgemeinen Listen-Typ geprueft werden (z.B. Listentyp
+// WritableGrid nicht darstellbar, obwohl Instanzen von WritableGridCoverage
+// in der Liste)!
+// Deshalb wird dies erst beim Einfuegen (Layer-Erzeugen) gecheckt!
+//    if ( super.isVisualisable( ((ListProperty)allProp[i]).getPropertyType().getType() ) )
+      visProp.add(allProp[i]);
+
+    return visProp;
+  }
+
+  /**
+   * Prueft, ob ein Objekt visualisiert werden kann. Dies ist der Fall,
+   * wenn es
+   * <ul>
+   *   <li>direkt von {@link LayeredMapPane#isVisualisable(Class) LayeredMapPane}
+   *       dargestellt werden kann</li>
+   *   <li><u>gleichzeitig</u> {@link WritableRaster} und {@link WritableGrid}
+   *       implementiert (z.B. {@link WritableGridRaster})
+   *   <li>sich um ein {@link XuluObject} handelt, das mind. eine darstellbare
+   *       Property beinhaltet</li>
+   * </ul>
+   * @param obj ein Objekt
+   */
+  public boolean isVisualisable(Object obj) {
+    obj = extractRealObject(obj);
+    if ( obj==null )
+      return false;
+    if ( isVisualisable( obj.getClass() ) )
+      return true;
+    // Pruefen, ob Objekt mind. eine darstellbaren Property hat
+    if ( obj instanceof Properties )
+      return determineVisualisableProperties((Properties)obj).size() > 0;
+    return false;
+  }
+
+  /**
+   * Fuegt ein Layer (als oberstes Layer) ein. Instanzen,
+   * <ul>
+   *   <li>die <u>gleichzeitig</u> {@link WritableRaster} und {@link WritableGrid}
+   *       implementieren (z.B. {@link WritableGridRaster})</li>
+   *   <li>von {@link WritableGridArray}</li>
+   * </ul>
+   * werden umgewandelt in ein Geotools-{@link GridCoverage2D}.
+   * @param obj ein (darstellbares) Objekt
+   * @param desc Beschreibung fuer das Objekt
+   * @param style Darstellungs-Style fuer das Layer
+   * @exception UnsupportedOperationException falls ein nicht-darstellbares
+   *            Objekt uebergeben wird
+   * @see #isVisualisable(Object)
+   * @see #isVisualisable(Class)
+   */
+  protected MapLayer addLayer(Object obj, String desc, Style style) {
+    obj = extractRealObject(obj);
+    try {
+      obj = GridUtil.convertToGridCoverage2D(obj);
+    } catch ( IllegalArgumentException err ) {
+      // Objekt kann nicht in GridCoverage2D umgewandelt werden
+    }
+
+    return layeredMapPane.addLayer(obj,desc,style);
+  }
+
+  /**
+   * Visualisiert ein Objekt. Handelt es sich bei dem Objekt um ein
+   * darstellbares Xulu-Objekt mit mehreren darstellbaren Eigenschaften,
+   * wird der Beschreibung der Property-Name hinzugefuegt.
+   * @param obj  Objekt
+   * @param desc Beschreibung zu dem Objekt, die in der Layer-Uebersicht
+   *             angezeigt wird (kann <code>null</code> sein)
+   * @exception java.lang.UnsupportedOperationException falls das Objekt nicht
+   *            visualisiert werden kann
+   */
+  public boolean add(Object obj, String desc) {
+    obj = extractRealObject(obj);
+
+    VisualisationUpdateListener newListener = null;
+
+    // Style aus XuluObject ermitteln
+    Style style = determineStyleFromObject(obj);
+
+    // Objekt ist direkt visualisierbar
+    if ( layeredMapPane.isVisualisable(obj) )
+      newListener = new UpdateListener(this,obj,this.addLayer(obj,desc,style));
+    else
+      // von einem Xulu-Objekt werden alle darstellbaren Propertys dargestellt
+      // > Proxy-UpdateListener
+      if ( obj instanceof Properties ) {
+        newListener = new UpdateListenerProxy(this, obj, "");
+        ((UpdateListenerProxy)newListener).reorganize();
+      }
+    // UpdateListener der Liste hinzufuegen
+    if ( newListener != null ) {
+      updateListener.add(newListener);
+      return true;
+    }
+
+    // Objekt konnte nicht dargestellt werden
+    if ( obj==null )
+      throw new UnsupportedOperationException( getClass().getSimpleName().concat(" can not visualise null-Objects!") );
+    throw new UnsupportedOperationException( getClass().getSimpleName().concat(" can not visualise instances of ").concat(obj.getClass().getName()) );
+  }
+
+  /**
+   * Schliesst alle Visualisierungen eines Objekts.
+   * @param obj zu entfernendes Objekt
+   * @return <code>false</code> falls das Objekt nicht (mehr) visualisiert wird
+   */
+  public boolean remove(Object obj) {
+    boolean objRemoved = false;
+    for (int i=updateListener.size()-1; i>=0; i--) {
+      VisualisationUpdateListener l = (VisualisationUpdateListener)updateListener.elementAt(i);
+      if ( l.getSourceObject().equals(obj) ) {
+        l.close();
+        updateListener.remove(l);
+        objRemoved = true;
+      }
+    }
+    return objRemoved;
+  }
+
+  /**
+   * Aktualisiert alle Visualisierungen eines Objekts.
+   * @param obj zu aktualisierendes Objekt
+   * @return <code>false</code> falls das Objekt nicht (mehr) visualisiert wird
+   */
+  public boolean update(Object obj) {
+    boolean objUpdated = false;
+    for (int i=updateListener.size()-1; i>=0; i--) {
+      VisualisationUpdateListener l = updateListener.elementAt(i);
+      if ( l.getSourceObject().equals(obj) ) {
+        l.refresh();
+        objUpdated = true;
+      }
+    }
+    return objUpdated;
+  }
+
+  /**
+   * If the given Object is a is an instance of <code>DataProxy</code> then
+   * this method returns the real encapulated Object. If the Object implements
+   * late loading functionality the Object is first loaded into memory.
+   */
+  public Object extractRealObject(Object obj) {
+    if (obj != null)
+      if (obj instanceof LateLoadingProxy) {
+        LateLoadingProxy proxy = (LateLoadingProxy) obj;
+        if (!proxy.isLoaded())
+          try {
+            proxy.loadData();
+          }
+          catch (LoadingException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+          }
+      }
+    if (obj instanceof DataProxy)
+      obj = ( (DataProxy) obj).getProxiedObject();
+    return obj;
+  }
+
+  protected static Style determineStyleFromObject(Object obj) {
+    Style style = null;
+    // Style aus XuluObject ermitteln
+    if ( obj instanceof XuluObject )
+      style = determineStyleFromObject( ((XuluObject)obj).getProperty( XuluObject.PROP_STYLE ) );
+    else if ( obj instanceof ScalarProperty ) {
+      Object styleObj = ((ScalarProperty)obj).getOneTimeReadAccess().getValue();
+      if ( styleObj != null ) {
+        if ( styleObj instanceof Style )
+          style = (Style)styleObj;
+        else if ( styleObj instanceof StyledMapStyle )
+          style = ((StyledMapStyle)styleObj).getGeoObjectStyle();
+      }
+    }
+    return style;
+  }
+
+  /**
+   * Dieser UpdateListener verknuepft ein Objekt mit einem oder mehreren
+   * Layern einer {@link LayeredMapFrame}-Instanz. Er kann unmittelbar als
+   * {@link schmitzm.data.event.ObjectListener} eingesetzt werden, um
+   * mit der Objekt-Aenderung automatisch die Visualisierung zu aktualisieren.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  protected class UpdateListener extends VisualisationUpdateListener {
+    private MapLayer[] layer      = null;
+    private MapContext mapContext = null;
+
+    /**
+     * Erzeugt einen neuen <code>UpdateListener</code>.
+     * @param tool  Visualisierungstool, mit dem der Listener verbunden ist
+     * @param obj   Objekt welches visualisiert wird
+     * @param layer Layer des {@link LayeredMapFrame} in denen das Objekt dargestellt ist
+     * @deprecated Ein UpdateListener soll nur noch fuer ein einziges Layer
+     *             zustaendig sein. In einer zukuenftigen Version wird dieser
+     *             Konstruktor entfernt!!
+     */
+    public UpdateListener(GTVisualisationTool tool, Object obj, MapLayer[] layer) {
+      super(tool,obj);
+      this.layer = layer;
+      this.mapContext = tool.layeredMapPane.getMapPane().getContext();
+    }
+
+    /**
+     * Erzeugt einen neuen <code>UpdateListener</code>.
+     * @param tool  Visualisierungstool, mit dem der Listener verbunden ist
+     * @param obj   Objekt welches visualisiert wird
+     * @param layer Layer des {@link LayeredMapFrame} in dem das Objekt dargestellt ist
+     */
+    public UpdateListener(GTVisualisationTool tool, Object obj, MapLayer layer) {
+      this(tool,obj,new MapLayer[] {layer});
+    }
+
+    /**
+     * Entfernt alle Layer, die zum Objekts gehoeren aus dem {@link LayeredMapFrame}.
+     */
+    public void close() {
+      for (int i=0; i<layer.length; i++)
+        // Layer kann schon nicht mehr existieren, wenn es bereits manuell
+        // geschlossen wurde!
+        if (layer[i] != null)
+          mapContext.removeLayer(layer[i]);
+      ((GTVisualisationTool)this.visTool).layeredMapPane.getMapPane().refresh();
+    }
+
+    /**
+     * Aktualisiert alle Layer im {@link LayeredMapFrame}.
+     */
+    public void refresh() {
+      // Aktualierung eines einzelnen Layers nicht moeglich
+      // --> alle Layer aktualisieren
+      ((GTVisualisationTool)this.visTool).layeredMapPane.getMapPane().refresh();
+
+//      for (int i=0; i<layer.length; i++)
+//        // Layer kann schon nicht mehr existieren, wenn es bereits manuell
+//        // geschlossen wurde!
+//        if (layer[i] != null) {
+//          // Update eines einzelnen Layers hier implementierten
+//        }
+    }
+  }
+
+
+  /**
+   * Dieser UpdateListener verknuepft ein Objekt mit einem oder mehreren
+   * anderen UpdateListenern und alle alle Funktionsaufrufe an diese weiter.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  protected class UpdateListenerProxy extends VisualisationUpdateListener {
+    private Vector<VisualisationUpdateListener> listener = null;
+    private String                              desc     = "";
+    private Style                               style    = null;
+    private boolean                             visObjectStructureChanged = true;
+    private ObjectListener                      objectListener = new ObjectListener() {
+      public void performObjectEvent(ObjectEvent e) {
+        if ( !(e instanceof NameChangeEvent) )
+          visObjectStructureChanged = true;
+      }
+    };
+
+    /**
+     * Erzeugt einen neuen <code>UpdateListenerProxy</code>, dem noch keine
+     * Listener zugeordnet sind.
+     * @param tool     Visualisierungstool, mit dem der Listener verbunden ist
+     * @param obj      Objekt welches visualisiert wird
+     * @param desc     Beschreibung fuer das Objekt (wird fuer die Bezeichnung
+     *                 des Layers benoetigt)
+     * @param style    Darstellungsstyle fuer neue Layer (wenn {@code null}, wird
+     *                 versucht, den Style aus dem Object (z.B. {@link XuluObject})
+     *                 zu ermitteln
+     */
+    public UpdateListenerProxy(GTVisualisationTool tool, Object obj, String desc, Style style) {
+      super(tool,obj);
+      this.listener = new Vector<VisualisationUpdateListener>();
+      this.desc     = desc;
+      // wenn kein Style angegeben wurde, versuchen, diesen aus dem Objekt
+      // zu ermitteln
+      if ( style == null )
+        style = determineStyleFromObject(obj);
+      this.style = style;
+    }
+
+    /**
+     * Erzeugt einen neuen <code>UpdateListenerProxy</code>, dem noch keine
+     * Listener zugeordnet sind. Der Style wird - sofern moeglich - aus dem Objekt
+     * (z.B. {@link XuluObject}) ermittelt.
+     * @param tool     Visualisierungstool, mit dem der Listener verbunden ist
+     * @param obj      Objekt welches visualisiert wird
+     * @param desc     Beschreibung fuer das Objekt (wird fuer die Bezeichnung
+     *                 des Layers benoetigt)
+     */
+    public UpdateListenerProxy(GTVisualisationTool tool, Object obj, String desc) {
+      this(tool, obj, desc, (Style)null);
+    }
+
+    /**
+     * Erzeugt einen neuen <code>UpdateListenerProxy</code>.
+     * @param tool     Visualisierungstool, mit dem der Listener verbunden ist
+     * @param obj      Objekt welches visualisiert wird
+     * @param desc     Beschreibung fuer das Objekt (wird fuer die Bezeichnung
+     *                 des Layers benoetigt)
+     * @param style    Darstellungsstyle fuer neue Layer (wenn {@code null}, wird
+     *                 versucht, den Style aus dem Object (z.B. {@link XuluObject})
+     *                 zu ermitteln
+     * @param listener anderer VisualisationUpdateListener an den die Ereignisse
+     *                 weitergegeben werden
+     */
+    public UpdateListenerProxy(GTVisualisationTool tool, Object obj, String desc, Style style, VisualisationUpdateListener listener) {
+      this(tool,obj,desc,style);
+      add( listener );
+    }
+
+    /**
+     * Erzeugt einen neuen <code>UpdateListenerProxy</code>. Der Style wird - sofern
+     * moeglich - aus dem Objekt (z.B. {@link XuluObject}) ermittelt.
+     * @param tool     Visualisierungstool, mit dem der Listener verbunden ist
+     * @param obj      Objekt welches visualisiert wird
+     * @param desc     Beschreibung fuer das Objekt (wird fuer die Bezeichnung
+     *                 des Layers benoetigt)
+     * @param listener anderer VisualisationUpdateListener an den die Ereignisse
+     *                 weitergegeben werden
+     */
+    public UpdateListenerProxy(GTVisualisationTool tool, Object obj, String desc, VisualisationUpdateListener listener) {
+      this(tool, obj,desc, null, listener);
+    }
+    /**
+     * Liefert die Anzahl der im Proxy enthaltenen Listener.
+     */
+    public int getSize() {
+      return this.listener.size();
+    }
+
+    /**
+     * Fuegt dem Proxy einen UpdateListener hinzu.
+     * @param l neuer UpdateListener
+     */
+    public void add(VisualisationUpdateListener l) {
+      this.listener.add( l );
+    }
+
+    /**
+     * Entfernt einen UpdateListener hinzu vom Proxy.
+     * @param l neuer UpdateListener
+     */
+    public void remove(VisualisationUpdateListener l) {
+      this.listener.remove( l );
+    }
+
+    /**
+     * Entfernt einen UpdateListener hinzu vom Proxy.
+     * @param i Index des zu entfernenden UpdateListener
+     * @return den entfernten UpdateListener
+     */
+    public VisualisationUpdateListener remove(int i) {
+      return this.listener.remove( i );
+    }
+
+    /**
+     * Ruft {@code close()} fuer alle Listener des Proxy auf.
+     */
+    public void close() {
+      for (int i=0; i<listener.size(); i++) {
+        VisualisationUpdateListener l = listener.elementAt(i);
+        // Listener kann schon nicht mehr existieren
+        if (l != null)
+          l.close();
+      }
+    }
+
+    /**
+     * Reorganisiert die Listener. Wenn sich die Struktur des Basis-Objekts
+     * geaendert hat (z.B. wenn einem Xulu-Objekt eine visualisierbare Property
+     * hinzugefuegt wurde), werden entsprechende Listener hinzugefuegt.
+     */
+    public void reorganize() {
+      // Flag zuruecksetzen, da Struktur nun aktualisiert wird
+      visObjectStructureChanged = false;
+
+      // falls es sich bei dem dargestellten Objekt um ein ObjectTraceable
+      // handelt, wird ein Listener hinzugefuegt, damit Wert-Aenderungen
+      // gemeldet werden
+      if ( this.visObject instanceof ObjectTraceable && !((ObjectTraceable)visObject).containsObjectListener(objectListener) )
+        ((ObjectTraceable)visObject).addObjectListener(objectListener);
+
+      // ListenerProxy fuer eine ScalarProperty erzeugen
+      if ( this.visObject instanceof ScalarProperty ) {
+        ScalarProperty propObj = (ScalarProperty)this.visObject;
+        Object         obj     = propObj.getOneTimeReadAccess().getValue();
+        // Wenn Inhalt der ScalarProperty nun ein anderer, bisheriges Layer
+        // ersetzen
+        if ( listener.size() == 1 && listener.firstElement().getSourceObject() != obj ) {
+          listener.firstElement().close();
+          listener.clear();
+        }
+        // Listener erzeugen, wenn noch kein Listener (mehr) fuer den Inhalt der
+        // ScalarProperty vorhanden
+        if ( listener.isEmpty() ) {
+          UpdateListenerProxy l = new UpdateListenerProxy((GTVisualisationTool)visTool, obj, desc, style);
+          l.reorganize();
+          listener.add( l );
+        }
+        return;
+      }
+
+      // ListenerProxy fuer die Elemente eine ListProperty erzeugen
+      if ( this.visObject instanceof ListProperty) {
+        ListProperty propObj = (ListProperty)this.visObject;
+        ListPropertyReadAccess listAccess = propObj.getReadAccess(this);
+        Vector listObjects = new Vector();
+        for (int j = 0; j < listAccess.getCount(); j++) {
+          Object listObject = listAccess.getValue(j);
+          // Darstellbarkeit des Listenelements checken
+          if (visTool.isVisualisable(listObject))
+            listObjects.add(listObject);
+        }
+
+        // Pruefen, ob darstellbare Objekte hinzugekommen ist
+        // --> aus 'listObjects' alle Objekte loeschen, fuer die bereits ein
+        //     Listener besteht
+        for (int i = 0; i < listener.size(); i++)
+          while (listObjects.remove(listener.elementAt(i).getSourceObject()));
+
+        // Fuer alle neuen (uebriggebliebenen) Objekte ein neues
+        // Listener-Element hinzufuegen
+        for (int i = 0; i < listObjects.size(); i++) {
+          Object listObject = listObjects.elementAt(i);
+          // Der Beschreibung den Listen-Index hinzufuegen
+          String layerDesc = desc.trim() + "[" + listAccess.indexOf(listObject) + "]";
+          UpdateListenerProxy l = new UpdateListenerProxy((GTVisualisationTool)this.visTool, listObject, layerDesc, style);
+          listener.add(l);
+          l.reorganize();
+        }
+        listAccess.release();
+        return;
+      }
+
+      // von einem Xulu-Objekt werden alle darstellbaren Propertys dargestellt
+      if ( this.visObject instanceof Properties ) {
+        Properties propObj = (Properties)this.visObject;
+
+        // wenn keine Beschreibung angegeben wurde, wird die
+        // Objekt-Beschreibung genommen
+        if ( (desc == null || desc.trim().equals("")) && propObj instanceof XuluObject)
+          desc = ((XuluObject)propObj).getDescription();
+        // alle visualisierbaren Propertys ermitteln
+        Vector<ValueProperty> prop = ((GTVisualisationTool)visTool).determineVisualisableProperties(propObj);
+
+        // Pruefen, ob darstellbare Property hinzugekommen ist
+        // --> aus 'prop' alle Properies loeschen, fuer die bereits ein
+        //     Listener besteht
+        for (int i=0; i < listener.size(); i++)
+          while ( prop.remove( listener.elementAt(i).getSourceObject() ) );
+
+        // Fuer alle neuen (uebriggebliebenen) Properties ein neues
+        // Listener-Element hinzufuegen
+        for (int i=0; i<prop.size(); i++) {
+          Property p = prop.elementAt(i);
+          // Der Beschreibung den Property-Namen hinzufuegen
+          String layerDesc = desc.trim() + "." + p.getName().trim();
+          UpdateListenerProxy l = new UpdateListenerProxy((GTVisualisationTool)this.visTool, prop.elementAt(i), layerDesc, style);
+          listener.add( l );
+          l.reorganize();
+        }
+        return;
+      }
+
+      // fuer alle anderen Objekte einen "normalen" Listener und ein Layer
+      // in der Map erzeugen
+      if ( listener.isEmpty() ) {
+        MapLayer layer = ((GTVisualisationTool)visTool).addLayer(visObject,desc,style);
+        UpdateListener l = new UpdateListener((GTVisualisationTool)visTool, visObject, layer);
+        listener.add( l );
+      }
+    }
+
+
+    /**
+     * Ruft {@code refresh()} fuer alle Listener des Proxy auf.
+     */
+    public void refresh() {
+      // nur wenn sich die Struktur des Basis-Objekts geaendert hat, wird
+      // die Listener-Struktur aktualisiert
+      if ( visObjectStructureChanged )
+        reorganize();
+
+      for (int i=0; i<listener.size(); i++) {
+        VisualisationUpdateListener l = listener.elementAt(i);
+        // Listener kann schon nicht mehr existieren
+        if (l != null)
+          l.refresh();
+      }
+    }
+  }
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/vis/JFreeChartVisualisationTool.java
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/vis/JFreeChartVisualisationTool.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/vis/JFreeChartVisualisationTool.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,778 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package edu.bonn.xulu.plugin.vis;
+
+import java.awt.Dimension;
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.FlowLayout;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import javax.swing.JMenuItem;
+import javax.swing.JFrame;
+import javax.swing.JToggleButton;
+import javax.swing.AbstractAction;
+import javax.swing.AbstractButton;
+import java.util.Vector;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.jfree.data.xy.XYSeries;
+import org.jfree.data.xy.DefaultTableXYDataset;
+import org.jfree.chart.ChartPanel;
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.chart.renderer.xy.XYAreaRenderer;
+import org.jfree.chart.renderer.xy.XYItemRenderer;
+import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
+import org.jfree.chart.renderer.xy.XYBarRenderer;
+import org.jfree.chart.plot.DefaultDrawingSupplier;
+import org.jfree.chart.labels.StandardXYToolTipGenerator;
+import org.jfree.chart.urls.StandardXYURLGenerator;
+import org.jfree.chart.plot.XYPlot;
+
+import org.apache.log4j.Logger;
+
+import schmitzm.swing.JPanel;
+import schmitzm.swing.ButtonGroup;
+import schmitzm.swing.table.MutableTable;
+import schmitzm.swing.table.AbstractMutableTableModel;
+import schmitzm.data.property.Property;
+import schmitzm.data.property.ValueProperty;
+import schmitzm.data.property.ListProperty;
+import schmitzm.data.property.ListPropertyReadAccess;
+import schmitzm.data.property.MatrixProperty;
+import schmitzm.data.property.PropertyReadAccess;
+
+import adagios.swing.MultiSplitPane;
+
+import edu.bonn.xulu.XuluModellingPlatform;
+import edu.bonn.xulu.appl.VisualisationTool;
+import edu.bonn.xulu.appl.VisualisationUpdateListener;
+import edu.bonn.xulu.appl.XuluConstants;
+
+import static schmitzm.jfree.JFreeChartUtil.RESOURCE;
+import static edu.bonn.xulu.appl.XuluConstants.XULU_VIS_RES;
+
+// nur fuer Doku
+
+
+
+
+
+/**
+ * Diese Klasse stellt ein Visualisierungstool dar, in dem Zahlenreihen in Form
+ * von Charts angezeigt werden koennen. Folgende Datentypen werden unterstuetzt:
+ * <ul>
+ *   <li></li>
+ * </ul>
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public class JFreeChartVisualisationTool extends JFrame implements VisualisationTool {
+  private static final Logger LOGGER = Logger.getLogger(JFreeChartVisualisationTool.class.getSimpleName());
+
+  /** Zaehlt die Instanzen (nur fuer den Titel) */
+  private static int instanceCount = 1;
+  /** Speichert die verteilten UpdateListener */
+  protected Vector<VisualisationUpdateListener> updateListener = new Vector<VisualisationUpdateListener>();
+
+  protected XYItemRenderer  AREA_RENDERER  = new XYAreaRenderer(XYAreaRenderer.AREA);
+  protected XYItemRenderer  LINE_RENDERER  = new XYLineAndShapeRenderer(true,false); //new XYAreaRenderer(XYAreaRenderer.SHAPES_AND_LINES);
+  protected XYItemRenderer  BAR_RENDERER   = new XYBarRenderer(0.5d);
+  protected XYItemRenderer  POINT_RENDERER = new XYLineAndShapeRenderer(false,true); //new XYAreaRenderer(XYAreaRenderer.SHAPES);
+
+  /** Speichert das Panel, in dem die einzelnen Charts angezeigt werden. */
+  protected ChartPanel chartPanel = null;
+  /** Enthaelt die im Diagramm angezeigten Daten. */
+//  protected DefaultCategoryDataset dataSet = null;
+  protected DefaultTableXYDataset dataSet = null;
+  /** Enthaelt den {@link Plot} des {@linkplain JFreeChart Chart}. */
+  protected XYPlot chartPlot = null;
+
+  /** Button um das Chart als Punkt-Diagramm einzustellen. */
+  protected JToggleButton pointButton = null;
+  /** Button um das Chart als Linien-Diagramm einzustellen. */
+  protected JToggleButton lineButton  = null;
+  /** Button um das Chart als Balken-Diagramm einzustellen. */
+  protected JToggleButton barButton   = null;
+  /** Button um das Chart als Flaechen-Diagramm einzustellen. */
+  protected JToggleButton areaButton   = null;
+  /** Speichert das Panel, in dem die Button angezeigt werden, mit denen
+   *  zwischen den verschiedenen Styles gewechselt werden kann. */
+  protected JPanel buttonPanel = null;
+  /** Buttongroup, die Steuert, das im {@link buttonPanel} immer nur ein
+   *  Toggle-Button aktiviert ist */
+  protected ButtonGroup buttonGroup = null;
+  /** Tabelle, in der die Datenobjekte angezeigt werden. */
+  protected MutableTable objectTable = null;
+  /** Split-Pane, in dem Daten-Liste und Chart angezeigt werden. */
+  protected MultiSplitPane horSplitPane = null;
+
+  /**
+   * Erzeugt ein neues {@code JFreeChartVisualisationTool}-Fenster.
+   */
+  public JFreeChartVisualisationTool() {
+    super();
+    this.setIconImage( XuluConstants.XULU_ICON.getImage() );
+    this.setTitle(XULU_VIS_RES.getString("JFreeChartVisualiationTool.FrameTitle").concat(" (").concat(String.valueOf(instanceCount++)).concat(")"));
+
+    // Panel, in dem die Charts angezeigt werden
+    this.chartPanel = new ChartPanel(null);
+
+//    this.dataSet    = new DefaultCategoryDataset();
+    this.dataSet    = new DefaultTableXYDataset();
+
+    // Button, mit denen zwischen den Anzeigeformen gewechselt werden kann
+    this.buttonPanel = new JPanel();
+    this.buttonPanel.setLayout( new FlowLayout(FlowLayout.CENTER, 5, 5) );
+    this.buttonGroup = new ButtonGroup();
+    this.pointButton = createButton( RESOURCE.getString("diagram.points") );
+    this.lineButton  = createButton( RESOURCE.getString("diagram.lines") );
+    this.barButton   = createButton( RESOURCE.getString("diagram.bars") );
+    this.areaButton  = createButton( RESOURCE.getString("diagram.areas") );
+    this.pointButton.setSelected(true);
+    // Tabelle, in der die Chart-Datensaetze angezeigt werden
+    this.objectTable = new MutableTable( new ChartDataTableModel(), MutableTable.ITEM_REMOVE ) {
+      public PopupMenu createPopupMenu(int mask) {
+        PopupMenu menu = super.createPopupMenu(mask);
+        JMenuItem rotateItem = new JMenuItem( XULU_VIS_RES.getString("JFreeChartVisualiationTool.RotateData") );
+        rotateItem.addActionListener( new ActionListener() {
+          public void actionPerformed(ActionEvent e) {
+            performChartDataRotation();
+          }
+        });
+        menu.add( rotateItem );
+        return menu;
+      }
+    };
+    this.objectTable.setTableHeader(null);
+
+    // GUI zusammensetzen
+    this.horSplitPane = new MultiSplitPane(2,MultiSplitPane.HORIZONTAL_SPLIT);
+    this.horSplitPane.setResizeWeigth( new double[] {0.2,0.8} );
+    this.horSplitPane.setDividerSize(5);
+    this.horSplitPane.setInnerBorder(null);
+    this.horSplitPane.getContainer(0).add(objectTable.createScrollPane(),BorderLayout.CENTER);
+    this.horSplitPane.getContainer(1).add(chartPanel);
+
+    this.setPreferredSize( new Dimension(600,400) );
+
+    Container contentPane = this.getContentPane();
+    contentPane.setLayout( new BorderLayout() );
+    contentPane.add(horSplitPane, BorderLayout.CENTER);
+    contentPane.add(buttonPanel, BorderLayout.SOUTH);
+    pack();
+    checkChartPlotExists();
+  }
+
+  private JToggleButton createButton(String caption) {
+    JToggleButton button = new JToggleButton( new StyleButtonAction(caption) );
+    this.buttonPanel.add(button);
+    this.buttonGroup.add(button);
+
+    return button;
+  }
+
+  /**
+   * Macht nichts, da die Xulu-Applikation nicht fuer die Visualisierung
+   * benoetigt wird.
+   */
+  public void initialize(XuluModellingPlatform appl) {
+  }
+
+  /**
+   * Verbirgt das {@code JFreeChartVisualisationTool}-Fenster, entfernt alle (durch
+   * {@code UpdateListener}) damit verbundenen Charts und "vernichtet"
+   * anschliessend das Fenster mit {@link #dispose()}.
+   */
+  public void close() {
+    // Fenster unsichtbar machen
+    setVisible(false);
+    // Alle Layer schliessen
+    for (int i=0; i<updateListener.size(); i++)
+      ((VisualisationUpdateListener)updateListener.elementAt(i)).close();
+    // Frame "vernichten"
+    dispose();
+  }
+
+  /**
+   * Setzt den Titel des Fensters und des Charts.
+   * @param title neue Bezeichnung
+   */
+  public void setTitle(String title) {
+    super.setTitle(title);
+    if ( chartPanel != null && chartPanel.getChart() != null )
+      chartPanel.getChart().setTitle(title);
+  }
+
+  /**
+   * Prueft, ob Instanzen einer bestimmten Klasse visualisiert werden koennen.
+   * {@code JFreeChartVisualisationTool} kann Instanzen folgende Klassen
+   * darstellen:
+   * <ul>
+   *   <li>{@link ListProperty} mit {@linkplain Number numerischen} Elementen</li>
+   *   <li>{@link MatrixProperty} mit {@linkplain Number numerischen} Elementen</li>
+   * </ul>
+   */
+  public boolean isVisualisable(Class c) {
+    return ListProperty.class.isAssignableFrom( c ) ||
+           MatrixProperty.class.isAssignableFrom( c );
+  }
+
+  /**
+   * Prueft, ob ein Objekt visualisiert werden kann.
+   * {@code JFreeChartVisualisationTool} kann folgende Objekt-Instanzen darstellen:
+   * <ul>
+   *   <li>{@link ListProperty} mit {@linkplain Number numerischen} Elementen</li>
+   *   <li>{@link MatrixProperty} mit {@linkplain Number numerischen} Elementen</li>
+   * </ul>
+   * @param obj ein Objekt
+   */
+  public boolean isVisualisable(Object obj) {
+    if ( obj==null )
+      return false;
+    if ( !isVisualisable( obj.getClass() ) )
+      return false;
+
+    // Pruefen, ob ValueProperty mit numerischem Inhalt
+    if ( !(obj instanceof ValueProperty) ||
+         !Number.class.isAssignableFrom( ((ValueProperty)obj).getType() ) )
+      return false;
+
+    // Wenn ListProperty, dann darstellbar
+    if ( obj instanceof ListProperty )
+      return true;
+    // Wenn MatrixProperty, dann darf diese maximal 2-dimensional sein
+    if ( obj instanceof MatrixProperty )
+      return ((MatrixProperty)obj).getDimension() <= 2;
+
+    return false;
+  }
+
+  /**
+   * Visualisiert ein Objekt.
+   * @param obj  Objekt
+   * @param desc Beschreibung zu dem Objekt, die in der Layer-Uebersicht
+   *             angezeigt wird (kann <code>null</code> sein)
+   * @exception java.lang.UnsupportedOperationException falls das Objekt nicht
+   *            visualisiert werden kann
+   * @return immer {@code true}
+   */
+  public boolean add(Object obj, String desc) {
+    // Pruefen, ob Objekt dargestellt werden kann
+    if ( !isVisualisable(obj) )
+      if ( obj==null )
+        throw new UnsupportedOperationException( getClass().getSimpleName().concat(" can not visualise null-Objects!") );
+      else
+        throw new UnsupportedOperationException( getClass().getSimpleName().concat(" can not visualise instances of ").concat(obj.getClass().getName()) );
+
+    VisualisationUpdateListener newListener = null;
+    if ( obj instanceof ListProperty )
+      newListener = new ListPropertyUpdateListener(this, (ListProperty)obj);
+    else if ( obj instanceof MatrixProperty )
+      newListener = new MatrixPropertyUpdateListener(this, (MatrixProperty)obj);
+    else
+      // Kann eigentlich nicht vorkommen!
+      throw new UnsupportedOperationException( getClass().getSimpleName().concat(" can not visualise instances of ").concat(obj.getClass().getName()) );
+    updateListener.add(newListener);
+    newListener.refresh();
+    ((ChartDataTableModel)objectTable.getModel()).fireTableDataChanged();
+    return true;
+  }
+
+  /**
+   * Schliesst alle Darstellungen eines Objekts.
+   * @param obj zu entfernendes Objekt
+   * @return <code>false</code> falls das Objekt nicht (mehr) visualisiert wird
+   */
+  public boolean remove(Object obj) {
+    boolean objRemoved = false;
+    for (int i=updateListener.size()-1; i>=0; i--) {
+      VisualisationUpdateListener l = (VisualisationUpdateListener)updateListener.elementAt(i);
+      if ( l.getSourceObject().equals(obj) ) {
+        l.close();
+        updateListener.remove(l);
+        objRemoved = true;
+      }
+    }
+    if ( objRemoved )
+      ((ChartDataTableModel)objectTable.getModel()).fireTableDataChanged();
+
+    return objRemoved;
+  }
+
+  /**
+   * Aktualisiert alle Visualisierungen eines Objekts.
+   * @param obj zu aktualisierendes Objekt
+   * @return <code>false</code> falls das Objekt nicht (mehr) visualisiert wird
+   */
+  public boolean update(Object obj) {
+    boolean objUpdated = false;
+    for (int i=updateListener.size()-1; i>=0; i--) {
+      VisualisationUpdateListener l = updateListener.elementAt(i);
+      if ( l.getSourceObject().equals(obj) ) {
+        l.refresh();
+        objUpdated = true;
+      }
+    }
+    return objUpdated;
+  }
+
+  /**
+   * Prueft, ob das ChartPanel bereits einen Plot besitzt. Wenn nicht,
+   * wird ein Standard-Chart (ohne Daten) generiert.
+   */
+  private void checkChartPlotExists() {
+    if ( chartPlot == null ) {
+        // Standard-Chart verwenden (ohne Daten)
+        this.chartPanel.setChart(
+          ChartFactory.createScatterPlot(
+            this.getTitle(),
+            "",
+            "",
+            null,
+            PlotOrientation.VERTICAL,
+            true, // legend
+            true, // tooltips
+            true  // URL
+          )
+        );
+        this.chartPlot = chartPanel.getChart().getXYPlot();
+    }
+  }
+
+  /**
+   * Aktualisiert die Datenbasis des Charts, so dass die Auswirkung
+   * geaenderter oder neuer Daten sichtbar wird.
+   */
+  protected void updateChartData() {
+//    checkChartPlotExists();
+    chartPlot.setDataset( dataSet );
+  }
+
+  /**
+   * Aktualisiert das Chart-Layout gemaess des in der GUI ausgewaehlten
+   * Chart-Typ.
+   */
+  protected void updateChartType() {
+//    checkChartPlotExists();
+    if ( buttonGroup.getSelectedButton() == null )
+      pointButton.setSelected(true);
+    AbstractButton button = buttonGroup.getSelectedButton();
+
+    XYItemRenderer newRenderer = null;
+    if ( button == pointButton )
+      newRenderer = POINT_RENDERER;
+    // Linien-Diagramm
+    if ( button == lineButton )
+      newRenderer = LINE_RENDERER;
+    // Balken-Diagramm
+    if ( button == barButton )
+      newRenderer = BAR_RENDERER;
+    // Flaechen-Diagramm
+    if ( button == areaButton )
+      newRenderer = AREA_RENDERER;
+
+    if ( newRenderer != null ) {
+      newRenderer.setBaseToolTipGenerator( new StandardXYToolTipGenerator() );
+      newRenderer.setURLGenerator( new StandardXYURLGenerator() );
+      chartPlot.setDrawingSupplier( new DefaultDrawingSupplier() );
+      chartPlot.setRenderer(newRenderer);
+    }
+  }
+
+  private void performChartDataRotation() {
+    int selRow[] = objectTable.getSelectedRows();
+    for (int r=selRow.length-1; r>=0; r--)
+      ((UpdateListener)updateListener.elementAt(r)).rotateVisualisationObject();
+  }
+
+//  /**
+//   * Erzeugt eine neues Chart aus dem {@link #dataSet}.
+//   */
+//  protected JFreeChart createChart() {
+//    if ( buttonGroup.getSelectedButton() == null )
+//      pointButton.setSelected(true);
+//    AbstractButton button = buttonGroup.getSelectedButton();
+//
+//    // Punkt-Diagramm
+//    if ( button == pointButton )
+//      return ChartFactory.createScatterPlot(
+//        this.getTitle(),
+//        "",
+//        "",
+//        dataSet,
+//        PlotOrientation.VERTICAL,
+//        true, // legend
+//        true, // tooltips
+//        true  // URL
+//      );
+//    // Linien-Diagramm
+//    if ( button == lineButton )
+//      return ChartFactory.createXYLineChart(
+//        this.getTitle(),
+//        "",
+//        "",
+//        dataSet,
+//        PlotOrientation.VERTICAL,
+//        true, // legend
+//        true, // tooltips
+//        true  // URL
+//      );
+//    // Balken-Diagramm
+//    if ( button == barButton )
+//      return ChartFactory.createXYBarChart(
+//        this.getTitle(),
+//        "",
+//        false,
+//        "",
+//        new XYBarDataset( (XYDataset)dataSet, 0.5d),
+////        (IntervalXYDataset)(dataSet instanceof TableXYDataset ? (TableXYDataset)dataSet : new XYBarDataset( (XYDataset) dataSet, 0.5d)),
+////        dataSet,
+//        PlotOrientation.VERTICAL,
+//        true, // legend
+//        true, // tooltips
+//        true // URL
+//      );
+//    // Flaechen-Diagramm
+//    if ( button == areaButton )
+//      return ChartFactory.createXYAreaChart(
+//        this.getTitle(),
+//        "",
+//        "",
+//        dataSet,
+//        PlotOrientation.VERTICAL,
+//        true, // legend
+//        true, // tooltips
+//        true // URL
+//      );
+//
+//
+//    return null;
+//  }
+
+  /**
+   * Diese Klasse stellt die Aktion fuer alle Style-Button des
+   * {@link JFreeChartVisualisationTool} dar.
+   * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  protected class StyleButtonAction extends AbstractAction {
+
+    /**
+     * Erzeugt einen neue Aktion
+     */
+    public StyleButtonAction(String caption) {
+      super();
+//      Icon icon = SwingUtil.createImageIconFromResourcePath("resource/icons/small/info.gif","Info");
+//      this.putValue( SHORT_DESCRIPTION, ... );
+//      this.putValue( SMALL_ICON, ... );
+//      if ( icon == null )
+      this.putValue( NAME, caption );
+    }
+
+    /**
+     * Fuehrt die Style-Aktion aus. Fuehrt {@link updateChart()} aus.
+     * @param e das ActionEvent
+     */
+    public void actionPerformed(ActionEvent e) {
+      updateChartType();
+    }
+  }
+
+  /**
+   * Daten-Modell fuer die im Chart dargestellten Objekte. Dieses enthaelt
+   * nur eine Spalte in der die Bezeichnung des jeweiligen Objekts angezeigt
+   * wird.
+   * @see {@link UpdateListener#getObjectDesc()}
+   * @author <a href="mailto:Martin.Schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  protected class ChartDataTableModel extends AbstractMutableTableModel {
+    /**
+     * Erzeugt ein neues Tabellen-Modell.
+     */
+    public ChartDataTableModel() {
+      super();
+    }
+
+    /**
+     * Liefert die Spaltennamen der Tabelle.
+     */
+    @Override
+    public String[] createColumnNames() {
+      return new String[] {XULU_VIS_RES.getString("JFreeChartVisualiationTool.ChartObjects")};
+    }
+    
+    /**
+     * Liefert die Anzahl an Zeilen, also die Anzahl an visualisierten
+     * Datenobjekten.
+     */
+    public int getRowCount() {
+      return updateListener.size();
+    }
+
+    /**
+     * Liefert die Objekt-Beschreibung des jeweiligen {@link UpdateListener}
+     * @param row Zeilenindex (beginnend bei 0)
+     * @param col Spaltenindex (beginnend bei 0, wird nicht verwendet)
+     */
+    public Object getValueAt(int row, int col) {
+      return ((UpdateListener)updateListener.elementAt(row)).getObjectDesc();
+    }
+
+    /**
+     * Entfernt ein Datenobjekt aus dem Chart.
+     * @see UpdateListener#close()
+     * @param row Zeilenindex (beginnend bei 0)
+     */
+    public void performRemoveRow(int row) {
+      updateListener.elementAt(row).close();
+      updateListener.remove(row);
+    }
+
+    /**
+     * Macht nichts, da die Eintraege in der Chart-Datentabelle nicht
+     * veraendert werden koennen.
+     * @param row Zeilenindex (beginnend bei 0)
+     * @param col Spaltenindex (beginnend bei 0)
+     */
+    public void performChangeData(int row, int col) {
+    }
+
+    /**
+     * Macht nichts, da (manuell) keine Eintraege in der Chart-Datentabelle
+     * eingefuegt werden koennen.
+     */
+    public void performAddRow() {
+    }
+  }
+
+  /**
+   * Dieser UpdateListener verknuepft ein Objekt mit einem oder mehreren
+   * Charts in einer {@link JFreeChartVisualisationTool}-Instanz. Er kann unmittelbar als
+   * {@link schmitzm.data.event.ObjectListener} eingesetzt werden, um
+   * mit der Objekt-Aenderung automatisch die Visualisierung zu aktualisieren.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  protected abstract class UpdateListener extends VisualisationUpdateListener {
+    /** Enthaelt alle Daten-Serien, die zu dem Objekt gehoeren. */
+    protected Set<XYSeries> objectSeries = new HashSet<XYSeries>();
+
+    /**
+     * Erzeugt einen neuen <code>UpdateListener</code>.
+     * @param tool  Visualisierungstool, mit dem der Listener verbunden ist
+     * @param obj   Objekt welches visualisiert wird
+     * @param chart Chart in dem das Objekt dargestellt ist
+     */
+    public UpdateListener(JFreeChartVisualisationTool tool, Object obj) {
+      super(tool,obj);
+    }
+
+    /**
+     * Liefert eine Beschreibung des visualisierten Objekts.
+     */
+    public abstract String getObjectDesc();
+
+    /**
+     * Entfernt das Charts, das zum Objekt gehoert aus dem {@link JFreeChartVisualisationTool}.
+     */
+    public void close() {
+      // Die alten Daten aus dem DataSet entfernen
+      removeVisualisationObjectFromDataSet();
+      // Chart aktualisieren
+      updateChartData();
+    }
+
+    /**
+     * Aktualisiert das Chart im {@link JFreeChartVisualisationTool}.
+     */
+    public void refresh() {
+      // Die alten Daten aus dem DataSet entfernen
+      removeVisualisationObjectFromDataSet();
+      // Die Daten des Objekts neu im DataSet einfuegen
+      putVisualisationObjectToDataSet();
+      // Chart aktualisieren
+      updateChartData();
+    }
+
+    /**
+     * Erzeugt eine {@link XYSeries} fuer die Werte einer Liste und
+     * fuegt die Series dem DataSet des {@link JFreeChartVisualisationTool}
+     * hinzu.
+     * @param listProp eine Liste von Werten
+     */
+    protected abstract void putVisualisationObjectToDataSet();
+
+    /**
+     * Erzeugt eine leere {@link XYSeries} und fuegt diese in die Series-Liste
+     * des Objekts, sowie in das DataSet des {@link JFreeChartVisualisationTool}
+     * ein.
+     */
+    protected XYSeries createXYSeries(Comparable rowKey) {
+      XYSeries newSeries = new XYSeries(rowKey,true,false);
+      objectSeries.add( newSeries );
+      dataSet.addSeries( newSeries );
+      return newSeries;
+    }
+
+    /**
+     * Entfernt alle zu dem Objekt gehoerenden Series aus dem DataSet des
+     * {@link JFreeChartVisualisationTool}.
+     */
+    protected void removeVisualisationObjectFromDataSet() {
+      for (XYSeries series : objectSeries) {
+        dataSet.removeSeries(series);
+        series.clear();
+      }
+      objectSeries.clear();
+    }
+
+    /**
+     * Verdreht die X- und Y-Achse des Daten-Objekts. Diese Standard-Implementierung
+     * macht nichts.
+     */
+    public void rotateVisualisationObject() {
+    }
+  }
+
+  /**
+   * Dieser UpdateListener verknuepft eine {@link ListProperty} mit einem oder mehreren
+   * Charts in einer {@link JFreeChartVisualisationTool}-Instanz. Er kann unmittelbar als
+   * {@link schmitzm.data.event.ObjectListener} eingesetzt werden, um
+   * mit der Objekt-Aenderung automatisch die Visualisierung zu aktualisieren.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  protected class ListPropertyUpdateListener extends UpdateListener {
+    /**
+     * Erzeugt einen neuen <code>UpdateListener</code>.
+     * @param tool  Visualisierungstool, mit dem der Listener verbunden ist
+     * @param obj   Objekt welches visualisiert wird
+     * @param chart Chart in dem das Objekt dargestellt ist
+     */
+    public ListPropertyUpdateListener(JFreeChartVisualisationTool tool, ListProperty obj) {
+      super(tool,obj);
+    }
+
+    /**
+     * Liefert eine Beschreibung des visualisierten Objekts.
+     */
+    public String getObjectDesc() {
+      return ((Property)visObject).getName();
+    }
+
+    /**
+     * Erzeugt eine {@link XYSeries} fuer die Werte einer Liste und
+     * fuegt die Series dem DataSet des {@link JFreeChartVisualisationTool}
+     * hinzu.
+     * @param listProp eine Liste von Werten
+     */
+    protected void putVisualisationObjectToDataSet() {
+      ListProperty listProp = (ListProperty)visObject;
+      XYSeries newSeries = createXYSeries(listProp.getName());
+      ListPropertyReadAccess list = listProp.getReadAccess(this);
+      for (int i=0; i<list.getCount(); i++) {
+        Number value  = (Number)list.getValue(i);
+        Number colKey = i;
+        newSeries.addOrUpdate(colKey, value);
+      }
+      list.release();
+    }
+  }
+
+  /**
+   * Dieser UpdateListener verknuepft eine {@link MatrixProperty} mit einem oder mehreren
+   * Charts in einer {@link JFreeChartVisualisationTool}-Instanz. Er kann unmittelbar als
+   * {@link schmitzm.data.event.ObjectListener} eingesetzt werden, um
+   * mit der Objekt-Aenderung automatisch die Visualisierung zu aktualisieren.
+   * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+   * @version 1.0
+   */
+  protected class MatrixPropertyUpdateListener extends UpdateListener {
+    private boolean horSeries = true;
+
+    /**
+     * Erzeugt einen neuen <code>UpdateListener</code>.
+     * @param tool  Visualisierungstool, mit dem der Listener verbunden ist
+     * @param obj   Objekt welches visualisiert wird
+     * @param chart Chart in dem das Objekt dargestellt ist
+     */
+    public MatrixPropertyUpdateListener(JFreeChartVisualisationTool tool, MatrixProperty obj) {
+      super(tool,obj);
+    }
+
+    /**
+     * Liefert eine Beschreibung des visualisierten Objekts.
+     */
+    public String getObjectDesc() {
+      return ((Property)visObject).getName();
+    }
+
+    /**
+     * Erzeugt eine {@link XYSeries} fuer jede Zeile einer Matrix und
+     * fuegt die Series dem DataSet des {@link JFreeChartVisualisationTool}
+     * hinzu.
+     * @param matrixProp eine 1- oder 2-dim. Matrix von Werten
+     */
+    protected void putVisualisationObjectToDataSet() {
+      MatrixProperty     matrixProp = (MatrixProperty)visObject;
+      String             propName   = matrixProp.getName();
+      PropertyReadAccess matrix     = matrixProp.getReadAccess(this);
+
+      // 1-dimensionale Matrix
+      if ( matrixProp.getDimension() == 1 ) {
+        XYSeries newSeries = createXYSeries(propName);
+        for (int i=0; i<matrixProp.getSize(0); i++) {
+          Number colKey = i;
+          Number value  = (Number)matrix.getValue(i);
+          newSeries.addOrUpdate(colKey,value);
+        }
+      }
+      // 2-dimensionale Matrix
+      int rowDim = horSeries ? 1 : 0;
+      int colDim = horSeries ? 0 : 1;
+      if ( matrixProp.getDimension() == 2 ) {
+        for (int row=0; row<matrixProp.getSize(rowDim); row++) {
+          XYSeries newSeries = createXYSeries(propName + "["+row+"]");
+          for (int col=0; col<matrixProp.getSize(colDim); col++) {
+            Number colKey = col;
+            Number value  = (Number)matrix.getValue( horSeries ? new int[] {col,row} : new int[] {row,col});
+            newSeries.addOrUpdate(colKey,value);
+          }
+        }
+      }
+      matrix.release();
+    }
+
+    /**
+     * Verdreht die X- und Y-Achse des Daten-Objekts. Macht nichts, wenn die
+     * Matrix 1-dimensional ist.
+     */
+    public void rotateVisualisationObject() {
+      MatrixProperty matrixProp = (MatrixProperty)visObject;
+      if ( matrixProp.getDimension() <= 1 )
+        return;
+      // Alte Daten aus Dataset entfernen
+      removeVisualisationObjectFromDataSet();
+      // Rotations-Flag verdrehen
+      horSeries = !horSeries;
+      // Daten neu in das Dataset einfuegen
+      putVisualisationObjectToDataSet();
+    }
+
+  }
+
+
+}

Added: trunk/src/edu/bonn/xulu/plugin/vis/package.html
===================================================================
--- trunk/src/edu/bonn/xulu/plugin/vis/package.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/edu/bonn/xulu/plugin/vis/package.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,8 @@
+<html>
+<body>
+	In diesem Paket können die benutzerdefinierten Visualisierungstools für die
+	benutzerdefinierten Datentypen der Xulu-Modelling-Platform implementiert werden.
+	Damit diese in der Xulu-Anwendung verwendet werden können, müssen sie von
+	{@link edu.bonn.xulu.appl.VisualisationTool} abgeleitet sein.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/overview.html
===================================================================
--- trunk/src/overview.html	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/overview.html	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,12 @@
+<html>
+<body>
+	Diese Klassenbibliothek wurde für die {@linkplain edu.bonn.xulu.XuluModellingPlatform Xulu-Modelling-Plattform} erstellt.
+	Diese setzt sich aus allgemeinen Klassen zusammen, sowie aus Klassen, die speziell fuer die
+	Xulu-Anwendung implementiert sind.
+	Letztere sind unterhalb des Pakets {@link edu.bonn.xulu} hinterlegt.<br>
+	Die einzelnen Komponenten der Xulu-Applikation (z.B. Datenpool, Registry, ...) sind von den
+	dazugehörigen GUI-Komponenten ({@link edu.bonn.xulu.gui}) getrennt.<br>
+	Die <code>main</code>-Methode fuer die (GUI der) Xulu-Modelling-Plattform befindet sich in der
+	Klasse {@link edu.bonn.xulu.XuluModellingPlatform}.
+</body>
+</html>
\ No newline at end of file

Added: trunk/src/skrueger/gol/GameOfLife.java
===================================================================
--- trunk/src/skrueger/gol/GameOfLife.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/skrueger/gol/GameOfLife.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,129 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package skrueger.gol;
+
+import java.awt.image.DataBuffer;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.ScalarProperty;
+import edu.bonn.xulu.model.AbstractStepModel;
+
+public class GameOfLife extends AbstractStepModel {
+	private WritableGrid inputGrid;
+	private WritableGrid outputGrid;
+
+	public GameOfLife() {
+		super(new GameOfLifeContentManager() );
+		
+		stepCount = 1000;
+	}
+
+	@Override
+	public void performModelStep(int stepNo) {
+		
+		int[][] diffs = new int[][] { 
+				{ -1,-1 }, {0,-1}, {1,-1} , 
+				{ -1,0 },  {1,0},
+				{ -1,1 },  {0,1}, {1,1}	
+				};
+		
+		boolean anyBodyAlive = false;
+		
+		boolean[][] tmpGrid = new boolean[inputGrid.getWidth()][inputGrid.getHeight()];
+
+		for (int i = 1; i < inputGrid.getWidth()-1; i++ ) {
+			for (int ii = 1; ii < inputGrid.getHeight()-1; ii++ ) {
+				checkBreakingCommands();
+
+				int X = inputGrid.getMinX() + i;
+				int Y = inputGrid.getMinY() + ii;
+				
+				int anzNachbarn = 0;
+				
+				for (int d = 0; d < diffs.length; d++) {
+					float rasterSample = outputGrid.getRasterSampleAsFloat(X +diffs[d][0], Y +diffs[d][1]);
+					if (rasterSample > 0f) 
+						anzNachbarn++;
+				}
+				
+				boolean lebt = outputGrid.getRasterSampleAsFloat(X , Y ) > 0f;
+				
+				// Neugruendung
+				if (!lebt && (anzNachbarn==3)) 
+					tmpGrid[i][ii] = true;
+				else 
+					if (lebt && ((anzNachbarn < 2) || (anzNachbarn > 3 )) )
+						tmpGrid[i][ii] = false;
+					else 
+						tmpGrid[i][ii] = lebt;
+					
+					if (anzNachbarn>0) anyBodyAlive = true;
+			}
+		}
+
+		// TempGrid auf das echte Grid schreiben
+		for (int i = 1; i < inputGrid.getWidth()-1;i++ ) {
+			for (int ii = 1; ii < inputGrid.getHeight()-1; ii++ ) {
+
+				int X = inputGrid.getMinX() + i;
+				int Y = inputGrid.getMinY() + ii;
+
+				outputGrid.setRasterSample( tmpGrid[i][ii] ? 1f : 0f ,X ,Y);
+		
+				
+			}
+		}
+		
+		if (!anyBodyAlive) {
+			stepCount = stepNo;
+			statusOut.println("Lebt keiner mehr... höre hier auf!");
+		}
+	}
+
+	@Override
+	public void performModelDispose() {
+		// TODO Auto-generated method stub
+		
+	}
+
+	@Override
+	public void performModelInit() {
+		ScalarProperty sp = (ScalarProperty) this.contManager.getResource(0).getData();
+		inputGrid = (WritableGrid) sp.getOneTimeReadAccess().getValue();
+		
+		sp = (ScalarProperty) this.contManager.getResource(1).getData();
+		outputGrid = (WritableGrid) sp.getOneTimeWriteAccess().getValue();
+		
+		int startAnz = 0;
+		for (int i = 0; i < inputGrid.getWidth();i++ ) {
+			for (int ii = 0; ii < inputGrid.getHeight(); ii++ ) {
+				if (inputGrid.getSampleType() == DataBuffer.TYPE_FLOAT) {
+					float val = (float) Math.random();
+					if (val > 0.7 ) {
+						val = 1f; 
+						startAnz++;
+					}
+						else val = 0f;
+					
+					inputGrid.setRasterSample(val, inputGrid.getMinX() + i, inputGrid.getMinY() + ii);
+					outputGrid.setRasterSample(val, inputGrid.getMinX() + i, inputGrid.getMinY() + ii);
+				} else {
+					statusOut.println("schlecht!");
+				}
+			}
+		}
+		statusOut.println("Anzahl der startenden Individuen: "+startAnz);
+		
+		
+	}
+	
+}

Added: trunk/src/skrueger/gol/GameOfLifeContentManager.java
===================================================================
--- trunk/src/skrueger/gol/GameOfLifeContentManager.java	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/src/skrueger/gol/GameOfLifeContentManager.java	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,36 @@
+/** XULU - This file is part of the eXtendable Unified Land Use Modelling Platform (XULU)
+
+    This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+    This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
+
+    Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
+    Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
+    Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
+ **/
+
+package skrueger.gol;
+
+import schmitzm.data.WritableGrid;
+import schmitzm.data.property.ScalarProperty;
+import edu.bonn.xulu.data.XuluDataException;
+import edu.bonn.xulu.model.AbstractModelContentManager;
+import edu.bonn.xulu.model.ValuePropertyResource;
+
+public class GameOfLifeContentManager extends AbstractModelContentManager {
+
+	public GameOfLifeContentManager() {
+		super(2);
+
+		resource[0] = new ValuePropertyResource("Startzustand für GoL", ScalarProperty.class , WritableGrid.class ,false);
+
+		resource[1] = new ValuePropertyResource("GoL zur Laufzeit", ScalarProperty.class , WritableGrid.class ,false);
+	}
+
+	@Override
+	public void checkAndError() throws XuluDataException {
+		// TODO Auto-generated method stub
+		super.checkAndError();
+	}
+
+}

Added: trunk/startXULU.bat
===================================================================
--- trunk/startXULU.bat	2009-02-24 23:27:09 UTC (rev 1)
+++ trunk/startXULU.bat	2009-02-25 11:54:01 UTC (rev 2)
@@ -0,0 +1,105 @@
+ at echo off
+setlocal
+
+set LIB_ROOT="lib"
+set SCHMITZM_LIB_ROOT="E:\Arbeit\SCHMITZM\Trunk\lib"
+
+rem ###################################################################
+rem #############   Xulu library paths and parameters   ###############
+rem ###################################################################
+set XULU_LIB=%LIB_ROOT%\xulu\XuluModellingPlatform.jar
+if "%1"=="/useXuluJar"     set XULU_LIB=%LIB_ROOT%\xulu\XuluModellingPlatform.jar
+if "%1"=="/useXuluClasses" set XULU_LIB=classes
+
+set XULU_REGISTRY=registry.xif
+set XULU_LANGUAGE=de
+set XULU_WORK_DIR=C:\
+set XULU_START_SCRIPTS=
+set XULU_RESOURCE=resource
+
+rem ####################################################
+rem #############   External libraries   ###############
+rem ####################################################
+
+rem ##### Where to find "Java Advanced Imaging" (and ImageIO) #####
+set JAI_ROOT=%LIB_ROOT%\jai-1_1_3\lib
+
+rem ##### Where to find "SCHMITZM library" #####
+set SCHMITZM_ROOT=%LIB_ROOT%\schmitzm
+
+rem ##### Where to find "JINI" #####
+set JINI_ROOT=%LIB_ROOT%\jini
+
+rem ##### Where to find "R" #####
+set R_ROOT=%LIB_ROOT%\JavaRInterface
+
+
+rem ##### combine the external libs #####
+set SCHMITZM_LIB=%SCHMITZM_ROOT%\schmitzm.jar
+set JAI_LIB=%JAI_ROOT%\*
+set JINI_LIB=%JINI_ROOT%\lib\*
+rem set JINI_LIB=%JINI_ROOT%\lib\*;%JINI_ROOT%\lib-dl\*;%JINI_ROOT%\lib-ext\*
+set R_LIB=%R_ROOT%\JRI.jar;%R_ROOT%\libjri.so;%R_ROOT%\libR.so
+
+set LIB_ALL=%XULU_LIB%;%SCHMITZM_LIB%;%JAI_LIB%;%JINI_LIB%;%R_LIB%
+
+
+rem ####################################################
+rem #######   External libraries of SCHMITZM   #########
+rem ####################################################
+set LIB_ROOT=%SCHMITZM_LIB_ROOT%
+
+rem ##### Where to find "GeoTools" #####
+set GT_ROOT=%LIB_ROOT%\gt2-2.4.4
+rem ##### Where to find gt2-arcgrid-2.1.x.jar (from SpearfishDemo) #####
+set GT_ARCGRID_ROOT=%LIB_ROOT%\geotoolsArcGrid
+
+rem ##### Where to find "Log4j" #####
+set LOG4J_ROOT=%LIB_ROOT%\log4j-1.2.14
+
+rem ##### Where to find "JINI" #####
+set JINI_ROOT=%LIB_ROOT%\jini
+
+rem ##### Where to find "jFreeChart" #####
+set JFREECHART_ROOT=%LIB_ROOT%\jFreeChart
+
+rem ##### combine the external libs #####
+set GT_LIB=%GT_ROOT%\*
+set GT_LIB=%GT_LIB%;%GT_ARCGRID_ROOT%\gt2-arcgrid-2.3.0-M0.jar;%GT_ARCGRID_ROOT%\junit-4.4.jar
+set LOG4J_LIB=%LOG4J_ROOT%\log4j-1.2.14.jar
+set JINI_LIB=%JINI_ROOT%\lib\*
+rem set JINI_LIB=%JINI_ROOT%\lib\*;%JINI_ROOT%\lib-dl\*;%JINI_ROOT%\lib-ext\*
+set JFREECHART_LIB=%JFREECHART_ROOT%\jfreechart-1.0.6.jar;%JFREECHART_ROOT%\jcommon-1.0.10.jar
+
+set LIB_ALL=%LIB_ALL%;%GT_LIB%;%LOG4J_LIB%;%JINI_LIB%;%JFREECHART_LIB%
+
+rem ##### combine the native libs #####
+set JAI_NATIVE=%JAI_ROOT%\native_win
+
+set LIB_NATIVE=%JAI_NATIVE%
+
+
+rem ##### combine Xulu starting parameters #####
+set XULU_PARAMS=
+if not "%XULU_LANGUAGE%"==""        set XULU_PARAMS=%XULU_PARAMS% -l %XULU_LANGUAGE%
+if not "%XULU_REGISTRY%"==""        set XULU_PARAMS=%XULU_PARAMS% -rf %XULU_REGISTRY%
+if not "%XULU_MODELS_LIB%"==""      set XULU_PARAMS=%XULU_PARAMS% -d %XULU_MODELS_LIB%
+if not "%XULU_WORK_DIR%"==""        set XULU_PARAMS=%XULU_PARAMS% -w "%XULU_WORK_DIR%"
+if not "%XULU_START_SCRIPTS%"==""   set XULU_PARAMS=%XULU_PARAMS% -s "%XULU_START_SCRIPTS%"
+
+
+rem ##### determine java interpreter #####
+set JAVA_PRG=start /B javaw
+rem set JAVA_PRG=java
+rem ##### for command line help, use java instead of javaw #####
+if "%1"=="/?"     set JAVA_PRG=java
+if "%1"=="?"      set JAVA_PRG=java
+if "%1"=="-?"     set JAVA_PRG=java
+if "%1"=="--help" set JAVA_PRG=java
+if "%1"=="-h"     set JAVA_PRG=java
+
+
+rem ##### start Xulu #####
+%JAVA_PRG% -Xms300M -Xmx1000M -version:1.6 -cp %XULU_RESOURCE%;%LIB_ALL% -Djava.library.path=%LIB_NATIVE% -splash:resource\icons\xulu_start.png edu.bonn.xulu.XuluModellingPlatform %XULU_PARAMS% %*
+
+endlocal



More information about the Xulu-commits mailing list