summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Branson <andrew@andrewbranson.net>2011-06-21 15:46:02 +0200
committerAndrew Branson <andrew@andrewbranson.net>2011-06-21 15:46:02 +0200
commit254ee6f47eebfc00462c10756a92066e82cc1a96 (patch)
tree8273ff95c704e6faa3f92b4711253427b9ba0481
Initial commit2.2
-rwxr-xr-x.classpath18
-rwxr-xr-x.project17
-rwxr-xr-xbin/UserCode.bat6
-rwxr-xr-xbin/ant.bat110
-rwxr-xr-xbin/conf/client.conf3
-rwxr-xr-xbin/conf/server.conf4
-rwxr-xr-xbin/env.bat5
-rwxr-xr-xbin/itemServer.bat7
-rwxr-xr-xbin/itemServer.sh15
-rwxr-xr-xbin/lcp.bat9
-rwxr-xr-xbin/runGUI.bat6
-rwxr-xr-xbin/runOutcomeEditor.bat5
-rwxr-xr-xbin/win32/SQLiteSpy.db3bin0 -> 3072 bytes
-rwxr-xr-xbin/win32/SQLiteSpy.exebin0 -> 1657856 bytes
-rwxr-xr-xbin/win32/Wrapper.dllbin0 -> 65536 bytes
-rwxr-xr-xbin/win32/clc.regbin0 -> 2360 bytes
-rwxr-xr-xbin/win32/iordump.exebin0 -> 1613824 bytes
-rwxr-xr-xbin/win32/sqlite3.exebin0 -> 322630 bytes
-rwxr-xr-xbin/win32/sqlite_jni.dllbin0 -> 241664 bytes
-rwxr-xr-xbuild.xml162
-rwxr-xr-xchangelog139
-rwxr-xr-xconnect/dev.clc.example29
-rwxr-xr-xjavadoc.xml8
-rwxr-xr-xlib/bsf.jarbin0 -> 80528 bytes
-rwxr-xr-xlib/castor-core.jarbin0 -> 55226 bytes
-rwxr-xr-xlib/castor-xml-schema.jarbin0 -> 347768 bytes
-rwxr-xr-xlib/castor-xml.jarbin0 -> 749083 bytes
-rwxr-xr-xlib/commons-logging.jarbin0 -> 38015 bytes
-rwxr-xr-xlib/dom4j.jarbin0 -> 446847 bytes
-rwxr-xr-xlib/js.jarbin0 -> 597407 bytes
-rwxr-xr-xlib/ldap.jarbin0 -> 275642 bytes
-rwxr-xr-xlib/wrapper.jarbin0 -> 52684 bytes
-rwxr-xr-xlib/xercesImpl.jarbin0 -> 1207073 bytes
-rwxr-xr-xlib/xml-apis.jarbin0 -> 195119 bytes
-rwxr-xr-xresources/boot/CA/CompositeActivityFactory.xml108
-rwxr-xr-xresources/boot/CA/ElementaryActivityFactory.xml108
-rwxr-xr-xresources/boot/CA/ManageCompositeActDef.xml219
-rwxr-xr-xresources/boot/CA/ManageElementaryActDef.xml219
-rwxr-xr-xresources/boot/CA/ManageSchema.xml218
-rwxr-xr-xresources/boot/CA/ManageScript.xml219
-rwxr-xr-xresources/boot/CA/NoWorkflow.xml22
-rwxr-xr-xresources/boot/CA/SchemaFactory.xml108
-rwxr-xr-xresources/boot/CA/ScriptFactory.xml108
-rwxr-xr-xresources/boot/CA/ServerItemWorkflow.xml217
-rwxr-xr-xresources/boot/EA/AssignNewVersionFromLast.xml20
-rwxr-xr-xresources/boot/EA/CreateNewAgent.xml19
-rwxr-xr-xresources/boot/EA/CreateNewItem.xml19
-rwxr-xr-xresources/boot/EA/CreateNewLocalObjectDef.xml19
-rwxr-xr-xresources/boot/EA/EditActivityDef.xml19
-rwxr-xr-xresources/boot/EA/EditProperties.xml20
-rwxr-xr-xresources/boot/EA/EditSchema.xml19
-rwxr-xr-xresources/boot/EA/EditScriptDefinition.xml19
-rwxr-xr-xresources/boot/LDAPboot.txt4
-rwxr-xr-xresources/boot/OD/CompositeActivityDef.xml186
-rwxr-xr-xresources/boot/OD/ElementaryActivityDef.xml29
-rwxr-xr-xresources/boot/OD/New.xml3
-rwxr-xr-xresources/boot/OD/NewAgent.xml20
-rwxr-xr-xresources/boot/OD/NewItem.xml73
-rwxr-xr-xresources/boot/OD/NewLocalObjectDef.xml20
-rwxr-xr-xresources/boot/OD/PredefinedStepOutcome.xml13
-rwxr-xr-xresources/boot/OD/PropertyDescription.xml36
-rwxr-xr-xresources/boot/OD/Schema.xml4
-rwxr-xr-xresources/boot/OD/Script.xml38
-rwxr-xr-xresources/boot/SC/CreateNewNumberedVersionFromLast.xml39
-rwxr-xr-xresources/boot/SC/LocalObjectDefCreator.xml57
-rwxr-xr-xresources/boot/SC/New.xml13
-rwxr-xr-xresources/boot/SC/ServerNewEntity.xml20
-rwxr-xr-xresources/boot/allbootitems.txt34
-rwxr-xr-xresources/boot/factory/CA.xml8
-rwxr-xr-xresources/boot/factory/EA.xml8
-rwxr-xr-xresources/boot/factory/OD.xml8
-rwxr-xr-xresources/boot/factory/SC.xml8
-rwxr-xr-xresources/boot/property/CAProp.xml5
-rwxr-xr-xresources/boot/property/EAProp.xml5
-rwxr-xr-xresources/boot/property/ODProp.xml5
-rwxr-xr-xresources/boot/property/SCProp.xml4
-rwxr-xr-xresources/images/Thumbs.dbbin0 -> 58368 bytes
-rwxr-xr-xresources/images/about.pngbin0 -> 1906 bytes
-rwxr-xr-xresources/images/compositeMember.gifbin0 -> 916 bytes
-rwxr-xr-xresources/images/elementaryMember.gifbin0 -> 872 bytes
-rwxr-xr-xresources/images/find.pngbin0 -> 795 bytes
-rwxr-xr-xresources/images/folder.pngbin0 -> 559 bytes
-rwxr-xr-xresources/images/graph/autolayout.pngbin0 -> 909 bytes
-rwxr-xr-xresources/images/graph/copy.pngbin0 -> 805 bytes
-rwxr-xr-xresources/images/graph/delete.pngbin0 -> 858 bytes
-rwxr-xr-xresources/images/graph/edge.pngbin0 -> 565 bytes
-rwxr-xr-xresources/images/graph/history.pngbin0 -> 991 bytes
-rwxr-xr-xresources/images/graph/load.pngbin0 -> 559 bytes
-rwxr-xr-xresources/images/graph/newvertex.pngbin0 -> 703 bytes
-rwxr-xr-xresources/images/graph/newvertex_large.pngbin0 -> 1221 bytes
-rwxr-xr-xresources/images/graph/print.pngbin0 -> 870 bytes
-rwxr-xr-xresources/images/graph/resizepad.gifbin0 -> 842 bytes
-rwxr-xr-xresources/images/graph/save.pngbin0 -> 892 bytes
-rwxr-xr-xresources/images/graph/selection.gifbin0 -> 132 bytes
-rwxr-xr-xresources/images/graph/start.pngbin0 -> 732 bytes
-rwxr-xr-xresources/images/graph/zoomout.pngbin0 -> 927 bytes
-rwxr-xr-xresources/images/info.pngbin0 -> 866 bytes
-rwxr-xr-xresources/images/leaf.pngbin0 -> 626 bytes
-rwxr-xr-xresources/images/loading.gifbin0 -> 1245 bytes
-rwxr-xr-xresources/images/next.pngbin0 -> 921 bytes
-rwxr-xr-xresources/images/reload.gifbin0 -> 1005 bytes
-rwxr-xr-xresources/images/typeicons/agent_16.pngbin0 -> 810 bytes
-rwxr-xr-xresources/images/typeicons/agent_32.pngbin0 -> 1803 bytes
-rwxr-xr-xresources/images/typeicons/compositeactivitydesc_16.pngbin0 -> 788 bytes
-rwxr-xr-xresources/images/typeicons/compositeactivitydesc_32.pngbin0 -> 2102 bytes
-rwxr-xr-xresources/images/typeicons/elementaryactivitydesc_16.pngbin0 -> 724 bytes
-rwxr-xr-xresources/images/typeicons/elementaryactivitydesc_32.pngbin0 -> 1871 bytes
-rwxr-xr-xresources/images/typeicons/localobjectfactory_16.pngbin0 -> 916 bytes
-rwxr-xr-xresources/images/typeicons/localobjectfactory_32.pngbin0 -> 2084 bytes
-rwxr-xr-xresources/images/typeicons/outcome_desc_32.pngbin0 -> 1881 bytes
-rwxr-xr-xresources/images/typeicons/outcomedesc_16.pngbin0 -> 840 bytes
-rwxr-xr-xresources/images/typeicons/outcomedesc_32.pngbin0 -> 1881 bytes
-rwxr-xr-xresources/images/typeicons/script_16.pngbin0 -> 894 bytes
-rwxr-xr-xresources/images/typeicons/script_32.pngbin0 -> 2056 bytes
-rwxr-xr-xresources/images/typeicons/server_16.pngbin0 -> 875 bytes
-rwxr-xr-xresources/images/typeicons/server_32.pngbin0 -> 1882 bytes
-rwxr-xr-xresources/mapFiles/CastorHashMapMap.xml41
-rwxr-xr-xresources/mapFiles/CollectionMap.xml113
-rwxr-xr-xresources/mapFiles/HistoryMap.xml43
-rwxr-xr-xresources/mapFiles/JobListMap.xml48
-rwxr-xr-xresources/mapFiles/KeyValuePairMap.xml30
-rwxr-xr-xresources/mapFiles/LifeCycleMap.xml121
-rwxr-xr-xresources/mapFiles/NewEntityMap.xml102
-rwxr-xr-xresources/mapFiles/PropertiesMap.xml46
-rwxr-xr-xresources/mapFiles/TransferMap.xml19
-rwxr-xr-xresources/mapFiles/ViewpointMap.xml21
-rwxr-xr-xresources/mapFiles/graphModelMap.xml126
-rwxr-xr-xresources/mapFiles/index.xml10
-rwxr-xr-xresources/openldap/README5
-rwxr-xr-xresources/openldap/cristal2.schema49
-rwxr-xr-xresources/openldap/slapd.conf20
-rwxr-xr-xresources/textFiles/consoleHelp.txt18
-rwxr-xr-xresources/textFiles/defaultConf.properties5
-rwxr-xr-xresources/textFiles/license.html38
-rwxr-xr-xresources/textFiles/version.txt1
-rwxr-xr-xsource/com/c2kernel/collection/Aggregation.java111
-rwxr-xr-xsource/com/c2kernel/collection/AggregationDescription.java59
-rwxr-xr-xsource/com/c2kernel/collection/AggregationInstance.java45
-rwxr-xr-xsource/com/c2kernel/collection/AggregationMember.java154
-rwxr-xr-xsource/com/c2kernel/collection/Collection.java32
-rwxr-xr-xsource/com/c2kernel/collection/CollectionDescription.java14
-rwxr-xr-xsource/com/c2kernel/collection/CollectionMember.java38
-rwxr-xr-xsource/com/c2kernel/collection/CollectionMemberList.java22
-rwxr-xr-xsource/com/c2kernel/collection/Dependency.java114
-rwxr-xr-xsource/com/c2kernel/collection/DependencyMember.java141
-rwxr-xr-xsource/com/c2kernel/collection/MembershipException.java21
-rwxr-xr-xsource/com/c2kernel/collection/Parent2ChildCollection.java119
-rwxr-xr-xsource/com/c2kernel/collection/RelationshipUtils.java33
-rwxr-xr-xsource/com/c2kernel/collection/gui/model/AggregationVertexFactory.java44
-rwxr-xr-xsource/com/c2kernel/collection/gui/model/AggregationVertexOutlineCreator.java43
-rwxr-xr-xsource/com/c2kernel/collection/gui/view/AggregationMemberRenderer.java124
-rwxr-xr-xsource/com/c2kernel/collection/gui/view/CollectionFrame.java41
-rwxr-xr-xsource/com/c2kernel/collection/gui/view/PropertyPanel.java36
-rwxr-xr-xsource/com/c2kernel/collection/gui/view/SelectedMemberPanel.java150
-rwxr-xr-xsource/com/c2kernel/entity/C2KLocalObject.java32
-rwxr-xr-xsource/com/c2kernel/entity/CorbaServer.java191
-rwxr-xr-xsource/com/c2kernel/entity/TraceableEntity.java335
-rwxr-xr-xsource/com/c2kernel/entity/TraceableLocator.java84
-rwxr-xr-xsource/com/c2kernel/entity/agent/ActiveEntity.java281
-rwxr-xr-xsource/com/c2kernel/entity/agent/ActiveLocator.java87
-rwxr-xr-xsource/com/c2kernel/entity/agent/Job.java343
-rwxr-xr-xsource/com/c2kernel/entity/agent/JobArrayList.java30
-rwxr-xr-xsource/com/c2kernel/entity/agent/JobList.java125
-rwxr-xr-xsource/com/c2kernel/entity/proxy/AgentProxy.java301
-rwxr-xr-xsource/com/c2kernel/entity/proxy/DomainPathSubscriber.java18
-rwxr-xr-xsource/com/c2kernel/entity/proxy/EntityProxy.java246
-rwxr-xr-xsource/com/c2kernel/entity/proxy/EntityProxyManager.java341
-rwxr-xr-xsource/com/c2kernel/entity/proxy/EntityProxyObserver.java25
-rwxr-xr-xsource/com/c2kernel/entity/proxy/ItemProxy.java212
-rwxr-xr-xsource/com/c2kernel/entity/proxy/MemberControl.java43
-rwxr-xr-xsource/com/c2kernel/entity/proxy/MemberSubscription.java121
-rwxr-xr-xsource/com/c2kernel/entity/proxy/ProxyClientConnection.java179
-rwxr-xr-xsource/com/c2kernel/entity/proxy/ProxyMessage.java110
-rwxr-xr-xsource/com/c2kernel/entity/proxy/ProxyServerConnection.java129
-rwxr-xr-xsource/com/c2kernel/entity/proxy/ProxySubscriber.java36
-rwxr-xr-xsource/com/c2kernel/entity/transfer/TransferItem.java131
-rwxr-xr-xsource/com/c2kernel/entity/transfer/TransferSet.java107
-rwxr-xr-xsource/com/c2kernel/events/Event.java296
-rwxr-xr-xsource/com/c2kernel/events/History.java94
-rwxr-xr-xsource/com/c2kernel/graph/controller/AutoScrollController.java39
-rwxr-xr-xsource/com/c2kernel/graph/controller/DeletionController.java89
-rwxr-xr-xsource/com/c2kernel/graph/controller/EdgeConstructionController.java244
-rwxr-xr-xsource/com/c2kernel/graph/controller/MultiSelectionDragController.java551
-rwxr-xr-xsource/com/c2kernel/graph/controller/StartVertexController.java77
-rwxr-xr-xsource/com/c2kernel/graph/controller/VertexConstructionController.java45
-rwxr-xr-xsource/com/c2kernel/graph/event/ClearedEvent.java6
-rwxr-xr-xsource/com/c2kernel/graph/event/EdgeRemovedEvent.java6
-rwxr-xr-xsource/com/c2kernel/graph/event/EdgesChangedEvent.java6
-rwxr-xr-xsource/com/c2kernel/graph/event/ElasticBandResizedEvent.java6
-rwxr-xr-xsource/com/c2kernel/graph/event/ElasticBandSetEvent.java6
-rwxr-xr-xsource/com/c2kernel/graph/event/EntireModelChangedEvent.java6
-rwxr-xr-xsource/com/c2kernel/graph/event/ForcedNotifyEvent.java6
-rwxr-xr-xsource/com/c2kernel/graph/event/GraphModelEvent.java7
-rwxr-xr-xsource/com/c2kernel/graph/event/GraphModelResizedEvent.java6
-rwxr-xr-xsource/com/c2kernel/graph/event/NewEdgeEndPointChangedEvent.java6
-rwxr-xr-xsource/com/c2kernel/graph/event/SelectionChangedEvent.java9
-rwxr-xr-xsource/com/c2kernel/graph/event/SelectionMovedEvent.java7
-rwxr-xr-xsource/com/c2kernel/graph/event/StartVertexIdChangedEvent.java6
-rwxr-xr-xsource/com/c2kernel/graph/event/VertexAddedEvent.java6
-rwxr-xr-xsource/com/c2kernel/graph/event/VertexCreatedEvent.java6
-rwxr-xr-xsource/com/c2kernel/graph/event/VertexMovedEvent.java6
-rwxr-xr-xsource/com/c2kernel/graph/event/VertexRemovedEvent.java6
-rwxr-xr-xsource/com/c2kernel/graph/event/VerticesChangedEvent.java6
-rwxr-xr-xsource/com/c2kernel/graph/layout/DefaultGraphLayoutGenerator.java116
-rwxr-xr-xsource/com/c2kernel/graph/layout/IntegerWrapper.java13
-rwxr-xr-xsource/com/c2kernel/graph/model/DirectedEdge.java99
-rwxr-xr-xsource/com/c2kernel/graph/model/EdgeFactory.java14
-rwxr-xr-xsource/com/c2kernel/graph/model/ElasticBand.java17
-rwxr-xr-xsource/com/c2kernel/graph/model/GraphModel.java884
-rwxr-xr-xsource/com/c2kernel/graph/model/GraphModelCastorData.java29
-rwxr-xr-xsource/com/c2kernel/graph/model/GraphModelManager.java142
-rwxr-xr-xsource/com/c2kernel/graph/model/GraphPoint.java18
-rwxr-xr-xsource/com/c2kernel/graph/model/Graphable.java53
-rwxr-xr-xsource/com/c2kernel/graph/model/GraphableEdge.java71
-rwxr-xr-xsource/com/c2kernel/graph/model/GraphableVertex.java254
-rwxr-xr-xsource/com/c2kernel/graph/model/Selection.java35
-rwxr-xr-xsource/com/c2kernel/graph/model/TypeNameAndConstructionInfo.java23
-rwxr-xr-xsource/com/c2kernel/graph/model/Vertex.java308
-rwxr-xr-xsource/com/c2kernel/graph/model/VertexFactory.java16
-rwxr-xr-xsource/com/c2kernel/graph/model/VertexOutlineCreator.java10
-rwxr-xr-xsource/com/c2kernel/graph/traversal/GraphTraversal.java85
-rwxr-xr-xsource/com/c2kernel/graph/view/DefaultDirectedEdgeRenderer.java75
-rwxr-xr-xsource/com/c2kernel/graph/view/DefaultVertexRenderer.java59
-rwxr-xr-xsource/com/c2kernel/graph/view/DirectedEdgeRenderer.java11
-rwxr-xr-xsource/com/c2kernel/graph/view/EditorModeListener.java8
-rwxr-xr-xsource/com/c2kernel/graph/view/EditorPanel.java100
-rwxr-xr-xsource/com/c2kernel/graph/view/EditorToolBar.java336
-rwxr-xr-xsource/com/c2kernel/graph/view/GraphPanel.java274
-rwxr-xr-xsource/com/c2kernel/graph/view/PropertyTable.java38
-rwxr-xr-xsource/com/c2kernel/graph/view/PropertyTableModel.java125
-rwxr-xr-xsource/com/c2kernel/graph/view/SelectedVertexPanel.java27
-rwxr-xr-xsource/com/c2kernel/graph/view/VertexPropertyPanel.java245
-rwxr-xr-xsource/com/c2kernel/graph/view/VertexRenderer.java11
-rwxr-xr-xsource/com/c2kernel/gui/Console.java269
-rwxr-xr-xsource/com/c2kernel/gui/DomainKeyConsumer.java16
-rwxr-xr-xsource/com/c2kernel/gui/DomainKeyListener.java27
-rwxr-xr-xsource/com/c2kernel/gui/DynamicTreeBuilder.java176
-rwxr-xr-xsource/com/c2kernel/gui/EntityDetails.java223
-rwxr-xr-xsource/com/c2kernel/gui/EntityFinder.java205
-rwxr-xr-xsource/com/c2kernel/gui/EntityTabManager.java88
-rwxr-xr-xsource/com/c2kernel/gui/LoginBox.java312
-rwxr-xr-xsource/com/c2kernel/gui/Main.java39
-rwxr-xr-xsource/com/c2kernel/gui/MainFrame.java306
-rwxr-xr-xsource/com/c2kernel/gui/MenuBuilder.java247
-rwxr-xr-xsource/com/c2kernel/gui/TreeBrowser.java197
-rwxr-xr-xsource/com/c2kernel/gui/data/Node.java234
-rwxr-xr-xsource/com/c2kernel/gui/data/NodeAgent.java31
-rwxr-xr-xsource/com/c2kernel/gui/data/NodeCollection.java66
-rwxr-xr-xsource/com/c2kernel/gui/data/NodeContext.java61
-rwxr-xr-xsource/com/c2kernel/gui/data/NodeEntity.java80
-rwxr-xr-xsource/com/c2kernel/gui/data/NodeItem.java110
-rwxr-xr-xsource/com/c2kernel/gui/data/NodeSubscriber.java13
-rwxr-xr-xsource/com/c2kernel/gui/tabs/AgentPropertiesPane.java50
-rwxr-xr-xsource/com/c2kernel/gui/tabs/CloseTabIcon.java67
-rwxr-xr-xsource/com/c2kernel/gui/tabs/CollectionPane.java100
-rwxr-xr-xsource/com/c2kernel/gui/tabs/DomainPathAdmin.java161
-rwxr-xr-xsource/com/c2kernel/gui/tabs/EntityTabPane.java182
-rwxr-xr-xsource/com/c2kernel/gui/tabs/ExecutionPane.java198
-rwxr-xr-xsource/com/c2kernel/gui/tabs/HistoryPane.java253
-rwxr-xr-xsource/com/c2kernel/gui/tabs/JTabbedPaneWithCloseIcons.java88
-rwxr-xr-xsource/com/c2kernel/gui/tabs/JobListPane.java295
-rwxr-xr-xsource/com/c2kernel/gui/tabs/PropertiesPane.java185
-rwxr-xr-xsource/com/c2kernel/gui/tabs/ViewpointPane.java501
-rwxr-xr-xsource/com/c2kernel/gui/tabs/WorkflowPane.java273
-rwxr-xr-xsource/com/c2kernel/gui/tabs/collection/AggregationView.java86
-rwxr-xr-xsource/com/c2kernel/gui/tabs/collection/CollectionHistoryWindow.java184
-rwxr-xr-xsource/com/c2kernel/gui/tabs/collection/CollectionView.java48
-rwxr-xr-xsource/com/c2kernel/gui/tabs/collection/DependencyView.java33
-rwxr-xr-xsource/com/c2kernel/gui/tabs/execution/ActivityItem.java46
-rwxr-xr-xsource/com/c2kernel/gui/tabs/execution/ActivityViewer.java292
-rwxr-xr-xsource/com/c2kernel/gui/tabs/execution/DefaultExecutor.java33
-rwxr-xr-xsource/com/c2kernel/gui/tabs/execution/Executor.java21
-rwxr-xr-xsource/com/c2kernel/gui/tabs/execution/RequestButton.java33
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/BasicOutcomeEditor.java100
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/InvalidOutcomeException.java11
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/InvalidSchemaException.java11
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/OutcomeException.java11
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/OutcomeHandler.java16
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/OutcomeNotInitialisedException.java11
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/form/AttributeList.java158
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/form/CardinalException.java14
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/form/DataRecord.java249
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/form/Dimension.java377
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/form/DimensionInstance.java32
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/form/DimensionTableModel.java308
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/form/Field.java137
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/form/HelpPane.java55
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/form/MultiLinePasteAdapter.java133
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/form/OutcomeEditor.java214
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/form/OutcomePanel.java362
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/form/OutcomeStructure.java283
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/form/StructuralException.java12
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/form/field/ArrayEditField.java166
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/form/field/ArrayTableModel.java106
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/form/field/BooleanEditField.java68
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/form/field/ComboField.java135
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/form/field/DecimalEditField.java115
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/form/field/FieldConstraints.java51
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/form/field/ImageEditField.java104
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/form/field/IntegerEditField.java113
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/form/field/ListOfValues.java31
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/form/field/LongStringEditField.java38
-rwxr-xr-xsource/com/c2kernel/gui/tabs/outcome/form/field/StringEditField.java252
-rwxr-xr-xsource/com/c2kernel/lifecycle/ActivityDef.java135
-rwxr-xr-xsource/com/c2kernel/lifecycle/ActivitySlotDef.java155
-rwxr-xr-xsource/com/c2kernel/lifecycle/AndSplitDef.java111
-rwxr-xr-xsource/com/c2kernel/lifecycle/CompositeActivityDef.java225
-rwxr-xr-xsource/com/c2kernel/lifecycle/JoinDef.java65
-rwxr-xr-xsource/com/c2kernel/lifecycle/LoopDef.java74
-rwxr-xr-xsource/com/c2kernel/lifecycle/NextDef.java94
-rwxr-xr-xsource/com/c2kernel/lifecycle/OrSplitDef.java23
-rwxr-xr-xsource/com/c2kernel/lifecycle/WfCastorHashMap.java33
-rwxr-xr-xsource/com/c2kernel/lifecycle/WfVertexDef.java83
-rwxr-xr-xsource/com/c2kernel/lifecycle/XOrSplitDef.java28
-rwxr-xr-xsource/com/c2kernel/lifecycle/chooser/ActivityChooser.java200
-rwxr-xr-xsource/com/c2kernel/lifecycle/chooser/LDAPEntryChooser.java70
-rwxr-xr-xsource/com/c2kernel/lifecycle/chooser/LDAPFileChooser.java119
-rwxr-xr-xsource/com/c2kernel/lifecycle/chooser/WorkflowDialogue.java20
-rwxr-xr-xsource/com/c2kernel/lifecycle/gui/model/WfDefGraphPanel.java58
-rwxr-xr-xsource/com/c2kernel/lifecycle/gui/model/WfEdgeDefFactory.java29
-rwxr-xr-xsource/com/c2kernel/lifecycle/gui/model/WfVertexDefFactory.java93
-rwxr-xr-xsource/com/c2kernel/lifecycle/gui/model/WfVertexDefOutlineCreator.java50
-rwxr-xr-xsource/com/c2kernel/lifecycle/gui/view/ActivitySlotDefRenderer.java70
-rwxr-xr-xsource/com/c2kernel/lifecycle/gui/view/CompActDefOutcomeHandler.java218
-rwxr-xr-xsource/com/c2kernel/lifecycle/gui/view/ElemActDefOutcomeHandler.java152
-rwxr-xr-xsource/com/c2kernel/lifecycle/gui/view/SplitJoinDefRenderer.java137
-rwxr-xr-xsource/com/c2kernel/lifecycle/gui/view/WfDirectedEdgeDefRenderer.java132
-rwxr-xr-xsource/com/c2kernel/lifecycle/gui/view/WfVertexDefRenderer.java29
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/Activity.java689
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/AdvancementCalculator.java228
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/AndSplit.java26
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/CompositeActivity.java448
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/EventList.java19
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/EventStorage.java24
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/JobPusher.java69
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/Join.java207
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/Loop.java104
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/Next.java82
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/OrSplit.java62
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/ParserWF.java357
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/Split.java217
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/WfVertex.java181
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/Workflow.java198
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/XOrSplit.java54
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/gui/model/WfEdgeFactory.java34
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/gui/model/WfGraphPanel.java58
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/gui/model/WfVertexFactory.java88
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/gui/model/WfVertexOutlineCreator.java51
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/gui/view/ActivityRenderer.java116
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/gui/view/FindActDefPanel.java69
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/gui/view/SplitJoinRenderer.java141
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/gui/view/TransitionPanel.java184
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/gui/view/WfDirectedEdgeRenderer.java128
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/gui/view/WfVertexRenderer.java22
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/predefined/AddC2KObject.java74
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/predefined/AddDomainPath.java66
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/predefined/AddStepsFromDescription.java55
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/predefined/AssignItemToSlot.java116
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/predefined/CreateItemFromDescription.java181
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/predefined/Erase.java83
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/predefined/Import.java68
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/predefined/PredefinedStep.java149
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/predefined/PredefinedStepContainer.java57
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/predefined/RemoveC2KObject.java66
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/predefined/RemoveDomainPath.java58
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/predefined/ReplaceDomainWorkflow.java52
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/predefined/ServerPredefinedStepContainer.java40
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/predefined/WriteProperty.java76
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/predefined/entitycreation/Aggregation.java26
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/predefined/entitycreation/AggregationMember.java21
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/predefined/entitycreation/CreateNewAgent.java46
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/predefined/entitycreation/CreateNewItem.java45
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/predefined/entitycreation/Dependency.java46
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/predefined/entitycreation/DependencyMember.java18
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/predefined/entitycreation/Geometry.java29
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/predefined/entitycreation/NewAgent.java65
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/predefined/entitycreation/NewItem.java145
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/predefined/entitycreation/Property.java26
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/stateMachine/StateMachine.java142
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/stateMachine/States.java40
-rwxr-xr-xsource/com/c2kernel/lifecycle/instance/stateMachine/Transitions.java41
-rwxr-xr-xsource/com/c2kernel/lifecycle/routingHelpers/ViewpointDataHelper.java79
-rwxr-xr-xsource/com/c2kernel/lookup/AgentPath.java152
-rwxr-xr-xsource/com/c2kernel/lookup/DomainPath.java153
-rwxr-xr-xsource/com/c2kernel/lookup/EntityPath.java172
-rwxr-xr-xsource/com/c2kernel/lookup/InvalidAgentPathException.java13
-rwxr-xr-xsource/com/c2kernel/lookup/InvalidEntityPathException.java13
-rwxr-xr-xsource/com/c2kernel/lookup/LDAPLookup.java461
-rwxr-xr-xsource/com/c2kernel/lookup/LDAPLookupUtils.java317
-rwxr-xr-xsource/com/c2kernel/lookup/LDAPPathSet.java70
-rwxr-xr-xsource/com/c2kernel/lookup/LDAPProperties.java38
-rwxr-xr-xsource/com/c2kernel/lookup/LDAPPropertyManager.java118
-rwxr-xr-xsource/com/c2kernel/lookup/LDAPRoleManager.java199
-rwxr-xr-xsource/com/c2kernel/lookup/LegacyLDAPPropertyManager.java70
-rwxr-xr-xsource/com/c2kernel/lookup/NextKeyManager.java72
-rwxr-xr-xsource/com/c2kernel/lookup/Path.java301
-rwxr-xr-xsource/com/c2kernel/lookup/RolePath.java117
-rwxr-xr-xsource/com/c2kernel/persistency/ClusterStorage.java104
-rwxr-xr-xsource/com/c2kernel/persistency/ClusterStorageException.java17
-rwxr-xr-xsource/com/c2kernel/persistency/ClusterStorageManager.java369
-rwxr-xr-xsource/com/c2kernel/persistency/LDAPClientReader.java39
-rwxr-xr-xsource/com/c2kernel/persistency/LDAPClusterStorage.java163
-rwxr-xr-xsource/com/c2kernel/persistency/ProxyLoader.java124
-rwxr-xr-xsource/com/c2kernel/persistency/RemoteMap.java404
-rwxr-xr-xsource/com/c2kernel/persistency/TransactionManager.java334
-rwxr-xr-xsource/com/c2kernel/persistency/XMLClusterStorage.java145
-rwxr-xr-xsource/com/c2kernel/persistency/outcome/Outcome.java159
-rwxr-xr-xsource/com/c2kernel/persistency/outcome/OutcomeValidator.java183
-rwxr-xr-xsource/com/c2kernel/persistency/outcome/Schema.java18
-rwxr-xr-xsource/com/c2kernel/persistency/outcome/SchemaValidator.java54
-rwxr-xr-xsource/com/c2kernel/persistency/outcome/Viewpoint.java176
-rwxr-xr-xsource/com/c2kernel/process/AbstractMain.java205
-rwxr-xr-xsource/com/c2kernel/process/Bootstrap.java356
-rwxr-xr-xsource/com/c2kernel/process/Gateway.java414
-rwxr-xr-xsource/com/c2kernel/process/ItemHTTPBridge.java52
-rwxr-xr-xsource/com/c2kernel/process/StandardClient.java16
-rwxr-xr-xsource/com/c2kernel/process/StandardServer.java125
-rwxr-xr-xsource/com/c2kernel/process/UserCodeProcess.java229
-rwxr-xr-xsource/com/c2kernel/property/Property.java82
-rwxr-xr-xsource/com/c2kernel/property/PropertyArrayList.java29
-rwxr-xr-xsource/com/c2kernel/property/PropertyDescription.java77
-rwxr-xr-xsource/com/c2kernel/property/PropertyDescriptionList.java53
-rwxr-xr-xsource/com/c2kernel/property/PropertyUtility.java87
-rwxr-xr-xsource/com/c2kernel/scripting/ErrorInfo.java43
-rwxr-xr-xsource/com/c2kernel/scripting/Parameter.java47
-rwxr-xr-xsource/com/c2kernel/scripting/ParameterException.java20
-rwxr-xr-xsource/com/c2kernel/scripting/Script.java438
-rwxr-xr-xsource/com/c2kernel/scripting/ScriptConsole.java234
-rwxr-xr-xsource/com/c2kernel/scripting/ScriptLoadingException.java24
-rwxr-xr-xsource/com/c2kernel/scripting/ScriptParsingException.java21
-rwxr-xr-xsource/com/c2kernel/scripting/ScriptingEngineException.java20
-rwxr-xr-xsource/com/c2kernel/utils/ActDefCache.java91
-rwxr-xr-xsource/com/c2kernel/utils/CastorArrayList.java30
-rwxr-xr-xsource/com/c2kernel/utils/CastorHashMap.java54
-rwxr-xr-xsource/com/c2kernel/utils/CastorXMLUtility.java126
-rwxr-xr-xsource/com/c2kernel/utils/DateUtility.java118
-rwxr-xr-xsource/com/c2kernel/utils/Dom4JElementParser.java38
-rwxr-xr-xsource/com/c2kernel/utils/FileStringUtility.java424
-rwxr-xr-xsource/com/c2kernel/utils/GTimeStampComparator.java26
-rwxr-xr-xsource/com/c2kernel/utils/KeyValuePair.java77
-rwxr-xr-xsource/com/c2kernel/utils/Language.java66
-rwxr-xr-xsource/com/c2kernel/utils/LocalObjectLoader.java77
-rwxr-xr-xsource/com/c2kernel/utils/Logger.java195
-rwxr-xr-xsource/com/c2kernel/utils/Resource.java187
-rwxr-xr-xsource/com/c2kernel/utils/SoftCache.java100
-rwxr-xr-xsource/com/c2kernel/utils/TransientCache.java115
-rwxr-xr-xsource/com/c2kernel/utils/XmlElementParser.java115
-rwxr-xr-xsource/com/c2kernel/utils/server/HTTPRequestHandler.java155
-rwxr-xr-xsource/com/c2kernel/utils/server/SimpleTCPIPServer.java112
-rwxr-xr-xsource/com/c2kernel/utils/server/SocketHandler.java15
-rwxr-xr-xsource/com/c2kernel/utils/server/UDPListener.java53
-rwxr-xr-xsource/idls/c2kernel/CommonExceptions.idl97
-rwxr-xr-xsource/idls/c2kernel/CommonTypes.idl42
-rwxr-xr-xsource/idls/c2kernel/Entity.idl182
454 files changed, 40924 insertions, 0 deletions
diff --git a/.classpath b/.classpath
new file mode 100755
index 0000000..89543fe
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="source"/>
+ <classpathentry kind="src" path="build/generated"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="lib" path="lib/js.jar"/>
+ <classpathentry kind="lib" path="lib/xercesImpl.jar"/>
+ <classpathentry kind="lib" path="lib/xml-apis.jar"/>
+ <classpathentry kind="lib" path="lib/wrapper.jar"/>
+ <classpathentry kind="lib" path="lib/bsf.jar"/>
+ <classpathentry kind="lib" path="lib/dom4j.jar"/>
+ <classpathentry kind="lib" path="lib/castor-xml.jar"/>
+ <classpathentry kind="lib" path="lib/castor-core.jar"/>
+ <classpathentry kind="lib" path="lib/castor-xml-schema.jar"/>
+ <classpathentry kind="lib" path="lib/commons-logging.jar"/>
+ <classpathentry kind="lib" path="lib/ldap.jar"/>
+ <classpathentry kind="output" path="build/classes"/>
+</classpath>
diff --git a/.project b/.project
new file mode 100755
index 0000000..342c899
--- /dev/null
+++ b/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>cristal-kernel</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>
diff --git a/bin/UserCode.bat b/bin/UserCode.bat
new file mode 100755
index 0000000..8c19296
--- /dev/null
+++ b/bin/UserCode.bat
@@ -0,0 +1,6 @@
+@echo off
+title Cristal 2 Usercode Agent
+call env.bat
+cd %CRISTAL_HOME%
+del %CRISTAL_HOME%\ucLog.txt
+java -classpath %LOCALCLASSPATH% com.c2kernel.process.UserCodeProcess -logFile %CRISTAL_HOME%\ucLog.txt -logLevel 0 -config %CRISTAL_HOME%\bin\conf\client.conf -connect %1
diff --git a/bin/ant.bat b/bin/ant.bat
new file mode 100755
index 0000000..c90887a
--- /dev/null
+++ b/bin/ant.bat
@@ -0,0 +1,110 @@
+@echo off
+
+if exist "%HOME%\antrc_pre.bat" call "%HOME%\antrc_pre.bat"
+
+if not "%OS%"=="Windows_NT" goto win9xStart
+:winNTStart
+@setlocal
+
+rem %~dp0 is name of current script under NT
+set DEFAULT_ANT_HOME=%~dp0
+
+rem : operator works similar to make : operator
+set DEFAULT_ANT_HOME=%DEFAULT_ANT_HOME%\..
+
+if "%ANT_HOME%"=="" set ANT_HOME=%DEFAULT_ANT_HOME%
+set DEFAULT_ANT_HOME=
+
+rem Need to check if we are using the 4NT shell...
+if "%eval[2+2]" == "4" goto setup4NT
+
+rem On NT/2K grab all arguments at once
+set ANT_CMD_LINE_ARGS=%*
+goto doneStart
+
+:setup4NT
+set ANT_CMD_LINE_ARGS=%$
+goto doneStart
+
+:win9xStart
+rem Slurp the command line arguments. This loop allows for an unlimited number of
+rem agruments (up to the command line limit, anyway).
+
+set ANT_CMD_LINE_ARGS=
+
+:setupArgs
+if %1a==a goto doneStart
+set ANT_CMD_LINE_ARGS=%ANT_CMD_LINE_ARGS% %1
+shift
+goto setupArgs
+
+:doneStart
+rem This label provides a place for the argument list loop to break out
+rem and for NT handling to skip to.
+
+rem find ANT_HOME
+if not "%ANT_HOME%"=="" goto checkJava
+
+rem check for ant in Program Files on system drive
+if not exist "%SystemDrive%\Program Files\ant" goto checkSystemDrive
+set ANT_HOME=%SystemDrive%\Program Files\ant
+goto checkJava
+
+:checkSystemDrive
+rem check for ant in root directory of system drive
+if not exist %SystemDrive%\ant\nul goto checkCDrive
+set ANT_HOME=%SystemDrive%\ant
+goto checkJava
+
+:checkCDrive
+rem check for ant in C:\ant for Win9X users
+if not exist C:\ant\nul goto noAntHome
+set ANT_HOME=C:\ant
+goto checkJava
+
+:noAntHome
+echo ANT_HOME is not set and ant could not be located. Please set ANT_HOME.
+goto end
+
+:checkJava
+set _JAVACMD=%JAVACMD%
+set LOCALCLASSPATH=%CLASSPATH%
+for %%i in ("%ANT_HOME%\lib\*.jar") do call "%ANT_HOME%\bin\lcp.bat" %%i
+
+if "%JAVA_HOME%" == "" goto noJavaHome
+if "%_JAVACMD%" == "" set _JAVACMD=%JAVA_HOME%\bin\java
+if exist "%JAVA_HOME%\lib\tools.jar" call "%ANT_HOME%\bin\lcp.bat" %JAVA_HOME%\lib\tools.jar
+if exist "%JAVA_HOME%\lib\classes.zip" call "%ANT_HOME%\bin\lcp.bat" %JAVA_HOME%\lib\classes.zip
+goto checkJikes
+
+:noJavaHome
+if "%_JAVACMD%" == "" set _JAVACMD=java
+echo.
+echo Warning: JAVA_HOME environment variable is not set.
+echo If build fails because sun.* classes could not be found
+echo you will need to set the JAVA_HOME environment variable
+echo to the installation directory of java.
+echo.
+
+:checkJikes
+if not "%JIKESPATH%" == "" goto runAntWithJikes
+
+:runAnt
+"%_JAVACMD%" -classpath "%LOCALCLASSPATH%" -Dant.home="%ANT_HOME%" %ANT_OPTS% org.apache.tools.ant.Main %ANT_CMD_LINE_ARGS%
+goto end
+
+:runAntWithJikes
+"%_JAVACMD%" -classpath "%LOCALCLASSPATH%" -Dant.home="%ANT_HOME%" -Djikes.class.path="%JIKESPATH%" %ANT_OPTS% org.apache.tools.ant.Main %ANT_CMD_LINE_ARGS%
+
+:end
+set LOCALCLASSPATH=
+set _JAVACMD=
+set ANT_CMD_LINE_ARGS=
+
+if not "%OS%"=="Windows_NT" goto mainEnd
+:winNTend
+@endlocal
+
+:mainEnd
+if exist "%HOME%\antrc_post.bat" call "%HOME%\antrc_post.bat"
+
diff --git a/bin/conf/client.conf b/bin/conf/client.conf
new file mode 100755
index 0000000..3a77f04
--- /dev/null
+++ b/bin/conf/client.conf
@@ -0,0 +1,3 @@
+LocalCentre=andy
+ClusterStorage=LDAPClientReader,ProxyLoader
+EnableItemErase=true
diff --git a/bin/conf/server.conf b/bin/conf/server.conf
new file mode 100755
index 0000000..a5a99d4
--- /dev/null
+++ b/bin/conf/server.conf
@@ -0,0 +1,4 @@
+LocalCentre=andy
+ClusterStorage=LDAPClusterStorage,XMLClusterStorage
+XMLStorage.root=C:/Users/andrew/workspace/cristal-kernel/db
+ItemServer.Console.allow=localhost,andrew
diff --git a/bin/env.bat b/bin/env.bat
new file mode 100755
index 0000000..f387d0e
--- /dev/null
+++ b/bin/env.bat
@@ -0,0 +1,5 @@
+@echo off
+set CRISTAL_HOME=%CD:~0,-4%
+set PATH=%PATH%;%CD%\win32
+set LOCALCLASSPATH=%CRISTAL_HOME%\build\classes
+for %%i in ("%CRISTAL_HOME%\lib\*.jar") do call "lcp.bat" %%i
diff --git a/bin/itemServer.bat b/bin/itemServer.bat
new file mode 100755
index 0000000..d154472
--- /dev/null
+++ b/bin/itemServer.bat
@@ -0,0 +1,7 @@
+@echo off
+title ItemServer
+call env.bat
+cd %CRISTAL_HOME%
+del %CRISTAL_HOME%\serverLog.txt
+java -Xmx256m -Xbootclasspath/p:%CRISTAL_HOME%\lib\OB.jar -classpath %LOCALCLASSPATH% com.c2kernel.process.StandardServer -logFile %CRISTAL_HOME%\serverLog.txt -logLevel 0 -config %CRISTAL_HOME%\bin\conf\server.conf -connect %1
+pause \ No newline at end of file
diff --git a/bin/itemServer.sh b/bin/itemServer.sh
new file mode 100755
index 0000000..3b32543
--- /dev/null
+++ b/bin/itemServer.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+CRISTAL2_HOME=/home/dracor/workspace/cristal-kernel
+
+for i in ${CRISTAL2_HOME}/lib/*.jar;
+ do
+ test -f $i || continue
+ LOCALCLASSPATH=${LOCALCLASSPATH}:${i}
+ echo ${i}
+ done
+
+LOCALCLASSPATH=${LOCALCLASSPATH}:${CRISTAL2_HOME}/build/lib/c2kernel.jar
+
+rm -f ${CRISTAL2_HOME}/serverLog.txt
+java -Xmx256m -Xbootclasspath/p:${CRISTAL2_HOME}/lib/OB.jar -classpath ${LOCALCLASSPATH} com.c2kernel.process.StandardServer -logFile ${CRISTAL2_HOME}/serverLog.txt -logLevel 8 -config ${CRISTAL2_HOME}/bin/conf/server.conf -connect ${CRISTAL2_HOME}/connect/uwe.clc
diff --git a/bin/lcp.bat b/bin/lcp.bat
new file mode 100755
index 0000000..f2bb801
--- /dev/null
+++ b/bin/lcp.bat
@@ -0,0 +1,9 @@
+set _CLASSPATHCOMPONENT=%1
+:argCheck
+if %2a==a goto gotAllArgs
+shift
+set _CLASSPATHCOMPONENT=%_CLASSPATHCOMPONENT% %1
+goto argCheck
+:gotAllArgs
+set LOCALCLASSPATH=%LOCALCLASSPATH%;%_CLASSPATHCOMPONENT%
+
diff --git a/bin/runGUI.bat b/bin/runGUI.bat
new file mode 100755
index 0000000..90ce2b8
--- /dev/null
+++ b/bin/runGUI.bat
@@ -0,0 +1,6 @@
+@echo off
+title Cristal 2 Gui
+call env.bat
+cd %CRISTAL_HOME%
+del %CRISTAL_HOME%\guiLog.txt
+java -classpath %LOCALCLASSPATH% com.c2kernel.gui.Main -logFile %CRISTAL_HOME%\guiLog.txt -logLevel 0 -config %CRISTAL_HOME%\bin\conf\client.conf -connect %1
diff --git a/bin/runOutcomeEditor.bat b/bin/runOutcomeEditor.bat
new file mode 100755
index 0000000..58f3700
--- /dev/null
+++ b/bin/runOutcomeEditor.bat
@@ -0,0 +1,5 @@
+@echo off
+title OutcomeEditor
+call env.bat
+cd %CRISTAL_HOME%
+java -classpath %LOCALCLASSPATH% com.c2kernel.gui.tabs.outcome.form.OutcomeEditor %1 %2
diff --git a/bin/win32/SQLiteSpy.db3 b/bin/win32/SQLiteSpy.db3
new file mode 100755
index 0000000..fd76b25
--- /dev/null
+++ b/bin/win32/SQLiteSpy.db3
Binary files differ
diff --git a/bin/win32/SQLiteSpy.exe b/bin/win32/SQLiteSpy.exe
new file mode 100755
index 0000000..04cf3c8
--- /dev/null
+++ b/bin/win32/SQLiteSpy.exe
Binary files differ
diff --git a/bin/win32/Wrapper.dll b/bin/win32/Wrapper.dll
new file mode 100755
index 0000000..38b7807
--- /dev/null
+++ b/bin/win32/Wrapper.dll
Binary files differ
diff --git a/bin/win32/clc.reg b/bin/win32/clc.reg
new file mode 100755
index 0000000..78bdc72
--- /dev/null
+++ b/bin/win32/clc.reg
Binary files differ
diff --git a/bin/win32/iordump.exe b/bin/win32/iordump.exe
new file mode 100755
index 0000000..5a9d947
--- /dev/null
+++ b/bin/win32/iordump.exe
Binary files differ
diff --git a/bin/win32/sqlite3.exe b/bin/win32/sqlite3.exe
new file mode 100755
index 0000000..4387f7b
--- /dev/null
+++ b/bin/win32/sqlite3.exe
Binary files differ
diff --git a/bin/win32/sqlite_jni.dll b/bin/win32/sqlite_jni.dll
new file mode 100755
index 0000000..875c435
--- /dev/null
+++ b/bin/win32/sqlite_jni.dll
Binary files differ
diff --git a/build.xml b/build.xml
new file mode 100755
index 0000000..3bff88d
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project basedir="." default="release-build" name="cristal">
+ <!--===================================================================-->
+ <!-- Global properties -->
+ <!-- NOTE: Ant will automatically will add all jar files to the -->
+ <!-- classpath from the $(ANT_HOME)/lib directory. In cristal2 -->
+ <!-- setup this directories are equal to the cristal2/lib -->
+ <!-- directory which eliminates thecalculation of classpath for -->
+ <!-- the most of the 'javac' tasks -->
+ <!--===================================================================-->
+ <property name="name" value="cristal2"/>
+ <property name="version" value="1.0"/>
+ <!--===================================================================-->
+ <!-- Directories -->
+ <!--===================================================================-->
+ <property name="src.dir" value="source"/>
+ <property name="idls.dir" value="${src.dir}/idls"/>
+ <property name="c2k.dir" value="com/c2kernel"/>
+ <property name="bin.dir" value="bin"/>
+ <property name="lib.dir" value="lib"/>
+ <property name="docs.dir" value="doc"/>
+ <property name="dist.dir" value="dist"/>
+ <property name="build.dir" value="build"/>
+ <property name="resource.dir" value="resources"/>
+ <!--===================================================================-->
+ <!-- Build Directories -->
+ <!--===================================================================-->
+ <property name="build.generated" value="${build.dir}/generated"/>
+ <property name="build.classes" value="${build.dir}/classes"/>
+ <property name="build.javadoc" value="${build.dir}/docs"/>
+ <property name="build.lib" value="${build.dir}/lib"/>
+ <!--===================================================================-->
+ <!-- Global javacc attributes -->
+ <!--===================================================================-->
+ <property name="debug" value="true"/>
+ <property name="deprecation" value="false"/>
+ <property name="optimize" value="true"/>
+ <property name="junit.fork" value="false"/>
+ <path id="c2classpath">
+ <fileset dir="${lib.dir}" includes="*.jar" />
+ <fileset dir="${build.classes}" />
+ </path>
+ <!-- ==================================================================-->
+ <!-- The pattern for the support files that need -->
+ <!-- to be copied when compiling classes -->
+ <!-- ==================================================================-->
+ <patternset id="resource.files">
+ <include name="boot/**/*.txt"/>
+ <include name="boot/**/*.xml"/>
+ <include name="schemas/*.xsd"/>
+ <include name="mapFiles/*.xml"/>
+ <include name="textFiles/*.*"/>
+ <include name="images/**/*.gif"/>
+ <include name="images/**/*.jpg"/>
+ <include name="images/**/*.png"/>
+ </patternset>
+
+ <!--===================================================================-->
+ <!-- Prepare the build (takes the timestamp see: Ant1.3 docs) -->
+ <!--===================================================================-->
+ <target name="prepare">
+ <tstamp/>
+ </target>
+ <!--===================================================================-->
+ <!-- Create directories required to build -->
+ <!--===================================================================-->
+ <target name="build-dirs">
+ <mkdir dir="${build.generated}"/>
+ <mkdir dir="${build.classes}"/>
+ <mkdir dir="${build.lib}"/>
+ </target>
+
+ <target name="clean" description="cleans up the build directories">
+ <delete dir="${build.dir}"/>
+ </target>
+ <!--===================================================================-->
+ <!-- Builds cristal2 completly calling all necessary 'build-*' targets -->
+ <!--===================================================================-->
+ <target name="release-build" depends="build-all" description="compiles cristal"/>
+ <!--===================================================================-->
+ <!-- Builds cristal2 cleanly -->
+ <!--===================================================================-->
+ <target name="rebuild" depends="clean, release-build" description="deletes and recompiles the whole of cristal2"/>
+ <!--===================================================================-->
+ <!-- Jars -->
+ <!--===================================================================-->
+ <target name="jars" depends="c2k-jar" description="creates the kernel and domain jars"/>
+ <target name="c2k-jar" depends="build-c2k" description="Compile Kernel jar">
+ <jar basedir="${build.classes}" includes="${c2k.dir}/**" jarfile="${build.lib}/c2kernel.jar"/>
+ </target>
+ <target name="clean-jars" depends="clean, jars" description="Builds fresh jars"/>
+ <!--===================================================================-->
+ <!-- Compile everything -->
+ <!--===================================================================-->
+ <target name="build-all" depends="build-c2k"/>
+ <!--===================================================================-->
+ <!-- Builds com.c2kernel packages -->
+ <!--===================================================================-->
+ <target name="build-c2k" depends="build-idls, resources" description="build com.c2kernel packages">
+ <javac classpath="${build.classes}" debug="${debug}" deprecation="${deprecation}" destdir="${build.classes}" includes="${c2k.dir}/**" optimize="${optimize}" srcdir="${src.dir}" includeantruntime="false">
+ <classpath>
+ <path refid="c2classpath"/>
+ </classpath>
+ </javac>
+ </target>
+ <!--===================================================================-->
+ <!-- Assembles cristal2 resources -->
+ <!--===================================================================-->
+ <target name="resources" depends="prepare, build-dirs" description="Moves all resources to the build directory for the Resource class to read">
+ <mkdir dir="${build.classes}/com/c2kernel/utils/resources"/>
+ <copy todir="${build.classes}/com/c2kernel/utils/resources">
+ <fileset dir="${resource.dir}">
+ <patternset refid="resource.files"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <!--===================================================================-->
+ <!-- Creates javadoc for the complete CRISTAL2 -->
+ <!--===================================================================-->
+ <target name="c2k-doc" description="Creates javadoc for the kernel" depends="prepare, build-dirs">
+ <mkdir dir="${build.javadoc}"/>
+ <javadoc author="true"
+ bottom="Copyright (C) 2000-2011 CRISTAL Consortium. All Rights Reserved." destdir="${build.javadoc}" doctitle="Cristal 2 Kernel" packagenames="com.c2kernel.*" sourcepath="${src.dir};${build.generated}" version="true" windowtitle="Cristal 2 Kernel">
+ <group packages="com.c2kernel" title="Cristal2 Kernel"/>
+ </javadoc>
+ </target>
+
+ <!--===================================================================-->
+ <!-- Compile IDLs -->
+ <!--===================================================================-->
+ <target name="idls-check">
+ <uptodate property="idls.notrequired" targetfile="${build.generated}/com/c2kernel/entity/ItemPOA.java">
+ <srcfiles dir="${idls.dir}" includes="**/*.idl"/>
+ </uptodate>
+ </target>
+ <target name="gen-idls" depends="prepare, build-dirs, idls-check" description="generate java from idls" unless="idls.notrequired">
+ <echo message="Starting compiling idls."/>
+ <apply dir="${idls.dir}/c2kernel" executable="idlj" failonerror="true">
+ <arg value="-v"/>
+ <arg value="-fall"/>
+ <arg value="-pkgPrefix"/>
+ <arg value="entity"/>
+ <arg value="com.c2kernel"/>
+ <arg value="-pkgPrefix"/>
+ <arg value="common"/>
+ <arg value="com.c2kernel"/>
+ <arg value="-td"/>
+ <arg value="${basedir}/${build.generated}"/>
+ <fileset dir="${idls.dir}/c2kernel">
+ <include name="*.idl"/>
+ </fileset>
+ </apply>
+ <echo message="Finished compiling idls."/>
+ </target>
+ <!--===================================================================-->
+ <!-- Compile Java code generated by java2idl -->
+ <!--===================================================================-->
+ <target name="build-idls" depends="gen-idls" description="compile idl generated java code">
+ <javac debug="${debug}" deprecation="${deprecation}" destdir="${build.classes}" optimize="${optimize}" srcdir="${build.generated}" includeantruntime="false"/>
+ </target>
+</project>
diff --git a/changelog b/changelog
new file mode 100755
index 0000000..3943af6
--- /dev/null
+++ b/changelog
@@ -0,0 +1,139 @@
+- SYS: Cleaned up some proxy methods. getContents() now calls storage directly.
+- SYS: Removed Orbacus. Use JDK ORB instead. Use JDK idlj compiler instead of Orbacus one. Remove all Orbacus tools.
+Build 3 - Last CERN
+- GUI: Local object creating script now opens new desc when done.
+- LDAP: Optimised Path setting by String.
+- DB: Renamed 'delete' method in storage to 'remove' for compatibility with javascript engine
+- WF: Fixed overwriting cached actdef properties, corrupting for future wfs
+Build 2
+- SYS: Reduced interdependency between kernel singletons. Less back-calls to the gateway.
+- GUI: Fixed bad subscription breaking collection pane refresh.
+- GUI: Fixed NullPointerException trying to open items from tree collection.
+- WF: Implemented version numbers for wfdef references
+- DB: Separated LocalObjectLoader from Resource. Implemented cache for unmarshalled activity defs.
+- WF: Cut down number of calls to 'PushJobsToAgent'. This was slowing instantiation.
+- WF: Further cleaning. Simplified instantiation.
+- GUI: Close all and close other tabs in the File menu
+- SYS: New agent proxy util method - getItemByPath
+- GUI: Stop cell edit when new row added
+Build 1
+- DB: Removed schema validator caching
+- GUI: New icon set. Reorganised all image resources.
+- INST: Updated installer to NSIS 2.06
+- GUI: Fixed bug with read-only tables not being read only.
+- GUI: Add and remove vertex properties
+- GUI: Attributes are included in the first grabFocus() search
+- GUI: Dimensions no longer create an empty first row when they are created, if their minOccurs is 0.
+- SYS: Item and Agent factories have been replaced with a single item created on boot. It is registered with the name of the server so it is now possible for a centre to be shared between more than one server process.
+- GUI: Cleaned up menus
+- GUI: Unified Wf and Coll property pane into a single Vertex one
+- WF: Removed a lot of Aglium specific stuff - commonInterface, timeOut, Prefill
+- WF: Removed errors on no child in compostite activity and XOR script existence checking (too heavy)
+- GUI: Elementary activity outcome handler - based on property pane.
+- GUI: Cut down calls to check for Admin role. GUI will have to be restarted for admin role change to take effect.
+- GUI: Better read-only support in vertex property panel. New panel for act defs - finds child act def item.
+- GRAPH: clicking outside a vertex selects the containing graphable vertex, if present. Used for editing props of composite activity def etc.
+- SYS: Entity Exception throwing clarified
+- LDAP: Role management API simplified. Roles can now have no agents.
+- LDAP: Reorganised the LDAP package into various managers, simplified API. Most calls now go through the Path objects. No LDAP library objects should leave the lookup package now.
+- COLL: ClassCastException on Dependency.removeMember(id) fixed
+- BOOT: Bootloader creates script, activity definition and schema items at boot time. Old resource schema loading disabled.
+- SYS: Console ports are automatically assigned if none is specified. Chosen port is logged. GUI Client Console menu option is aware of the choice.
+- SYS: Console access: Default policy is to only allow connection from localhost.
+- GUI: List Of Values in outcome form - only supports enumerations for now.
+- SCR: Added support for <include> tag in script xml to include other scripts
+- GUI: Removed 'auto-refresh execution pane' option - set to always reload
+- SYS: Changed SoftCache implementation to use ReferenceQueue to manage reaped objects. Should be more efficient.
+- LDAP: Changed LDAP property storage to attribute instead on child entry. Lots faster and appears in alias for query.
+- SYS: Moved all API objects out of AbstractMain into the Gateway. AbstractMain is no longer required to initialise a kernel process.
+- SYS: Moved Gateway to process package. Moved LDAP init to process.Bootstrap - will be entry point for basic item creation
+
+Changes for release 1.2
+-----------------------
+Build 22
+- GUI: Multiple table row select when read only
+Build 21
+- GUI: Aggregation history browsing
+- GUI: Image field editing
+Build 20
+- GUI: save/load execution xml
+Build 19
+- GUI: implemented Array editing
+Build 18
+- DB: Add 'queryToXML' to return the results as an XML string instead of a native result set.
+- WF: Disabled EventList in wf. Removed OutcomeDataHelper and all timeout and prefill code.
+Build 17
+- GUI: Added image display of Base64Binary schema datatype
+Build 16
+- WF: Removed state and transition translation tables - not used
+- GUI: Added activity state hacking for administrators in workflow pane
+Build 15
+- WF: Optimised CompositeActivityDef unmarshalling, it was loading child activity defs multiple times. Should speed up item registration, especially for large workflows. Also cut down on slot loading child actdef.
+Build 14
+- SYS: Fixed proxy subscription attempt before connection to proxy server established
+Build 13
+- GUI: SwingWorker style tree building, should stop the exceptions and empty space problems
+- GUI: Data records and dimensions that aren't immediately visible are deferred until they are selected
+- GUI: Console supports loading scripts from a file (with %s replacement with input text)
+- GUI: Workflow pane returns to last viewed graph on refresh/update. Property Panel resets on model change.
+- GUI: Outcome viewer empty fields are left empty in read-only mode.
+Build 12
+- GUI: Fixed crash of properties pane when user is not administrator
+- GUI: Fixed crash in viewpoint pane if no 'last' view is present for outcome type
+- GUI: Outcome form can cope with empty elements in tables (provided datatype is supplied)
+Build 11
+- SYS: Strings without translation are logged in the file 'untranslated.txt'
+- GUI: Removed translation calls for outcome form element names
+- GUI: Fixed strange tree behaviour (large white gaps, incomplete labels) caused by wrongly sized labels
+- GUI: Extended about box to include copyright notices and license links for third party components
+Build 10
+- GUI: Changed LoginBox key listener for compatibility with java 1.4
+- LDAP: Fixed read-ahead bug causing hang when invalid entry received
+- GUI: DomainPath edit section of property pane rewritten. Supports changing
+- GUI: New Collection pane supports multiple collections per item. Dependency view not yet implemented
+Build 9
+- GUI: Fixed tree refresh
+- DB: Added Schema validation
+Build 8
+- WF: Fixed Join proceeding when a previous Composite was still active
+- WF: Fixed Composite activity calculateAllJobs for Item.queryLifecycle filter=false
+- LDAP: LDAPLookup uses a query batch size to speed up loading of the tree. It will only load 100 nodes at a time.
+- UC: Usercode process suspends on all Throwables instead of just Exceptions. This catches OutOfMemoryErrors.
+- SYS: Added version resources
+
+Release 1.1
+-----------
+
+- WF: New workflow straight edge styles
+- DB: Storage clusters were not being queried in the order specified in the config. Fixed.
+- GUI: Combined Outcome and Viewpoint Panes as single History/Outcome/Event pane
+- DB: Fixed LDAP retrieval of properties
+- SYS: Partially implemented Entity Proxy reaping
+- SYS: Fixed proxy connection hang
+- SYS: Fixed proxy disconnection exception
+- GUI: Changed admin property updating to use marshalling
+- DB: Made persistent objects java.io.Serializable to allow simple binary cluster storage
+- WF: Multi-threaded job pushing
+- WF: SKIP transition clears reservation, as it could have been set by RESERVE
+- GUI: Copy/Paste graph layouts (only supported in Java 1.4+)
+- WF: Fixed loop/join backlink detection
+- SYS: Client notification of domain path changes
+- WF: Fixed bug where repeating activities were never ignorable
+- DB: Dependency collection was not marshalled properly
+- SYS: Implemented soft reference cache to let unused cached objects get reaped by the VM when memory is tight. Used for caching:
+ - Entities in memory on the server
+ - Entity Proxies
+ - C2KLocalObjects in ClusterStorage memory cache
+ - SchemaValidators
+- SYS: Server entity Reaper is no longer needed under soft caching.
+- SYS: Split kernel/domain resources. Domain specific jars can now be kept in the domain jar or at a URL.
+- SYS: Proxy subscriptions hold observers by WeakReference, to not lock them in memory.
+- SYS: Various EntityProxy utils
+- LDAP: Change IOR encoding to hostname to allow IP change
+- WF: Fixed addition of composite activities into instance workflow from composition
+
+Release 1.0
+-----------
+
+- Initial Release
+
diff --git a/connect/dev.clc.example b/connect/dev.clc.example
new file mode 100755
index 0000000..d912536
--- /dev/null
+++ b/connect/dev.clc.example
@@ -0,0 +1,29 @@
+// Cristal 2 Connect Local Centre example file
+// Copy this and change things
+
+// This name appears on the login box
+Name=Another Cristal Server
+Logo=http://path.to/image
+
+// Specify the URL for domain resources, or a package path
+DomainResourceURL=
+
+// Orbacus config
+ooc.iiop.port=1500
+
+// TCP server ports
+ItemServer.name=HOSTNAME
+ItemServer.HTTP.port=8000
+ItemServer.Proxy.port=1553
+ItemServer.Console.port=8080
+Incoming.port=89
+
+// LDAP Lookup config
+LDAP.GlobalPath=LDAPROOTPATH
+LDAP.RootPath=cn=cristal2
+LDAP.LocalPath=cn=LCNAME
+LDAP.port=389
+LDAP.host=LDAPHOSTNAME
+// note these two values should be removed when we're in production
+LDAP.user=LDAPROOTUSER
+LDAP.password=LDAPPASSWORD
diff --git a/javadoc.xml b/javadoc.xml
new file mode 100755
index 0000000..f0bd8cf
--- /dev/null
+++ b/javadoc.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<project default="javadoc">
+ <target name="javadoc">
+ <javadoc access="public" author="true" classpath="lib/castor-core.jar;lib/ldap.jar;lib/xml-apis.jar;lib/castor-xml.jar;lib/dom4j.jar;lib/OBUtil.jar;lib/xercesImpl.jar;lib/bsf.jar;lib/js.jar;lib/castor-xml-schema.jar;lib/wrapper.jar;lib/commons-logging.jar;lib/OB.jar" destdir="doc" doctitle="Cristal Kernel" nodeprecated="false" nodeprecatedlist="false" noindex="false" nonavbar="false" notree="false" packagenames="com.c2kernel.gui,com.c2kernel.lifecycle.instance,com.c2kernel.lifecycle.instance.gui.view,com.c2kernel.utils.server,com.c2kernel.process,com.c2kernel.events,com.c2kernel.lifecycle.gui.view,com.c2kernel.property,com.c2kernel.gui.tabs.outcome.form.field,com.c2kernel.gui.tabs.outcome,com.c2kernel.gui.tabs.outcome.form,com.c2kernel.lookup,com.c2kernel.utils,com.c2kernel.lifecycle,com.c2kernel.persistency,com.c2kernel.lifecycle.chooser,com.c2kernel.scripting,com.c2kernel.collection.gui.view,com.c2kernel.gui.tabs.collection,com.c2kernel.graph.model,com.c2kernel.graph.layout,com.c2kernel.lifecycle.routingHelpers,com.c2kernel.graph.traversal,com.c2kernel.entity.proxy,com.c2kernel.gui.data,com.c2kernel.lifecycle.gui.model,com.c2kernel.lifecycle.instance.gui.model,com.c2kernel.graph.view,com.c2kernel.persistency.outcome,com.c2kernel.lifecycle.instance.predefined,com.c2kernel.collection,com.c2kernel.lifecycle.instance.predefined.entitycreation,com.c2kernel.graph.event,com.c2kernel.gui.tabs,com.c2kernel.entity.agent,com.c2kernel.entity.transfer,com.c2kernel.lifecycle.instance.stateMachine,com.c2kernel.gui.tabs.execution,com.c2kernel.collection.gui.model,com.c2kernel.graph.controller" source="1.6" sourcefiles="source/com/c2kernel/entity/C2KLocalObject.java,source/com/c2kernel/entity/TraceableLocator.java,source/com/c2kernel/entity/TraceableEntity.java,source/com/c2kernel/entity/CorbaServer.java" sourcepath="build/generated;source" splitindex="true" use="true" version="true">
+ <link href="http://java.sun.com/javase/6/docs/api/"/>
+ </javadoc>
+ </target>
+</project>
diff --git a/lib/bsf.jar b/lib/bsf.jar
new file mode 100755
index 0000000..619a135
--- /dev/null
+++ b/lib/bsf.jar
Binary files differ
diff --git a/lib/castor-core.jar b/lib/castor-core.jar
new file mode 100755
index 0000000..03ff0b2
--- /dev/null
+++ b/lib/castor-core.jar
Binary files differ
diff --git a/lib/castor-xml-schema.jar b/lib/castor-xml-schema.jar
new file mode 100755
index 0000000..9dc9c00
--- /dev/null
+++ b/lib/castor-xml-schema.jar
Binary files differ
diff --git a/lib/castor-xml.jar b/lib/castor-xml.jar
new file mode 100755
index 0000000..8bf7639
--- /dev/null
+++ b/lib/castor-xml.jar
Binary files differ
diff --git a/lib/commons-logging.jar b/lib/commons-logging.jar
new file mode 100755
index 0000000..b73a80f
--- /dev/null
+++ b/lib/commons-logging.jar
Binary files differ
diff --git a/lib/dom4j.jar b/lib/dom4j.jar
new file mode 100755
index 0000000..b7b31eb
--- /dev/null
+++ b/lib/dom4j.jar
Binary files differ
diff --git a/lib/js.jar b/lib/js.jar
new file mode 100755
index 0000000..f92e9f9
--- /dev/null
+++ b/lib/js.jar
Binary files differ
diff --git a/lib/ldap.jar b/lib/ldap.jar
new file mode 100755
index 0000000..3709cb6
--- /dev/null
+++ b/lib/ldap.jar
Binary files differ
diff --git a/lib/wrapper.jar b/lib/wrapper.jar
new file mode 100755
index 0000000..d4ca1e9
--- /dev/null
+++ b/lib/wrapper.jar
Binary files differ
diff --git a/lib/xercesImpl.jar b/lib/xercesImpl.jar
new file mode 100755
index 0000000..33990e8
--- /dev/null
+++ b/lib/xercesImpl.jar
Binary files differ
diff --git a/lib/xml-apis.jar b/lib/xml-apis.jar
new file mode 100755
index 0000000..b338fb6
--- /dev/null
+++ b/lib/xml-apis.jar
Binary files differ
diff --git a/resources/boot/CA/CompositeActivityFactory.xml b/resources/boot/CA/CompositeActivityFactory.xml
new file mode 100755
index 0000000..1a963cb
--- /dev/null
+++ b/resources/boot/CA/CompositeActivityFactory.xml
@@ -0,0 +1,108 @@
+<CompositeActivityDef ID="-1" Name="CompositeActivityFactory" Height="0" Width="0" IsLayoutable="false" IsComposite="true">
+ <childrenGraphModel>
+ <GraphModelCastorData ClassNameOfVertexOutlineCreator="com.c2kernel.lifecycle.gui.model.WfVertexDefOutlineCreator" StartVertexId="5" NextId="14">
+ <JoinDef ID="6" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="321" y="325"/>
+ <OutlinePoint x="291" y="313"/>
+ <OutlinePoint x="351" y="313"/>
+ <OutlinePoint x="351" y="337"/>
+ <OutlinePoint x="291" y="337"/>
+ <InEdgeId>9</InEdgeId>
+ <Properties>
+ <KeyValuePair Key="Type" String="Join"/>
+ </Properties>
+ </JoinDef>
+ <JoinDef ID="5" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="321" y="92"/>
+ <OutlinePoint x="291" y="80"/>
+ <OutlinePoint x="351" y="80"/>
+ <OutlinePoint x="351" y="104"/>
+ <OutlinePoint x="291" y="104"/>
+ <InEdgeId>7</InEdgeId>
+ <OutEdgeId>12</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Type" String="Join"/>
+ </Properties>
+ </JoinDef>
+ <LoopDef ID="3" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false" isNext="0">
+ <CentrePoint x="321" y="211"/>
+ <OutlinePoint x="291" y="199"/>
+ <OutlinePoint x="351" y="199"/>
+ <OutlinePoint x="351" y="223"/>
+ <OutlinePoint x="291" y="223"/>
+ <InEdgeId>13</InEdgeId>
+ <OutEdgeId>7</OutEdgeId>
+ <OutEdgeId>9</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="LastNum" String="2"/>
+ <KeyValuePair Key="RoutingScriptVersion" String=""/>
+ <KeyValuePair Key="RoutingScriptName" String="javascript:true;"/>
+ </Properties>
+ </LoopDef>
+ <ActivitySlotDef ID="10" Name="CreateNewLocalObjectDef_" Height="60" Width="130" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="133" y="215"/>
+ <OutlinePoint x="68" y="185"/>
+ <OutlinePoint x="198" y="185"/>
+ <OutlinePoint x="198" y="245"/>
+ <OutlinePoint x="68" y="245"/>
+ <InEdgeId>12</InEdgeId>
+ <OutEdgeId>13</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Prefill" Boolean="false"/>
+ <KeyValuePair Key="Prefill Version" String="-1"/>
+ <KeyValuePair Key="Name" String="CreateNewCompositeActivityDef"/>
+ <KeyValuePair Key="NewType" String="CA"/>
+ </Properties>
+ <activityDef>CreateNewLocalObjectDef</activityDef>
+ </ActivitySlotDef>
+ <NextDef ID="13" OriginVertexId="10" TerminusVertexId="3">
+ <OriginPoint x="133" y="215"/>
+ <TerminusPoint x="321" y="211"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="12" OriginVertexId="5" TerminusVertexId="10">
+ <OriginPoint x="321" y="92"/>
+ <TerminusPoint x="133" y="215"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="9" OriginVertexId="3" TerminusVertexId="6">
+ <OriginPoint x="321" y="211"/>
+ <TerminusPoint x="321" y="325"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="false"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="7" OriginVertexId="3" TerminusVertexId="5">
+ <OriginPoint x="321" y="211"/>
+ <TerminusPoint x="321" y="92"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="true"/>
+ </Properties>
+ </NextDef>
+ </GraphModelCastorData>
+ </childrenGraphModel>
+ <Properties>
+ <KeyValuePair Key="Repeatable" Boolean="false"/>
+ <KeyValuePair Key="Agent Name" String=""/>
+ <KeyValuePair Key="Autostart" Boolean="true"/>
+ <KeyValuePair Key="Mail Message" String=""/>
+ <KeyValuePair Key="Mail event" String=""/>
+ <KeyValuePair Key="Description" String=""/>
+ <KeyValuePair Key="SchemaVersion" String=""/>
+ <KeyValuePair Key="Show time" Boolean="true"/>
+ <KeyValuePair Key="Viewpoint" String=""/>
+ <KeyValuePair Key="Agent Role" String=""/>
+ <KeyValuePair Key="SchemaType" String=""/>
+ <KeyValuePair Key="ScriptName" String=""/>
+ <KeyValuePair Key="Ignorable" Boolean="false"/>
+ <KeyValuePair Key="ScriptVersion" String=""/>
+ <KeyValuePair Key="Skippable" Boolean="false"/>
+ </Properties>
+ <castorNonLayoutableChildren>CreateNewLocalObjectDef</castorNonLayoutableChildren>
+</CompositeActivityDef>
diff --git a/resources/boot/CA/ElementaryActivityFactory.xml b/resources/boot/CA/ElementaryActivityFactory.xml
new file mode 100755
index 0000000..bf14607
--- /dev/null
+++ b/resources/boot/CA/ElementaryActivityFactory.xml
@@ -0,0 +1,108 @@
+<CompositeActivityDef ID="-1" Name="ElementaryActivityFactory" Height="0" Width="0" IsLayoutable="false" IsComposite="true">
+ <childrenGraphModel>
+ <GraphModelCastorData ClassNameOfVertexOutlineCreator="com.c2kernel.lifecycle.gui.model.WfVertexDefOutlineCreator" StartVertexId="5" NextId="14">
+ <JoinDef ID="6" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="321" y="325"/>
+ <OutlinePoint x="291" y="313"/>
+ <OutlinePoint x="351" y="313"/>
+ <OutlinePoint x="351" y="337"/>
+ <OutlinePoint x="291" y="337"/>
+ <InEdgeId>9</InEdgeId>
+ <Properties>
+ <KeyValuePair Key="Type" String="Join"/>
+ </Properties>
+ </JoinDef>
+ <JoinDef ID="5" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="321" y="92"/>
+ <OutlinePoint x="291" y="80"/>
+ <OutlinePoint x="351" y="80"/>
+ <OutlinePoint x="351" y="104"/>
+ <OutlinePoint x="291" y="104"/>
+ <InEdgeId>7</InEdgeId>
+ <OutEdgeId>12</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Type" String="Join"/>
+ </Properties>
+ </JoinDef>
+ <LoopDef ID="3" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false" isNext="0">
+ <CentrePoint x="321" y="211"/>
+ <OutlinePoint x="291" y="199"/>
+ <OutlinePoint x="351" y="199"/>
+ <OutlinePoint x="351" y="223"/>
+ <OutlinePoint x="291" y="223"/>
+ <InEdgeId>13</InEdgeId>
+ <OutEdgeId>7</OutEdgeId>
+ <OutEdgeId>9</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="LastNum" String="2"/>
+ <KeyValuePair Key="RoutingScriptVersion" String=""/>
+ <KeyValuePair Key="RoutingScriptName" String="javascript:true;"/>
+ </Properties>
+ </LoopDef>
+ <ActivitySlotDef ID="10" Name="CreateNewLocalObjectDef_" Height="60" Width="130" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="133" y="215"/>
+ <OutlinePoint x="68" y="185"/>
+ <OutlinePoint x="198" y="185"/>
+ <OutlinePoint x="198" y="245"/>
+ <OutlinePoint x="68" y="245"/>
+ <InEdgeId>12</InEdgeId>
+ <OutEdgeId>13</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Prefill" Boolean="false"/>
+ <KeyValuePair Key="Prefill Version" String="-1"/>
+ <KeyValuePair Key="Name" String="CreateNewElementaryActivityDef"/>
+ <KeyValuePair Key="NewType" String="EA"/>
+ </Properties>
+ <activityDef>CreateNewLocalObjectDef</activityDef>
+ </ActivitySlotDef>
+ <NextDef ID="13" OriginVertexId="10" TerminusVertexId="3">
+ <OriginPoint x="133" y="215"/>
+ <TerminusPoint x="321" y="211"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="12" OriginVertexId="5" TerminusVertexId="10">
+ <OriginPoint x="321" y="92"/>
+ <TerminusPoint x="133" y="215"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="9" OriginVertexId="3" TerminusVertexId="6">
+ <OriginPoint x="321" y="211"/>
+ <TerminusPoint x="321" y="325"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="false"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="7" OriginVertexId="3" TerminusVertexId="5">
+ <OriginPoint x="321" y="211"/>
+ <TerminusPoint x="321" y="92"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="true"/>
+ </Properties>
+ </NextDef>
+ </GraphModelCastorData>
+ </childrenGraphModel>
+ <Properties>
+ <KeyValuePair Key="Repeatable" Boolean="false"/>
+ <KeyValuePair Key="Agent Name" String=""/>
+ <KeyValuePair Key="Autostart" Boolean="true"/>
+ <KeyValuePair Key="Mail Message" String=""/>
+ <KeyValuePair Key="Mail event" String=""/>
+ <KeyValuePair Key="Description" String=""/>
+ <KeyValuePair Key="SchemaVersion" String=""/>
+ <KeyValuePair Key="Show time" Boolean="true"/>
+ <KeyValuePair Key="Viewpoint" String=""/>
+ <KeyValuePair Key="Agent Role" String=""/>
+ <KeyValuePair Key="SchemaType" String=""/>
+ <KeyValuePair Key="ScriptName" String=""/>
+ <KeyValuePair Key="Ignorable" Boolean="false"/>
+ <KeyValuePair Key="ScriptVersion" String=""/>
+ <KeyValuePair Key="Skippable" Boolean="false"/>
+ </Properties>
+ <castorNonLayoutableChildren>CreateNewLocalObjectDef</castorNonLayoutableChildren>
+</CompositeActivityDef>
diff --git a/resources/boot/CA/ManageCompositeActDef.xml b/resources/boot/CA/ManageCompositeActDef.xml
new file mode 100755
index 0000000..9a48f1c
--- /dev/null
+++ b/resources/boot/CA/ManageCompositeActDef.xml
@@ -0,0 +1,219 @@
+<CompositeActivityDef ID="-1" Name="ManageCompositeActDef" Height="0" Width="0" IsLayoutable="false" IsComposite="true">
+ <childrenGraphModel>
+ <GraphModelCastorData ClassNameOfVertexOutlineCreator="com.c2kernel.lifecycle.gui.model.WfVertexDefOutlineCreator" StartVertexId="13" NextId="26">
+ <LoopDef ID="15" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false" isNext="0">
+ <CentrePoint x="358" y="360"/>
+ <OutlinePoint x="328" y="348"/>
+ <OutlinePoint x="388" y="348"/>
+ <OutlinePoint x="388" y="372"/>
+ <OutlinePoint x="328" y="372"/>
+ <InEdgeId>19</InEdgeId>
+ <OutEdgeId>20</OutEdgeId>
+ <OutEdgeId>21</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="LastNum" String="2"/>
+ <KeyValuePair Key="RoutingScriptVersion" String=""/>
+ <KeyValuePair Key="RoutingScriptName" String="javascript:true;"/>
+ </Properties>
+ </LoopDef>
+ <JoinDef ID="14" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="357" y="132"/>
+ <OutlinePoint x="327" y="120"/>
+ <OutlinePoint x="387" y="120"/>
+ <OutlinePoint x="387" y="144"/>
+ <OutlinePoint x="327" y="144"/>
+ <InEdgeId>17</InEdgeId>
+ <InEdgeId>20</InEdgeId>
+ <OutEdgeId>18</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Type" String="Join"/>
+ </Properties>
+ </JoinDef>
+ <AndSplitDef ID="13" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="274" y="39"/>
+ <OutlinePoint x="244" y="27"/>
+ <OutlinePoint x="304" y="27"/>
+ <OutlinePoint x="304" y="51"/>
+ <OutlinePoint x="244" y="51"/>
+ <OutEdgeId>16</OutEdgeId>
+ <OutEdgeId>17</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="RoutingScriptVersion" String=""/>
+ <KeyValuePair Key="RoutingScriptName" String=""/>
+ </Properties>
+ </AndSplitDef>
+ <JoinDef ID="4" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="265" y="473"/>
+ <OutlinePoint x="235" y="461"/>
+ <OutlinePoint x="295" y="461"/>
+ <OutlinePoint x="295" y="485"/>
+ <OutlinePoint x="235" y="485"/>
+ <InEdgeId>8</InEdgeId>
+ <InEdgeId>21</InEdgeId>
+ <Properties>
+ <KeyValuePair Key="Type" String="Join"/>
+ </Properties>
+ </JoinDef>
+ <LoopDef ID="3" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false" isNext="0">
+ <CentrePoint x="177" y="359"/>
+ <OutlinePoint x="147" y="347"/>
+ <OutlinePoint x="207" y="347"/>
+ <OutlinePoint x="207" y="371"/>
+ <OutlinePoint x="147" y="371"/>
+ <InEdgeId>25</InEdgeId>
+ <OutEdgeId>7</OutEdgeId>
+ <OutEdgeId>8</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="LastNum" String="2"/>
+ <KeyValuePair Key="RoutingScriptVersion" String=""/>
+ <KeyValuePair Key="RoutingScriptName" String="javascript:true;"/>
+ </Properties>
+ </LoopDef>
+ <ActivitySlotDef ID="11" Name="AssignNewVersionFromLast_" Height="60" Width="130" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="270" y="251"/>
+ <OutlinePoint x="205" y="221"/>
+ <OutlinePoint x="335" y="221"/>
+ <OutlinePoint x="335" y="281"/>
+ <OutlinePoint x="205" y="281"/>
+ <InEdgeId>18</InEdgeId>
+ <OutEdgeId>19</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Prefill" Boolean="false"/>
+ <KeyValuePair Key="Prefill Version" String="-1"/>
+ <KeyValuePair Key="ViewName" String="CompositeActivityDef"/>
+ <KeyValuePair Key="Name" String="AssignNewActivityVersionFromLast"/>
+ </Properties>
+ <activityDef>AssignNewVersionFromLast</activityDef>
+ </ActivitySlotDef>
+ <JoinDef ID="2" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="175" y="131"/>
+ <OutlinePoint x="145" y="119"/>
+ <OutlinePoint x="205" y="119"/>
+ <OutlinePoint x="205" y="143"/>
+ <OutlinePoint x="145" y="143"/>
+ <InEdgeId>7</InEdgeId>
+ <InEdgeId>16</InEdgeId>
+ <OutEdgeId>24</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Type" String="Join"/>
+ </Properties>
+ </JoinDef>
+ <ActivitySlotDef ID="22" Name="EditDefinition" Height="60" Width="130" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="76" y="251"/>
+ <OutlinePoint x="11" y="221"/>
+ <OutlinePoint x="141" y="221"/>
+ <OutlinePoint x="141" y="281"/>
+ <OutlinePoint x="11" y="281"/>
+ <InEdgeId>24</InEdgeId>
+ <OutEdgeId>25</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Prefill" Boolean="false"/>
+ <KeyValuePair Key="Prefill Version" String="-1"/>
+ <KeyValuePair Key="Name" String="EditDefinition"/>
+ <KeyValuePair Key="SchemaType" String="CompositeActivityDef"/>
+ </Properties>
+ <activityDef>EditActivityDef</activityDef>
+ </ActivitySlotDef>
+ <NextDef ID="25" OriginVertexId="22" TerminusVertexId="3">
+ <OriginPoint x="76" y="251"/>
+ <TerminusPoint x="177" y="359"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="24" OriginVertexId="2" TerminusVertexId="22">
+ <OriginPoint x="175" y="131"/>
+ <TerminusPoint x="76" y="251"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="19" OriginVertexId="11" TerminusVertexId="15">
+ <OriginPoint x="270" y="251"/>
+ <TerminusPoint x="358" y="360"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="21" OriginVertexId="15" TerminusVertexId="4">
+ <OriginPoint x="358" y="360"/>
+ <TerminusPoint x="265" y="473"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="false"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="18" OriginVertexId="14" TerminusVertexId="11">
+ <OriginPoint x="357" y="132"/>
+ <TerminusPoint x="270" y="251"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="20" OriginVertexId="15" TerminusVertexId="14">
+ <OriginPoint x="358" y="360"/>
+ <TerminusPoint x="357" y="132"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="true"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="8" OriginVertexId="3" TerminusVertexId="4">
+ <OriginPoint x="177" y="359"/>
+ <TerminusPoint x="265" y="473"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="false"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="17" OriginVertexId="13" TerminusVertexId="14">
+ <OriginPoint x="274" y="39"/>
+ <TerminusPoint x="357" y="132"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="16" OriginVertexId="13" TerminusVertexId="2">
+ <OriginPoint x="274" y="39"/>
+ <TerminusPoint x="175" y="131"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="7" OriginVertexId="3" TerminusVertexId="2">
+ <OriginPoint x="177" y="359"/>
+ <TerminusPoint x="175" y="131"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="true"/>
+ </Properties>
+ </NextDef>
+ </GraphModelCastorData>
+ </childrenGraphModel>
+ <Properties>
+ <KeyValuePair Key="Expected Time" Integer="0"/>
+ <KeyValuePair Key="Repeatable" Boolean="false"/>
+ <KeyValuePair Key="Has Timeout" Boolean="false"/>
+ <KeyValuePair Key="Time Out Action" Integer="2"/>
+ <KeyValuePair Key="Agent Name" String=""/>
+ <KeyValuePair Key="Autostart" Boolean="true"/>
+ <KeyValuePair Key="Expected Time Unit" Integer="3"/>
+ <KeyValuePair Key="Maximum Time" Integer="0"/>
+ <KeyValuePair Key="Mail Message" String=""/>
+ <KeyValuePair Key="Mail event" String=""/>
+ <KeyValuePair Key="Maximum Time Unit" Integer="3"/>
+ <KeyValuePair Key="Description" String=""/>
+ <KeyValuePair Key="SchemaVersion" String=""/>
+ <KeyValuePair Key="Show time" Boolean="true"/>
+ <KeyValuePair Key="Viewpoint" String=""/>
+ <KeyValuePair Key="Agent Role" String=""/>
+ <KeyValuePair Key="Timeout Activated" Boolean="false"/>
+ <KeyValuePair Key="SchemaType" String=""/>
+ <KeyValuePair Key="ScriptName" String=""/>
+ <KeyValuePair Key="Ignorable" Boolean="false"/>
+ <KeyValuePair Key="ScriptVersion" String=""/>
+ <KeyValuePair Key="Skippable" Boolean="false"/>
+ </Properties>
+ <castorNonLayoutableChildren>AssignNewVersionFromLast</castorNonLayoutableChildren>
+ <castorNonLayoutableChildren>EditActivityDef</castorNonLayoutableChildren>
+</CompositeActivityDef>
diff --git a/resources/boot/CA/ManageElementaryActDef.xml b/resources/boot/CA/ManageElementaryActDef.xml
new file mode 100755
index 0000000..1aa3840
--- /dev/null
+++ b/resources/boot/CA/ManageElementaryActDef.xml
@@ -0,0 +1,219 @@
+<CompositeActivityDef ID="-1" Name="ManageElementaryActDef" Height="0" Width="0" IsLayoutable="false" IsComposite="true">
+ <childrenGraphModel>
+ <GraphModelCastorData ClassNameOfVertexOutlineCreator="com.c2kernel.lifecycle.gui.model.WfVertexDefOutlineCreator" StartVertexId="13" NextId="26">
+ <LoopDef ID="15" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false" isNext="0">
+ <CentrePoint x="358" y="360"/>
+ <OutlinePoint x="328" y="348"/>
+ <OutlinePoint x="388" y="348"/>
+ <OutlinePoint x="388" y="372"/>
+ <OutlinePoint x="328" y="372"/>
+ <InEdgeId>19</InEdgeId>
+ <OutEdgeId>20</OutEdgeId>
+ <OutEdgeId>21</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="LastNum" String="2"/>
+ <KeyValuePair Key="RoutingScriptVersion" String=""/>
+ <KeyValuePair Key="RoutingScriptName" String="javascript:true;"/>
+ </Properties>
+ </LoopDef>
+ <JoinDef ID="14" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="357" y="132"/>
+ <OutlinePoint x="327" y="120"/>
+ <OutlinePoint x="387" y="120"/>
+ <OutlinePoint x="387" y="144"/>
+ <OutlinePoint x="327" y="144"/>
+ <InEdgeId>17</InEdgeId>
+ <InEdgeId>20</InEdgeId>
+ <OutEdgeId>18</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Type" String="Join"/>
+ </Properties>
+ </JoinDef>
+ <JoinDef ID="4" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="265" y="473"/>
+ <OutlinePoint x="235" y="461"/>
+ <OutlinePoint x="295" y="461"/>
+ <OutlinePoint x="295" y="485"/>
+ <OutlinePoint x="235" y="485"/>
+ <InEdgeId>8</InEdgeId>
+ <InEdgeId>21</InEdgeId>
+ <Properties>
+ <KeyValuePair Key="Type" String="Join"/>
+ </Properties>
+ </JoinDef>
+ <AndSplitDef ID="13" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="274" y="39"/>
+ <OutlinePoint x="244" y="27"/>
+ <OutlinePoint x="304" y="27"/>
+ <OutlinePoint x="304" y="51"/>
+ <OutlinePoint x="244" y="51"/>
+ <OutEdgeId>16</OutEdgeId>
+ <OutEdgeId>17</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="RoutingScriptVersion" String=""/>
+ <KeyValuePair Key="RoutingScriptName" String=""/>
+ </Properties>
+ </AndSplitDef>
+ <LoopDef ID="3" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false" isNext="0">
+ <CentrePoint x="177" y="359"/>
+ <OutlinePoint x="147" y="347"/>
+ <OutlinePoint x="207" y="347"/>
+ <OutlinePoint x="207" y="371"/>
+ <OutlinePoint x="147" y="371"/>
+ <InEdgeId>25</InEdgeId>
+ <OutEdgeId>7</OutEdgeId>
+ <OutEdgeId>8</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="LastNum" String="2"/>
+ <KeyValuePair Key="RoutingScriptVersion" String=""/>
+ <KeyValuePair Key="RoutingScriptName" String="javascript:true;"/>
+ </Properties>
+ </LoopDef>
+ <JoinDef ID="2" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="175" y="131"/>
+ <OutlinePoint x="145" y="119"/>
+ <OutlinePoint x="205" y="119"/>
+ <OutlinePoint x="205" y="143"/>
+ <OutlinePoint x="145" y="143"/>
+ <InEdgeId>7</InEdgeId>
+ <InEdgeId>16</InEdgeId>
+ <OutEdgeId>24</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Type" String="Join"/>
+ </Properties>
+ </JoinDef>
+ <ActivitySlotDef ID="11" Name="AssignNewVersionFromLast_" Height="60" Width="130" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="270" y="251"/>
+ <OutlinePoint x="205" y="221"/>
+ <OutlinePoint x="335" y="221"/>
+ <OutlinePoint x="335" y="281"/>
+ <OutlinePoint x="205" y="281"/>
+ <InEdgeId>18</InEdgeId>
+ <OutEdgeId>19</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Prefill" Boolean="false"/>
+ <KeyValuePair Key="Prefill Version" String="-1"/>
+ <KeyValuePair Key="ViewName" String="ElementaryActivityDef"/>
+ <KeyValuePair Key="Name" String="AssignNewSchemaVersionFromLast"/>
+ </Properties>
+ <activityDef>AssignNewVersionFromLast</activityDef>
+ </ActivitySlotDef>
+ <ActivitySlotDef ID="22" Name="EditDefinition" Height="60" Width="130" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="76" y="251"/>
+ <OutlinePoint x="11" y="221"/>
+ <OutlinePoint x="141" y="221"/>
+ <OutlinePoint x="141" y="281"/>
+ <OutlinePoint x="11" y="281"/>
+ <InEdgeId>24</InEdgeId>
+ <OutEdgeId>25</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Prefill" Boolean="false"/>
+ <KeyValuePair Key="Prefill Version" String="-1"/>
+ <KeyValuePair Key="Name" String="EditDefinition"/>
+ <KeyValuePair Key="SchemaType" String="ElementaryActivityDef"/>
+ </Properties>
+ <activityDef>EditActivityDef</activityDef>
+ </ActivitySlotDef>
+ <NextDef ID="25" OriginVertexId="22" TerminusVertexId="3">
+ <OriginPoint x="76" y="251"/>
+ <TerminusPoint x="177" y="359"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="24" OriginVertexId="2" TerminusVertexId="22">
+ <OriginPoint x="175" y="131"/>
+ <TerminusPoint x="76" y="251"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="19" OriginVertexId="11" TerminusVertexId="15">
+ <OriginPoint x="270" y="251"/>
+ <TerminusPoint x="358" y="360"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="21" OriginVertexId="15" TerminusVertexId="4">
+ <OriginPoint x="358" y="360"/>
+ <TerminusPoint x="265" y="473"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="false"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="18" OriginVertexId="14" TerminusVertexId="11">
+ <OriginPoint x="357" y="132"/>
+ <TerminusPoint x="270" y="251"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="20" OriginVertexId="15" TerminusVertexId="14">
+ <OriginPoint x="358" y="360"/>
+ <TerminusPoint x="357" y="132"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="true"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="8" OriginVertexId="3" TerminusVertexId="4">
+ <OriginPoint x="177" y="359"/>
+ <TerminusPoint x="265" y="473"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="false"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="17" OriginVertexId="13" TerminusVertexId="14">
+ <OriginPoint x="274" y="39"/>
+ <TerminusPoint x="357" y="132"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="7" OriginVertexId="3" TerminusVertexId="2">
+ <OriginPoint x="177" y="359"/>
+ <TerminusPoint x="175" y="131"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="true"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="16" OriginVertexId="13" TerminusVertexId="2">
+ <OriginPoint x="274" y="39"/>
+ <TerminusPoint x="175" y="131"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ </GraphModelCastorData>
+ </childrenGraphModel>
+ <Properties>
+ <KeyValuePair Key="Expected Time" Integer="0"/>
+ <KeyValuePair Key="Repeatable" Boolean="false"/>
+ <KeyValuePair Key="Has Timeout" Boolean="false"/>
+ <KeyValuePair Key="Time Out Action" Integer="2"/>
+ <KeyValuePair Key="Agent Name" String=""/>
+ <KeyValuePair Key="Autostart" Boolean="true"/>
+ <KeyValuePair Key="Expected Time Unit" Integer="3"/>
+ <KeyValuePair Key="Maximum Time" Integer="0"/>
+ <KeyValuePair Key="Mail Message" String=""/>
+ <KeyValuePair Key="Mail event" String=""/>
+ <KeyValuePair Key="Maximum Time Unit" Integer="3"/>
+ <KeyValuePair Key="Description" String=""/>
+ <KeyValuePair Key="SchemaVersion" String=""/>
+ <KeyValuePair Key="Show time" Boolean="true"/>
+ <KeyValuePair Key="Viewpoint" String=""/>
+ <KeyValuePair Key="Agent Role" String=""/>
+ <KeyValuePair Key="Timeout Activated" Boolean="false"/>
+ <KeyValuePair Key="SchemaType" String=""/>
+ <KeyValuePair Key="ScriptName" String=""/>
+ <KeyValuePair Key="Ignorable" Boolean="false"/>
+ <KeyValuePair Key="ScriptVersion" String=""/>
+ <KeyValuePair Key="Skippable" Boolean="false"/>
+ </Properties>
+ <castorNonLayoutableChildren>AssignNewVersionFromLast</castorNonLayoutableChildren>
+ <castorNonLayoutableChildren>EditActivityDef</castorNonLayoutableChildren>
+</CompositeActivityDef>
diff --git a/resources/boot/CA/ManageSchema.xml b/resources/boot/CA/ManageSchema.xml
new file mode 100755
index 0000000..da501e4
--- /dev/null
+++ b/resources/boot/CA/ManageSchema.xml
@@ -0,0 +1,218 @@
+<CompositeActivityDef ID="-1" Name="ManageSchema" Height="0" Width="0" IsLayoutable="false" IsComposite="true">
+ <childrenGraphModel>
+ <GraphModelCastorData ClassNameOfVertexOutlineCreator="com.c2kernel.lifecycle.gui.model.WfVertexDefOutlineCreator" StartVertexId="13" NextId="22">
+ <LoopDef ID="15" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false" isNext="0">
+ <CentrePoint x="358" y="360"/>
+ <OutlinePoint x="328" y="348"/>
+ <OutlinePoint x="388" y="348"/>
+ <OutlinePoint x="388" y="372"/>
+ <OutlinePoint x="328" y="372"/>
+ <InEdgeId>19</InEdgeId>
+ <OutEdgeId>20</OutEdgeId>
+ <OutEdgeId>21</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="LastNum" String="2"/>
+ <KeyValuePair Key="RoutingScriptVersion" String=""/>
+ <KeyValuePair Key="RoutingScriptName" String="javascript:true;"/>
+ </Properties>
+ </LoopDef>
+ <JoinDef ID="14" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="357" y="132"/>
+ <OutlinePoint x="327" y="120"/>
+ <OutlinePoint x="387" y="120"/>
+ <OutlinePoint x="387" y="144"/>
+ <OutlinePoint x="327" y="144"/>
+ <InEdgeId>17</InEdgeId>
+ <InEdgeId>20</InEdgeId>
+ <OutEdgeId>18</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Type" String="Join"/>
+ </Properties>
+ </JoinDef>
+ <AndSplitDef ID="13" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="274" y="39"/>
+ <OutlinePoint x="244" y="27"/>
+ <OutlinePoint x="304" y="27"/>
+ <OutlinePoint x="304" y="51"/>
+ <OutlinePoint x="244" y="51"/>
+ <OutEdgeId>16</OutEdgeId>
+ <OutEdgeId>17</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="RoutingScriptVersion" String=""/>
+ <KeyValuePair Key="RoutingScriptName" String=""/>
+ </Properties>
+ </AndSplitDef>
+ <JoinDef ID="4" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="265" y="473"/>
+ <OutlinePoint x="235" y="461"/>
+ <OutlinePoint x="295" y="461"/>
+ <OutlinePoint x="295" y="485"/>
+ <OutlinePoint x="235" y="485"/>
+ <InEdgeId>8</InEdgeId>
+ <InEdgeId>21</InEdgeId>
+ <Properties>
+ <KeyValuePair Key="Type" String="Join"/>
+ </Properties>
+ </JoinDef>
+ <LoopDef ID="3" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false" isNext="0">
+ <CentrePoint x="177" y="359"/>
+ <OutlinePoint x="147" y="347"/>
+ <OutlinePoint x="207" y="347"/>
+ <OutlinePoint x="207" y="371"/>
+ <OutlinePoint x="147" y="371"/>
+ <InEdgeId>6</InEdgeId>
+ <OutEdgeId>7</OutEdgeId>
+ <OutEdgeId>8</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="LastNum" String="2"/>
+ <KeyValuePair Key="RoutingScriptVersion" String=""/>
+ <KeyValuePair Key="RoutingScriptName" String="javascript:true;"/>
+ </Properties>
+ </LoopDef>
+ <ActivitySlotDef ID="11" Name="AssignNewVersionFromLast_" Height="60" Width="130" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="270" y="251"/>
+ <OutlinePoint x="205" y="221"/>
+ <OutlinePoint x="335" y="221"/>
+ <OutlinePoint x="335" y="281"/>
+ <OutlinePoint x="205" y="281"/>
+ <InEdgeId>18</InEdgeId>
+ <OutEdgeId>19</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Prefill" Boolean="false"/>
+ <KeyValuePair Key="Prefill Version" String="-1"/>
+ <KeyValuePair Key="ViewName" String="Schema"/>
+ <KeyValuePair Key="Name" String="AssignNewSchemaVersionFromLast"/>
+ </Properties>
+ <activityDef>AssignNewVersionFromLast</activityDef>
+ </ActivitySlotDef>
+ <JoinDef ID="2" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="175" y="131"/>
+ <OutlinePoint x="145" y="119"/>
+ <OutlinePoint x="205" y="119"/>
+ <OutlinePoint x="205" y="143"/>
+ <OutlinePoint x="145" y="143"/>
+ <InEdgeId>7</InEdgeId>
+ <InEdgeId>16</InEdgeId>
+ <OutEdgeId>5</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Type" String="Join"/>
+ </Properties>
+ </JoinDef>
+ <ActivitySlotDef ID="0" Name="EditDefinition" Height="60" Width="130" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="93" y="252"/>
+ <OutlinePoint x="28" y="222"/>
+ <OutlinePoint x="158" y="222"/>
+ <OutlinePoint x="158" y="282"/>
+ <OutlinePoint x="28" y="282"/>
+ <InEdgeId>5</InEdgeId>
+ <OutEdgeId>6</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Prefill" Boolean="false"/>
+ <KeyValuePair Key="Prefill Version" String="-1"/>
+ <KeyValuePair Key="Name" String="EditDefinition"/>
+ </Properties>
+ <activityDef>EditSchema</activityDef>
+ </ActivitySlotDef>
+ <NextDef ID="21" OriginVertexId="15" TerminusVertexId="4">
+ <OriginPoint x="358" y="360"/>
+ <TerminusPoint x="265" y="473"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="false"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="19" OriginVertexId="11" TerminusVertexId="15">
+ <OriginPoint x="270" y="251"/>
+ <TerminusPoint x="358" y="360"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="20" OriginVertexId="15" TerminusVertexId="14">
+ <OriginPoint x="358" y="360"/>
+ <TerminusPoint x="357" y="132"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="true"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="18" OriginVertexId="14" TerminusVertexId="11">
+ <OriginPoint x="357" y="132"/>
+ <TerminusPoint x="270" y="251"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="8" OriginVertexId="3" TerminusVertexId="4">
+ <OriginPoint x="177" y="359"/>
+ <TerminusPoint x="265" y="473"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="false"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="17" OriginVertexId="13" TerminusVertexId="14">
+ <OriginPoint x="274" y="39"/>
+ <TerminusPoint x="357" y="132"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="7" OriginVertexId="3" TerminusVertexId="2">
+ <OriginPoint x="177" y="359"/>
+ <TerminusPoint x="175" y="131"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="true"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="16" OriginVertexId="13" TerminusVertexId="2">
+ <OriginPoint x="274" y="39"/>
+ <TerminusPoint x="175" y="131"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="6" OriginVertexId="0" TerminusVertexId="3">
+ <OriginPoint x="93" y="252"/>
+ <TerminusPoint x="177" y="359"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="5" OriginVertexId="2" TerminusVertexId="0">
+ <OriginPoint x="175" y="131"/>
+ <TerminusPoint x="93" y="252"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ </GraphModelCastorData>
+ </childrenGraphModel>
+ <Properties>
+ <KeyValuePair Key="Expected Time" Integer="0"/>
+ <KeyValuePair Key="Repeatable" Boolean="false"/>
+ <KeyValuePair Key="Has Timeout" Boolean="false"/>
+ <KeyValuePair Key="Time Out Action" Integer="2"/>
+ <KeyValuePair Key="Agent Name" String=""/>
+ <KeyValuePair Key="Autostart" Boolean="true"/>
+ <KeyValuePair Key="Expected Time Unit" Integer="3"/>
+ <KeyValuePair Key="Maximum Time" Integer="0"/>
+ <KeyValuePair Key="Mail Message" String=""/>
+ <KeyValuePair Key="Mail event" String=""/>
+ <KeyValuePair Key="Maximum Time Unit" Integer="3"/>
+ <KeyValuePair Key="Description" String=""/>
+ <KeyValuePair Key="SchemaVersion" String=""/>
+ <KeyValuePair Key="Show time" Boolean="true"/>
+ <KeyValuePair Key="Viewpoint" String=""/>
+ <KeyValuePair Key="Agent Role" String=""/>
+ <KeyValuePair Key="Timeout Activated" Boolean="false"/>
+ <KeyValuePair Key="SchemaType" String=""/>
+ <KeyValuePair Key="ScriptName" String=""/>
+ <KeyValuePair Key="Ignorable" Boolean="false"/>
+ <KeyValuePair Key="ScriptVersion" String=""/>
+ <KeyValuePair Key="Skippable" Boolean="false"/>
+ </Properties>
+ <castorNonLayoutableChildren>AssignNewVersionFromLast</castorNonLayoutableChildren>
+ <castorNonLayoutableChildren>EditSchema</castorNonLayoutableChildren>
+</CompositeActivityDef>
diff --git a/resources/boot/CA/ManageScript.xml b/resources/boot/CA/ManageScript.xml
new file mode 100755
index 0000000..f8100b0
--- /dev/null
+++ b/resources/boot/CA/ManageScript.xml
@@ -0,0 +1,219 @@
+<CompositeActivityDef ID="-1" Name="ManageScript" Height="0" Width="0" IsLayoutable="false" IsComposite="true">
+ <childrenGraphModel>
+ <GraphModelCastorData ClassNameOfVertexOutlineCreator="com.c2kernel.lifecycle.gui.model.WfVertexDefOutlineCreator" StartVertexId="11" NextId="27">
+ <LoopDef ID="15" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false" isNext="0">
+ <CentrePoint x="425" y="291"/>
+ <OutlinePoint x="395" y="279"/>
+ <OutlinePoint x="455" y="279"/>
+ <OutlinePoint x="455" y="303"/>
+ <OutlinePoint x="395" y="303"/>
+ <InEdgeId>24</InEdgeId>
+ <OutEdgeId>25</OutEdgeId>
+ <OutEdgeId>26</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="LastNum" String="2"/>
+ <KeyValuePair Key="RoutingScriptVersion" String=""/>
+ <KeyValuePair Key="RoutingScriptName" String="javascript:true;"/>
+ </Properties>
+ </LoopDef>
+ <LoopDef ID="14" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false" isNext="0">
+ <CentrePoint x="184" y="289"/>
+ <OutlinePoint x="154" y="277"/>
+ <OutlinePoint x="214" y="277"/>
+ <OutlinePoint x="214" y="301"/>
+ <OutlinePoint x="154" y="301"/>
+ <InEdgeId>21</InEdgeId>
+ <OutEdgeId>22</OutEdgeId>
+ <OutEdgeId>23</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="LastNum" String="2"/>
+ <KeyValuePair Key="RoutingScriptVersion" String=""/>
+ <KeyValuePair Key="RoutingScriptName" String="javascript:true;"/>
+ </Properties>
+ </LoopDef>
+ <JoinDef ID="13" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="425" y="80"/>
+ <OutlinePoint x="395" y="68"/>
+ <OutlinePoint x="455" y="68"/>
+ <OutlinePoint x="455" y="92"/>
+ <OutlinePoint x="395" y="92"/>
+ <InEdgeId>18</InEdgeId>
+ <InEdgeId>25</InEdgeId>
+ <OutEdgeId>20</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Type" String="Join"/>
+ </Properties>
+ </JoinDef>
+ <JoinDef ID="12" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="184" y="80"/>
+ <OutlinePoint x="154" y="68"/>
+ <OutlinePoint x="214" y="68"/>
+ <OutlinePoint x="214" y="92"/>
+ <OutlinePoint x="154" y="92"/>
+ <InEdgeId>17</InEdgeId>
+ <InEdgeId>23</InEdgeId>
+ <OutEdgeId>19</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Type" String="Join"/>
+ </Properties>
+ </JoinDef>
+ <AndSplitDef ID="11" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="305" y="26"/>
+ <OutlinePoint x="275" y="14"/>
+ <OutlinePoint x="335" y="14"/>
+ <OutlinePoint x="335" y="38"/>
+ <OutlinePoint x="275" y="38"/>
+ <OutEdgeId>17</OutEdgeId>
+ <OutEdgeId>18</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="RoutingScriptVersion" String=""/>
+ <KeyValuePair Key="RoutingScriptName" String=""/>
+ </Properties>
+ </AndSplitDef>
+ <ActivitySlotDef ID="0" Name="EditDefinition" Height="60" Width="130" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="115" y="182"/>
+ <OutlinePoint x="50" y="152"/>
+ <OutlinePoint x="180" y="152"/>
+ <OutlinePoint x="180" y="212"/>
+ <OutlinePoint x="50" y="212"/>
+ <InEdgeId>19</InEdgeId>
+ <OutEdgeId>21</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Prefill" Boolean="false"/>
+ <KeyValuePair Key="Prefill Version" String="-1"/>
+ <KeyValuePair Key="Name" String="EditDefinition"/>
+ </Properties>
+ <activityDef>EditScriptDefinition</activityDef>
+ </ActivitySlotDef>
+ <ActivitySlotDef ID="9" Name="AssignNewVersionFromLast_" Height="60" Width="130" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="344" y="184"/>
+ <OutlinePoint x="279" y="154"/>
+ <OutlinePoint x="409" y="154"/>
+ <OutlinePoint x="409" y="214"/>
+ <OutlinePoint x="279" y="214"/>
+ <InEdgeId>20</InEdgeId>
+ <OutEdgeId>24</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Prefill" Boolean="false"/>
+ <KeyValuePair Key="Prefill Version" String="-1"/>
+ <KeyValuePair Key="ViewName" String="Script"/>
+ <KeyValuePair Key="Name" String="AssignNewVersionFromLast"/>
+ </Properties>
+ <activityDef>AssignNewVersionFromLast</activityDef>
+ </ActivitySlotDef>
+ <JoinDef ID="16" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="293" y="399"/>
+ <OutlinePoint x="263" y="387"/>
+ <OutlinePoint x="323" y="387"/>
+ <OutlinePoint x="323" y="411"/>
+ <OutlinePoint x="263" y="411"/>
+ <InEdgeId>22</InEdgeId>
+ <InEdgeId>26</InEdgeId>
+ <Properties>
+ <KeyValuePair Key="Type" String="Join"/>
+ </Properties>
+ </JoinDef>
+ <NextDef ID="26" OriginVertexId="15" TerminusVertexId="16">
+ <OriginPoint x="425" y="291"/>
+ <TerminusPoint x="293" y="399"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="false"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="25" OriginVertexId="15" TerminusVertexId="13">
+ <OriginPoint x="425" y="291"/>
+ <TerminusPoint x="425" y="80"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="true"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="24" OriginVertexId="9" TerminusVertexId="15">
+ <OriginPoint x="344" y="184"/>
+ <TerminusPoint x="425" y="291"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="23" OriginVertexId="14" TerminusVertexId="12">
+ <OriginPoint x="184" y="289"/>
+ <TerminusPoint x="184" y="80"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="true"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="22" OriginVertexId="14" TerminusVertexId="16">
+ <OriginPoint x="184" y="289"/>
+ <TerminusPoint x="293" y="399"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="false"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="19" OriginVertexId="12" TerminusVertexId="0">
+ <OriginPoint x="184" y="80"/>
+ <TerminusPoint x="115" y="182"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="21" OriginVertexId="0" TerminusVertexId="14">
+ <OriginPoint x="115" y="182"/>
+ <TerminusPoint x="184" y="289"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="20" OriginVertexId="13" TerminusVertexId="9">
+ <OriginPoint x="425" y="80"/>
+ <TerminusPoint x="344" y="184"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="18" OriginVertexId="11" TerminusVertexId="13">
+ <OriginPoint x="305" y="26"/>
+ <TerminusPoint x="425" y="80"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="17" OriginVertexId="11" TerminusVertexId="12">
+ <OriginPoint x="305" y="26"/>
+ <TerminusPoint x="184" y="80"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ </GraphModelCastorData>
+ </childrenGraphModel>
+ <Properties>
+ <KeyValuePair Key="Expected Time" Integer="0"/>
+ <KeyValuePair Key="Has Timeout" Boolean="false"/>
+ <KeyValuePair Key="Repeatable" Boolean="false"/>
+ <KeyValuePair Key="Time Out Action" Integer="2"/>
+ <KeyValuePair Key="Agent Name" String=""/>
+ <KeyValuePair Key="Expected Time Unit" Integer="3"/>
+ <KeyValuePair Key="Autostart" Boolean="true"/>
+ <KeyValuePair Key="Maximum Time" Integer="0"/>
+ <KeyValuePair Key="Mail Message" String=""/>
+ <KeyValuePair Key="Mail event" String=""/>
+ <KeyValuePair Key="Maximum Time Unit" Integer="3"/>
+ <KeyValuePair Key="Description" String=""/>
+ <KeyValuePair Key="SchemaVersion" String=""/>
+ <KeyValuePair Key="Prefill" Boolean="false"/>
+ <KeyValuePair Key="Show time" Boolean="true"/>
+ <KeyValuePair Key="Agent Role" String=""/>
+ <KeyValuePair Key="Viewpoint" String=""/>
+ <KeyValuePair Key="Timeout Activated" Boolean="false"/>
+ <KeyValuePair Key="SchemaType" String=""/>
+ <KeyValuePair Key="Ignorable" Boolean="false"/>
+ <KeyValuePair Key="ScriptName" String=""/>
+ <KeyValuePair Key="Skippable" Boolean="false"/>
+ <KeyValuePair Key="ScriptVersion" String=""/>
+ </Properties>
+ <castorNonLayoutableChildren>EditScriptDefinition</castorNonLayoutableChildren>
+ <castorNonLayoutableChildren>AssignNewVersionFromLast</castorNonLayoutableChildren>
+</CompositeActivityDef>
diff --git a/resources/boot/CA/NoWorkflow.xml b/resources/boot/CA/NoWorkflow.xml
new file mode 100755
index 0000000..c0e2d6f
--- /dev/null
+++ b/resources/boot/CA/NoWorkflow.xml
@@ -0,0 +1,22 @@
+<CompositeActivityDef ID="-1" Name="NoWorkflow" Height="0" Width="0" IsLayoutable="false" IsComposite="true">
+ <childrenGraphModel>
+ <GraphModelCastorData ClassNameOfVertexOutlineCreator="com.c2kernel.lifecycle.gui.model.WfVertexDefOutlineCreator" StartVertexId="-1" NextId="0"/>
+ </childrenGraphModel>
+ <Properties>
+ <KeyValuePair Key="Autostart" Boolean="true"/>
+ <KeyValuePair Key="ScriptVersion" String=""/>
+ <KeyValuePair Key="Agent Role" String=""/>
+ <KeyValuePair Key="Agent Name" String=""/>
+ <KeyValuePair Key="ScriptName" String=""/>
+ <KeyValuePair Key="Show time" Boolean="true"/>
+ <KeyValuePair Key="Mail Message" String=""/>
+ <KeyValuePair Key="Viewpoint" String=""/>
+ <KeyValuePair Key="SchemaType" String=""/>
+ <KeyValuePair Key="Ignorable" Boolean="false"/>
+ <KeyValuePair Key="Repeatable" Boolean="false"/>
+ <KeyValuePair Key="Skippable" Boolean="false"/>
+ <KeyValuePair Key="SchemaVersion" String=""/>
+ <KeyValuePair Key="Description" String=""/>
+ <KeyValuePair Key="Mail event" String=""/>
+ </Properties>
+</CompositeActivityDef>
diff --git a/resources/boot/CA/SchemaFactory.xml b/resources/boot/CA/SchemaFactory.xml
new file mode 100755
index 0000000..aa903db
--- /dev/null
+++ b/resources/boot/CA/SchemaFactory.xml
@@ -0,0 +1,108 @@
+<CompositeActivityDef ID="-1" Name="SchemaFactory" Height="0" Width="0" IsLayoutable="false" IsComposite="true">
+ <childrenGraphModel>
+ <GraphModelCastorData ClassNameOfVertexOutlineCreator="com.c2kernel.lifecycle.gui.model.WfVertexDefOutlineCreator" StartVertexId="5" NextId="14">
+ <JoinDef ID="6" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="321" y="325"/>
+ <OutlinePoint x="291" y="313"/>
+ <OutlinePoint x="351" y="313"/>
+ <OutlinePoint x="351" y="337"/>
+ <OutlinePoint x="291" y="337"/>
+ <InEdgeId>9</InEdgeId>
+ <Properties>
+ <KeyValuePair Key="Type" String="Join"/>
+ </Properties>
+ </JoinDef>
+ <JoinDef ID="5" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="321" y="92"/>
+ <OutlinePoint x="291" y="80"/>
+ <OutlinePoint x="351" y="80"/>
+ <OutlinePoint x="351" y="104"/>
+ <OutlinePoint x="291" y="104"/>
+ <InEdgeId>7</InEdgeId>
+ <OutEdgeId>12</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Type" String="Join"/>
+ </Properties>
+ </JoinDef>
+ <LoopDef ID="3" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false" isNext="0">
+ <CentrePoint x="321" y="211"/>
+ <OutlinePoint x="291" y="199"/>
+ <OutlinePoint x="351" y="199"/>
+ <OutlinePoint x="351" y="223"/>
+ <OutlinePoint x="291" y="223"/>
+ <InEdgeId>13</InEdgeId>
+ <OutEdgeId>7</OutEdgeId>
+ <OutEdgeId>9</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="LastNum" String="2"/>
+ <KeyValuePair Key="RoutingScriptVersion" String=""/>
+ <KeyValuePair Key="RoutingScriptName" String="javascript:true;"/>
+ </Properties>
+ </LoopDef>
+ <ActivitySlotDef ID="10" Name="CreateNewLocalObjectDef_" Height="60" Width="130" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="133" y="215"/>
+ <OutlinePoint x="68" y="185"/>
+ <OutlinePoint x="198" y="185"/>
+ <OutlinePoint x="198" y="245"/>
+ <OutlinePoint x="68" y="245"/>
+ <InEdgeId>12</InEdgeId>
+ <OutEdgeId>13</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Prefill" Boolean="false"/>
+ <KeyValuePair Key="Prefill Version" String="-1"/>
+ <KeyValuePair Key="Name" String="CreateNewSchema"/>
+ <KeyValuePair Key="NewType" String="OD"/>
+ </Properties>
+ <activityDef>CreateNewLocalObjectDef</activityDef>
+ </ActivitySlotDef>
+ <NextDef ID="13" OriginVertexId="10" TerminusVertexId="3">
+ <OriginPoint x="133" y="215"/>
+ <TerminusPoint x="321" y="211"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="12" OriginVertexId="5" TerminusVertexId="10">
+ <OriginPoint x="321" y="92"/>
+ <TerminusPoint x="133" y="215"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="9" OriginVertexId="3" TerminusVertexId="6">
+ <OriginPoint x="321" y="211"/>
+ <TerminusPoint x="321" y="325"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="false"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="7" OriginVertexId="3" TerminusVertexId="5">
+ <OriginPoint x="321" y="211"/>
+ <TerminusPoint x="321" y="92"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="true"/>
+ </Properties>
+ </NextDef>
+ </GraphModelCastorData>
+ </childrenGraphModel>
+ <Properties>
+ <KeyValuePair Key="Repeatable" Boolean="false"/>
+ <KeyValuePair Key="Agent Name" String=""/>
+ <KeyValuePair Key="Autostart" Boolean="true"/>
+ <KeyValuePair Key="Mail Message" String=""/>
+ <KeyValuePair Key="Mail event" String=""/>
+ <KeyValuePair Key="Description" String=""/>
+ <KeyValuePair Key="SchemaVersion" String=""/>
+ <KeyValuePair Key="Show time" Boolean="true"/>
+ <KeyValuePair Key="Viewpoint" String=""/>
+ <KeyValuePair Key="Agent Role" String=""/>
+ <KeyValuePair Key="SchemaType" String=""/>
+ <KeyValuePair Key="ScriptName" String=""/>
+ <KeyValuePair Key="Ignorable" Boolean="false"/>
+ <KeyValuePair Key="ScriptVersion" String=""/>
+ <KeyValuePair Key="Skippable" Boolean="false"/>
+ </Properties>
+ <castorNonLayoutableChildren>CreateNewLocalObjectDef</castorNonLayoutableChildren>
+</CompositeActivityDef>
diff --git a/resources/boot/CA/ScriptFactory.xml b/resources/boot/CA/ScriptFactory.xml
new file mode 100755
index 0000000..dac5ba7
--- /dev/null
+++ b/resources/boot/CA/ScriptFactory.xml
@@ -0,0 +1,108 @@
+<CompositeActivityDef ID="-1" Name="ScriptFactory" Height="0" Width="0" IsLayoutable="false" IsComposite="true">
+ <childrenGraphModel>
+ <GraphModelCastorData ClassNameOfVertexOutlineCreator="com.c2kernel.lifecycle.gui.model.WfVertexDefOutlineCreator" StartVertexId="5" NextId="14">
+ <JoinDef ID="6" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="321" y="325"/>
+ <OutlinePoint x="291" y="313"/>
+ <OutlinePoint x="351" y="313"/>
+ <OutlinePoint x="351" y="337"/>
+ <OutlinePoint x="291" y="337"/>
+ <InEdgeId>9</InEdgeId>
+ <Properties>
+ <KeyValuePair Key="Type" String="Join"/>
+ </Properties>
+ </JoinDef>
+ <JoinDef ID="5" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="321" y="92"/>
+ <OutlinePoint x="291" y="80"/>
+ <OutlinePoint x="351" y="80"/>
+ <OutlinePoint x="351" y="104"/>
+ <OutlinePoint x="291" y="104"/>
+ <InEdgeId>7</InEdgeId>
+ <OutEdgeId>12</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Type" String="Join"/>
+ </Properties>
+ </JoinDef>
+ <LoopDef ID="3" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false" isNext="0">
+ <CentrePoint x="321" y="211"/>
+ <OutlinePoint x="291" y="199"/>
+ <OutlinePoint x="351" y="199"/>
+ <OutlinePoint x="351" y="223"/>
+ <OutlinePoint x="291" y="223"/>
+ <InEdgeId>13</InEdgeId>
+ <OutEdgeId>7</OutEdgeId>
+ <OutEdgeId>9</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="LastNum" String="2"/>
+ <KeyValuePair Key="RoutingScriptVersion" String=""/>
+ <KeyValuePair Key="RoutingScriptName" String="javascript:true;"/>
+ </Properties>
+ </LoopDef>
+ <ActivitySlotDef ID="10" Name="CreateNewLocalObjectDef_" Height="60" Width="130" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="133" y="215"/>
+ <OutlinePoint x="68" y="185"/>
+ <OutlinePoint x="198" y="185"/>
+ <OutlinePoint x="198" y="245"/>
+ <OutlinePoint x="68" y="245"/>
+ <InEdgeId>12</InEdgeId>
+ <OutEdgeId>13</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Prefill" Boolean="false"/>
+ <KeyValuePair Key="Prefill Version" String="-1"/>
+ <KeyValuePair Key="Name" String="CreateNewScript"/>
+ <KeyValuePair Key="NewType" String="SC"/>
+ </Properties>
+ <activityDef>CreateNewLocalObjectDef</activityDef>
+ </ActivitySlotDef>
+ <NextDef ID="13" OriginVertexId="10" TerminusVertexId="3">
+ <OriginPoint x="133" y="215"/>
+ <TerminusPoint x="321" y="211"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="12" OriginVertexId="5" TerminusVertexId="10">
+ <OriginPoint x="321" y="92"/>
+ <TerminusPoint x="133" y="215"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="9" OriginVertexId="3" TerminusVertexId="6">
+ <OriginPoint x="321" y="211"/>
+ <TerminusPoint x="321" y="325"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="false"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="7" OriginVertexId="3" TerminusVertexId="5">
+ <OriginPoint x="321" y="211"/>
+ <TerminusPoint x="321" y="92"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="true"/>
+ </Properties>
+ </NextDef>
+ </GraphModelCastorData>
+ </childrenGraphModel>
+ <Properties>
+ <KeyValuePair Key="Repeatable" Boolean="false"/>
+ <KeyValuePair Key="Agent Name" String=""/>
+ <KeyValuePair Key="Autostart" Boolean="true"/>
+ <KeyValuePair Key="Mail Message" String=""/>
+ <KeyValuePair Key="Mail event" String=""/>
+ <KeyValuePair Key="Description" String=""/>
+ <KeyValuePair Key="SchemaVersion" String=""/>
+ <KeyValuePair Key="Show time" Boolean="true"/>
+ <KeyValuePair Key="Viewpoint" String=""/>
+ <KeyValuePair Key="Agent Role" String=""/>
+ <KeyValuePair Key="SchemaType" String=""/>
+ <KeyValuePair Key="ScriptName" String=""/>
+ <KeyValuePair Key="Ignorable" Boolean="false"/>
+ <KeyValuePair Key="ScriptVersion" String=""/>
+ <KeyValuePair Key="Skippable" Boolean="false"/>
+ </Properties>
+ <castorNonLayoutableChildren>CreateNewLocalObjectDef</castorNonLayoutableChildren>
+</CompositeActivityDef>
diff --git a/resources/boot/CA/ServerItemWorkflow.xml b/resources/boot/CA/ServerItemWorkflow.xml
new file mode 100755
index 0000000..e480b07
--- /dev/null
+++ b/resources/boot/CA/ServerItemWorkflow.xml
@@ -0,0 +1,217 @@
+<CompositeActivityDef ID="-1" Name="ServerItemWorkflow" Height="0" Width="0" IsLayoutable="false" IsComposite="true">
+ <childrenGraphModel>
+ <GraphModelCastorData ClassNameOfVertexOutlineCreator="com.c2kernel.lifecycle.gui.model.WfVertexDefOutlineCreator" StartVertexId="4" NextId="21">
+ <JoinDef ID="9" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="244" y="378"/>
+ <OutlinePoint x="214" y="366"/>
+ <OutlinePoint x="274" y="366"/>
+ <OutlinePoint x="274" y="390"/>
+ <OutlinePoint x="214" y="390"/>
+ <InEdgeId>16</InEdgeId>
+ <InEdgeId>17</InEdgeId>
+ <Properties>
+ <KeyValuePair Key="Type" String="Join"/>
+ </Properties>
+ </JoinDef>
+ <LoopDef ID="8" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false" isNext="0">
+ <CentrePoint x="448" y="271"/>
+ <OutlinePoint x="418" y="259"/>
+ <OutlinePoint x="478" y="259"/>
+ <OutlinePoint x="478" y="283"/>
+ <OutlinePoint x="418" y="283"/>
+ <InEdgeId>15</InEdgeId>
+ <OutEdgeId>16</OutEdgeId>
+ <OutEdgeId>19</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="LastNum" String="2"/>
+ <KeyValuePair Key="RoutingScriptVersion" String=""/>
+ <KeyValuePair Key="RoutingScriptName" String="javascript:true;"/>
+ </Properties>
+ </LoopDef>
+ <LoopDef ID="7" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false" isNext="0">
+ <CentrePoint x="36" y="284"/>
+ <OutlinePoint x="6" y="272"/>
+ <OutlinePoint x="66" y="272"/>
+ <OutlinePoint x="66" y="296"/>
+ <OutlinePoint x="6" y="296"/>
+ <InEdgeId>14</InEdgeId>
+ <OutEdgeId>17</OutEdgeId>
+ <OutEdgeId>18</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="LastNum" String="2"/>
+ <KeyValuePair Key="RoutingScriptVersion" String=""/>
+ <KeyValuePair Key="RoutingScriptName" String="javascript:true;"/>
+ </Properties>
+ </LoopDef>
+ <JoinDef ID="6" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="431" y="73"/>
+ <OutlinePoint x="401" y="61"/>
+ <OutlinePoint x="461" y="61"/>
+ <OutlinePoint x="461" y="85"/>
+ <OutlinePoint x="401" y="85"/>
+ <InEdgeId>11</InEdgeId>
+ <InEdgeId>19</InEdgeId>
+ <OutEdgeId>13</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Type" String="Join"/>
+ </Properties>
+ </JoinDef>
+ <JoinDef ID="5" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="51" y="78"/>
+ <OutlinePoint x="21" y="66"/>
+ <OutlinePoint x="81" y="66"/>
+ <OutlinePoint x="81" y="90"/>
+ <OutlinePoint x="21" y="90"/>
+ <InEdgeId>10</InEdgeId>
+ <InEdgeId>18</InEdgeId>
+ <OutEdgeId>12</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Type" String="Join"/>
+ </Properties>
+ </JoinDef>
+ <AndSplitDef ID="4" Name="" Height="24" Width="60" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="239" y="23"/>
+ <OutlinePoint x="209" y="11"/>
+ <OutlinePoint x="269" y="11"/>
+ <OutlinePoint x="269" y="35"/>
+ <OutlinePoint x="209" y="35"/>
+ <OutEdgeId>10</OutEdgeId>
+ <OutEdgeId>11</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="RoutingScriptVersion" String=""/>
+ <KeyValuePair Key="RoutingScriptName" String=""/>
+ </Properties>
+ </AndSplitDef>
+ <ActivitySlotDef ID="2" Name="CreateNewAgent_" Height="60" Width="130" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="339" y="189"/>
+ <OutlinePoint x="274" y="159"/>
+ <OutlinePoint x="404" y="159"/>
+ <OutlinePoint x="404" y="219"/>
+ <OutlinePoint x="274" y="219"/>
+ <InEdgeId>13</InEdgeId>
+ <OutEdgeId>15</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Prefill" Boolean="false"/>
+ <KeyValuePair Key="Prefill Version" String="-1"/>
+ <KeyValuePair Key="Name" String="CreateNewAgent"/>
+ </Properties>
+ <activityDef>CreateNewAgent</activityDef>
+ </ActivitySlotDef>
+ <ActivitySlotDef ID="0" Name="CreateNewItem_" Height="60" Width="130" IsLayoutable="true" IsComposite="false">
+ <CentrePoint x="165" y="190"/>
+ <OutlinePoint x="100" y="160"/>
+ <OutlinePoint x="230" y="160"/>
+ <OutlinePoint x="230" y="220"/>
+ <OutlinePoint x="100" y="220"/>
+ <InEdgeId>12</InEdgeId>
+ <OutEdgeId>14</OutEdgeId>
+ <Properties>
+ <KeyValuePair Key="Prefill" Boolean="false"/>
+ <KeyValuePair Key="Prefill Version" String="-1"/>
+ <KeyValuePair Key="Name" String="CreateNewItem"/>
+ </Properties>
+ <activityDef>CreateNewItem</activityDef>
+ </ActivitySlotDef>
+ <NextDef ID="19" OriginVertexId="8" TerminusVertexId="6">
+ <OriginPoint x="448" y="271"/>
+ <TerminusPoint x="431" y="73"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="true"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="18" OriginVertexId="7" TerminusVertexId="5">
+ <OriginPoint x="36" y="284"/>
+ <TerminusPoint x="51" y="78"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="true"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="17" OriginVertexId="7" TerminusVertexId="9">
+ <OriginPoint x="36" y="284"/>
+ <TerminusPoint x="244" y="378"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="false"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="16" OriginVertexId="8" TerminusVertexId="9">
+ <OriginPoint x="448" y="271"/>
+ <TerminusPoint x="244" y="378"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ <KeyValuePair Key="Alias" String="false"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="15" OriginVertexId="2" TerminusVertexId="8">
+ <OriginPoint x="339" y="189"/>
+ <TerminusPoint x="448" y="271"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="14" OriginVertexId="0" TerminusVertexId="7">
+ <OriginPoint x="165" y="190"/>
+ <TerminusPoint x="36" y="284"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="13" OriginVertexId="6" TerminusVertexId="2">
+ <OriginPoint x="431" y="73"/>
+ <TerminusPoint x="339" y="189"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="12" OriginVertexId="5" TerminusVertexId="0">
+ <OriginPoint x="51" y="78"/>
+ <TerminusPoint x="165" y="190"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="11" OriginVertexId="4" TerminusVertexId="6">
+ <OriginPoint x="239" y="23"/>
+ <TerminusPoint x="431" y="73"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ <NextDef ID="10" OriginVertexId="4" TerminusVertexId="5">
+ <OriginPoint x="239" y="23"/>
+ <TerminusPoint x="51" y="78"/>
+ <Properties>
+ <KeyValuePair Key="Type" String="Straight"/>
+ </Properties>
+ </NextDef>
+ </GraphModelCastorData>
+ </childrenGraphModel>
+ <Properties>
+ <KeyValuePair Key="Expected Time" Integer="0"/>
+ <KeyValuePair Key="Repeatable" Boolean="false"/>
+ <KeyValuePair Key="Has Timeout" Boolean="false"/>
+ <KeyValuePair Key="Time Out Action" Integer="2"/>
+ <KeyValuePair Key="Agent Name" String=""/>
+ <KeyValuePair Key="Autostart" Boolean="true"/>
+ <KeyValuePair Key="Expected Time Unit" Integer="3"/>
+ <KeyValuePair Key="Maximum Time" Integer="0"/>
+ <KeyValuePair Key="Mail Message" String=""/>
+ <KeyValuePair Key="Mail event" String=""/>
+ <KeyValuePair Key="Maximum Time Unit" Integer="3"/>
+ <KeyValuePair Key="Description" String=""/>
+ <KeyValuePair Key="SchemaVersion" String=""/>
+ <KeyValuePair Key="Show time" Boolean="true"/>
+ <KeyValuePair Key="Viewpoint" String=""/>
+ <KeyValuePair Key="Agent Role" String=""/>
+ <KeyValuePair Key="Timeout Activated" Boolean="false"/>
+ <KeyValuePair Key="SchemaType" String=""/>
+ <KeyValuePair Key="ScriptName" String=""/>
+ <KeyValuePair Key="Ignorable" Boolean="false"/>
+ <KeyValuePair Key="ScriptVersion" String=""/>
+ <KeyValuePair Key="Skippable" Boolean="false"/>
+ </Properties>
+ <castorNonLayoutableChildren>CreateNewAgent</castorNonLayoutableChildren>
+ <castorNonLayoutableChildren>CreateNewItem</castorNonLayoutableChildren>
+</CompositeActivityDef>
diff --git a/resources/boot/EA/AssignNewVersionFromLast.xml b/resources/boot/EA/AssignNewVersionFromLast.xml
new file mode 100755
index 0000000..1ef30b5
--- /dev/null
+++ b/resources/boot/EA/AssignNewVersionFromLast.xml
@@ -0,0 +1,20 @@
+<ActivityDef ID="10" Name="AssignNewVersionFromLast" Height="0" Width="0" IsLayoutable="false" IsComposite="false">
+ <Properties>
+ <KeyValuePair Key="Repeatable" Boolean="false"/>
+ <KeyValuePair Key="Agent Name" String=""/>
+ <KeyValuePair Key="Autostart" Boolean="true"/>
+ <KeyValuePair Key="Mail Message" String=""/>
+ <KeyValuePair Key="Mail event" String=""/>
+ <KeyValuePair Key="Description" String="Creates a new numbered viewpoint as a clone of the last for use in workflows. You can change the referenced version in the Data Viewer."/>
+ <KeyValuePair Key="SchemaVersion" String=""/>
+ <KeyValuePair Key="Show time" Boolean="true"/>
+ <KeyValuePair Key="Viewpoint" String=""/>
+ <KeyValuePair Key="Agent Role" String="Admin"/>
+ <KeyValuePair Key="SchemaType" String=""/>
+ <KeyValuePair Key="ScriptName" String="CreateNewNumberedVersionFromLast"/>
+ <KeyValuePair Key="Ignorable" Boolean="false"/>
+ <KeyValuePair Key="ScriptVersion" String="0"/>
+ <KeyValuePair Key="Skippable" Boolean="false"/>
+ <KeyValuePair Key="ViewName" String=""/>
+ </Properties>
+</ActivityDef>
diff --git a/resources/boot/EA/CreateNewAgent.xml b/resources/boot/EA/CreateNewAgent.xml
new file mode 100755
index 0000000..49f1f32
--- /dev/null
+++ b/resources/boot/EA/CreateNewAgent.xml
@@ -0,0 +1,19 @@
+<ActivityDef ID="3" Name="CreateNewAgent" Height="0" Width="0" IsLayoutable="false" IsComposite="false">
+ <Properties>
+ <KeyValuePair Key="Repeatable" Boolean="false"/>
+ <KeyValuePair Key="Agent Name" String=""/>
+ <KeyValuePair Key="Autostart" Boolean="true"/>
+ <KeyValuePair Key="Mail Message" String=""/>
+ <KeyValuePair Key="Mail event" String=""/>
+ <KeyValuePair Key="Description" String="Allows you to create a new Agent"/>
+ <KeyValuePair Key="SchemaVersion" String="0"/>
+ <KeyValuePair Key="Show time" Boolean="true"/>
+ <KeyValuePair Key="Viewpoint" String=""/>
+ <KeyValuePair Key="Agent Role" String="Admin"/>
+ <KeyValuePair Key="SchemaType" String="NewAgent"/>
+ <KeyValuePair Key="ScriptName" String="ServerNewEntity"/>
+ <KeyValuePair Key="Ignorable" Boolean="false"/>
+ <KeyValuePair Key="ScriptVersion" String="0"/>
+ <KeyValuePair Key="Skippable" Boolean="false"/>
+ </Properties>
+</ActivityDef>
diff --git a/resources/boot/EA/CreateNewItem.xml b/resources/boot/EA/CreateNewItem.xml
new file mode 100755
index 0000000..8daaf74
--- /dev/null
+++ b/resources/boot/EA/CreateNewItem.xml
@@ -0,0 +1,19 @@
+<ActivityDef ID="1" Name="CreateNewItem" Height="0" Width="0" IsLayoutable="false" IsComposite="false">
+ <Properties>
+ <KeyValuePair Key="Repeatable" Boolean="false"/>
+ <KeyValuePair Key="Agent Name" String=""/>
+ <KeyValuePair Key="Autostart" Boolean="true"/>
+ <KeyValuePair Key="Mail Message" String=""/>
+ <KeyValuePair Key="Mail event" String=""/>
+ <KeyValuePair Key="Description" String="Allows you to create a new item without a description"/>
+ <KeyValuePair Key="SchemaVersion" String="0"/>
+ <KeyValuePair Key="Show time" Boolean="true"/>
+ <KeyValuePair Key="Viewpoint" String=""/>
+ <KeyValuePair Key="Agent Role" String="Admin"/>
+ <KeyValuePair Key="SchemaType" String="NewItem"/>
+ <KeyValuePair Key="ScriptName" String="ServerNewEntity"/>
+ <KeyValuePair Key="Ignorable" Boolean="false"/>
+ <KeyValuePair Key="ScriptVersion" String="0"/>
+ <KeyValuePair Key="Skippable" Boolean="false"/>
+ </Properties>
+</ActivityDef>
diff --git a/resources/boot/EA/CreateNewLocalObjectDef.xml b/resources/boot/EA/CreateNewLocalObjectDef.xml
new file mode 100755
index 0000000..e4a9426
--- /dev/null
+++ b/resources/boot/EA/CreateNewLocalObjectDef.xml
@@ -0,0 +1,19 @@
+<ActivityDef ID="11" Name="CreateNewLocalObjectDef" Height="0" Width="0" IsLayoutable="false" IsComposite="false">
+ <Properties>
+ <KeyValuePair Key="Repeatable" Boolean="false"/>
+ <KeyValuePair Key="Agent Name" String=""/>
+ <KeyValuePair Key="Autostart" Boolean="true"/>
+ <KeyValuePair Key="Mail Message" String=""/>
+ <KeyValuePair Key="Mail event" String=""/>
+ <KeyValuePair Key="Description" String="CreateNewLocalObjectDef"/>
+ <KeyValuePair Key="SchemaVersion" String="0"/>
+ <KeyValuePair Key="Show time" Boolean="true"/>
+ <KeyValuePair Key="Viewpoint" String=""/>
+ <KeyValuePair Key="Agent Role" String="Admin"/>
+ <KeyValuePair Key="SchemaType" String="NewLocalObjectDef"/>
+ <KeyValuePair Key="ScriptName" String="LocalObjectDefCreator"/>
+ <KeyValuePair Key="Ignorable" Boolean="false"/>
+ <KeyValuePair Key="ScriptVersion" String="0"/>
+ <KeyValuePair Key="Skippable" Boolean="false"/>
+ </Properties>
+</ActivityDef>
diff --git a/resources/boot/EA/EditActivityDef.xml b/resources/boot/EA/EditActivityDef.xml
new file mode 100755
index 0000000..e90c225
--- /dev/null
+++ b/resources/boot/EA/EditActivityDef.xml
@@ -0,0 +1,19 @@
+<ActivityDef ID="23" Name="EditActivityDef" Height="0" Width="0" IsLayoutable="false" IsComposite="false">
+ <Properties>
+ <KeyValuePair Key="Repeatable" Boolean="false"/>
+ <KeyValuePair Key="Agent Name" String=""/>
+ <KeyValuePair Key="Autostart" Boolean="true"/>
+ <KeyValuePair Key="Mail Message" String=""/>
+ <KeyValuePair Key="Mail event" String=""/>
+ <KeyValuePair Key="Description" String="Edit this Activity Definition"/>
+ <KeyValuePair Key="SchemaVersion" String="0"/>
+ <KeyValuePair Key="Show time" Boolean="true"/>
+ <KeyValuePair Key="Viewpoint" String="last"/>
+ <KeyValuePair Key="Agent Role" String="Admin"/>
+ <KeyValuePair Key="SchemaType" String=""/>
+ <KeyValuePair Key="ScriptName" String=""/>
+ <KeyValuePair Key="Ignorable" Boolean="false"/>
+ <KeyValuePair Key="ScriptVersion" String=""/>
+ <KeyValuePair Key="Skippable" Boolean="false"/>
+ </Properties>
+</ActivityDef>
diff --git a/resources/boot/EA/EditProperties.xml b/resources/boot/EA/EditProperties.xml
new file mode 100755
index 0000000..15d51b8
--- /dev/null
+++ b/resources/boot/EA/EditProperties.xml
@@ -0,0 +1,20 @@
+<!-- edited with XMLSPY v5 rel. 4 U (http://www.xmlspy.com) by Andrew Branson (CERN) -->
+<ActivityDef ID="251" Name="EditProperties" Height="0" Width="0" IsLayoutable="false" IsComposite="false">
+ <Properties>
+ <KeyValuePair Key="SchemaType" String="PropertyDescription"/>
+ <KeyValuePair Key="Description" String="Define the properties for instances of this description"/>
+ <KeyValuePair Key="ItemSystemKey" String=""/>
+ <KeyValuePair Key="Agent Name" String=""/>
+ <KeyValuePair Key="ScriptName" String=""/>
+ <KeyValuePair Key="Mail event" String=""/>
+ <KeyValuePair Key="Autostart" Boolean="true"/>
+ <KeyValuePair Key="Skippable" Boolean="false"/>
+ <KeyValuePair Key="Agent Role" String="Coor"/>
+ <KeyValuePair Key="Name" String="EditProperties"/>
+ <KeyValuePair Key="ScriptVersion" String=""/>
+ <KeyValuePair Key="Viewpoint" String="last"/>
+ <KeyValuePair Key="SchemaVersion" String="0"/>
+ <KeyValuePair Key="Mail Message" String=""/>
+ <KeyValuePair Key="Repeatable" Boolean="false"/>
+ </Properties>
+</ActivityDef>
diff --git a/resources/boot/EA/EditSchema.xml b/resources/boot/EA/EditSchema.xml
new file mode 100755
index 0000000..3b01fdc
--- /dev/null
+++ b/resources/boot/EA/EditSchema.xml
@@ -0,0 +1,19 @@
+<ActivityDef ID="1" Name="EditSchema" Height="0" Width="0" IsLayoutable="false" IsComposite="false">
+ <Properties>
+ <KeyValuePair Key="Repeatable" Boolean="false"/>
+ <KeyValuePair Key="Agent Name" String=""/>
+ <KeyValuePair Key="Autostart" Boolean="true"/>
+ <KeyValuePair Key="Mail Message" String=""/>
+ <KeyValuePair Key="Mail event" String=""/>
+ <KeyValuePair Key="Description" String="Edit this XML Schema"/>
+ <KeyValuePair Key="SchemaVersion" String="0"/>
+ <KeyValuePair Key="Show time" Boolean="true"/>
+ <KeyValuePair Key="Viewpoint" String="last"/>
+ <KeyValuePair Key="Agent Role" String="Admin"/>
+ <KeyValuePair Key="SchemaType" String="Schema"/>
+ <KeyValuePair Key="ScriptName" String=""/>
+ <KeyValuePair Key="Ignorable" Boolean="false"/>
+ <KeyValuePair Key="ScriptVersion" String=""/>
+ <KeyValuePair Key="Skippable" Boolean="false"/>
+ </Properties>
+</ActivityDef>
diff --git a/resources/boot/EA/EditScriptDefinition.xml b/resources/boot/EA/EditScriptDefinition.xml
new file mode 100755
index 0000000..11c14ec
--- /dev/null
+++ b/resources/boot/EA/EditScriptDefinition.xml
@@ -0,0 +1,19 @@
+<ActivityDef ID="1" Name="EditScriptDefinition" Height="0" Width="0" IsLayoutable="false" IsComposite="false">
+ <Properties>
+ <KeyValuePair Key="Repeatable" Boolean="false"/>
+ <KeyValuePair Key="Agent Name" String=""/>
+ <KeyValuePair Key="Autostart" Boolean="true"/>
+ <KeyValuePair Key="Mail Message" String=""/>
+ <KeyValuePair Key="Mail event" String=""/>
+ <KeyValuePair Key="Description" String="Edit this script definition"/>
+ <KeyValuePair Key="SchemaVersion" String="0"/>
+ <KeyValuePair Key="Show time" Boolean="true"/>
+ <KeyValuePair Key="Agent Role" String="Admin"/>
+ <KeyValuePair Key="Viewpoint" String="last"/>
+ <KeyValuePair Key="SchemaType" String="Script"/>
+ <KeyValuePair Key="Ignorable" Boolean="false"/>
+ <KeyValuePair Key="ScriptName" String=""/>
+ <KeyValuePair Key="Skippable" Boolean="false"/>
+ <KeyValuePair Key="ScriptVersion" String=""/>
+ </Properties>
+</ActivityDef>
diff --git a/resources/boot/LDAPboot.txt b/resources/boot/LDAPboot.txt
new file mode 100755
index 0000000..995d47d
--- /dev/null
+++ b/resources/boot/LDAPboot.txt
@@ -0,0 +1,4 @@
+cn=entity,
+cn=last,cn=entity,
+cn=domain,
+cn=agent,cn=domain, \ No newline at end of file
diff --git a/resources/boot/OD/CompositeActivityDef.xml b/resources/boot/OD/CompositeActivityDef.xml
new file mode 100755
index 0000000..e840734
--- /dev/null
+++ b/resources/boot/OD/CompositeActivityDef.xml
@@ -0,0 +1,186 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
+ <xs:element name="CentrePoint">
+ <xs:complexType>
+ <xs:attribute name="x" type="xs:short" use="required"/>
+ <xs:attribute name="y" type="xs:short" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="CompositeActivityDef">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="childrenGraphModel">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="GraphModelCastorData">
+ <xs:complexType>
+ <xs:choice maxOccurs="unbounded">
+ <xs:element name="ActivitySlotDef">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="CentrePoint"/>
+ <xs:element ref="OutlinePoint" minOccurs="4" maxOccurs="4"/>
+ <xs:element ref="InEdgeId" minOccurs="0"/>
+ <xs:element ref="OutEdgeId" minOccurs="0"/>
+ <xs:element ref="Properties"/>
+ <xs:element name="activityDef" type="xs:string"/>
+ </xs:sequence>
+ <xs:attribute name="ID" type="xs:byte" use="required"/>
+ <xs:attribute name="Name" type="xs:string" use="required"/>
+ <xs:attribute name="Height" type="xs:integer" use="required"/>
+ <xs:attribute name="Width" type="xs:integer" use="required"/>
+ <xs:attribute name="IsLayoutable" type="xs:boolean" use="required"/>
+ <xs:attribute name="IsComposite" type="xs:boolean" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="JoinDef">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="CentrePoint"/>
+ <xs:element ref="OutlinePoint" maxOccurs="unbounded"/>
+ <xs:element ref="InEdgeId" maxOccurs="unbounded"/>
+ <xs:element ref="OutEdgeId" minOccurs="0"/>
+ <xs:element ref="Properties"/>
+ </xs:sequence>
+ <xs:attribute name="ID" type="xs:byte" use="required"/>
+ <xs:attribute name="Name" type="xs:string" use="required"/>
+ <xs:attribute name="Height" type="xs:byte" use="required"/>
+ <xs:attribute name="Width" type="xs:byte" use="required"/>
+ <xs:attribute name="IsLayoutable" type="xs:boolean" use="required"/>
+ <xs:attribute name="IsComposite" type="xs:boolean" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="LoopDef">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="CentrePoint"/>
+ <xs:element ref="OutlinePoint" minOccurs="4" maxOccurs="4"/>
+ <xs:element ref="InEdgeId"/>
+ <xs:element ref="OutEdgeId" maxOccurs="unbounded"/>
+ <xs:element ref="Properties"/>
+ </xs:sequence>
+ <xs:attribute name="ID" type="xs:byte" use="required"/>
+ <xs:attribute name="Name" type="xs:string" use="required"/>
+ <xs:attribute name="Height" type="xs:byte" use="required"/>
+ <xs:attribute name="Width" type="xs:byte" use="required"/>
+ <xs:attribute name="IsLayoutable" type="xs:boolean" use="required"/>
+ <xs:attribute name="IsComposite" type="xs:boolean" use="required"/>
+ <xs:attribute name="isNext" type="xs:boolean" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="NextDef">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="OriginPoint">
+ <xs:complexType>
+ <xs:attribute name="x" type="xs:short" use="required"/>
+ <xs:attribute name="y" type="xs:short" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="TerminusPoint">
+ <xs:complexType>
+ <xs:attribute name="x" type="xs:short" use="required"/>
+ <xs:attribute name="y" type="xs:short" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element ref="Properties"/>
+ </xs:sequence>
+ <xs:attribute name="ID" type="xs:byte" use="required"/>
+ <xs:attribute name="OriginVertexId" type="xs:byte" use="required"/>
+ <xs:attribute name="TerminusVertexId" type="xs:byte" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="XOrSplitDef">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="CentrePoint"/>
+ <xs:element ref="OutlinePoint" minOccurs="4" maxOccurs="4"/>
+ <xs:element ref="InEdgeId" minOccurs="0"/>
+ <xs:element ref="OutEdgeId" maxOccurs="unbounded"/>
+ <xs:element ref="Properties"/>
+ </xs:sequence>
+ <xs:attribute name="ID" type="xs:byte" use="required"/>
+ <xs:attribute name="Name" type="xs:string" use="required"/>
+ <xs:attribute name="Height" type="xs:byte" use="required"/>
+ <xs:attribute name="Width" type="xs:byte" use="required"/>
+ <xs:attribute name="IsLayoutable" type="xs:boolean" use="required"/>
+ <xs:attribute name="IsComposite" type="xs:boolean" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="OrSplitDef">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="CentrePoint"/>
+ <xs:element ref="OutlinePoint" minOccurs="4" maxOccurs="4"/>
+ <xs:element ref="InEdgeId" minOccurs="0"/>
+ <xs:element ref="OutEdgeId" maxOccurs="unbounded"/>
+ <xs:element ref="Properties"/>
+ </xs:sequence>
+ <xs:attribute name="ID" type="xs:byte" use="required"/>
+ <xs:attribute name="Name" type="xs:string" use="required"/>
+ <xs:attribute name="Height" type="xs:byte" use="required"/>
+ <xs:attribute name="Width" type="xs:byte" use="required"/>
+ <xs:attribute name="IsLayoutable" type="xs:boolean" use="required"/>
+ <xs:attribute name="IsComposite" type="xs:boolean" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="AndSplitDef">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="CentrePoint"/>
+ <xs:element ref="OutlinePoint" minOccurs="4" maxOccurs="4"/>
+ <xs:element ref="InEdgeId" minOccurs="0"/>
+ <xs:element ref="OutEdgeId" maxOccurs="unbounded"/>
+ <xs:element ref="Properties"/>
+ </xs:sequence>
+ <xs:attribute name="ID" type="xs:byte" use="required"/>
+ <xs:attribute name="Name" type="xs:string" use="required"/>
+ <xs:attribute name="Height" type="xs:byte" use="required"/>
+ <xs:attribute name="Width" type="xs:byte" use="required"/>
+ <xs:attribute name="IsLayoutable" type="xs:boolean" use="required"/>
+ <xs:attribute name="IsComposite" type="xs:boolean" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ <xs:attribute name="ClassNameOfVertexOutlineCreator" type="xs:string" use="required"/>
+ <xs:attribute name="StartVertexId" type="xs:byte" use="required"/>
+ <xs:attribute name="NextId" type="xs:byte" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element ref="Properties"/>
+ <xs:element name="castorNonLayoutableChildren" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="ID" type="xs:integer" use="required"/>
+ <xs:attribute name="Name" type="xs:string" use="required"/>
+ <xs:attribute name="Height" type="xs:integer" use="required"/>
+ <xs:attribute name="Width" type="xs:integer" use="required"/>
+ <xs:attribute name="IsLayoutable" type="xs:boolean" use="required"/>
+ <xs:attribute name="IsComposite" type="xs:boolean" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="InEdgeId" type="xs:byte"/>
+ <xs:element name="OutEdgeId" type="xs:byte"/>
+ <xs:element name="OutlinePoint">
+ <xs:complexType>
+ <xs:attribute name="x" type="xs:short" use="required"/>
+ <xs:attribute name="y" type="xs:short" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Properties">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="KeyValuePair" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="Key" type="xs:string" use="required"/>
+ <xs:attribute name="String" type="xs:string" use="optional"/>
+ <xs:attribute name="Boolean" type="xs:boolean" use="optional"/>
+ <xs:attribute name="Integer" type="xs:int" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
diff --git a/resources/boot/OD/ElementaryActivityDef.xml b/resources/boot/OD/ElementaryActivityDef.xml
new file mode 100755
index 0000000..ea637e4
--- /dev/null
+++ b/resources/boot/OD/ElementaryActivityDef.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
+ <xs:element name="ActivityDef">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Properties">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="KeyValuePair" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="Key" type="xs:string" use="optional"/>
+ <xs:attribute name="Boolean" type="xs:boolean" use="optional"/>
+ <xs:attribute name="String" type="xs:string" use="optional"/>
+ <xs:attribute name="Integer" type="xs:int" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="ID" type="xs:byte" use="required"/>
+ <xs:attribute name="Name" type="xs:string" use="required"/>
+ <xs:attribute name="Height" type="xs:integer" use="optional"/>
+ <xs:attribute name="Width" type="xs:integer" use="optional"/>
+ <xs:attribute name="IsLayoutable" type="xs:boolean" use="required" fixed="false"/>
+ <xs:attribute name="IsComposite" type="xs:boolean" use="required" fixed="false"/>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
diff --git a/resources/boot/OD/New.xml b/resources/boot/OD/New.xml
new file mode 100755
index 0000000..91755c8
--- /dev/null
+++ b/resources/boot/OD/New.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
+</xs:schema>
diff --git a/resources/boot/OD/NewAgent.xml b/resources/boot/OD/NewAgent.xml
new file mode 100755
index 0000000..773f4fc
--- /dev/null
+++ b/resources/boot/OD/NewAgent.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- edited with XMLSpy v2005 rel. 3 U (http://www.altova.com) by Andrew Branson (CERN) -->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
+ <xs:element name="NewAgent">
+ <xs:annotation>
+ <xs:documentation>Complete Structure for new agent</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Role" type="xs:string" maxOccurs="unbounded">
+ <xs:annotation>
+ <xs:documentation>The initial roles that this Agent will hold</xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="password" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
diff --git a/resources/boot/OD/NewItem.xml b/resources/boot/OD/NewItem.xml
new file mode 100755
index 0000000..bcd5298
--- /dev/null
+++ b/resources/boot/OD/NewItem.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- edited with XMLSpy v2005 rel. 3 U (http://www.altova.com) by Andrew Branson (CERN) -->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
+ <xs:element name="NewItem">
+ <xs:annotation>
+ <xs:documentation>Complete Structure for new item</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Property" minOccurs="0" maxOccurs="unbounded">
+ <xs:annotation>
+ <xs:documentation>New Properties for the item</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="value" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Aggregation" minOccurs="0" maxOccurs="unbounded">
+ <xs:annotation>
+ <xs:documentation>A new collection with layout</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="AggregationMember" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Geometry">
+ <xs:annotation>
+ <xs:documentation>The position and size of this member slot on the layout</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:attribute name="x" type="xs:int" use="required"/>
+ <xs:attribute name="y" type="xs:int" use="required"/>
+ <xs:attribute name="width" type="xs:int" use="required"/>
+ <xs:attribute name="height" type="xs:int" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="slotNo" type="xs:int" use="required"/>
+ <xs:attribute name="itemDescriptionPath" type="xs:string" use="optional"/>
+ <xs:attribute name="itemPath" type="xs:string" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="isDescription" type="xs:boolean" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Dependency" minOccurs="0" maxOccurs="unbounded">
+ <xs:annotation>
+ <xs:documentation>A new collection without layout</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="DependencyMember" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="itemPath" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="isDescription" type="xs:boolean" use="required"/>
+ <xs:attribute name="itemDescriptionPath" type="xs:string" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="initialPath" type="xs:string" use="required"/>
+ <xs:attribute name="workflow" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
diff --git a/resources/boot/OD/NewLocalObjectDef.xml b/resources/boot/OD/NewLocalObjectDef.xml
new file mode 100755
index 0000000..0186872
--- /dev/null
+++ b/resources/boot/OD/NewLocalObjectDef.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- edited with XMLSpy v2006 sp1 U (http://www.altova.com) by Andrew Branson (CERN) -->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
+ <xs:element name="NewLocalObjectDef">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ObjectName" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>Please give a name for your new object.</xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="SubFolder" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>If you want to store your object in a subfolder, give the subpath here.</xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
diff --git a/resources/boot/OD/PredefinedStepOutcome.xml b/resources/boot/OD/PredefinedStepOutcome.xml
new file mode 100755
index 0000000..bc0ac52
--- /dev/null
+++ b/resources/boot/OD/PredefinedStepOutcome.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
+ <xs:element name="PredefinedStepOutcome">
+ <xs:annotation>
+ <xs:documentation>General holder for predefined step outcomes we can't be bothered to define a proper schema for</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="param" type="xs:string" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
diff --git a/resources/boot/OD/PropertyDescription.xml b/resources/boot/OD/PropertyDescription.xml
new file mode 100755
index 0000000..886092a
--- /dev/null
+++ b/resources/boot/OD/PropertyDescription.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
+ <xs:element name="AllProperties">
+ <xs:annotation>
+ <xs:documentation>Defines the properties that will exist in instances of this description when initially created.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PropertyDescription" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="Name" type="xs:string" use="required">
+ <xs:annotation>
+ <xs:documentation>The name of the new property.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="IsClassIdentifier" type="xs:boolean" use="required">
+ <xs:annotation>
+ <xs:documentation>Whether this property is used to identify the class of this item. Properties flagged as 'true' here are used to check type when these items are assigned to collections.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="DefaultValue" type="xs:string" use="optional">
+ <xs:annotation>
+ <xs:documentation>The initial value of the property when it is created.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="IsMutable" type="xs:boolean" use="optional">
+ <xs:annotation>
+ <xs:documentation>Whether or not the property can have its value changed once it has been created.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
diff --git a/resources/boot/OD/Schema.xml b/resources/boot/OD/Schema.xml
new file mode 100755
index 0000000..fed1949
--- /dev/null
+++ b/resources/boot/OD/Schema.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
+<!-- empty schema as the real one is too complicated for our validator -->
+</xs:schema> \ No newline at end of file
diff --git a/resources/boot/OD/Script.xml b/resources/boot/OD/Script.xml
new file mode 100755
index 0000000..5726aca
--- /dev/null
+++ b/resources/boot/OD/Script.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- edited with XMLSpy v2005 rel. 3 U (http://www.altova.com) by Andrew Branson (CERN) -->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
+ <xs:element name="cristalscript">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="include" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="version" type="xs:integer" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="param" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="type" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="output" minOccurs="0">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="optional"/>
+ <xs:attribute name="type" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="script">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="language" type="xs:string" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
diff --git a/resources/boot/SC/CreateNewNumberedVersionFromLast.xml b/resources/boot/SC/CreateNewNumberedVersionFromLast.xml
new file mode 100755
index 0000000..bb66f4c
--- /dev/null
+++ b/resources/boot/SC/CreateNewNumberedVersionFromLast.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<cristalscript>
+ <output name="errors" type="com.c2kernel.scripting.ErrorInfo"/>
+ <script language="javascript" name="CreateNewNumberedVersionFromLast"><![CDATA[
+
+ var job = bsf.lookupBean("job");
+ var item = bsf.lookupBean("item");
+ var agent = bsf.lookupBean("agent");
+ var errorBuffer = bsf.lookupBean("errors");
+
+ var viewName = job.getActPropString("ViewName");
+
+ if (viewName.equals("")) {
+ errorBuffer.addError("ViewName not specified. Cannot create new version.");
+ errorBuffer.setFatal();
+ }
+
+ if (!(errorBuffer.getFatal())) {
+ var lastView = -1;
+ var existingViews = item.getContents("/ViewPoint/"+viewName);
+ for (i=0; i<existingViews.length; i++) {
+ var thisView = parseInt(existingViews[i]);
+ if (thisView!=NaN && lastView < thisView) lastView = thisView;
+ }
+ lastView++;
+ try {
+ var existingLast = agent.unmarshall(item.queryData("/ViewPoint/"+viewName+"/last"));
+ } catch (e) {
+ errorBuffer.addError("No data found. You must submit at least one version before executing this activity.");
+ errorBuffer.setFatal();
+ }
+ if (!(errorBuffer.getFatal())) {
+ existingLast.setName(lastView);
+ agent.execute(item, "AddC2KObject", existingLast);
+ }
+ }
+ errorBuffer;
+ ]]></script>
+</cristalscript>
diff --git a/resources/boot/SC/LocalObjectDefCreator.xml b/resources/boot/SC/LocalObjectDefCreator.xml
new file mode 100755
index 0000000..c57cbc1
--- /dev/null
+++ b/resources/boot/SC/LocalObjectDefCreator.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<cristalscript>
+ <output name="errors" type="com.c2kernel.scripting.ErrorInfo"/>
+ <script language="javascript" name="LocalObjectDefCreator"><![CDATA[
+ importClass(Packages.com.c2kernel.utils.CastorXMLUtility);
+ importClass(Packages.com.c2kernel.utils.Resource);
+ importClass(Packages.com.c2kernel.process.Bootstrap);
+ importClass(Packages.com.c2kernel.lifecycle.CompositeActivityDef);
+ importClass(Packages.com.c2kernel.lifecycle.ActivityDef);
+
+ var job = bsf.lookupBean("job");
+ var item = bsf.lookupBean("item");
+ var agent = bsf.lookupBean("agent");
+ var errorBuffer = bsf.lookupBean("errors");
+ var type = job.getActPropString("NewType");
+ var name = job.getOutcome().getDOM().getDocumentElement().
+ getElementsByTagName("ObjectName").item(0).getFirstChild().getData();
+ var folder = job.getOutcome().getDOM().getDocumentElement().
+ getElementsByTagName("SubFolder").item(0).getFirstChild();
+ var domPath = Bootstrap.getTypeRoot(type).toString();
+ if (folder != null) domPath = domPath + "/" + folder.getData();
+
+ var params = new Array(2);
+ params[0] = name;
+
+ params[1] = domPath;
+
+ if (!(errorBuffer.getFatal())) {
+ try {
+ agent.execute(item, "CreateItemFromDescription", params);
+ } catch (e) {
+ errorBuffer.addError("Could not create "+name+": "+e.message);
+ errorBuffer.setFatal();
+ }
+ }
+
+ if (!(errorBuffer.getFatal())) { // store an outcome in the new desc
+ var newObj;
+ if (type.equals("EA") || type.equals("CA")) {
+ var newAct = type.equals("CA")?new CompositeActivityDef(): new ActivityDef();
+ newAct.setName(name);
+ newObj = CastorXMLUtility.marshall(newAct);
+ }
+ else
+ newObj = Resource.getTextResource("boot/"+type+"/New.xml");
+
+ var newPath = new Packages.com.c2kernel.lookup.DomainPath(domPath+"/"+name);
+ var newItem = agent.getItem(newPath);
+ newItem.requestAction(agent.getSystemKey(), "workflow/domain/EditDefinition", 4, newObj);
+ var tree = Packages.com.c2kernel.gui.MainFrame.treeBrowser;
+ if (tree != null) // open new item in the gui
+ tree.push(newPath);
+
+ }
+ errorBuffer;
+ ]]></script>
+</cristalscript>
diff --git a/resources/boot/SC/New.xml b/resources/boot/SC/New.xml
new file mode 100755
index 0000000..a706310
--- /dev/null
+++ b/resources/boot/SC/New.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<cristalscript>
+ <output name="errors" type="com.c2kernel.scripting.ErrorInfo"/>
+ <script language="javascript" name=""><![CDATA[
+
+ var job = bsf.lookupBean("job");
+ var item = bsf.lookupBean("item");
+ var agent = bsf.lookupBean("agent");
+ var errorBuffer = bsf.lookupBean("errors");
+
+ errorBuffer;
+ ]]></script>
+</cristalscript>
diff --git a/resources/boot/SC/ServerNewEntity.xml b/resources/boot/SC/ServerNewEntity.xml
new file mode 100755
index 0000000..2f89927
--- /dev/null
+++ b/resources/boot/SC/ServerNewEntity.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<cristalscript>
+ <output name="errors" type="com.c2kernel.scripting.ErrorInfo"/>
+ <script language="javascript" name="LocalObjectDefCreator"><![CDATA[
+
+ var job = bsf.lookupBean("job");
+ var item = bsf.lookupBean("item");
+ var agent = bsf.lookupBean("agent");
+ var errorBuffer = bsf.lookupBean("errors");
+ try {
+ var schema = job.getActPropString("SchemaType");
+ var predef = schema.equals("NewItem")?"CreateNewItem":"CreateNewAgent";
+ item.requestAction(agent.getSystemKey(), "workflow/predefined/"+predef, Packages.com.c2kernel.lifecycle.instance.stateMachine.Transitions.DONE, job.getOutcomeString());
+ } catch (e) {
+ errorBuffer.addError(e.getMessage());
+ errorBuffer.setFatal();
+ }
+ errorBuffer;
+ ]]></script>
+</cristalscript>
diff --git a/resources/boot/allbootitems.txt b/resources/boot/allbootitems.txt
new file mode 100755
index 0000000..004bdf1
--- /dev/null
+++ b/resources/boot/allbootitems.txt
@@ -0,0 +1,34 @@
+OD/Schema
+OD/CompositeActivityDef
+OD/ElementaryActivityDef
+OD/PredefinedStepOutcome
+OD/PropertyDescription
+OD/Script
+OD/NewLocalObjectDef
+OD/NewItem
+OD/NewAgent
+EA/AssignNewVersionFromLast
+EA/EditActivityDef
+EA/EditSchema
+EA/EditScriptDefinition
+EA/CreateNewLocalObjectDef
+EA/CreateNewItem
+EA/CreateNewAgent
+EA/EditProperties
+CA/ManageCompositeActDef
+CA/ManageElementaryActDef
+CA/ManageSchema
+CA/ManageScript
+CA/SchemaFactory
+CA/CompositeActivityFactory
+CA/ElementaryActivityFactory
+CA/ScriptFactory
+CA/NoWorkflow
+CA/ServerItemWorkflow
+SC/CreateNewNumberedVersionFromLast
+SC/LocalObjectDefCreator
+SC/ServerNewEntity
+factory/CA
+factory/EA
+factory/OD
+factory/SC \ No newline at end of file
diff --git a/resources/boot/factory/CA.xml b/resources/boot/factory/CA.xml
new file mode 100755
index 0000000..908647a
--- /dev/null
+++ b/resources/boot/factory/CA.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<NewItem initialPath="/desc" name="CompositeActivityDefFactory" workflow="CompositeActivityFactory">
+ <Property name="LocalObjectType" value="CompositeActivityDef"/>
+ <Property name="Type" value="LocalObjectFactory"/>
+ <Dependency name="Workflow" isDescription="false">
+ <DependencyMember itemPath="/desc/ActivityDesc/system/kernel/ManageCompositeActDef"/>
+ </Dependency>
+</NewItem>
diff --git a/resources/boot/factory/EA.xml b/resources/boot/factory/EA.xml
new file mode 100755
index 0000000..1185f10
--- /dev/null
+++ b/resources/boot/factory/EA.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<NewItem initialPath="/desc" name="ElementaryActivityDefFactory" workflow="ElementaryActivityFactory">
+ <Property name="LocalObjectType" value="ElementaryActivityDef"/>
+ <Property name="Type" value="LocalObjectFactory"/>
+ <Dependency name="Workflow" isDescription="false">
+ <DependencyMember itemPath="/desc/ActivityDesc/system/kernel/ManageElementaryActDef"/>
+ </Dependency>
+</NewItem>
diff --git a/resources/boot/factory/OD.xml b/resources/boot/factory/OD.xml
new file mode 100755
index 0000000..275048b
--- /dev/null
+++ b/resources/boot/factory/OD.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<NewItem initialPath="/desc" name="SchemaFactory" workflow="SchemaFactory">
+ <Property name="LocalObjectType" value="Schema"/>
+ <Property name="Type" value="LocalObjectFactory"/>
+ <Dependency name="Workflow" isDescription="false">
+ <DependencyMember itemPath="/desc/ActivityDesc/system/kernel/ManageSchema"/>
+ </Dependency>
+</NewItem>
diff --git a/resources/boot/factory/SC.xml b/resources/boot/factory/SC.xml
new file mode 100755
index 0000000..7f3f97e
--- /dev/null
+++ b/resources/boot/factory/SC.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<NewItem initialPath="/desc" name="ScriptFactory" workflow="ScriptFactory">
+ <Property name="LocalObjectType" value="Script"/>
+ <Property name="Type" value="LocalObjectFactory"/>
+ <Dependency name="Workflow" isDescription="false">
+ <DependencyMember itemPath="/desc/ActivityDesc/system/kernel/ManageScript"/>
+ </Dependency>
+</NewItem>
diff --git a/resources/boot/property/CAProp.xml b/resources/boot/property/CAProp.xml
new file mode 100755
index 0000000..d5b2bea
--- /dev/null
+++ b/resources/boot/property/CAProp.xml
@@ -0,0 +1,5 @@
+<AllProperties>
+ <PropertyDescription Name="Name" IsClassIdentifier="false" DefaultValue="" IsMutable="false"/>
+ <PropertyDescription Name="Complexity" IsClassIdentifier="true" DefaultValue="Composite" IsMutable="false"/>
+ <PropertyDescription Name="Type" IsClassIdentifier="true" DefaultValue="ActivityDesc" IsMutable="false"/>
+</AllProperties>
diff --git a/resources/boot/property/EAProp.xml b/resources/boot/property/EAProp.xml
new file mode 100755
index 0000000..ddf07c1
--- /dev/null
+++ b/resources/boot/property/EAProp.xml
@@ -0,0 +1,5 @@
+<AllProperties>
+ <PropertyDescription Name="Name" IsClassIdentifier="false" DefaultValue="" IsMutable="false"/>
+ <PropertyDescription Name="Complexity" IsClassIdentifier="true" DefaultValue="Elementary" IsMutable="false"/>
+ <PropertyDescription Name="Type" IsClassIdentifier="true" DefaultValue="ActivityDesc" IsMutable="false"/>
+</AllProperties>
diff --git a/resources/boot/property/ODProp.xml b/resources/boot/property/ODProp.xml
new file mode 100755
index 0000000..0c85444
--- /dev/null
+++ b/resources/boot/property/ODProp.xml
@@ -0,0 +1,5 @@
+<AllProperties>
+ <PropertyDescription Name="Name" IsClassIdentifier="false" DefaultValue="" IsMutable="false"/>
+ <PropertyDescription Name="Type" IsClassIdentifier="true" DefaultValue="OutcomeDesc" IsMutable="false"/>
+ <PropertyDescription Name="Breakapart" IsClassIdentifier="false" DefaultValue="0" IsMutable="false"/>
+</AllProperties>
diff --git a/resources/boot/property/SCProp.xml b/resources/boot/property/SCProp.xml
new file mode 100755
index 0000000..356f2f9
--- /dev/null
+++ b/resources/boot/property/SCProp.xml
@@ -0,0 +1,4 @@
+<AllProperties>
+ <PropertyDescription Name="Name" IsClassIdentifier="false" DefaultValue="" IsMutable="false"/>
+ <PropertyDescription Name="Type" IsClassIdentifier="true" DefaultValue="Script" IsMutable="false"/>
+</AllProperties>
diff --git a/resources/images/Thumbs.db b/resources/images/Thumbs.db
new file mode 100755
index 0000000..551f7e5
--- /dev/null
+++ b/resources/images/Thumbs.db
Binary files differ
diff --git a/resources/images/about.png b/resources/images/about.png
new file mode 100755
index 0000000..3f34032
--- /dev/null
+++ b/resources/images/about.png
Binary files differ
diff --git a/resources/images/compositeMember.gif b/resources/images/compositeMember.gif
new file mode 100755
index 0000000..9e267fc
--- /dev/null
+++ b/resources/images/compositeMember.gif
Binary files differ
diff --git a/resources/images/elementaryMember.gif b/resources/images/elementaryMember.gif
new file mode 100755
index 0000000..9aa677e
--- /dev/null
+++ b/resources/images/elementaryMember.gif
Binary files differ
diff --git a/resources/images/find.png b/resources/images/find.png
new file mode 100755
index 0000000..54d2a6f
--- /dev/null
+++ b/resources/images/find.png
Binary files differ
diff --git a/resources/images/folder.png b/resources/images/folder.png
new file mode 100755
index 0000000..c969ff4
--- /dev/null
+++ b/resources/images/folder.png
Binary files differ
diff --git a/resources/images/graph/autolayout.png b/resources/images/graph/autolayout.png
new file mode 100755
index 0000000..4470ace
--- /dev/null
+++ b/resources/images/graph/autolayout.png
Binary files differ
diff --git a/resources/images/graph/copy.png b/resources/images/graph/copy.png
new file mode 100755
index 0000000..77b67a3
--- /dev/null
+++ b/resources/images/graph/copy.png
Binary files differ
diff --git a/resources/images/graph/delete.png b/resources/images/graph/delete.png
new file mode 100755
index 0000000..180fc21
--- /dev/null
+++ b/resources/images/graph/delete.png
Binary files differ
diff --git a/resources/images/graph/edge.png b/resources/images/graph/edge.png
new file mode 100755
index 0000000..12593ae
--- /dev/null
+++ b/resources/images/graph/edge.png
Binary files differ
diff --git a/resources/images/graph/history.png b/resources/images/graph/history.png
new file mode 100755
index 0000000..f7defb1
--- /dev/null
+++ b/resources/images/graph/history.png
Binary files differ
diff --git a/resources/images/graph/load.png b/resources/images/graph/load.png
new file mode 100755
index 0000000..c969ff4
--- /dev/null
+++ b/resources/images/graph/load.png
Binary files differ
diff --git a/resources/images/graph/newvertex.png b/resources/images/graph/newvertex.png
new file mode 100755
index 0000000..324b65a
--- /dev/null
+++ b/resources/images/graph/newvertex.png
Binary files differ
diff --git a/resources/images/graph/newvertex_large.png b/resources/images/graph/newvertex_large.png
new file mode 100755
index 0000000..aade756
--- /dev/null
+++ b/resources/images/graph/newvertex_large.png
Binary files differ
diff --git a/resources/images/graph/print.png b/resources/images/graph/print.png
new file mode 100755
index 0000000..f417d83
--- /dev/null
+++ b/resources/images/graph/print.png
Binary files differ
diff --git a/resources/images/graph/resizepad.gif b/resources/images/graph/resizepad.gif
new file mode 100755
index 0000000..0f1b5d6
--- /dev/null
+++ b/resources/images/graph/resizepad.gif
Binary files differ
diff --git a/resources/images/graph/save.png b/resources/images/graph/save.png
new file mode 100755
index 0000000..1c4f461
--- /dev/null
+++ b/resources/images/graph/save.png
Binary files differ
diff --git a/resources/images/graph/selection.gif b/resources/images/graph/selection.gif
new file mode 100755
index 0000000..92595c7
--- /dev/null
+++ b/resources/images/graph/selection.gif
Binary files differ
diff --git a/resources/images/graph/start.png b/resources/images/graph/start.png
new file mode 100755
index 0000000..b1212e2
--- /dev/null
+++ b/resources/images/graph/start.png
Binary files differ
diff --git a/resources/images/graph/zoomout.png b/resources/images/graph/zoomout.png
new file mode 100755
index 0000000..b65dcc1
--- /dev/null
+++ b/resources/images/graph/zoomout.png
Binary files differ
diff --git a/resources/images/info.png b/resources/images/info.png
new file mode 100755
index 0000000..7c98fba
--- /dev/null
+++ b/resources/images/info.png
Binary files differ
diff --git a/resources/images/leaf.png b/resources/images/leaf.png
new file mode 100755
index 0000000..acbdea8
--- /dev/null
+++ b/resources/images/leaf.png
Binary files differ
diff --git a/resources/images/loading.gif b/resources/images/loading.gif
new file mode 100755
index 0000000..24f86d4
--- /dev/null
+++ b/resources/images/loading.gif
Binary files differ
diff --git a/resources/images/next.png b/resources/images/next.png
new file mode 100755
index 0000000..4be5f63
--- /dev/null
+++ b/resources/images/next.png
Binary files differ
diff --git a/resources/images/reload.gif b/resources/images/reload.gif
new file mode 100755
index 0000000..2739941
--- /dev/null
+++ b/resources/images/reload.gif
Binary files differ
diff --git a/resources/images/typeicons/agent_16.png b/resources/images/typeicons/agent_16.png
new file mode 100755
index 0000000..1820787
--- /dev/null
+++ b/resources/images/typeicons/agent_16.png
Binary files differ
diff --git a/resources/images/typeicons/agent_32.png b/resources/images/typeicons/agent_32.png
new file mode 100755
index 0000000..b69c918
--- /dev/null
+++ b/resources/images/typeicons/agent_32.png
Binary files differ
diff --git a/resources/images/typeicons/compositeactivitydesc_16.png b/resources/images/typeicons/compositeactivitydesc_16.png
new file mode 100755
index 0000000..14e0c55
--- /dev/null
+++ b/resources/images/typeicons/compositeactivitydesc_16.png
Binary files differ
diff --git a/resources/images/typeicons/compositeactivitydesc_32.png b/resources/images/typeicons/compositeactivitydesc_32.png
new file mode 100755
index 0000000..dec52db
--- /dev/null
+++ b/resources/images/typeicons/compositeactivitydesc_32.png
Binary files differ
diff --git a/resources/images/typeicons/elementaryactivitydesc_16.png b/resources/images/typeicons/elementaryactivitydesc_16.png
new file mode 100755
index 0000000..4db99b3
--- /dev/null
+++ b/resources/images/typeicons/elementaryactivitydesc_16.png
Binary files differ
diff --git a/resources/images/typeicons/elementaryactivitydesc_32.png b/resources/images/typeicons/elementaryactivitydesc_32.png
new file mode 100755
index 0000000..def8c90
--- /dev/null
+++ b/resources/images/typeicons/elementaryactivitydesc_32.png
Binary files differ
diff --git a/resources/images/typeicons/localobjectfactory_16.png b/resources/images/typeicons/localobjectfactory_16.png
new file mode 100755
index 0000000..9979ee7
--- /dev/null
+++ b/resources/images/typeicons/localobjectfactory_16.png
Binary files differ
diff --git a/resources/images/typeicons/localobjectfactory_32.png b/resources/images/typeicons/localobjectfactory_32.png
new file mode 100755
index 0000000..f43f44f
--- /dev/null
+++ b/resources/images/typeicons/localobjectfactory_32.png
Binary files differ
diff --git a/resources/images/typeicons/outcome_desc_32.png b/resources/images/typeicons/outcome_desc_32.png
new file mode 100755
index 0000000..0139f7e
--- /dev/null
+++ b/resources/images/typeicons/outcome_desc_32.png
Binary files differ
diff --git a/resources/images/typeicons/outcomedesc_16.png b/resources/images/typeicons/outcomedesc_16.png
new file mode 100755
index 0000000..b5829ba
--- /dev/null
+++ b/resources/images/typeicons/outcomedesc_16.png
Binary files differ
diff --git a/resources/images/typeicons/outcomedesc_32.png b/resources/images/typeicons/outcomedesc_32.png
new file mode 100755
index 0000000..0139f7e
--- /dev/null
+++ b/resources/images/typeicons/outcomedesc_32.png
Binary files differ
diff --git a/resources/images/typeicons/script_16.png b/resources/images/typeicons/script_16.png
new file mode 100755
index 0000000..203e519
--- /dev/null
+++ b/resources/images/typeicons/script_16.png
Binary files differ
diff --git a/resources/images/typeicons/script_32.png b/resources/images/typeicons/script_32.png
new file mode 100755
index 0000000..a1e8d3a
--- /dev/null
+++ b/resources/images/typeicons/script_32.png
Binary files differ
diff --git a/resources/images/typeicons/server_16.png b/resources/images/typeicons/server_16.png
new file mode 100755
index 0000000..b3ff15b
--- /dev/null
+++ b/resources/images/typeicons/server_16.png
Binary files differ
diff --git a/resources/images/typeicons/server_32.png b/resources/images/typeicons/server_32.png
new file mode 100755
index 0000000..d7bf297
--- /dev/null
+++ b/resources/images/typeicons/server_32.png
Binary files differ
diff --git a/resources/mapFiles/CastorHashMapMap.xml b/resources/mapFiles/CastorHashMapMap.xml
new file mode 100755
index 0000000..601cf06
--- /dev/null
+++ b/resources/mapFiles/CastorHashMapMap.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+
+<mapping>
+ <class name="com.c2kernel.utils.KeyValuePair">
+ <map-to xml="KeyValuePair"/>
+ <field name="mKey"
+ type="string"
+ direct="false"
+ get-method="getKey"
+ set-method="setKey">
+ <bind-xml name="Key" node="attribute"/>
+ </field>
+ <field name="IntegerValue"
+ type="java.lang.Integer"
+ direct="false">
+ <bind-xml name="Integer" node="attribute"/>
+ </field>
+ <field name="StringValue"
+ type="java.lang.String"
+ direct="false">
+ <bind-xml name="String" node="attribute"/>
+ </field>
+ <field name="BooleanValue"
+ type="java.lang.Boolean"
+ direct="false">
+ <bind-xml name="Boolean" node="attribute"/>
+ </field>
+ <field name="FloatValue"
+ type="java.lang.Float"
+ direct="false">
+ <bind-xml name="Float" node="attribute"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.utils.CastorArrayList">
+ <map-to xml="ArrayList"/>
+ <field name="list" collection="arraylist" direct="true" container="false">
+ <bind-xml name="ArrayListMember" node="element"/>
+ </field>
+ </class>
+</mapping>
+
diff --git a/resources/mapFiles/CollectionMap.xml b/resources/mapFiles/CollectionMap.xml
new file mode 100755
index 0000000..d346eac
--- /dev/null
+++ b/resources/mapFiles/CollectionMap.xml
@@ -0,0 +1,113 @@
+<?xml version="1.0"?>
+<!-- edited with XML Spy v4.2 U (http://www.xmlspy.com) by Sebastian Gaspard (Agilium) -->
+<mapping>
+ <class name="com.c2kernel.collection.CollectionMemberList">
+ <map-to xml="CollectionMemberList"/>
+ <field name="list"
+ collection="arraylist"
+ direct="true"
+ type="com.c2kernel.collection.CollectionMember">
+ <bind-xml auto-naming="deriveByClass" node="element"/>
+ </field>
+ </class>
+
+ <class name="com.c2kernel.collection.DependencyMember">
+ <map-to xml="DependencyMember"/>
+ <field name="ID" type="integer" direct="false">
+ <bind-xml name="ID" node="attribute"/>
+ </field>
+ <field name="mEntityKey"
+ type="integer"
+ direct="false"
+ get-method="getEntityKey"
+ set-method="setEntityKey">
+ <bind-xml name="EntityKey" node="attribute"/>
+ </field>
+ <field name="mProperties"
+ type="com.c2kernel.utils.KeyValuePair"
+ collection="array"
+ container="false"
+ direct="false"
+ get-method="getKeyValuePairs"
+ set-method="setKeyValuePairs">
+ <bind-xml name="Properties" node="element"/>
+ </field>
+ </class>
+
+ <class name="com.c2kernel.collection.AggregationMember"
+ extends="com.c2kernel.graph.model.GraphableVertex">
+ <map-to xml="AggregationMember"/>
+ <field name="mEntityKey"
+ type="integer"
+ direct="false"
+ get-method="getEntityKey"
+ set-method="setEntityKey">
+ <bind-xml name="EntityKey" node="attribute"/>
+ </field>
+ <field name="mClassProps"
+ type="string"
+ direct="false"
+ get-method="getClassProps"
+ set-method="setClassProps">
+ <bind-xml name="ClassProps" node="attribute"/>
+ </field>
+ </class>
+
+
+ <class name="com.c2kernel.collection.Parent2ChildCollection">
+ <map-to xml="Parent2ChildCollection"/>
+ <field name="mMembers"
+ type="com.c2kernel.collection.CollectionMemberList"
+ direct="false"
+ get-method="getMembers"
+ set-method="setMembers">
+ <bind-xml auto-naming="deriveByClass" node="element"/>
+ </field>
+ <field name="mURLInfo"
+ type="string"
+ direct="false"
+ get-method="getURLInfo"
+ set-method="setURLInfo">
+ <bind-xml name="URLInfo" node="attribute"/>
+ </field>
+ <field name="mName"
+ type="string"
+ direct="false"
+ get-method="getName"
+ set-method="setName">
+ <bind-xml name="CollectionName" node="attribute"/>
+ </field>
+
+ </class>
+ <class name="com.c2kernel.collection.Dependency" extends="com.c2kernel.collection.Parent2ChildCollection">
+ <map-to xml="Dependency"/>
+ <field name="mClassProps"
+ type="string"
+ direct="false"
+ get-method="getClassProps"
+ set-method="setClassProps">
+ <bind-xml name="ClassProps" node="attribute"/>
+ </field>
+ <field name="mProperties"
+ type="com.c2kernel.utils.KeyValuePair"
+ collection="array"
+ container="false"
+ direct="false"
+ get-method="getKeyValuePairs"
+ set-method="setKeyValuePairs">
+ <bind-xml name="Properties" node="element"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.collection.Aggregation" extends="com.c2kernel.collection.Parent2ChildCollection">
+ <map-to xml="Aggregation"/>
+ <field name="mLayout" type="com.c2kernel.graph.model.GraphModel" direct="false" get-method="getLayout" set-method="setLayout">
+ <bind-xml name="Layout" node="element"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.collection.AggregationDescription" extends="com.c2kernel.collection.Aggregation">
+ <map-to xml="AggregationDescription"/>
+ </class>
+ <class name="com.c2kernel.collection.AggregationInstance" extends="com.c2kernel.collection.Aggregation">
+ <map-to xml="AggregationInstance"/>
+ </class>
+</mapping>
diff --git a/resources/mapFiles/HistoryMap.xml b/resources/mapFiles/HistoryMap.xml
new file mode 100755
index 0000000..803bf64
--- /dev/null
+++ b/resources/mapFiles/HistoryMap.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<mapping>
+
+ <class name="com.c2kernel.events.Event">
+ <map-to xml="Event"/>
+ <field name="mID" type="integer" direct="false" get-method="getID" set-method="setID">
+ <bind-xml name="ID" node="attribute"/>
+ </field>
+ <field name="mEntitySystemKey" type="integer" direct="false" get-method="getEntitySystemKey" set-method="setEntitySystemKey">
+ <bind-xml name="EntitySystemKey" node="attribute"/>
+ </field>
+ <field name="mStepName" type="string" direct="false" get-method="getStepName" set-method="setStepName">
+ <bind-xml name="StepName" node="attribute"/>
+ </field>
+ <field name="mStepPath" type="string" direct="false" get-method="getStepPath" set-method="setStepPath">
+ <bind-xml name="StepPath" node="attribute"/>
+ </field>
+ <field name="mStepType" type="string" direct="false" get-method="getStepType" set-method="setStepType">
+ <bind-xml name="StepType" node="attribute"/>
+ </field>
+ <field name="mCurrentState" type="integer" direct="false" get-method="getCurrentState" set-method="setCurrentState">
+ <bind-xml name="CurrentState" node="attribute"/>
+ </field>
+ <field name="mTransition" type="integer" direct="false" get-method="getTransition" set-method="setTransition">
+ <bind-xml name="Transition" node="attribute"/>
+ </field>
+
+ <field name="mAgentName" type="string" direct="false"
+ get-method="getAgentName"
+ set-method="setAgentName">
+ <bind-xml name="AgentId" node="attribute"/>
+ </field>
+ <field name="mAgentRole" type="string" direct="false"
+ get-method="getAgentRole"
+ set-method="setAgentRole">
+ <bind-xml name="AgentRole" node="attribute"/>
+ </field>
+
+ <field name="mTimeStamp" type="com.c2kernel.common.GTimeStamp" direct="false" get-method="getTimeStamp" set-method="setTimeStamp">
+ <bind-xml name="TimeStamp" node="element"/>
+ </field>
+ </class>
+</mapping>
diff --git a/resources/mapFiles/JobListMap.xml b/resources/mapFiles/JobListMap.xml
new file mode 100755
index 0000000..7352248
--- /dev/null
+++ b/resources/mapFiles/JobListMap.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0"?>
+<mapping>
+ <class name="com.c2kernel.entity.agent.Job">
+ <map-to xml="Job"/>
+ <field name="mItemSysKey" type="integer" direct="false" get-method="getItemSysKey" set-method="setItemSysKey">
+ <bind-xml name="ItemSysKey" node="attribute"/>
+ </field>
+ <field name="mID" type="integer" direct="false" get-method="getID" set-method="setID">
+ <bind-xml name="ID" node="attribute"/>
+ </field>
+ <field name="mStepPath" type="string" direct="false" get-method="getStepPath" set-method="setStepPath">
+ <bind-xml name="StepPath" node="attribute"/>
+ </field>
+ <field name="mPossibleTransition" type="integer" direct="false" get-method="getPossibleTransition" set-method="setPossibleTransition">
+ <bind-xml name="PossibleTransition" node="attribute"/>
+ </field>
+ <field name="mCurrentState" type="integer" direct="false" get-method="getCurrentState" set-method="setCurrentState">
+ <bind-xml name="CurrentState" node="attribute"/>
+ </field>
+ <field name="mTargetState" type="integer" direct="false" get-method="getTargetState" set-method="setTargetState">
+ <bind-xml name="TargetState" node="attribute"/>
+ </field>
+ <field name="mStepName" type="string" direct="false" get-method="getStepName" set-method="setStepName">
+ <bind-xml name="StepName" node="attribute"/>
+ </field>
+ <field name="mAgentId" type="integer" direct="false" get-method="getAgentId" set-method="setAgentId">
+ <bind-xml name="AgentId" node="attribute"/>
+ </field>
+ <field name="mAgentName" type="string" direct="false" get-method="getAgentName" set-method="setAgentName">
+ <bind-xml name="AgentName" node="attribute"/>
+ </field>
+ <field name="mAgentRole" type="string" direct="false" get-method="getAgentRole" set-method="setAgentRole">
+ <bind-xml name="AgentRole" node="attribute"/>
+ </field>
+ <field name="mStepType" type="string" direct="false" get-method="getStepType" set-method="setStepType">
+ <bind-xml name="StepType" node="attribute"/>
+ </field>
+ <field name="mActProps" type="com.c2kernel.utils.KeyValuePair" collection="array" container="false" direct="false" get-method="getKeyValuePairs" set-method="setKeyValuePairs">
+ <bind-xml name="ActProps" node="element"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.entity.agent.JobArrayList">
+ <map-to xml="JobArrayList"/>
+ <field name="list" collection="arraylist" direct="true" type="com.c2kernel.entity.agent.Job">
+ <bind-xml name="JobArrayList" node="element"/>
+ </field>
+ </class>
+</mapping>
diff --git a/resources/mapFiles/KeyValuePairMap.xml b/resources/mapFiles/KeyValuePairMap.xml
new file mode 100755
index 0000000..8175151
--- /dev/null
+++ b/resources/mapFiles/KeyValuePairMap.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+
+<mapping>
+ <class name="com.c2kernel.utils.KeyValuePair">
+ <map-to xml="KeyValuePair"/>
+ <field name="mKey"
+ type="string"
+ direct="false"
+ get-method="getKey"
+ set-method="setKey">
+ <bind-xml name="Key" node="attribute"/>
+ </field>
+ <field name="IntegerValue"
+ type="java.lang.Integer"
+ direct="false">
+ <bind-xml name="Integer" node="attribute"/>
+ </field>
+ <field name="StringValue"
+ type="java.lang.String"
+ direct="false">
+ <bind-xml name="String" node="attribute"/>
+ </field>
+ <field name="BooleanValue"
+ type="java.lang.Boolean"
+ direct="false">
+ <bind-xml name="Boolean" node="attribute"/>
+ </field>
+ </class>
+</mapping>
+
diff --git a/resources/mapFiles/LifeCycleMap.xml b/resources/mapFiles/LifeCycleMap.xml
new file mode 100755
index 0000000..8291dee
--- /dev/null
+++ b/resources/mapFiles/LifeCycleMap.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0"?>
+<mapping>
+ <class name="com.c2kernel.lifecycle.NextDef" extends="com.c2kernel.graph.model.GraphableEdge">
+ <map-to xml="NextDef"/>
+ </class>
+ <class name="com.c2kernel.lifecycle.WfVertexDef" extends="com.c2kernel.graph.model.GraphableVertex">
+ <map-to xml="WfVertexDef"/>
+ </class>
+ <class name="com.c2kernel.lifecycle.ActivityDef" extends="com.c2kernel.lifecycle.WfVertexDef">
+ <map-to xml="ActivityDef"/>
+ </class>
+ <class name="com.c2kernel.lifecycle.CompositeActivityDef" extends="com.c2kernel.lifecycle.ActivityDef">
+ <map-to xml="CompositeActivityDef"/>
+ <field name="castorNonLayoutableChildren" type="string" direct="false" collection="array">
+ <bind-xml name="castorNonLayoutableChildren" node="element"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.lifecycle.ActivitySlotDef" extends="com.c2kernel.lifecycle.WfVertexDef">
+ <map-to xml="ActivitySlotDef"/>
+ <field name="activityDef" type="string" direct="false">
+ <bind-xml name="activityDef" node="element"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.lifecycle.JoinDef" extends="com.c2kernel.lifecycle.WfVertexDef">
+ <map-to xml="JoinDef"/>
+ </class>
+ <class name="com.c2kernel.lifecycle.AndSplitDef" extends="com.c2kernel.lifecycle.WfVertexDef">
+ <map-to xml="AndSplitDef"/>
+ </class>
+ <class name="com.c2kernel.lifecycle.OrSplitDef" extends="com.c2kernel.lifecycle.AndSplitDef">
+ <map-to xml="OrSplitDef"/>
+ </class>
+ <class name="com.c2kernel.lifecycle.XOrSplitDef" extends="com.c2kernel.lifecycle.AndSplitDef">
+ <map-to xml="XOrSplitDef"/>
+ </class>
+ <class name="com.c2kernel.lifecycle.LoopDef" extends="com.c2kernel.lifecycle.XOrSplitDef">
+ <map-to xml="LoopDef"/>
+ <field name="isNext" type="integer" direct="true">
+ <bind-xml name="isNext" node="attribute"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.lifecycle.instance.Next" extends="com.c2kernel.graph.model.GraphableEdge">
+ <map-to xml="Next"/>
+ </class>
+ <class name="com.c2kernel.lifecycle.instance.WfVertex" extends="com.c2kernel.graph.model.GraphableVertex"/>
+ <class name="com.c2kernel.lifecycle.instance.Activity" extends="com.c2kernel.lifecycle.instance.WfVertex">
+ <map-to xml="AtomicActivity"/>
+ <field name="active" type="boolean" direct="false">
+ <bind-xml name="active" node="attribute"/>
+ </field>
+ <field name="state" type="integer" direct="false">
+ <bind-xml name="state" node="attribute"/>
+ </field>
+ <field name="type" type="string" direct="false">
+ <bind-xml name="Type" node="attribute"/>
+ </field>
+ <field name="eventIds" type="com.c2kernel.lifecycle.instance.EventStorage" direct="true">
+ <bind-xml name="eventIds" node="element"/>
+ </field>
+ <field name="startDate" type="com.c2kernel.common.GTimeStamp" direct="false">
+ <bind-xml name="startDate" node="element"/>
+ </field>
+ <field name="activeDate" type="com.c2kernel.common.GTimeStamp" direct="false">
+ <bind-xml name="activeDate" node="element"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.lifecycle.instance.CompositeActivity" extends="com.c2kernel.lifecycle.instance.Activity">
+ <map-to xml="CompositeActivity"/>
+ </class>
+ <class name="com.c2kernel.lifecycle.instance.Workflow" extends="com.c2kernel.lifecycle.instance.CompositeActivity">
+ <map-to xml="Workflow"/>
+ </class>
+ <class name="com.c2kernel.lifecycle.instance.Join" extends="com.c2kernel.lifecycle.instance.WfVertex">
+ <map-to xml="Join"/>
+ <field name="counter" type="integer" direct="true">
+ <bind-xml name="counter" node="attribute"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.lifecycle.instance.Split" extends="com.c2kernel.lifecycle.instance.WfVertex">
+ <map-to xml="Split"/>
+ </class>
+ <class name="com.c2kernel.lifecycle.instance.AndSplit" extends="com.c2kernel.lifecycle.instance.Split">
+ <map-to xml="AndSplit"/>
+ </class>
+ <class name="com.c2kernel.lifecycle.instance.OrSplit" extends="com.c2kernel.lifecycle.instance.Split">
+ <map-to xml="OrSplit"/>
+ </class>
+ <class name="com.c2kernel.lifecycle.instance.XOrSplit" extends="com.c2kernel.lifecycle.instance.Split">
+ <map-to xml="XOrSplit"/>
+ </class>
+ <class name="com.c2kernel.lifecycle.instance.Loop" extends="com.c2kernel.lifecycle.instance.XOrSplit">
+ <map-to xml="Loop"/>
+ </class>
+ <class name="com.c2kernel.lifecycle.instance.predefined.PredefinedStepContainer">
+ <map-to xml="PredefinedStepContainer"/>
+ <field name="ID" type="integer" direct="false">
+ <bind-xml name="id" node="attribute"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.lifecycle.instance.predefined.ServerPredefinedStepContainer" extends="com.c2kernel.lifecycle.instance.predefined.PredefinedStepContainer">
+ <map-to xml="ServerPredefinedStepContainer"/>
+ </class>
+ <class name="com.c2kernel.lifecycle.instance.EventStorage">
+ <map-to xml="EventStorage"/>
+ <field name="lastTransitionStored" type="integer" direct="true">
+ <bind-xml name="lastTransitionStored" node="attribute"/>
+ </field>
+ <field name="lists" type="com.c2kernel.lifecycle.instance.EventList" collection="array" direct="false">
+ <bind-xml name="lists" node="element"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.lifecycle.instance.EventList">
+ <map-to xml="EventList"/>
+ <field name="transition" type="integer" direct="true">
+ <bind-xml name="transition" node="attribute"/>
+ </field>
+ <field name="nums" type="integer" collection="array" direct="false">
+ <bind-xml name="nums" node="element"/>
+ </field>
+ </class>
+</mapping>
diff --git a/resources/mapFiles/NewEntityMap.xml b/resources/mapFiles/NewEntityMap.xml
new file mode 100755
index 0000000..5d9d7ca
--- /dev/null
+++ b/resources/mapFiles/NewEntityMap.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0"?>
+<mapping>
+ <class name="com.c2kernel.lifecycle.instance.predefined.entitycreation.NewItem">
+ <map-to xml="NewItem"/>
+ <field name="name" type="string" direct="true">
+ <bind-xml name="name" node="attribute"/>
+ </field>
+ <field name="initialPath" type="string" direct="true">
+ <bind-xml name="initialPath" node="attribute"/>
+ </field>
+ <field name="workflow" type="string" direct="true">
+ <bind-xml name="workflow" node="attribute"/>
+ </field>
+ <field name="propertyList" collection="arraylist" direct="true" type="com.c2kernel.lifecycle.instance.predefined.entitycreation.Property">
+ <bind-xml name="Property" node="element"/>
+ </field>
+ <field name="aggregationList" collection="arraylist" direct="true" type="com.c2kernel.lifecycle.instance.predefined.entitycreation.Aggregation">
+ <bind-xml name="Aggregation" node="element"/>
+ </field>
+ <field name="dependencyList" collection="arraylist" direct="true" type="com.c2kernel.lifecycle.instance.predefined.entitycreation.Dependency">
+ <bind-xml name="Dependency" node="element"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.lifecycle.instance.predefined.entitycreation.Property">
+ <field name="name" type="string" direct="true">
+ <bind-xml name="name" node="attribute"/>
+ </field>
+ <field name="value" type="string" direct="true">
+ <bind-xml name="value" node="attribute"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.lifecycle.instance.predefined.entitycreation.Aggregation">
+ <field name="name" type="string" direct="true">
+ <bind-xml name="name" node="attribute"/>
+ </field>
+ <field name="isDescription" type="boolean" direct="true">
+ <bind-xml name="isDescription" node="attribute"/>
+ </field>
+ <field name="aggregationMemberList" collection="arraylist" direct="true" type="com.c2kernel.lifecycle.instance.predefined.entitycreation.AggregationMember">
+ <bind-xml name="AggregationMember" node="element"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.lifecycle.instance.predefined.entitycreation.AggregationMember">
+ <field name="slotNo" type="int" direct="true">
+ <bind-xml name="slotNo" node="attribute"/>
+ </field>
+ <field name="itemDescriptionPath" type="string" direct="true">
+ <bind-xml name="itemDescriptionPath" node="attribute"/>
+ </field>
+ <field name="itemPath" type="string" direct="true">
+ <bind-xml name="itemPath" node="attribute"/>
+ </field>
+ <field name="geometry" direct="true" type="com.c2kernel.lifecycle.instance.predefined.entitycreation.Geometry">
+ <bind-xml name="Geometry" node="element"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.lifecycle.instance.predefined.entitycreation.Geometry">
+ <field name="x" type="int" direct="true">
+ <bind-xml name="x" node="attribute"/>
+ </field>
+ <field name="y" type="int" direct="true">
+ <bind-xml name="y" node="attribute"/>
+ </field>
+ <field name="width" type="int" direct="true">
+ <bind-xml name="width" node="attribute"/>
+ </field>
+ <field name="height" type="int" direct="true">
+ <bind-xml name="height" node="attribute"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.lifecycle.instance.predefined.entitycreation.Dependency">
+ <field name="name" type="string" direct="true">
+ <bind-xml name="name" node="attribute"/>
+ </field>
+ <field name="isDescription" type="boolean" direct="true">
+ <bind-xml name="isDescription" node="attribute"/>
+ </field>
+ <field name="itemDescriptionPath" type="string" direct="true">
+ <bind-xml name="itemDescriptionPath" node="attribute"/>
+ </field>
+ <field name="dependencyMemberList" collection="arraylist" direct="true" type="com.c2kernel.lifecycle.instance.predefined.entitycreation.DependencyMember">
+ <bind-xml name="DependencyMember" node="element"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.lifecycle.instance.predefined.entitycreation.DependencyMember">
+ <field name="itemPath" type="string" direct="true">
+ <bind-xml name="itemPath" node="attribute"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.lifecycle.instance.predefined.entitycreation.NewAgent">
+ <map-to xml="NewAgent"/>
+ <field name="name" type="string" direct="true">
+ <bind-xml name="name" node="attribute"/>
+ </field>
+ <field name="password" type="string" direct="true">
+ <bind-xml name="password" node="attribute"/>
+ </field>
+ <field name="roles" collection="arraylist" direct="true" type="string">
+ <bind-xml name="Role" node="element"/>
+ </field>
+ </class>
+</mapping>
diff --git a/resources/mapFiles/PropertiesMap.xml b/resources/mapFiles/PropertiesMap.xml
new file mode 100755
index 0000000..7936a75
--- /dev/null
+++ b/resources/mapFiles/PropertiesMap.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<mapping>
+ <class name="com.c2kernel.property.Property">
+ <map-to xml="Property"/>
+ <field name="mName" type="string" direct="false" get-method="getName" set-method="setName">
+ <bind-xml name="Name" node="attribute"/>
+ </field>
+ <field name="mValue" type="string" direct="false" get-method="getValue" set-method="setValue">
+ <bind-xml name="Value" node="element"/>
+ </field>
+ </class>
+
+ <class name="com.c2kernel.property.PropertyDescription">
+ <map-to xml="PropertyDescription"/>
+ <field name="mName" type="string" direct="false" get-method="getName" set-method="setName">
+ <bind-xml name="Name" node="attribute"/>
+ </field>
+ <field name="mIsClassIdentifier" type="boolean" direct="false" get-method="getIsClassIdentifier" set-method="setIsClassIdentifier">
+ <bind-xml name="IsClassIdentifier" node="attribute"/>
+ </field>
+ <field name="mDefaultValue" type="string" direct="false" get-method="getDefaultValue" set-method="setDefaultValue">
+ <bind-xml name="DefaultValue" node="attribute"/>
+ </field>
+ <field name="mIsMutable" type="boolean" direct="false" get-method="getIsMutable" set-method="setIsMutable">
+ <bind-xml name="IsMutable" node="attribute"/>
+ </field>
+ </class>
+
+
+ <class name="com.c2kernel.property.PropertyDescriptionList">
+ <map-to xml="AllProperties"/>
+ <field name="list" collection="arraylist" direct="true" type="com.c2kernel.property.PropertyDescription">
+ <bind-xml name="PropertyDescription" node="element"/>
+ </field>
+ </class>
+
+ <class name="com.c2kernel.property.PropertyArrayList">
+ <map-to xml="PropertyList"/>
+ <field name="list"
+ collection="arraylist"
+ direct="true"
+ type="com.c2kernel.property.Property">
+ <bind-xml name="Property" node="element"/>
+ </field>
+ </class>
+</mapping>
diff --git a/resources/mapFiles/TransferMap.xml b/resources/mapFiles/TransferMap.xml
new file mode 100755
index 0000000..a280ef3
--- /dev/null
+++ b/resources/mapFiles/TransferMap.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<mapping>
+ <class name="com.c2kernel.entity.transfer.TransferSet">
+ <map-to xml="TransferSet"/>
+ <field name="items" collection="arraylist" direct="true"
+ type="com.c2kernel.entity.transfer.TransferItem">
+ <bind-xml name="Item" node="element"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.entity.transfer.TransferItem">
+ <field name="sysKey" type="integer" direct="true">
+ <bind-xml name="sysKey" node="attribute"/>
+ </field>
+ <field name="domainPaths" collection="arraylist" direct="true"
+ type="string">
+ <bind-xml name="DomainPaths" node="element"/>
+ </field>
+ </class>
+</mapping>
diff --git a/resources/mapFiles/ViewpointMap.xml b/resources/mapFiles/ViewpointMap.xml
new file mode 100755
index 0000000..6799418
--- /dev/null
+++ b/resources/mapFiles/ViewpointMap.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<mapping>
+ <class name="com.c2kernel.persistency.outcome.Viewpoint">
+ <map-to xml="Viewpoint"/>
+ <field name="sysKey" type="integer" direct="false" get-method="getSysKey" set-method="setSysKey">
+ <bind-xml name="SysKey" node="attribute"/>
+ </field>
+ <field name="schemaName" type="string" direct="false" get-method="getSchemaName" set-method="setSchemaName">
+ <bind-xml name="SchemaName" node="attribute"/>
+ </field>
+ <field name="name" type="string" direct="false" get-method="getName" set-method="setName">
+ <bind-xml name="Name" node="attribute"/>
+ </field>
+ <field name="schemaVersion" type="integer" direct="false" get-method="getSchemaVersion" set-method="setSchemaVersion">
+ <bind-xml name="SchemaVersion" node="attribute"/>
+ </field>
+ <field name="eventId" type="integer" direct="false" get-method="getEventId" set-method="setEventId">
+ <bind-xml name="Last" node="attribute"/>
+ </field>
+ </class>
+</mapping>
diff --git a/resources/mapFiles/graphModelMap.xml b/resources/mapFiles/graphModelMap.xml
new file mode 100755
index 0000000..cebb589
--- /dev/null
+++ b/resources/mapFiles/graphModelMap.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0"?>
+<!-- edited with XML Spy v4.2 U (http://www.xmlspy.com) by Sebastian Gaspard (Agilium) -->
+<mapping>
+ <class name="com.c2kernel.graph.model.GraphModel">
+ <map-to xml="GraphModel"/>
+ <field name="GraphModelCastorData" type="com.c2kernel.graph.model.GraphModelCastorData" direct="false">
+ <bind-xml auto-naming="deriveByClass" node="element"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.graph.model.GraphPoint">
+ <map-to xml="GraphPoint"/>
+ <field name="x" type="integer" direct="true">
+ <bind-xml name="x" node="attribute"/>
+ </field>
+ <field name="y" type="integer" direct="true">
+ <bind-xml name="y" node="attribute"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.graph.model.GraphModelCastorData">
+ <map-to xml="GraphModelCastorData"/>
+ <field name="mClassNameOfVertexOutlineCreator" type="string" direct="true">
+ <bind-xml name="ClassNameOfVertexOutlineCreator" node="attribute"/>
+ </field>
+ <field name="mVertexImpls" type="com.c2kernel.graph.model.Vertex" direct="true" collection="array">
+ <bind-xml auto-naming="deriveByClass" node="element"/>
+ </field>
+ <field name="mEdgeImpls" type="com.c2kernel.graph.model.DirectedEdge" direct="true" collection="array">
+ <bind-xml auto-naming="deriveByClass" node="element"/>
+ </field>
+ <field name="mStartVertexId" type="integer" direct="true">
+ <bind-xml name="StartVertexId" node="attribute"/>
+ </field>
+ <field name="mNextId" type="integer" direct="true">
+ <bind-xml name="NextId" node="attribute"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.graph.model.Vertex">
+ <map-to xml="Vertex"/>
+ <field name="ID" type="integer" direct="false">
+ <bind-xml name="ID" node="attribute"/>
+ </field>
+ <field name="Name" type="string" direct="false">
+ <bind-xml name="Name" node="attribute"/>
+ </field>
+ <field name="Height" type="integer" direct="false">
+ <bind-xml name="Height" node="attribute"/>
+ </field>
+ <field name="Width" type="integer" direct="false">
+ <bind-xml name="Width" node="attribute"/>
+ </field>
+ <field name="CentrePoint" type="com.c2kernel.graph.model.GraphPoint" direct="false">
+ <bind-xml name="CentrePoint" node="element"/>
+ </field>
+ <field name="OutlinePoints" type="com.c2kernel.graph.model.GraphPoint" direct="false" collection="array">
+ <bind-xml name="OutlinePoint" node="element"/>
+ </field>
+ <field name="InEdgeIds" type="integer" direct="false" collection="array">
+ <bind-xml name="InEdgeId" node="element"/>
+ </field>
+ <field name="OutEdgeIds" type="integer" direct="false" collection="array">
+ <bind-xml name="OutEdgeId" node="element"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.graph.model.DirectedEdge">
+ <map-to xml="DirectedEdge"/>
+ <field name="ID" type="integer" direct="false">
+ <bind-xml name="ID" node="attribute"/>
+ </field>
+ <field name="OriginPoint" type="com.c2kernel.graph.model.GraphPoint" direct="false">
+ <bind-xml name="OriginPoint" node="element"/>
+ </field>
+ <field name="TerminusPoint" type="com.c2kernel.graph.model.GraphPoint" direct="false">
+ <bind-xml name="TerminusPoint" node="element"/>
+ </field>
+ <field name="OriginVertexId" type="integer" direct="false">
+ <bind-xml name="OriginVertexId" node="attribute"/>
+ </field>
+ <field name="TerminusVertexId" type="integer" direct="false">
+ <bind-xml name="TerminusVertexId" node="attribute"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.graph.model.GraphableEdge" extends="com.c2kernel.graph.model.DirectedEdge">
+ <map-to xml="GraphableEdge"/>
+ <field name="mProperties"
+ type="com.c2kernel.utils.KeyValuePair"
+ collection="array"
+ container="false"
+ direct="false"
+ get-method="getKeyValuePairs"
+ set-method="setKeyValuePairs">
+ <bind-xml name="Properties" node="element"/>
+ </field>
+ </class>
+ <class name="com.c2kernel.graph.model.GraphableVertex" extends="com.c2kernel.graph.model.Vertex">
+ <map-to xml="GraphableVertex"/>
+ <field name="mIsLayoutable"
+ type="boolean"
+ direct="false"
+ get-method="getIsLayoutable"
+ set-method="setIsLayoutable">
+ <bind-xml name="IsLayoutable" node="attribute"/>
+ </field>
+ <field name="mIsComposite"
+ type="boolean"
+ direct="false"
+ get-method="getIsComposite"
+ set-method="setIsComposite">
+ <bind-xml name="IsComposite" node="attribute"/>
+ </field>
+ <field name="childrenGraphModel" type="com.c2kernel.graph.model.GraphModel" direct="false">
+ <bind-xml name="childrenGraphModel" node="element"/>
+ </field>
+ <field name="cNonLayoutableChildren" type="com.c2kernel.graph.model.GraphableVertex" direct="false" collection="array">
+ <bind-xml auto-naming="deriveByClass" node="element"/>
+ </field>
+ <field name="mProperties"
+ type="com.c2kernel.utils.KeyValuePair"
+ collection="array"
+ container="false"
+ direct="false"
+ get-method="getKeyValuePairs"
+ set-method="setKeyValuePairs">
+ <bind-xml name="Properties" node="element"/>
+ </field>
+ </class>
+</mapping>
diff --git a/resources/mapFiles/index.xml b/resources/mapFiles/index.xml
new file mode 100755
index 0000000..58295a1
--- /dev/null
+++ b/resources/mapFiles/index.xml
@@ -0,0 +1,10 @@
+graphModelMap.xml
+KeyValuePairMap.xml
+HistoryMap.xml
+PropertiesMap.xml
+LifeCycleMap.xml
+CollectionMap.xml
+JobListMap.xml
+ViewpointMap.xml
+TransferMap.xml
+NewEntityMap.xml \ No newline at end of file
diff --git a/resources/openldap/README b/resources/openldap/README
new file mode 100755
index 0000000..6bfdabc
--- /dev/null
+++ b/resources/openldap/README
@@ -0,0 +1,5 @@
+cristal2.schema goes in OpenLDAP/schemas, or change the include line to point to it here.
+
+edit your slapd.conf to include it, and replace the env vars with your local path.
+edit the suffix and rootdn and rootpass
+use this slapd to help you
diff --git a/resources/openldap/cristal2.schema b/resources/openldap/cristal2.schema
new file mode 100755
index 0000000..2370964
--- /dev/null
+++ b/resources/openldap/cristal2.schema
@@ -0,0 +1,49 @@
+attributetype ( 1.3.6.1.4.1.96.64.10.1 NAME 'intsyskey'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
+attributetype ( 1.3.6.1.4.1.96.64.10.6 NAME 'ior'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+ SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.96.64.10.7 NAME 'cristalprop'
+ EQUALITY caseIgnoreMatch
+ SUBSTR caseIgnoreSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+objectclass ( 1.3.6.1.4.1.96.64.10.10 NAME 'cristalentity' SUP top STRUCTURAL
+ MUST ( cn $ objectclass )
+ MAY ( intsyskey $ ior $ cristalprop ) )
+
+objectclass ( 1.3.6.1.4.1.96.64.10.13 NAME 'cristalcontext' SUP top STRUCTURAL
+ MUST ( cn $ objectclass )
+ MAY ( intsyskey ) )
+
+objectclass ( 1.3.6.1.4.1.96.64.10.15 NAME 'aliasObject' SUP alias STRUCTURAL
+ MUST ( cn $ objectclass $ aliasedObjectName ) )
+
+# agent
+attributetype ( 1.3.6.1.4.1.96.64.10.8 NAME 'jobList'
+ EQUALITY booleanMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )
+
+ # uid must store userName if agent (for authentication to work)
+objectclass ( 1.3.6.1.4.1.96.64.10.14 NAME 'cristalagent' SUP cristalentity STRUCTURAL
+ MUST ( userPassword $ uid ) )
+
+objectclass ( 1.3.6.1.4.1.96.64.10.16 NAME 'cristalrole' SUP top STRUCTURAL
+ MUST ( cn $ objectclass )
+ MAY ( jobList $ uniqueMember ) )
+
+# old
+
+attributetype ( 1.3.6.1.4.1.96.64.10.2 NAME 'propval'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+ SINGLE-VALUE )
+
+objectclass ( 1.3.6.1.4.1.96.64.10.11 NAME 'cristalproperty' SUP top STRUCTURAL
+ MUST ( cn $ objectclass )
+ MAY ( propval ) )
+
diff --git a/resources/openldap/slapd.conf b/resources/openldap/slapd.conf
new file mode 100755
index 0000000..65cebf1
--- /dev/null
+++ b/resources/openldap/slapd.conf
@@ -0,0 +1,20 @@
+# $OpenLDAP: pkg/ldap/servers/slapd/slapd.conf,v 1.8.8.7 2001/09/27 20:00:31 kurt Exp $
+#
+# See slapd.conf(5) for details on configuration options.
+# This file should NOT be world readable.
+#
+include D:/openldap-2_0_19_debug/schema/core.schema
+include D:/openldap-2_0_19_debug/schema/cristal2.schema
+pidfile D:/openldap-2_0_19_debug/slapd.pid
+argsfile D:/openldap-2_0_19_debug/slapd.args
+
+
+# if no access controls are present, the default is:
+# Allow read by all
+# rootdn can always write!
+
+database ldbm
+suffix "o=cern,c=ch"
+rootdn "cn=Directory Manager,o=cern,c=ch"
+rootpw estrella
+index objectClass eq
diff --git a/resources/textFiles/consoleHelp.txt b/resources/textFiles/consoleHelp.txt
new file mode 100755
index 0000000..2b96172
--- /dev/null
+++ b/resources/textFiles/consoleHelp.txt
@@ -0,0 +1,18 @@
+Cristal 2 scripting console
+---------------------------
+Commands entered here are directly parsed by the javascript engine. You can call methods directly on five objects pre-loaded from the Gateway:
+proxy - the EntityProxyManager
+storage - the TransactionManager
+db - the ClusterStorageManager
+lookup - the LDAPLookup (server context)
+orb - the ORB
+
+Your output is a log stream, by default set to level 0. Change your log level with 'log n'.
+View this message with 'help'.
+
+Useful methods:
+proxy.reportCurrentProxies(logLevel);
+proxy.reportConnections(logLevel);
+storage.dumpPendingTransactions(logLevel);
+db.clearCache([sysKey][, rootPath]);
+db.dumpCacheContents(logLevel);
diff --git a/resources/textFiles/defaultConf.properties b/resources/textFiles/defaultConf.properties
new file mode 100755
index 0000000..dbc58de
--- /dev/null
+++ b/resources/textFiles/defaultConf.properties
@@ -0,0 +1,5 @@
+OutcomeHandler.CompositeActivityDef.0=com.c2kernel.lifecycle.gui.view.CompActDefOutcomeHandler
+OutcomeHandler.ElementaryActivityDef.0=com.c2kernel.lifecycle.gui.view.ElemActDefOutcomeHandler
+OutcomeHandler.Schema.0=com.c2kernel.gui.tabs.outcome.BasicOutcomeEditor
+OutcomeHandler.Script.0=com.c2kernel.gui.tabs.outcome.BasicOutcomeEditor
+banner=about.png
diff --git a/resources/textFiles/license.html b/resources/textFiles/license.html
new file mode 100755
index 0000000..eede128
--- /dev/null
+++ b/resources/textFiles/license.html
@@ -0,0 +1,38 @@
+<h3>Cristal 2 Kernel</h3>
+<i>Copyright (c) 2001-2004 The European Centre For Particle Physics Research. All Rights Reserved.</i>
+<p>Cristal Kernel utilizes the following software products:
+<ul>
+ <li><b><a href="http://java.sun.com">Java 2 Programming Language and Runtime Enviroment</a></b>
+ <br><i>Copyright &copy; 2003, Sun Microsystems, Inc.</i>
+
+ <li><b><a href="http://www.openldap.org/">OpenLDAP</a></b>
+ <br><i>Copyright &copy; 2004, OpenLDAP Foundation</i>
+
+ <li><b><a href="http://xml.apache.org/xerces2-j/index.html">Xerces2 Java Parser</a></b>
+ <br><i>Copyright &copy; 2000-2005, The Apache Software Foundation. All rights reserved.</i>
+
+ <li><b><a href="http://jakarta.apache.org/bsf/">Jakarta Bean Scripting Framework</a></b>
+ <br><i>Copyright &copy; 2000-2005, The Apache Software Foundation. All rights reserved.</i>
+
+ <li><b><a href="http://www.castor.org/">Castor XML</a></b>
+ <br><i>Copyright &copy;, 1999-2005 Intalio Inc., and others. All Rights Reserved.</i>
+
+ <li><b><a href="http://www.mozilla.org/rhino/">Mozilla Rhino</b></a>
+ <br><i>Copyright &copy; 1998-2005 The Mozilla Organization</i>
+
+ <li><b><a href="http://developer.novell.com/ndk/jldap.htm">Novell LDAP Classes for Java</a></b>
+ <br><i>Copyright &copy; 2004 Novell, Inc. </i>
+
+ <li><b><a href="http://wrapper.tanukisoftware.org/">Java Service Wrapper</a></b>
+ <br><i>Copyright &copy; 1999, 2003 TanukiSoftware.org</i>
+</ul>
+<h3>Third Party Licenses</h3>
+<ul>
+ <li>Java 2 License: <a href="http://java.com/en/download/license.jsp">http://java.com/en/download/license.jsp</a>
+ <li>Apache Software License: <a href="http://www.apache.org/LICENSE.txt">http://www.apache.org/LICENSE.txt</a>
+ <li>DOM License: <a href="http://www.w3.org/Consortium/Legal/copyright-software-19980720">http://www.w3.org/Consortium/Legal/copyright-software-19980720</a>
+ <li>SAX License: <a href="http://www.saxproject.org/?selected=pd">http://www.saxproject.org/?selected=pd</a>
+ <li>Castor License: <a href="http://www.castor.org/license.html">http://www.castor.org/license.html</a>
+ <li>Mozilla License: <a href="http://www.mozilla.org/MPL/">http://www.mozilla.org/MPL/</a>
+ <li>JSW License: <a href="http://wrapper.tanukisoftware.org/doc/english/license.html">http://wrapper.tanukisoftware.org/doc/english/license.html</a>
+</ul> \ No newline at end of file
diff --git a/resources/textFiles/version.txt b/resources/textFiles/version.txt
new file mode 100755
index 0000000..17e85ef
--- /dev/null
+++ b/resources/textFiles/version.txt
@@ -0,0 +1 @@
+C2Kernel V2.2 Build 2 \ No newline at end of file
diff --git a/source/com/c2kernel/collection/Aggregation.java b/source/com/c2kernel/collection/Aggregation.java
new file mode 100755
index 0000000..72b8005
--- /dev/null
+++ b/source/com/c2kernel/collection/Aggregation.java
@@ -0,0 +1,111 @@
+package com.c2kernel.collection;
+
+import java.util.Iterator;
+
+import com.c2kernel.collection.gui.model.AggregationVertexOutlineCreator;
+import com.c2kernel.graph.model.*;
+import com.c2kernel.utils.*;
+
+/**
+ * @version $Revision: 1.59 $ $Date: 2004/08/10 07:56:08 $
+ * @author $Author: abranson $
+ */
+
+abstract public class Aggregation extends Parent2ChildCollection
+{
+
+ protected GraphModel mLayout = new GraphModel(new AggregationVertexOutlineCreator());
+
+ private final TypeNameAndConstructionInfo[] mVertexTypeNameAndConstructionInfo = {
+ new TypeNameAndConstructionInfo(Language.translate("Slot"), "AggregationMember")
+ };
+
+ public Aggregation()
+ {
+ setName("Aggregation");
+ mMembers = new CollectionMemberList();
+ }
+
+
+ public GraphModel getLayout()
+ {
+ return mLayout;
+ }
+
+ public void setLayout(GraphModel layout)
+ {
+ mLayout = layout;
+ }
+
+ public TypeNameAndConstructionInfo[] getVertexTypeNameAndConstructionInfo()
+ {
+ return mVertexTypeNameAndConstructionInfo;
+ }
+
+ public boolean exists(int entityKey)
+ {
+ for (int i=0; i<size(); i++)
+ {
+ AggregationMember element = (AggregationMember) mMembers.list.get(i);
+ if (element.getEntityKey() == entityKey)
+ return true;
+ }
+ return false;
+ }
+
+ public AggregationMember getMemberPair(int vertexID)
+ {
+ for (int i=0; i<size(); i++)
+ {
+ AggregationMember element = (AggregationMember) mMembers.list.get(i);
+ if (element.getID() == vertexID)
+ return element;
+ }
+ return null;
+ }
+
+ public void addMember(int entityKey, CastorHashMap props, String classProps, GraphPoint location, int w, int h)
+ throws MembershipException
+ {
+ // Create new member object
+ AggregationMember aggMem = new AggregationMember();
+ aggMem.setProperties(props);
+ aggMem.setClassProps(classProps);
+ aggMem.assignEntity(entityKey);
+
+ // create vertex
+ com.c2kernel.graph.model.Vertex vertex = new com.c2kernel.graph.model.Vertex();
+ vertex.setHeight(h); vertex.setWidth(w);
+ mLayout.addVertexAndCreateId(vertex,location);
+ aggMem.setCollection(this);
+ aggMem.setID(vertex.getID());
+ aggMem.setIsLayoutable(true);
+ aggMem.setIsComposite( RelationshipUtils.getIsComposite(entityKey) );
+ mMembers.list.add(aggMem);
+ Logger.msg(8, "AggregationDescription::addMember(" + entityKey + ") added to children linked to vertexid " + vertex.getID());
+ }
+
+
+ public void addMember(int entityKey, CastorHashMap props, String classProps) throws MembershipException
+ {
+ addMember(entityKey, props, classProps, new GraphPoint(100,100*getCounter()), 20, 20);
+ }
+
+ public void addMember(int entityKey) throws MembershipException {
+ throw new MembershipException("Aggregations cannot accept arbitrary members without type info");
+
+ }
+
+ public void removeMember(int memberId) throws MembershipException {
+ for (Iterator iter = mMembers.list.iterator(); iter.hasNext();) {
+ AggregationMember element = (AggregationMember)iter.next();
+ if (element.getID() == memberId) {
+ element.clearEntity();
+ mLayout.removeVertex(getLayout().getVertexById(memberId));
+ return;
+ }
+ }
+ throw new MembershipException("Member "+memberId+" not found");
+ }
+
+}
diff --git a/source/com/c2kernel/collection/AggregationDescription.java b/source/com/c2kernel/collection/AggregationDescription.java
new file mode 100755
index 0000000..07a6818
--- /dev/null
+++ b/source/com/c2kernel/collection/AggregationDescription.java
@@ -0,0 +1,59 @@
+package com.c2kernel.collection;
+
+/**
+ * @version $Revision: 1.34 $ $Date: 2004/03/23 09:29:41 $
+ * @author $Author: abranson $
+ */
+
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.property.*;
+import com.c2kernel.utils.Logger;
+
+public class AggregationDescription extends Aggregation implements CollectionDescription
+{
+
+ public AggregationDescription()
+ {
+ setName("AggregationDescription");
+ mMembers = new CollectionMemberList();
+ }
+
+ public AggregationDescription(String name)
+ {
+ setName(name);
+ mMembers = new CollectionMemberList();
+ }
+
+
+ public Collection newInstance()
+ {
+ AggregationInstance newInstance = new AggregationInstance(getName());
+ newInstance.setURLInfo(getURLInfo());
+ //for each desc member
+ for (int i=0; i<size(); i++)
+ {
+ AggregationMember mem = (AggregationMember) mMembers.list.get(i);
+ //get the propdesc of the member item
+ PropertyDescriptionList pdList = PropertyUtility.getPropertyDescriptionOutcome(mem.getEntityKey());
+ if (pdList!=null)
+ {
+ //create the new props of the member object
+ try {
+ Vertex v = getLayout().getVertexById(mem.getID());
+ newInstance.addMember(-1, PropertyUtility.createProperty(pdList), pdList.getClassProps(),v.getCentrePoint(),v.getWidth(),v.getHeight());
+ } catch (MembershipException e) {
+ // won't happen as we're not assigning an entity
+ }
+ }
+ else
+ {
+ Logger.error("AggregationDescription::newInstance() There is no PropertyDescription. Cannot instantiate. " + mem.getEntityKey());
+ return null;
+ }
+
+
+ }
+
+ return newInstance;
+ }
+}
diff --git a/source/com/c2kernel/collection/AggregationInstance.java b/source/com/c2kernel/collection/AggregationInstance.java
new file mode 100755
index 0000000..0fbbf71
--- /dev/null
+++ b/source/com/c2kernel/collection/AggregationInstance.java
@@ -0,0 +1,45 @@
+package com.c2kernel.collection;
+
+/**
+ * @version $Revision: 1.30 $ $Date: 2003/06/04 13:21:24 $
+ * @author $Author: abranson $
+ */
+
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.utils.CastorHashMap;
+
+public class AggregationInstance extends Aggregation
+{
+
+ public AggregationInstance()
+ {
+ setName("AggregationInstance");
+ mMembers = new CollectionMemberList();
+ }
+
+ public AggregationInstance(String name)
+ {
+ setName(name);
+ mMembers = new CollectionMemberList();
+ }
+
+
+ public void addMember(int entityKey, CastorHashMap props, String classProps)
+ throws MembershipException
+ {
+ if( entityKey!=-1 && exists(entityKey))
+ throw new MembershipException(entityKey+" already exists in this collection.");
+ else
+ super.addMember(entityKey, props, classProps);
+ }
+
+ public void addMember(int entityKey, CastorHashMap props, String classProps, GraphPoint location, int w, int h)
+ throws MembershipException
+ {
+ if( entityKey!=-1 && exists(entityKey))
+ throw new MembershipException(entityKey+" already exists in this collection.");
+ else
+ super.addMember(entityKey, props, classProps, location, w, h);
+ }
+}
+
diff --git a/source/com/c2kernel/collection/AggregationMember.java b/source/com/c2kernel/collection/AggregationMember.java
new file mode 100755
index 0000000..753f503
--- /dev/null
+++ b/source/com/c2kernel/collection/AggregationMember.java
@@ -0,0 +1,154 @@
+package com.c2kernel.collection;
+
+import java.awt.Image;
+import java.util.StringTokenizer;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.proxy.EntityProxy;
+import com.c2kernel.graph.model.GraphableVertex;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.lookup.InvalidEntityPathException;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.property.Property;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.Resource;
+
+/**
+* @version $Revision: 1.11 $ $Date: 2005/12/01 14:23:15 $
+* @author $Author: abranson $
+*/
+
+
+//this extends Vertex for inherit the graph visualization
+//this does not implement MemberObject anylonger. it is a java object.
+//eventually the member object corba interface will be phased out.
+public class AggregationMember extends GraphableVertex implements CollectionMember
+{
+
+ private int mEntityKey = -1;
+ private EntityProxy mEntity = null;
+ private Collection mCollection = null;
+ private String mClassProps = null;
+ String entityName;
+ Image image;
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public AggregationMember()
+ {
+ super();
+ mEntityKey = -1;
+ mCollection = null;
+ }
+
+ public void setEntityKey(int entityKey) {
+ mEntityKey = entityKey;
+ entityName = null;
+ }
+
+ public void setCollection(Collection aggregation)
+ {
+ mCollection = aggregation;
+ }
+
+ public void setClassProps(String props)
+ {
+ mClassProps = props;
+ }
+
+ public int getEntityKey()
+ {
+ return mEntityKey;
+ }
+
+ public Collection getCollection()
+ {
+ return mCollection;
+ }
+
+ public String getClassProps()
+ {
+ return mClassProps;
+ }
+
+ public void assignEntity(int entityKey) throws MembershipException
+ {
+ if (entityKey > -1) {
+ if (mClassProps == null || getProperties() == null)
+ throw new MembershipException("ClassProps not yet set. Cannot check membership validity.");
+
+ //for each mandatory prop check if its in the member property and has the matching value
+ StringTokenizer sub = new StringTokenizer(mClassProps, ",");
+ while (sub.hasMoreTokens())
+ {
+ String aClassProp = sub.nextToken();
+ try {
+ String memberValue = (String)getProperties().get(aClassProp);
+ Property entityProperty = (Property)Gateway.getStorage().get(entityKey, ClusterStorage.PROPERTY+"/"+aClassProp, null);
+ if (entityProperty == null)
+ throw new MembershipException("Property "+aClassProp+ " does not exist for entityKey=" + entityKey );
+ if (entityProperty.getValue() == null || !entityProperty.getValue().equalsIgnoreCase(memberValue))
+ throw new MembershipException("Value of mandatory prop "+aClassProp+" does not match: " + entityProperty.getValue()+"!="+memberValue);
+ }
+ catch (MembershipException ex) {
+ throw ex;
+ }
+ catch (Exception ex)
+ {
+ Logger.error(ex);
+ throw new MembershipException("Error checking properties");
+ }
+ }
+ }
+
+ mEntityKey = entityKey;
+ mEntity = null;
+ entityName = null;
+ }
+
+ public void clearEntity() {
+ mEntityKey = -1;
+ mEntity = null;
+ }
+
+ public EntityProxy resolveEntity() throws ObjectNotFoundException {
+ if (mEntity == null) {
+ try {
+ EntityPath path = new EntityPath(mEntityKey);
+ mEntity = Gateway.getProxyManager().getProxy(path);
+ } catch (InvalidEntityPathException ex) {
+ throw new ObjectNotFoundException("No member defined", "");
+ }
+ }
+ return mEntity;
+
+ }
+
+ public Image getImage() {
+ if (image == null) {
+ image = Resource.getImageResource("typeicons/"+getProperties().get("Type")+"_16.png").getImage();
+ }
+ return image;
+ }
+
+ public String getEntityName() {
+ if (entityName == null) {
+ if (mEntityKey > -1) {
+ try {
+ entityName = resolveEntity().getName();
+ } catch (ObjectNotFoundException ex) {
+ Logger.error(ex);
+ entityName = "Error ("+mEntityKey+")";
+ }
+ }
+ else
+ entityName = "Empty";
+ }
+
+ return entityName;
+ }
+
+}
diff --git a/source/com/c2kernel/collection/Collection.java b/source/com/c2kernel/collection/Collection.java
new file mode 100755
index 0000000..745309c
--- /dev/null
+++ b/source/com/c2kernel/collection/Collection.java
@@ -0,0 +1,32 @@
+package com.c2kernel.collection;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.utils.CastorHashMap;
+
+/**
+ * @version $Revision: 1.13 $ $Date: 2004/05/14 15:39:39 $
+ * @author $Author: abranson $
+ */
+public interface Collection extends C2KLocalObject
+{
+ public static final short EMPTY = -1;
+
+ public int getCounter();
+
+ public void setCounter(int count);
+
+ public int size();
+
+ public void setMembers(CollectionMemberList newMembers);
+
+ public CollectionMemberList getMembers();
+
+ public void addMember(int entityKey, CastorHashMap props, String classProps) throws MembershipException;
+
+ public void addMember(int entityKey) throws MembershipException;
+
+ public void removeMember(int memberId) throws MembershipException;
+
+ public CollectionMember getMember(int memberId) throws ObjectNotFoundException;
+
+}
diff --git a/source/com/c2kernel/collection/CollectionDescription.java b/source/com/c2kernel/collection/CollectionDescription.java
new file mode 100755
index 0000000..01318ed
--- /dev/null
+++ b/source/com/c2kernel/collection/CollectionDescription.java
@@ -0,0 +1,14 @@
+package com.c2kernel.collection;
+
+/**************************************************************************
+ *
+ * $Revision: 1.1 $
+ * $Date: 2003/03/11 11:09:07 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public interface CollectionDescription extends Collection {
+ public Collection newInstance();
+}
diff --git a/source/com/c2kernel/collection/CollectionMember.java b/source/com/c2kernel/collection/CollectionMember.java
new file mode 100755
index 0000000..18b5d55
--- /dev/null
+++ b/source/com/c2kernel/collection/CollectionMember.java
@@ -0,0 +1,38 @@
+package com.c2kernel.collection;
+
+import java.io.Serializable;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.proxy.EntityProxy;
+import com.c2kernel.utils.CastorHashMap;
+
+/**************************************************************************
+ * CollectionMember interface is the superclass of all members
+ * This should be temporary - if we manage to rip GraphableVertex from Vertex,
+ * then that should be the superclass.
+ *
+ * $Revision: 1.19 $
+ * $Date: 2004/01/22 11:24:44 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public interface CollectionMember extends Serializable {
+
+ public void setEntityKey(int entityKey) throws MembershipException;
+ public int getEntityKey();
+
+ public void assignEntity(int entityKey) throws MembershipException;
+ public void clearEntity();
+ public EntityProxy resolveEntity() throws ObjectNotFoundException;
+
+ public void setID(int Id);
+ public int getID();
+
+ public void setProperties(CastorHashMap props);
+ public CastorHashMap getProperties();
+
+ public void setClassProps(String classProps);
+ public String getClassProps();
+}
diff --git a/source/com/c2kernel/collection/CollectionMemberList.java b/source/com/c2kernel/collection/CollectionMemberList.java
new file mode 100755
index 0000000..35f4134
--- /dev/null
+++ b/source/com/c2kernel/collection/CollectionMemberList.java
@@ -0,0 +1,22 @@
+/**************************************************************************
+ *
+ * $Revision: 1.1 $
+ * $Date: 2003/05/15 13:10:09 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.collection;
+
+import com.c2kernel.utils.CastorArrayList;
+
+public class CollectionMemberList extends CastorArrayList
+{
+
+ public CollectionMemberList()
+ {
+ super();
+ }
+
+}
diff --git a/source/com/c2kernel/collection/Dependency.java b/source/com/c2kernel/collection/Dependency.java
new file mode 100755
index 0000000..1b74d42
--- /dev/null
+++ b/source/com/c2kernel/collection/Dependency.java
@@ -0,0 +1,114 @@
+package com.c2kernel.collection;
+
+import java.util.Iterator;
+
+import com.c2kernel.utils.*;
+
+/*
+Dependency Object
+Objectified link representing dependency between items.
+e.g.: Used for ProductDesc::Item-dependency-dependencymember-WfDesc::Item
+*/
+
+/**
+ * @version $Revision: 1.15 $ $Date: 2005/04/07 08:03:21 $
+ * @author $Author: abranson $
+ */
+public class Dependency extends Parent2ChildCollection
+{
+
+ protected CastorHashMap mProperties = new CastorHashMap();
+ protected String mClassProps = "";
+
+ public Dependency()
+ {
+ setName("Dependency");
+ mMembers = new CollectionMemberList();
+ }
+
+ public Dependency(String name)
+ {
+ setName(name);
+ mMembers = new CollectionMemberList();
+ }
+
+ public CastorHashMap getProperties() {
+ return mProperties;
+ }
+
+ public void setProperties(CastorHashMap props) {
+ mProperties = props;
+ }
+
+ public KeyValuePair[] getKeyValuePairs()
+ {
+ return mProperties.getKeyValuePairs();
+ }
+ public void setKeyValuePairs(KeyValuePair[] pairs)
+ {
+ mProperties.setKeyValuePairs(pairs);
+ }
+
+ public void setClassProps(String classProps) {
+ this.mClassProps = classProps;
+ }
+
+ public String getClassProps() {
+ return mClassProps;
+ }
+
+ public void addMember(int entityKey) throws MembershipException {
+ // create member object
+ DependencyMember depMember = new DependencyMember();
+ depMember.setID(getCounter());
+ depMember.setProperties(mProperties);
+ depMember.setClassProps(mClassProps);
+
+ // assign entity
+ depMember.assignEntity(entityKey);
+ mMembers.list.add(depMember);
+ Logger.msg(8, "Dependency::addMember(" + entityKey + ") added to children.");
+ }
+
+ public void addMember(int entityKey, CastorHashMap props, String classProps)
+ throws MembershipException
+ {
+ if (classProps != null && !classProps.equals(mClassProps))
+ throw new MembershipException("Cannot change classProps in dependency member");
+ DependencyMember depMember = new DependencyMember();
+ depMember.setID(getCounter());
+
+ // merge props
+ CastorHashMap newProps = new CastorHashMap();
+ for (Iterator iter = props.keySet().iterator(); iter.hasNext();) {
+ String key = (String)iter.next();
+ newProps.put(key, props.get(key));
+
+ }
+ // class props override local
+ for (Iterator iter = mProperties.keySet().iterator(); iter.hasNext();) {
+ String key = (String)iter.next();
+ newProps.put(key, mProperties.get(key));
+
+ }
+ depMember.setProperties(newProps);
+ depMember.setClassProps(mClassProps);
+
+ // assign entity
+ depMember.assignEntity(entityKey);
+ mMembers.list.add(depMember);
+ Logger.msg(8, "Dependency::addMember(" + entityKey + ") added to children.");
+ }
+
+ public void removeMember(int memberId) throws MembershipException {
+ for (Iterator iter = mMembers.list.iterator(); iter.hasNext();) {
+ DependencyMember element = (DependencyMember)iter.next();
+ if (element.getID() == memberId) {
+ mMembers.list.remove(element);
+ return;
+ }
+ }
+ throw new MembershipException("Member "+memberId+" not found");
+ }
+
+}
diff --git a/source/com/c2kernel/collection/DependencyMember.java b/source/com/c2kernel/collection/DependencyMember.java
new file mode 100755
index 0000000..bb28c91
--- /dev/null
+++ b/source/com/c2kernel/collection/DependencyMember.java
@@ -0,0 +1,141 @@
+package com.c2kernel.collection;
+
+import java.util.StringTokenizer;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.proxy.EntityProxy;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.lookup.InvalidEntityPathException;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.property.Property;
+import com.c2kernel.utils.CastorHashMap;
+import com.c2kernel.utils.KeyValuePair;
+import com.c2kernel.utils.Logger;
+
+
+/**
+* @version $Revision: 1.10 $ $Date: 2004/10/21 08:02:23 $
+* @author $Author: abranson $
+*/
+
+
+public class DependencyMember implements CollectionMember
+{
+
+ private int mEntityKey = -1;
+ private EntityProxy mEntity = null;
+ private int mId = -1;
+ private CastorHashMap mProperties = null;
+ private String mClassProps;
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public DependencyMember()
+ {
+ mEntityKey = -1;
+ mProperties = new CastorHashMap();
+ }
+
+
+ public void setEntityKey(int entityKey)
+ {
+ mEntityKey = entityKey;
+ mEntity = null;
+ }
+
+ public int getEntityKey()
+ {
+ return mEntityKey;
+ }
+
+ public void setProperties(CastorHashMap props)
+ {
+ mProperties = props;
+ }
+
+ public CastorHashMap getProperties()
+ {
+ return mProperties;
+ }
+
+ public KeyValuePair[] getKeyValuePairs()
+ {
+ return mProperties.getKeyValuePairs();
+ }
+ public void setKeyValuePairs(KeyValuePair[] pairs)
+ {
+ mProperties.setKeyValuePairs(pairs);
+ }
+
+ public int getID() {
+ return mId;
+ }
+
+ public void setID(int id) {
+ mId = id;
+ }
+
+ public void setClassProps(String props)
+ {
+ mClassProps = props;
+ }
+
+ public String getClassProps()
+ {
+ return mClassProps;
+ }
+
+ public void assignEntity(int entityKey) throws MembershipException
+ {
+ if (entityKey > -1) {
+ if (mClassProps == null || getProperties() == null)
+ throw new MembershipException("ClassProps not yet set. Cannot check membership validity.");
+
+ //for each mandatory prop check if its in the member property and has the matching value
+ StringTokenizer sub = new StringTokenizer(mClassProps, ",");
+ while (sub.hasMoreTokens())
+ {
+ String aClassProp = sub.nextToken();
+ try {
+ String memberValue = (String)getProperties().get(aClassProp);
+ Property entityProperty = (Property)Gateway.getStorage().get(entityKey, ClusterStorage.PROPERTY+"/"+aClassProp, null);
+ if (entityProperty == null)
+ throw new MembershipException("Property "+aClassProp+ " does not exist for entityKey=" + entityKey );
+ if (!entityProperty.getValue().equalsIgnoreCase(memberValue))
+ throw new MembershipException("DependencyMember::checkProperty() Values of mandatory prop "+aClassProp+" do not match " + entityProperty.getValue()+"!="+memberValue);
+ }
+ catch (Exception ex)
+ {
+ Logger.error(ex);
+ throw new MembershipException("Error checking properties");
+ }
+ }
+ }
+
+ mEntityKey = entityKey;
+ mEntity = null;
+ }
+
+ public void clearEntity() {
+ mEntityKey = -1;
+ mEntity = null;
+ }
+
+ public EntityProxy resolveEntity() throws ObjectNotFoundException {
+ if (mEntity == null) {
+ try {
+ EntityPath path = new EntityPath(mEntityKey);
+ mEntity = Gateway.getProxyManager().getProxy(path);
+ } catch (InvalidEntityPathException ex) {
+ throw new ObjectNotFoundException("No member defined", "");
+ }
+ }
+ return mEntity;
+
+ }
+
+
+}
diff --git a/source/com/c2kernel/collection/MembershipException.java b/source/com/c2kernel/collection/MembershipException.java
new file mode 100755
index 0000000..912d52c
--- /dev/null
+++ b/source/com/c2kernel/collection/MembershipException.java
@@ -0,0 +1,21 @@
+package com.c2kernel.collection;
+
+/**************************************************************************
+ *
+ * $Revision: 1.1 $
+ * $Date: 2003/05/09 14:23:01 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class MembershipException extends Exception {
+
+ public MembershipException() {
+ super();
+ }
+
+ public MembershipException(String s) {
+ super(s);
+ }
+}
diff --git a/source/com/c2kernel/collection/Parent2ChildCollection.java b/source/com/c2kernel/collection/Parent2ChildCollection.java
new file mode 100755
index 0000000..0160444
--- /dev/null
+++ b/source/com/c2kernel/collection/Parent2ChildCollection.java
@@ -0,0 +1,119 @@
+package com.c2kernel.collection;
+import java.util.Iterator;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.utils.CastorHashMap;
+
+/**
+ * @version $Revision: 1.23 $ $Date: 2004/05/14 15:39:39 $
+ * @author $Author: abranson $
+ */
+abstract public class Parent2ChildCollection implements Collection
+{
+
+ private int mCounter = -1; // Contains next available Member ID
+ protected CollectionMemberList mMembers = new CollectionMemberList();
+ protected int mID = -1;
+ protected String mName = ""; // Not checked for uniqueness
+ protected String mURLInfo = "";
+
+ public int getCounter()
+ {
+ if (mCounter == -1)
+ for (Iterator iter = mMembers.list.iterator(); iter.hasNext();) {
+ CollectionMember element = (CollectionMember)iter.next();
+ if (mCounter < element.getID())
+ mCounter = element.getID();
+ }
+ return ++mCounter;
+ }
+
+ public void setCounter(int count)
+ {
+ mCounter = count;
+ }
+
+
+ public int size()
+ {
+ return mMembers.list.size();
+ }
+
+ public void setID(int id)
+ {
+ mID = id;
+ }
+
+ public int getID()
+ {
+ return mID;
+ }
+
+ public void setName(String name)
+ {
+ mName = name;
+ }
+
+ public void setURLInfo(String urlInfo)
+ {
+ mURLInfo = urlInfo;
+ }
+
+ public String getName()
+ {
+ return mName;
+ }
+
+ public String getClusterType()
+ {
+ return ClusterStorage.COLLECTION;
+ }
+
+ public String getURLInfo()
+ {
+ return mURLInfo;
+ }
+
+ public void setMembers(CollectionMemberList newMembers)
+ {
+ mMembers = newMembers;
+ }
+
+ public boolean contains(int entityKey) {
+ for (Iterator iter = mMembers.list.iterator(); iter.hasNext();) {
+ CollectionMember element = (CollectionMember)iter.next();
+ if (element.getEntityKey() == entityKey)
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isFull()
+ {
+ for (int i=0; i<size(); i++)
+ {
+ CollectionMember element = (CollectionMember) mMembers.list.get(i);
+ if (element.getEntityKey() == -1)
+ return false;
+ }
+ return true;
+ }
+
+ public CollectionMember getMember(int memberId) throws ObjectNotFoundException {
+ for (Iterator iter = mMembers.list.iterator(); iter.hasNext();) {
+ CollectionMember element = (CollectionMember)iter.next();
+ if (element.getID() == memberId)
+ return element;
+ }
+ throw new ObjectNotFoundException("Member "+memberId+" not found in "+mName, "");
+ }
+
+ public CollectionMemberList getMembers()
+ {
+ return mMembers;
+ }
+
+ public abstract void addMember(int entityKey, CastorHashMap props, String classProps) throws MembershipException;
+
+}
diff --git a/source/com/c2kernel/collection/RelationshipUtils.java b/source/com/c2kernel/collection/RelationshipUtils.java
new file mode 100755
index 0000000..fdd7e6b
--- /dev/null
+++ b/source/com/c2kernel/collection/RelationshipUtils.java
@@ -0,0 +1,33 @@
+package com.c2kernel.collection;
+
+
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.process.Gateway;
+
+
+/**
+ * @version $Revision: 1.22 $ $Date: 2004/10/21 08:02:23 $
+ * @author $Author: abranson $
+ */
+
+public class RelationshipUtils
+{
+
+ static public boolean getIsComposite(int entityKey)
+ {
+ if (entityKey == -1) return false;
+ try
+ {
+ if ( ((Aggregation) Gateway.getProxyManager().getProxy(new EntityPath(entityKey)).getObject(ClusterStorage.COLLECTION+"/Composition" )).size() > 0 )
+ return true;
+ }
+ catch (Exception ex)
+ {
+ //do nothing - member has no composition, thus elementary
+ }
+
+ return false;
+ }
+
+}
diff --git a/source/com/c2kernel/collection/gui/model/AggregationVertexFactory.java b/source/com/c2kernel/collection/gui/model/AggregationVertexFactory.java
new file mode 100755
index 0000000..d99ef3c
--- /dev/null
+++ b/source/com/c2kernel/collection/gui/model/AggregationVertexFactory.java
@@ -0,0 +1,44 @@
+package com.c2kernel.collection.gui.model;
+
+import java.awt.Point;
+
+import com.c2kernel.collection.Aggregation;
+import com.c2kernel.collection.MembershipException;
+import com.c2kernel.graph.model.GraphModelManager;
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.graph.model.TypeNameAndConstructionInfo;
+import com.c2kernel.graph.model.VertexFactory;
+import com.c2kernel.utils.CastorHashMap;
+import com.c2kernel.utils.Logger;
+
+
+public class AggregationVertexFactory implements VertexFactory
+{
+ private Aggregation mAggregation = null;
+
+
+ public void setCreationContext(Object aggregation)
+ {
+ if (aggregation != null && aggregation instanceof Aggregation)
+ mAggregation = (Aggregation)aggregation;
+ }
+
+
+ public void create
+ (
+ GraphModelManager graphModelManager,
+ Point location,
+ TypeNameAndConstructionInfo typeNameAndConstructionInfo
+ )
+ {
+ if (typeNameAndConstructionInfo.mInfo.equals("AggregationMember")) {
+ try {
+ mAggregation.addMember(-1, new CastorHashMap(), "", new GraphPoint(location.x, location.y), 40, 40);
+ } catch (MembershipException ex) {
+ Logger.error(ex);
+ Logger.exceptionDialog(ex);
+ }
+ }
+ }
+}
+
diff --git a/source/com/c2kernel/collection/gui/model/AggregationVertexOutlineCreator.java b/source/com/c2kernel/collection/gui/model/AggregationVertexOutlineCreator.java
new file mode 100755
index 0000000..ed19f9c
--- /dev/null
+++ b/source/com/c2kernel/collection/gui/model/AggregationVertexOutlineCreator.java
@@ -0,0 +1,43 @@
+package com.c2kernel.collection.gui.model;
+
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.graph.model.VertexOutlineCreator;
+
+
+public class AggregationVertexOutlineCreator implements VertexOutlineCreator
+{
+ public void setOutline(Vertex vertex)
+ {
+ GraphPoint centre = vertex.getCentrePoint();
+ int height = vertex.getHeight();
+ int width = vertex.getWidth();
+
+
+ if (height==0 || width==0)
+ vertex.setOutlinePoints
+ (
+ new GraphPoint[]
+ {
+ new GraphPoint(centre.x-20, centre.y-20),
+ new GraphPoint(centre.x+20, centre.y-20),
+ new GraphPoint(centre.x+20, centre.y+20),
+ new GraphPoint(centre.x-20, centre.y+20)
+
+ }
+ );
+ else
+
+ vertex.setOutlinePoints
+ (
+ new GraphPoint[]
+ {
+ new GraphPoint(centre.x-width/2, centre.y-height/2),
+ new GraphPoint(centre.x+width/2, centre.y-height/2),
+ new GraphPoint(centre.x+width/2, centre.y+height/2),
+ new GraphPoint(centre.x-width/2, centre.y+height/2)
+
+ }
+ );
+ }
+}
diff --git a/source/com/c2kernel/collection/gui/view/AggregationMemberRenderer.java b/source/com/c2kernel/collection/gui/view/AggregationMemberRenderer.java
new file mode 100755
index 0000000..0d3cb03
--- /dev/null
+++ b/source/com/c2kernel/collection/gui/view/AggregationMemberRenderer.java
@@ -0,0 +1,124 @@
+package com.c2kernel.collection.gui.view;
+
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+
+import com.c2kernel.collection.Aggregation;
+import com.c2kernel.collection.AggregationMember;
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.graph.view.VertexRenderer;
+import com.c2kernel.utils.Logger;
+
+/**
+ * @version $Revision: 1.24 $ $Date: 2005/12/01 14:23:15 $
+ * @author $Author: abranson $
+ */
+
+public class AggregationMemberRenderer implements VertexRenderer
+{
+
+ private Aggregation mAggregation = null;
+
+ public AggregationMemberRenderer()
+ {
+ }
+
+ public void setAggregation(Aggregation agg)
+ {
+ mAggregation = agg;
+ }
+
+
+ public void draw(Graphics2D g2d, Vertex vertex)
+ {
+ GraphPoint centre = vertex.getCentrePoint();
+ GraphPoint[] outline = vertex.getOutlinePoints();
+ FontMetrics metrics = g2d.getFontMetrics();
+
+ AggregationMember memberPair = mAggregation.getMemberPair(vertex.getID());
+
+ try
+ {
+ String name = memberPair.getEntityName();
+
+ g2d.drawString( name,
+ centre.x-metrics.stringWidth(name)/2,
+ topYOfOutline(outline) );
+
+ g2d.drawImage
+ (
+ memberPair.getImage(),
+ centre.x - 8,
+ centre.y - 8,
+ null
+ );
+
+
+
+ // Draw the outline of the vertex
+ if(outline.length > 1)
+ {
+ for(int i=0; i<outline.length-1; i++)
+ {
+ g2d.drawLine
+ (
+ outline[i].x,
+ outline[i].y,
+ outline[i+1].x,
+ outline[i+1].y
+ );
+ }
+
+ g2d.drawLine
+ (
+ outline[outline.length-1].x,
+ outline[outline.length-1].y,
+ outline[0].x,
+ outline[0].y
+ );
+ }
+
+
+ }
+ catch (Exception ex)
+ {
+ Logger.error("AggregationMemberRenderer::draw() " + ex);
+ }
+ }
+
+
+ int topYOfOutline(GraphPoint[] outline)
+ {
+ int topY = outline[0].y;
+ int i = 0;
+
+
+ for(i=1; i<outline.length; i++)
+ {
+ if(outline[i].y < topY)
+ {
+ topY = outline[i].y;
+ }
+ }
+
+ return topY;
+ }
+
+ int bottomYOfOutline(GraphPoint[] outline)
+ {
+ int bottomY = outline[0].y;
+ int i = 0;
+
+
+ for(i=1; i<outline.length; i++)
+ {
+ if(outline[i].y > bottomY)
+ {
+ bottomY = outline[i].y;
+ }
+ }
+
+ return bottomY;
+ }
+}
diff --git a/source/com/c2kernel/collection/gui/view/CollectionFrame.java b/source/com/c2kernel/collection/gui/view/CollectionFrame.java
new file mode 100755
index 0000000..2d40436
--- /dev/null
+++ b/source/com/c2kernel/collection/gui/view/CollectionFrame.java
@@ -0,0 +1,41 @@
+package com.c2kernel.collection.gui.view;
+
+import java.awt.GridLayout;
+
+import javax.swing.JFrame;
+
+import com.c2kernel.collection.Aggregation;
+import com.c2kernel.gui.tabs.CollectionPane;
+
+
+/**
+ * @version $Revision: 1.10 $ $Date: 2003/04/06 15:06:36 $
+ * @author $Author: abranson $
+ */
+
+public class CollectionFrame extends JFrame
+{
+
+ private CollectionPane mCollectionPane = new CollectionPane();
+
+ public CollectionFrame()
+ {
+ createLayout();
+ }
+
+ public void setAggregation(Aggregation aggregation)
+ {
+ mCollectionPane.add(aggregation);
+ }
+
+
+ private void createLayout()
+ {
+ getContentPane().setLayout(new GridLayout(1, 1));
+
+ getContentPane().add(mCollectionPane);
+
+ setSize(1000, 1000);
+ setVisible(true);
+ }
+}
diff --git a/source/com/c2kernel/collection/gui/view/PropertyPanel.java b/source/com/c2kernel/collection/gui/view/PropertyPanel.java
new file mode 100755
index 0000000..903ddf9
--- /dev/null
+++ b/source/com/c2kernel/collection/gui/view/PropertyPanel.java
@@ -0,0 +1,36 @@
+package com.c2kernel.collection.gui.view;
+
+import com.c2kernel.collection.AggregationMember;
+import com.c2kernel.collection.Collection;
+import com.c2kernel.collection.CollectionMember;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.graph.view.VertexPropertyPanel;
+
+public class PropertyPanel extends VertexPropertyPanel {
+
+ Collection mCollection;
+
+ public PropertyPanel() {
+ super();
+ }
+
+ public void setCollection(Collection collection) {
+ mCollection = collection;
+ }
+
+ public void setVertex(Vertex vert) {
+ try {
+ CollectionMember newMember = mCollection.getMember(vert.getID());
+ if (newMember instanceof AggregationMember) {
+ super.setVertex((AggregationMember)newMember);
+ return;
+ }
+ else
+ clear();
+ } catch (ObjectNotFoundException ex) {
+ clear();
+ selObjClass.setText("No Collection Member object found");
+ }
+ }
+}
diff --git a/source/com/c2kernel/collection/gui/view/SelectedMemberPanel.java b/source/com/c2kernel/collection/gui/view/SelectedMemberPanel.java
new file mode 100755
index 0000000..5e66c1e
--- /dev/null
+++ b/source/com/c2kernel/collection/gui/view/SelectedMemberPanel.java
@@ -0,0 +1,150 @@
+package com.c2kernel.collection.gui.view;
+
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.*;
+
+import com.c2kernel.collection.AggregationMember;
+import com.c2kernel.collection.MembershipException;
+import com.c2kernel.entity.proxy.EntityProxy;
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.graph.view.SelectedVertexPanel;
+import com.c2kernel.gui.DomainKeyConsumer;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Language;
+
+/**************************************************************************
+ *
+ * $Revision: 1.10 $
+ * $Date: 2005/05/12 10:12:52 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+
+public class SelectedMemberPanel extends SelectedVertexPanel implements DomainKeyConsumer {
+
+ JLabel slotNumber = new JLabel();
+ JTextField memberKey = new JTextField(14);
+
+ JButton findButton = new JButton(Language.translate("Find"));
+ JToggleButton changeButton = new JToggleButton(Language.translate("Change"));
+ JButton removeButton = new JButton(Language.translate("Remove"));
+
+ SelectedMemberPanel me;
+ AggregationMember selectedMember = null;
+
+ public SelectedMemberPanel() {
+ me=this;
+ setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+
+ JPanel attrs = new JPanel(new GridLayout(3,2));
+ attrs.add(new JLabel(Language.translate("Slot Number:")));
+ attrs.add(slotNumber);
+ attrs.add(new JLabel(Language.translate("Assigned Member:")));
+ attrs.add(memberKey);
+ memberKey.setEditable(false);
+
+ add(attrs);
+ add(Box.createVerticalStrut(10));
+
+ findButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent ae) {
+ String code = memberKey.getText();
+ if (code == null || code.length() == 0)
+ code = memberKey.getText().replace('/',' ');
+ MainFrame.itemFinder.pushNewKey(code);
+ }
+ });
+
+ changeButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent ae) {
+ if (changeButton.getModel().isSelected()) {
+ MainFrame.status.setText(Language.translate("Please scan or type your barcode to assign in the top field"));
+ MainFrame.itemFinder.setConsumer(me, "Assign");
+ findButton.setEnabled(false);
+ }
+ else {
+ MainFrame.status.setText("");
+ MainFrame.itemFinder.clearConsumer(me);
+ if (selectedMember.getEntityKey() > -1) findButton.setEnabled(true);
+ }
+ }
+ });
+
+ removeButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent ae) {
+ selectedMember.clearEntity();
+ selectedMember.getProperties().remove("Name");
+ select(selectedMember);
+ }
+ });
+
+ Box buttonBox = Box.createHorizontalBox();
+ buttonBox.add(findButton);
+ if (MainFrame.isAdmin) {
+ buttonBox.add(changeButton);
+ buttonBox.add(removeButton);
+ }
+
+ setButtons(false);
+ add(buttonBox);
+ }
+
+ public void select(Vertex vert) {
+ selectedMember = (AggregationMember)vert;
+ slotNumber.setText(String.valueOf(vert.getID()));
+ int memberId = selectedMember.getEntityKey();
+ String name = "Empty";
+ try {
+ EntityProxy member = Gateway.getProxyManager().getProxy(new EntityPath(memberId));
+ name = member.getName();
+ } catch (Exception e) { }
+ memberKey.setText(name);
+ setButtons(true);
+
+ revalidate();
+ }
+
+ public void clear() {
+ slotNumber.setText("");
+ memberKey.setText("");
+ setButtons(false);
+ revalidate();
+ }
+
+ public void setButtons(boolean state) {
+ findButton.setEnabled(state);
+ changeButton.getModel().setSelected(false);
+ changeButton.setEnabled(state);
+ removeButton.setEnabled(state);
+ MainFrame.itemFinder.clearConsumer(me);
+ }
+ /**
+ *
+ */
+ public void push(DomainPath key) {
+ MainFrame.status.setText("Assigning entity "+key.getSysKey()+" to slot "+selectedMember.getID());
+ try {
+ selectedMember.assignEntity(key.getSysKey());
+ select(selectedMember);
+ } catch (MembershipException ex) {
+ JOptionPane.showMessageDialog(null, "Product does not fit in this slot", "Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+ /**
+ *
+ */
+ public void push(String name) {
+ JOptionPane.showMessageDialog(null, "Product is not known in this centre", "Error", JOptionPane.ERROR_MESSAGE);
+ }
+
+}
+
diff --git a/source/com/c2kernel/entity/C2KLocalObject.java b/source/com/c2kernel/entity/C2KLocalObject.java
new file mode 100755
index 0000000..06bf867
--- /dev/null
+++ b/source/com/c2kernel/entity/C2KLocalObject.java
@@ -0,0 +1,32 @@
+package com.c2kernel.entity;
+
+import java.io.Serializable;
+
+/**
+ * Objects that are to be stored by Cristal Entities must implement this interface and be (un)marshallable by Castor
+ * i.e. have a map file properly registered in the kernel. Domain implementors should not create new C2KLocalObjects
+ * <p>Each object will be stored as the path /clustertype/name in most cases. Exceptions are:
+ * <ul>
+ * <li>Outcomes - /Outcome/SchemaType/SchemaVersion/EventId
+ * <li>Viewpoints - /ViewPoint/SchemaType/Name
+ * </ul>
+ *
+ * @see com.c2kernel.persistency.ClusterStorage
+ * @see com.c2kernel.persistency.ClusterStorageManager
+ *
+ * @author Andrew Branson
+ *
+ * $Revision: 1.5 $
+ * $Date: 2004/01/22 11:10:41 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ */
+
+public interface C2KLocalObject extends Serializable {
+
+ public void setName(String name);
+ public String getName();
+
+ public String getClusterType();
+}
diff --git a/source/com/c2kernel/entity/CorbaServer.java b/source/com/c2kernel/entity/CorbaServer.java
new file mode 100755
index 0000000..948b1a6
--- /dev/null
+++ b/source/com/c2kernel/entity/CorbaServer.java
@@ -0,0 +1,191 @@
+package com.c2kernel.entity;
+
+import java.util.Map;
+
+import org.omg.PortableServer.POA;
+import org.omg.PortableServer.POAManager;
+import org.omg.PortableServer.Servant;
+import org.omg.PortableServer.POAManagerPackage.AdapterInactive;
+
+import com.c2kernel.common.CannotManageException;
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.ObjectAlreadyExistsException;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.agent.ActiveEntity;
+import com.c2kernel.entity.agent.ActiveLocator;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.lookup.InvalidEntityPathException;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.SoftCache;
+
+/**************************************************************************
+ *
+ * $Revision: 1.8 $
+ * $Date: 2005/10/13 08:13:44 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+
+public class CorbaServer {
+ private Map mEntityCache;
+ private POA mRootPOA;
+ private POA mItemPOA;
+ private POA mAgentPOA;
+ private POAManager mPOAManager;
+
+ public CorbaServer() throws InvalidDataException {
+ mEntityCache = new SoftCache(50);
+
+ // init POA
+ try {
+ setupPOA();
+ mPOAManager.activate();
+ } catch (Exception ex) {
+ Logger.error(ex);
+ throw new InvalidDataException("Error initialising POA", "");
+ }
+
+ new Thread(new Runnable() {
+ public void run() {
+ Thread.currentThread().setName("ORB Invoker");
+ Gateway.getORB().run();
+ }
+ }).start();
+ }
+
+ public void close() {
+ try {
+ mPOAManager.deactivate(true, true);
+ } catch (AdapterInactive ex) {
+ Logger.error(ex);
+ }
+ }
+
+ /**************************************************************************
+ * Initialises the C2KRootPOA with policies which are suitable for Factory objects
+ **************************************************************************/
+ public void setupPOA() throws Exception {
+
+ //Initialise the RootPOA
+ mRootPOA = org.omg.PortableServer.POAHelper.narrow(
+ Gateway.getORB().resolve_initial_references("RootPOA"));
+
+ //Initilaise the default POAManager
+
+ mPOAManager = mRootPOA.the_POAManager();
+
+ org.omg.CORBA.Policy[] poaPolicies;
+
+ // Create POA for use by the entities
+ org.omg.CORBA.Policy[] policies = new org.omg.CORBA.Policy[6];
+
+ policies[0] = mRootPOA.create_id_assignment_policy(
+ org.omg.PortableServer.IdAssignmentPolicyValue.USER_ID);
+ policies[1] = mRootPOA.create_lifespan_policy(
+ org.omg.PortableServer.LifespanPolicyValue.PERSISTENT);
+ policies[2] = mRootPOA.create_servant_retention_policy(
+ org.omg.PortableServer.ServantRetentionPolicyValue.NON_RETAIN);
+ policies[3] = mRootPOA.create_id_uniqueness_policy(
+ org.omg.PortableServer.IdUniquenessPolicyValue.UNIQUE_ID);
+ policies[4] = mRootPOA.create_request_processing_policy(
+ org.omg.PortableServer.RequestProcessingPolicyValue.
+ USE_SERVANT_MANAGER);
+ policies[5] = mRootPOA.create_implicit_activation_policy(
+ org.omg.PortableServer.ImplicitActivationPolicyValue.
+ NO_IMPLICIT_ACTIVATION);
+
+ mItemPOA = mRootPOA.create_POA( "Item",
+ mRootPOA.the_POAManager(),
+ policies );
+ mAgentPOA = mRootPOA.create_POA( "Agent",
+ mRootPOA.the_POAManager(),
+ policies );
+
+ //Create the locators
+ TraceableLocator itemLocator = new TraceableLocator( mItemPOA );
+ mItemPOA.set_servant_manager( itemLocator._this( Gateway.getORB() ) );
+
+ ActiveLocator agentLocator = new ActiveLocator( mAgentPOA );
+ mAgentPOA.set_servant_manager( agentLocator._this( Gateway.getORB() ) );
+
+ }
+
+
+ /**************************************************************************
+ * Returns a CORBA servant for a pre-existing entity
+ **************************************************************************/
+ private Servant getEntity(int sysKey, org.omg.PortableServer.POA poa) throws ObjectNotFoundException {
+ try {
+ EntityPath entityPath = new EntityPath(sysKey);
+ Servant entity = null;
+ synchronized (mEntityCache) {
+ entity = (Servant)mEntityCache.get(entityPath);
+ if (entity == null) {
+ Logger.msg(7, "Creating new servant for "+sysKey);
+
+ Class entityClass = Gateway.getLDAPLookup().getEntityClass(entityPath);
+
+ if (entityClass == TraceableEntity.class) {
+ if (poa == null) poa = mItemPOA;
+ entity = new TraceableEntity(sysKey, poa);
+ }
+ else if (entityClass == ActiveEntity.class) {
+ if (poa == null) poa = mAgentPOA;
+ entity = new ActiveEntity(sysKey, poa);
+ }
+ mEntityCache.put(entityPath, entity);
+ }
+ }
+ return entity;
+
+ } catch (InvalidEntityPathException ex) {
+ throw new ObjectNotFoundException("Invalid Entity Key", "");
+ }
+ }
+
+ /**************************************************************************
+ * Wrapper for fetching Items
+ **************************************************************************/
+ public TraceableEntity getItem(int sysKey, org.omg.PortableServer.POA poa) throws ObjectNotFoundException {
+ return (TraceableEntity)getEntity(sysKey, poa);
+ }
+
+ /**************************************************************************
+ * Wrapper for fetching Agents
+ **************************************************************************/
+ public ActiveEntity getAgent(int sysKey, org.omg.PortableServer.POA poa) throws ObjectNotFoundException {
+ return (ActiveEntity)getEntity(sysKey, poa);
+ }
+
+ /**
+ * @param entityPath
+ * @return
+ */
+ public Servant createEntity(EntityPath entityPath) throws CannotManageException, ObjectAlreadyExistsException {
+ try {
+ if (entityPath == null)
+ entityPath = Gateway.getLDAPLookup().getNextKeyManager().generateNextEntityKey();
+ } catch (Exception ex) {
+ Logger.error(ex);
+ throw new CannotManageException("Cannot generate next entity key");
+ }
+ boolean isAgent = entityPath instanceof AgentPath;
+ POA myPOA = isAgent?mAgentPOA:mItemPOA;
+ org.omg.CORBA.Object obj = myPOA.create_reference_with_id(entityPath.getOID(), isAgent?AgentHelper.id():ItemHelper.id());
+ entityPath.setIOR(obj);
+ Servant entity;
+ if (isAgent)
+ entity = new ActiveEntity(entityPath.getSysKey(), myPOA);
+ else
+ entity = new TraceableEntity(entityPath.getSysKey(), myPOA);
+ synchronized (mEntityCache) {
+ mEntityCache.put(entityPath, entity);
+ }
+ return entity;
+
+ }
+}
diff --git a/source/com/c2kernel/entity/TraceableEntity.java b/source/com/c2kernel/entity/TraceableEntity.java
new file mode 100755
index 0000000..49bbe47
--- /dev/null
+++ b/source/com/c2kernel/entity/TraceableEntity.java
@@ -0,0 +1,335 @@
+/**************************************************************************
+ * TraceableEntity
+ *
+ * $Workfile$
+ * $Revision: 1.108 $
+ * $Date: 2005/10/06 14:46:22 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.entity;
+
+import java.util.Iterator;
+
+import com.c2kernel.common.AccessRightsException;
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.InvalidTransitionException;
+import com.c2kernel.common.ObjectAlreadyExistsException;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.common.PersistencyException;
+import com.c2kernel.entity.agent.JobArrayList;
+import com.c2kernel.lifecycle.instance.CompositeActivity;
+import com.c2kernel.lifecycle.instance.Workflow;
+import com.c2kernel.lifecycle.instance.stateMachine.Transitions;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.lookup.InvalidEntityPathException;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.persistency.ClusterStorageException;
+import com.c2kernel.persistency.TransactionManager;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.property.Property;
+import com.c2kernel.property.PropertyArrayList;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.Logger;
+
+/**************************************************************************
+*
+* @author $Author: abranson $ $Date: 2005/10/06 14:46:22 $
+* @version $Revision: 1.108 $
+* <pre>
+* ,. '\'\ ,---.
+* . | \\ l\\l_ // |
+* _ _ | \\/ `/ `.| |
+* /~\\ \ //~\ | Y | | || Y |
+* | \\ \ // | | \| | |\ / |
+* [ || || ] \ | o|o | > /
+* ] Y || || Y [ \___\_--_ /_/__/
+* | \_|l,------.l|_/ | /.-\(____) /--.\
+* | >' `< | `--(______)----'
+* \ (/~`--____--'~\) / u// u / \
+* `-_>-__________-<_-' / \ / /|
+* /(_#(__)#_)\ ( .) / / ]
+* \___/__\___/ `.`' / [
+* /__`--'__\ |`-' |
+* /\(__,>-~~ __) | |_
+* /\//\\( `--~~ ) _l |-:.
+* '\/ <^\ /^> | ` ( < \\
+* _\ >-__-< /_ ,-\ ,-~~->. \ `:._,/
+* (___\ /___) (____/ (____) `-'
+* Kovax and, paradoxically, Kovax
+* </pre>
+***************************************************************************/
+
+public class TraceableEntity extends ItemPOA
+{
+
+ private int mSystemKey;
+ private org.omg.PortableServer.POA mPoa;
+ private TransactionManager mStorage;
+
+
+ /**************************************************************************
+ * Constructor used by the Locator only
+ **************************************************************************/
+ public TraceableEntity( int key,
+ org.omg.PortableServer.POA poa )
+ {
+ Logger.msg(5,"TraceableEntity::constructor() - SystemKey:" + key );
+
+ mSystemKey = key;
+ mPoa = poa;
+ mStorage = Gateway.getStorage();
+ }
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public org.omg.PortableServer.POA _default_POA()
+ {
+ if(mPoa != null)
+ return mPoa;
+ else
+ return super._default_POA();
+ }
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public int getSystemKey()
+ {
+ Logger.msg(8, "TraceableEntity::getSystemKey() - " + mSystemKey);
+ return mSystemKey;
+ }
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public void initialise( int agentId,
+ String propString,
+ String initWfString
+ )
+ throws AccessRightsException,
+ InvalidDataException,
+ PersistencyException
+ {
+ Logger.msg(1, "TraceableEntity::initialise("+mSystemKey+") - agent:"+agentId);
+ synchronized (this) {
+ Workflow lc = null;
+ PropertyArrayList props = null;
+
+ AgentPath agentPath;
+ try {
+ agentPath = new AgentPath(agentId);
+ } catch (InvalidEntityPathException e) {
+ throw new AccessRightsException("Invalid Agent Id:" + agentId);
+ }
+
+ //unmarshalling checks the validity of the received strings
+
+ // create properties
+ if (!propString.equals("")) {
+ try {
+ props = (PropertyArrayList)CastorXMLUtility.unmarshall(propString);
+ for (Iterator i = props.list.iterator(); i.hasNext();) {
+ Property thisProp = (Property)i.next();
+ mStorage.put(mSystemKey, thisProp, props);
+ }
+ } catch (Throwable ex) {
+ Logger.msg(8, "TraceableEntity::initialise("+mSystemKey+ ") - Properties were invalid: "+propString);
+ Logger.error(ex);
+ mStorage.abort(props);
+ }
+ mStorage.commit(props);
+ }
+
+ // create wf
+ try {
+ if (initWfString == null || initWfString.equals(""))
+ lc = new Workflow(new CompositeActivity());
+ else
+ lc = new Workflow((CompositeActivity)CastorXMLUtility.unmarshall(initWfString));
+ lc.initialise(mSystemKey, agentPath);
+ mStorage.put(mSystemKey, lc, null);
+ } catch (Throwable ex) {
+ Logger.msg(8, "TraceableEntity::initialise("+mSystemKey+") - Workflow was invalid: "+initWfString);
+ Logger.error(ex);
+ }
+ }
+ }
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ //requestdata is xmlstring
+ public void requestAction( int agentId,
+ String stepPath,
+ int transitionID,
+ String requestData
+ )
+ throws AccessRightsException,
+ InvalidTransitionException,
+ ObjectNotFoundException,
+ InvalidDataException,
+ PersistencyException,
+ ObjectAlreadyExistsException
+ {
+ synchronized (this) {
+ try {
+
+ Logger.msg(1, "TraceableEntity::request("+mSystemKey+") - " +
+ Transitions.getTransitionName(transitionID) + " "+stepPath + " by " +agentId );
+
+ AgentPath agent = new AgentPath(agentId);
+ Workflow lifeCycle = (Workflow)mStorage.get(mSystemKey, ClusterStorage.LIFECYCLE+"/workflow", null);
+
+ lifeCycle.requestAction( agent,
+ stepPath,
+ transitionID,
+ requestData );
+
+ // store the workflow if we've changed the state of the domain wf
+ if (!(stepPath.startsWith("workflow/predefined")))
+ mStorage.put(mSystemKey, lifeCycle, null);
+
+ // Normal operation exceptions
+ } catch (AccessRightsException ex) {
+ Logger.msg("Propagating AccessRightsException back to the calling agent");
+ throw ex;
+ } catch (InvalidTransitionException ex) {
+ Logger.msg("Propagating InvalidTransitionException back to the calling agent");
+ throw ex;
+ } catch (ObjectNotFoundException ex) {
+ Logger.msg("Propagating ObjectNotFoundException back to the calling agent");
+ throw ex;
+ // errors
+ } catch (ClusterStorageException ex) {
+ Logger.error(ex);
+ throw new PersistencyException("Error on storage: "+ex.getMessage(), "");
+ } catch (InvalidEntityPathException ex) {
+ Logger.error(ex);
+ throw new AccessRightsException("Invalid Agent Id: "+agentId, "");
+ } catch (InvalidDataException ex) {
+ Logger.error(ex);
+ Logger.msg("Propagating InvalidDataException back to the calling agent");
+ throw ex;
+ } catch (ObjectAlreadyExistsException ex) {
+ Logger.error(ex);
+ Logger.msg("Propagating ObjectAlreadyExistsException back to the calling agent");
+ throw ex;
+ // non-CORBA exception hasn't been caught!
+ } catch (Throwable ex) {
+ Logger.error("Unknown Error: requestAction on "+mSystemKey+" by "+agentId+" executing "+stepPath);
+ Logger.error(ex);
+ throw new InvalidDataException("Extraordinary Exception during execution:"+ex.getClass().getName()+" - "+ex.getMessage(), "");
+ }
+ }
+ }
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public String queryLifeCycle( int agentId,
+ boolean filter
+ )
+ throws AccessRightsException,
+ ObjectNotFoundException,
+ PersistencyException
+ {
+ synchronized (this) {
+ Logger.msg(1, "TraceableEntity::queryLifeCycle("+mSystemKey+") - agent: " + agentId);
+
+ try
+ {
+ AgentPath agent = new AgentPath(agentId);
+ Workflow wf = (Workflow)mStorage.get(mSystemKey, ClusterStorage.LIFECYCLE+"/workflow", null);
+ JobArrayList jobBag = new JobArrayList();
+ CompositeActivity domainWf = (CompositeActivity)wf.search("workflow/domain");
+ jobBag.list = filter?domainWf.calculateJobs(agent, true):domainWf.calculateAllJobs(agent, true);
+ Logger.msg(1, "TraceableEntity::queryLifeCycle("+mSystemKey+") - Returning "+jobBag.list.size()+" jobs.");
+ return CastorXMLUtility.marshall( jobBag );
+ }
+ catch( Throwable ex )
+ {
+ Logger.error(ex);
+ return "<ERROR/>";
+ }
+ }
+ }
+
+ /**************************************************************************
+ * The description for operation getData.
+ *
+ * @param path - the path to the object required
+ * the suffix 'all' retrieves a listing of all keys on that level
+ *
+ * @return The result string in xml format
+ * except 'all' which returns a comma sep list
+ *
+ * @exception ObjectNotFoundException
+ * ************************************************************************/
+ public String queryData(String path)
+ throws AccessRightsException,
+ ObjectNotFoundException,
+ PersistencyException
+ {
+ synchronized (this) {
+ String result = "";
+
+ Logger.msg(1, "TraceableEntity::queryData("+mSystemKey+") - " + path );
+
+ try
+ { // check for cluster contents query
+
+ if (path.endsWith("/all"))
+ {
+ int allPos = path.lastIndexOf("all");
+ String query = path.substring(0,allPos);
+ String[] ids = mStorage.getClusterContents( mSystemKey, query );
+
+ for( int i=0; i<ids.length; i++ )
+ {
+ result += ids[i];
+
+ if( i != ids.length-1 )
+ result += ",";
+ }
+ }
+ //****************************************************************
+ else
+ { // retrieve the object instead
+ C2KLocalObject obj = mStorage.get( mSystemKey, path, null );
+
+ // marshall it, or in the case of an outcome get the data.
+ result = CastorXMLUtility.marshall(obj);
+ }
+ }
+ catch (ObjectNotFoundException ex) {
+ throw ex;
+ }
+ catch(Throwable ex)
+ {
+ Logger.warning("TraceableEntity::queryData("+mSystemKey+") - "+
+ path + " Failed: "+ex.getClass().getName());
+ throw new PersistencyException("Server exception: "+ex.getClass().getName(), "");
+ }
+
+ if( Logger.doLog(9) )
+ Logger.msg(9, "TraceableEntity::queryData("+mSystemKey+") - result:" + result );
+
+ return result;
+ }
+ }
+ /**
+ *
+ */
+ protected void finalize() throws Throwable {
+ Logger.msg(7, "Item "+mSystemKey+" reaped");
+ Gateway.getStorage().clearCache(mSystemKey, null);
+ super.finalize();
+ }
+
+}
diff --git a/source/com/c2kernel/entity/TraceableLocator.java b/source/com/c2kernel/entity/TraceableLocator.java
new file mode 100755
index 0000000..09a19e3
--- /dev/null
+++ b/source/com/c2kernel/entity/TraceableLocator.java
@@ -0,0 +1,84 @@
+/**************************************************************************
+ * TraceableLocator
+ *
+ * $Workfile$
+ * $Revision: 1.15 $
+ * $Date: 2005/10/05 07:39:37 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.entity;
+
+
+import java.sql.Timestamp;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Logger;
+
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2005/10/05 07:39:37 $
+ * @version $Revision: 1.15 $
+ **************************************************************************/
+public class TraceableLocator extends org.omg.PortableServer.ServantLocatorPOA
+{
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ private org.omg.PortableServer.POA mParentPoa;
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public TraceableLocator( org.omg.PortableServer.POA poa )
+ {
+ mParentPoa = poa;
+ }
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public org.omg.PortableServer.Servant preinvoke(
+ byte[] oid,
+ org.omg.PortableServer.POA poa,
+ String operation,
+ org.omg.PortableServer.ServantLocatorPackage.CookieHolder cookie )
+ {
+ try
+ {
+
+ int syskey = Integer.parseInt(new String(oid));
+ org.omg.PortableServer.Servant servant=null;
+
+ Logger.msg(1,"===========================================================");
+ Logger.msg(1,"Item called at "+new Timestamp( System.currentTimeMillis()) +": " + operation +
+ "(" + syskey + ")." );
+
+ return Gateway.getCorbaServer().getItem(syskey, mParentPoa);
+
+ }
+ catch (ObjectNotFoundException ex)
+ {
+ Logger.error("ObjectNotFoundException::TraceableLocator::preinvoke() " + ex.toString());
+ throw new org.omg.CORBA.OBJECT_NOT_EXIST();
+ }
+ }
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public void postinvoke(
+ byte[] oid,
+ org.omg.PortableServer.POA poa,
+ String operation,
+ java.lang.Object the_cookie,
+ org.omg.PortableServer.Servant the_servant )
+ { }
+}
diff --git a/source/com/c2kernel/entity/agent/ActiveEntity.java b/source/com/c2kernel/entity/agent/ActiveEntity.java
new file mode 100755
index 0000000..cb77bbb
--- /dev/null
+++ b/source/com/c2kernel/entity/agent/ActiveEntity.java
@@ -0,0 +1,281 @@
+/**************************************************************************
+ * BasicAgent.java
+ *
+ * $Revision: 1.39 $
+ * $Date: 2005/04/26 06:48:12 $
+ *
+ * Copyright (C) 2001-2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.entity.agent;
+
+import java.util.Iterator;
+
+import com.c2kernel.common.*;
+import com.c2kernel.entity.AgentPOA;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.lookup.InvalidEntityPathException;
+import com.c2kernel.lookup.RolePath;
+import com.c2kernel.persistency.ClusterStorageException;
+import com.c2kernel.persistency.TransactionManager;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.property.PropertyArrayList;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.Logger;
+
+/**************************************************************************
+ * ActiveEntity
+ *
+ * @author $Author: abranson $ $Date: 2005/04/26 06:48:12 $
+ * @version $Revision: 1.39 $
+ **************************************************************************/
+public class ActiveEntity extends AgentPOA
+{
+
+ /**************************************************************************
+ * The CORBA Portable Object Adapter which holds the Agent
+ **************************************************************************/
+ private org.omg.PortableServer.POA mPOA = null;
+
+ /**************************************************************************
+ * The C2Kernel system key of the Agent
+ **************************************************************************/
+ private int mSystemKey = -1;
+
+ /**************************************************************************
+ * Connection to the persistency backeng
+ **************************************************************************/
+ private TransactionManager mDatabase = null;
+
+ /**************************************************************************
+ * The agent's joblist
+ **************************************************************************/
+ private JobList currentJobs;
+ /**
+ *
+ * @param key
+ * @param poa
+ */
+ public ActiveEntity( int key,
+ org.omg.PortableServer.POA poa )
+ {
+ Logger.msg(5, "ActiveEntity::constructor() - SystemKey:" + key );
+
+ mSystemKey = key;
+ mPOA = poa;
+ mDatabase = Gateway.getStorage();
+
+ Logger.msg(5, "ActiveEntity::constructor - completed.");
+ }
+
+ /**
+ * initialise cristal2 properties & collector
+ */
+ public void initialise( String agentProps )
+ throws AccessRightsException,
+ InvalidDataException,
+ PersistencyException
+ {
+ PropertyArrayList props = null;
+ Logger.msg(1, "ActiveEntity::initialise("+mSystemKey+")");
+ //initialise cristal2 properties & collector
+ try
+ {
+ props = initProps( agentProps );
+ mDatabase.commit( props );
+ }
+ catch( ClusterStorageException ex )
+ {
+ Logger.error("ActiveEntity::init() - Failed to init props/collector, aborting!");
+ Logger.error(ex);
+
+ mDatabase.abort( props );
+ throw new PersistencyException("Failed to init props => transaction aborted!");
+ }
+
+ Logger.msg(5, "ActiveEntity::init() - completed.");
+ }
+
+ /**
+ *
+ * @param propsString
+ * @return Properties
+ * @throws InvalidDataException Properties cannot be unmarshalled
+ * @throws ClusterStorageException
+ */
+ private PropertyArrayList initProps( String propsString )
+ throws InvalidDataException,
+ ClusterStorageException
+ {
+ PropertyArrayList props = null;
+
+ // create properties
+ if( !propsString.equals("") && propsString != null )
+ {
+ try
+ {
+ props = (PropertyArrayList)CastorXMLUtility.unmarshall(propsString);
+ }
+ catch( Exception ex )
+ {
+ //any exception during unmarshall indicates that data was
+ //incorrect or the castor mapping was not set up
+ Logger.error(ex);
+ throw new InvalidDataException(ex.toString(), null);
+ }
+
+ Iterator iter = props.list.iterator();
+
+ while( iter.hasNext() )
+ mDatabase.put( mSystemKey, (C2KLocalObject)iter.next(), props );
+ }
+ else
+ {
+ Logger.warning("ActiveEntity::initProps() - NO Properties!");
+ }
+
+ return props;
+ }
+
+ /**************************************************************************
+ *
+ *
+ **************************************************************************/
+ public org.omg.PortableServer.POA _default_POA()
+ {
+ if(mPOA != null)
+ return mPOA;
+ else
+ return super._default_POA();
+ }
+
+
+ /**************************************************************************
+ *
+ *
+ **************************************************************************/
+ public int getSystemKey()
+ {
+ return mSystemKey;
+ }
+
+
+ /**************************************************************************
+ *
+ *
+ **************************************************************************/
+ public String queryData(String xpath)
+ throws AccessRightsException,
+ ObjectNotFoundException,
+ PersistencyException
+ {
+ String result = "";
+ int allPos = -1;
+
+ Logger.msg(1, "ActiveEntity::queryData("+mSystemKey+") - " + xpath );
+
+ try
+ {
+ if( (allPos=xpath.indexOf("all")) != -1 )
+ {
+ String query = xpath.substring(0,allPos);
+ String[] ids = mDatabase.getClusterContents( mSystemKey, query );
+
+ for( int i=0; i<ids.length; i++ )
+ {
+
+ result += ids[i];
+
+ if( i != ids.length-1 )
+ result += ",";
+ }
+ }
+ //****************************************************************
+ else
+ {
+ C2KLocalObject obj = mDatabase.get( mSystemKey, xpath, null );
+
+ result = CastorXMLUtility.marshall(obj);
+ }
+
+ }
+ catch (ObjectNotFoundException ex) {
+ throw ex;
+ }
+ catch(Throwable ex)
+ {
+ Logger.error("ActiveEntity::queryData("+mSystemKey+") - " +
+ xpath + " FAILED");
+ Logger.error(ex);
+ result = "<ERROR/>";
+ }
+
+ Logger.msg(7, "ActiveEntity::queryData("+mSystemKey+") - result:" + result );
+
+ return result;
+ }
+
+
+
+ /**
+ * Called by an activity when it reckons we need to update our joblist for it
+ */
+
+ public synchronized void refreshJobList(int sysKey, String stepPath, String newJobs) {
+ try {
+ JobArrayList newJobList = (JobArrayList)CastorXMLUtility.unmarshall(newJobs);
+
+ // get our joblist
+ if (currentJobs == null)
+ currentJobs = new JobList( mSystemKey, null);
+
+ // remove old jobs for this item
+ currentJobs.removeJobsForStep( sysKey, stepPath );
+
+ // merge new jobs in
+ for (Iterator iter = newJobList.list.iterator(); iter.hasNext();) {
+ Job newJob = (Job)iter.next();
+ Logger.msg(6, "Adding job for "+newJob.getItemSysKey()+"/"+newJob.getStepPath()+":"+newJob.getPossibleTransition());
+ currentJobs.addJob(newJob);
+ }
+
+ } catch (Throwable ex) {
+ Logger.error("Could not refresh job list.");
+ Logger.error(ex);
+ }
+
+ }
+
+ public void addRole(String roleName) throws CannotManageException, ObjectNotFoundException {
+ RolePath newRole = Gateway.getLDAPLookup().getRoleManager().getRolePath(roleName);
+ try {
+ newRole.addAgent(new AgentPath(mSystemKey));
+ } catch (InvalidEntityPathException ex) {
+ throw new CannotManageException("Invalid syskey for agent: "+mSystemKey, "");
+ } catch (ObjectCannotBeUpdated ex) {
+ throw new CannotManageException("Could not update role");
+ }
+ }
+
+ public void removeRole(String roleName) throws CannotManageException, ObjectNotFoundException {
+ RolePath rolePath = Gateway.getLDAPLookup().getRoleManager().getRolePath(roleName);
+ try {
+ rolePath.removeAgent(new AgentPath(mSystemKey));
+ } catch (InvalidEntityPathException e) {
+ throw new CannotManageException("Invalid syskey for agent: "+mSystemKey, "");
+ } catch (ObjectCannotBeUpdated ex) {
+ throw new CannotManageException("Could not update role");
+ }
+ }
+ /**
+ *
+ */
+ protected void finalize() throws Throwable {
+ Logger.msg(7, "Agent "+mSystemKey+" reaped");
+ Gateway.getStorage().clearCache(mSystemKey, null);
+ super.finalize();
+ }
+
+}
diff --git a/source/com/c2kernel/entity/agent/ActiveLocator.java b/source/com/c2kernel/entity/agent/ActiveLocator.java
new file mode 100755
index 0000000..25324ee
--- /dev/null
+++ b/source/com/c2kernel/entity/agent/ActiveLocator.java
@@ -0,0 +1,87 @@
+/**************************************************************************
+ * TraceableLocator
+ *
+ * $Workfile$
+ * $Revision: 1.9 $
+ * $Date: 2005/10/05 07:39:36 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.entity.agent;
+
+
+import java.sql.Timestamp;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Logger;
+
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2005/10/05 07:39:36 $
+ * @version $Revision: 1.9 $
+ **************************************************************************/
+public class ActiveLocator extends org.omg.PortableServer.ServantLocatorPOA
+{
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ private org.omg.PortableServer.POA mParentPoa;
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public ActiveLocator( org.omg.PortableServer.POA poa )
+ {
+ mParentPoa = poa;
+ }
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public org.omg.PortableServer.Servant preinvoke(
+ byte[] oid,
+ org.omg.PortableServer.POA poa,
+ String operation,
+ org.omg.PortableServer.ServantLocatorPackage.CookieHolder cookie )
+ {
+
+ try
+ {
+ int syskey = Integer.parseInt(new String(oid));
+
+ org.omg.PortableServer.Servant servant;
+
+ Logger.msg(1,"===========================================================");
+ Logger.msg(1,"Agent called at "+new Timestamp( System.currentTimeMillis()) +": " + operation +
+ "(" + syskey + ")." );
+
+ return Gateway.getCorbaServer().getAgent(syskey, mParentPoa);
+
+ }
+ catch (ObjectNotFoundException ex)
+ {
+ Logger.error("ObjectNotFoundException::ActiveLocator::preinvoke() "+ex.toString());
+ throw new org.omg.CORBA.OBJECT_NOT_EXIST();
+ }
+ }
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public void postinvoke(
+ byte[] oid,
+ org.omg.PortableServer.POA poa,
+ String operation,
+ java.lang.Object the_cookie,
+ org.omg.PortableServer.Servant the_servant )
+ {
+ }
+}
diff --git a/source/com/c2kernel/entity/agent/Job.java b/source/com/c2kernel/entity/agent/Job.java
new file mode 100755
index 0000000..12423d6
--- /dev/null
+++ b/source/com/c2kernel/entity/agent/Job.java
@@ -0,0 +1,343 @@
+package com.c2kernel.entity.agent;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.entity.proxy.AgentProxy;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.lifecycle.instance.stateMachine.Transitions;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.lookup.InvalidEntityPathException;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.persistency.outcome.Outcome;
+import com.c2kernel.persistency.outcome.Viewpoint;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.CastorHashMap;
+import com.c2kernel.utils.KeyValuePair;
+import com.c2kernel.utils.Logger;
+
+/*******************************************************************************
+ * @author $Author: abranson $ $Date: 2005/05/20 13:07:49 $
+ * @version $Revision: 1.62 $
+ ******************************************************************************/
+public class Job implements C2KLocalObject
+{
+ private int mID;
+
+ private String mName;
+
+ private int mItemSysKey;
+
+ private String mStepPath;
+
+ private int mPossibleTransition;
+
+ private int mCurrentState;
+
+ private int mTargetState;
+
+ private String mStepName;
+
+ private int mAgentId = -1;
+
+ private String mAgentName;
+
+ private String mAgentRole;
+
+ private CastorHashMap mActProps = new CastorHashMap();
+
+ private String mOutcome;
+
+ private String mStepType;
+
+ private ItemProxy item = null;
+
+ private AgentProxy agent = null;
+
+ /***************************************************************************
+ * Empty constructor for Castor
+ **************************************************************************/
+ public Job()
+ {
+ }
+
+ /***************************************************************************
+ *
+ **************************************************************************/
+ public Job(int sysKey, String path, int transition, int currState, int targState, String stepName, CastorHashMap actProps, String stepType, String agentName)
+ {
+ setItemSysKey(sysKey);
+ setStepPath(path);
+ setPossibleTransition(transition);
+ setCurrentState(currState);
+ setTargetState(targState);
+ setStepName(stepName);
+ setActProps(actProps);
+ setStepType(stepType);
+ setAgentName(agentName);
+ }
+
+ public int getItemSysKey()
+ {
+ return mItemSysKey;
+ }
+
+ public ItemProxy getItemProxy() throws ObjectNotFoundException, InvalidEntityPathException
+ {
+ if (item == null)
+ item = (ItemProxy) Gateway.getProxyManager().getProxy(new EntityPath(mItemSysKey));
+ return item;
+ }
+
+ public AgentProxy getAgentProxy() throws ObjectNotFoundException, InvalidEntityPathException
+ {
+ if (agent == null)
+ agent = (AgentProxy) Gateway.getProxyManager().getProxy(new EntityPath(getAgentId()));
+ return agent;
+ }
+
+ public String getDescription()
+ {
+ String desc = (String) mActProps.get("Description");
+ if (desc == null)
+ desc = "No Description";
+ return desc;
+ }
+
+ public String getSchemaType()
+ {
+ return (String) mActProps.get("SchemaType");
+ }
+
+ public int getSchemaVersion()
+ {
+ try
+ {
+ return Integer.parseInt((String) mActProps.get("SchemaVersion"));
+ } catch (NumberFormatException ex)
+ {
+ return -1;
+ }
+ }
+
+ public void setOutcome(String outcome)
+ {
+ mOutcome = outcome;
+ }
+
+ public String getOutcomeString()
+ {
+ Logger.debug(8, "getOutcomeString() " + (mOutcome == null && isOutcomeUsed()));
+ if (mOutcome == null && isOutcomeUsed())
+ {
+ String viewName = (String) getActProp("Viewpoint");
+ mOutcome = null;
+ if (viewName.length() > 0)
+ try
+ {
+ Viewpoint view = (Viewpoint) Gateway.getStorage().get(getItemSysKey(), ClusterStorage.VIEWPOINT + "/" + getSchemaType() + "/" + viewName, null);
+ mOutcome = view.getOutcome().getData();
+ } catch (Exception ex)
+ { // not found, return null
+ }
+ }
+ return mOutcome;
+ }
+
+ public Outcome getOutcome()
+ {
+ Logger.msg(1, "Get outcome");
+ return new Outcome(-1, getOutcomeString(), getSchemaType(), getSchemaVersion());
+ }
+
+ public int getAgentId() throws ObjectNotFoundException
+ {
+ if (mAgentId == -1)
+ mAgentId = Gateway.getLDAPLookup().getRoleManager().getAgentPath(getAgentName()).getSysKey();
+ return mAgentId;
+ }
+
+ public void setAgentId(int id)
+ {
+ mAgentId = id;
+ agent = null;
+ }
+
+ public String getAgentName()
+ {
+ if (mAgentName == null)
+ mAgentName = (String) mActProps.get("AgentName");
+ return mAgentName;
+ }
+
+ public void setAgentName(String agentName)
+ {
+ mAgentName = agentName;
+ }
+
+ public String getAgentRole()
+ {
+ if (mAgentRole == null)
+ mAgentRole = (String) mActProps.get("Agent Role");
+ return mAgentRole;
+ }
+
+ public void setAgentRole(String role)
+ {
+ mAgentRole = role;
+ }
+
+ public boolean isOutcomeUsed()
+ {
+ String schemaType = getSchemaType();
+ return (Boolean.TRUE.equals(getActProp("AlwaysUseOutcome")) || mPossibleTransition == Transitions.DONE || mPossibleTransition == Transitions.COMPLETE) && !(schemaType == null || schemaType.equals(""));
+ }
+
+ public int getID()
+ {
+ return mID;
+ }
+
+ public String getName()
+ {
+ return mName;
+ }
+
+ public void setID(int id)
+ {
+ mID = id;
+ mName = String.valueOf(id);
+ }
+
+ public void setName(String name)
+ {
+ mName = name;
+ try
+ {
+ mID = Integer.parseInt(name);
+ } catch (NumberFormatException ex)
+ {
+ mID = -1;
+ }
+ }
+
+ public void setItemSysKey(int sysKey)
+ {
+ mItemSysKey = sysKey;
+ item = null;
+ }
+
+ public String getClusterType()
+ {
+ return ClusterStorage.JOB;
+ }
+
+ public boolean equals(Job job)
+ {
+ return (getItemSysKey() == job.getItemSysKey()) && this.mStepPath.equals(job.mStepPath) && this.mPossibleTransition == job.mPossibleTransition;
+ }
+
+ public Object getActProp(String name)
+ {
+ return mActProps.get(name);
+ }
+
+ public String getActPropString(String name)
+ {
+ try
+ {
+ return mActProps.get(name).toString();
+ } catch (NullPointerException ex)
+ {
+ return null;
+ }
+ }
+
+ public String getStepName()
+ {
+ return mStepName;
+ }
+
+ public void setStepName(String string)
+ {
+ mStepName = string;
+ }
+
+ public String getStepPath()
+ {
+ return mStepPath;
+ }
+
+ public void setStepPath(String string)
+ {
+ mStepPath = string;
+ }
+
+ public int getPossibleTransition()
+ {
+ return mPossibleTransition;
+ }
+
+ public void setPossibleTransition(int lint)
+ {
+ mPossibleTransition = lint;
+ }
+
+ public CastorHashMap getActProps()
+ {
+ return mActProps;
+ }
+
+ public void setActProps(CastorHashMap map)
+ {
+ mActProps = map;
+ }
+
+ public KeyValuePair[] getKeyValuePairs()
+ {
+ return mActProps.getKeyValuePairs();
+ }
+
+ public void setKeyValuePairs(KeyValuePair[] pairs)
+ {
+ mActProps.setKeyValuePairs(pairs);
+ }
+
+ public int getCurrentState()
+ {
+ return mCurrentState;
+ }
+
+ public void setCurrentState(int string)
+ {
+ mCurrentState = string;
+ }
+
+ public int getTargetState() {
+ return mTargetState;
+ }
+
+ public void setTargetState(int mTargetState) {
+ this.mTargetState = mTargetState;
+ }
+
+ /**
+ * Returns the actType.
+ *
+ * @return String
+ */
+ public String getStepType()
+ {
+ return mStepType;
+ }
+
+ /**
+ * Sets the actType.
+ *
+ * @param actType
+ * The actType to set
+ */
+ public void setStepType(String actType)
+ {
+ mStepType = actType;
+ }
+} \ No newline at end of file
diff --git a/source/com/c2kernel/entity/agent/JobArrayList.java b/source/com/c2kernel/entity/agent/JobArrayList.java
new file mode 100755
index 0000000..b6eb2c2
--- /dev/null
+++ b/source/com/c2kernel/entity/agent/JobArrayList.java
@@ -0,0 +1,30 @@
+/**************************************************************************
+ *
+ * $Revision: 1.2 $
+ * $Date: 2003/06/20 11:44:30 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.entity.agent;
+
+import java.util.ArrayList;
+
+import com.c2kernel.utils.CastorArrayList;
+
+public class JobArrayList extends CastorArrayList
+{
+
+ public JobArrayList()
+ {
+ super();
+ }
+
+ public JobArrayList(ArrayList aList)
+ {
+ super(aList);
+ }
+
+
+}
diff --git a/source/com/c2kernel/entity/agent/JobList.java b/source/com/c2kernel/entity/agent/JobList.java
new file mode 100755
index 0000000..d0d05d5
--- /dev/null
+++ b/source/com/c2kernel/entity/agent/JobList.java
@@ -0,0 +1,125 @@
+package com.c2kernel.entity.agent;
+
+import java.util.Iterator;
+import java.util.Vector;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.lookup.InvalidEntityPathException;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.persistency.RemoteMap;
+import com.c2kernel.utils.Logger;
+
+
+/**************************************************************************
+*
+* @author $Author: abranson $ $Date: 2006/03/03 13:52:21 $
+* @version $Revision: 1.15 $
+***************************************************************************/
+public class JobList extends RemoteMap
+{
+
+ /**************************************************************************
+ * Empty constructor for Castor
+ **************************************************************************/
+ public JobList(int sysKey, Object locker)
+ throws ObjectNotFoundException, InvalidEntityPathException
+ {
+ super(sysKey, ClusterStorage.JOB, locker);
+ }
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public void addJob( Job job )
+ {
+ synchronized(this) {
+ int jobId = getLastId()+1;
+ job.setID(jobId);
+ put(String.valueOf(jobId), job);
+ }
+ }
+
+ /**
+ * Cannot be stored
+ */
+ public String getClusterType() {
+ return null;
+ }
+
+ public int containsJob( Job job )
+ {
+ Iterator actMembers = keySet().iterator();
+ Job j = null;
+
+ while( actMembers.hasNext() )
+ {
+ j = (Job)actMembers.next();
+
+ if( j.equals(job) )
+ return j.getID();
+ }
+
+ return -1;
+ }
+
+ public Job getJob(int id) {
+ return (Job)get(String.valueOf(id));
+ }
+
+
+ /**
+ * @param job
+ */
+ public void removeJobsWithSysKey( int sysKey )
+ {
+ Iterator currentMembers = values().iterator();
+ Job j = null;
+
+ while( currentMembers.hasNext() )
+ {
+ j = (Job)currentMembers.next();
+
+ if( j.getItemSysKey() == sysKey )
+ remove( String.valueOf(j.getID()) );
+ }
+
+ Logger.msg(5, "JobList::removeJobsWithSysKey() - " + sysKey + " DONE." );
+ }
+
+ public void removeJobsForStep( int sysKey, String stepPath )
+ {
+ Iterator currentMembers = values().iterator();
+ while( currentMembers.hasNext() )
+ {
+ Job j = (Job)currentMembers.next();
+ if( j.getItemSysKey() == sysKey && j.getStepPath().equals(stepPath))
+ remove( String.valueOf(j.getID()) );
+ }
+
+ Logger.msg(5, "JobList::removeJobsForStep() - " + sysKey + " DONE." );
+ }
+ /**
+ * @param itemKey
+ * @param string
+ * @return
+ */
+ public Vector getJobsOfSysKey(int sysKey)
+ {
+ Iterator currentMembers = values().iterator();
+ Job j = null;
+ Vector jobs = new Vector();
+
+ while( currentMembers.hasNext() )
+ {
+ j = (Job)currentMembers.next();
+
+ if( j.getItemSysKey() == sysKey )
+ jobs.add(j);
+ }
+
+ Logger.msg(5, "JobList::getJobsOfSysKey() - returning " + jobs.size() + " Jobs." );
+
+ return jobs;
+ }
+} \ No newline at end of file
diff --git a/source/com/c2kernel/entity/proxy/AgentProxy.java b/source/com/c2kernel/entity/proxy/AgentProxy.java
new file mode 100755
index 0000000..af77031
--- /dev/null
+++ b/source/com/c2kernel/entity/proxy/AgentProxy.java
@@ -0,0 +1,301 @@
+/**************************************************************************
+ * AgentProxy.java
+ *
+ * $Revision: 1.37 $
+ * $Date: 2005/10/05 07:39:36 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.entity.proxy;
+
+import java.util.Date;
+import java.util.Enumeration;
+
+import com.c2kernel.common.AccessRightsException;
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.InvalidTransitionException;
+import com.c2kernel.common.ObjectAlreadyExistsException;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.common.PersistencyException;
+import com.c2kernel.entity.Agent;
+import com.c2kernel.entity.AgentHelper;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.entity.ManageableEntity;
+import com.c2kernel.entity.agent.Job;
+import com.c2kernel.lifecycle.instance.predefined.PredefinedStep;
+import com.c2kernel.lifecycle.instance.stateMachine.Transitions;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.lookup.InvalidEntityPathException;
+import com.c2kernel.lookup.Path;
+import com.c2kernel.persistency.outcome.OutcomeValidator;
+import com.c2kernel.persistency.outcome.Schema;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.scripting.ErrorInfo;
+import com.c2kernel.scripting.Script;
+import com.c2kernel.scripting.ScriptingEngineException;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.LocalObjectLoader;
+import com.c2kernel.utils.Logger;
+
+/******************************************************************************
+ * It is a wrapper for the connection and communication with Agent
+ * It caches data loaded from the Agent to reduce communication
+ *
+ * @version $Revision: 1.37 $ $Date: 2005/10/05 07:39:36 $
+ * @author $Author: abranson $
+ ******************************************************************************/
+public class AgentProxy extends EntityProxy
+{
+ AgentPath path;
+
+ /**************************************************************************
+ * Creates an AgentProxy without cache and change notification
+ **************************************************************************/
+ public AgentProxy( org.omg.CORBA.Object ior,
+ int systemKey)
+ throws ObjectNotFoundException
+ {
+ super(ior, systemKey);
+ try {
+ path = new AgentPath(systemKey);
+ } catch (InvalidEntityPathException e) {
+ throw new ObjectNotFoundException();
+ }
+ }
+
+ public ManageableEntity narrow() throws ObjectNotFoundException
+ {
+ try {
+ return AgentHelper.narrow(mIOR);
+ } catch (org.omg.CORBA.BAD_PARAM ex) { }
+ throw new ObjectNotFoundException("CORBA Object was not an Agent, or the server is down.");
+ }
+ /**************************************************************************
+ *
+ *
+ **************************************************************************/
+ public void initialise( String agentProps, String collector )
+ throws AccessRightsException,
+ InvalidDataException,
+ PersistencyException,
+ ObjectNotFoundException
+ {
+ Logger.msg(7, "AgentProxy::initialise - started");
+
+ ((Agent)getEntity()).initialise( agentProps );
+ }
+
+ public AgentPath getPath() {
+ return path;
+ }
+
+ /**
+ * Executes a job on the given item using this agent.
+ *
+ * @param item - item holding this job
+ * @param job - the job to execute
+ */
+ public void execute(ItemProxy item, Job job)
+ throws AccessRightsException,
+ InvalidTransitionException,
+ ObjectNotFoundException,
+ InvalidDataException,
+ PersistencyException,
+ ObjectAlreadyExistsException
+ {
+ OutcomeValidator validator = null;
+ String scriptName = job.getActPropString("ScriptName");
+ Date startTime = new Date();
+ Logger.msg(3, "AgentProxy - executing "+job.getStepPath()+" for "+path.getAgentName());
+ // get the outcome validator if present
+ if (job.isOutcomeUsed())
+ {
+
+ // get schema info from act props
+ String schemaName = job.getActPropString("SchemaType");
+ int schemaVersion;
+ try {
+ schemaVersion = Integer.parseInt(job.getActPropString("SchemaVersion"));
+ } catch (Exception e) {
+ throw new InvalidDataException(e.getClass().getName()+" extracing schema version", "");
+ }
+ Logger.msg(5, "AgentProxy - fetching schema "+schemaName+"_"+schemaVersion+" for validation");
+ // retrieve schema
+ Schema schema = LocalObjectLoader.getSchema(schemaName, schemaVersion);
+
+ if (schema == null)
+ throw new InvalidDataException("Job references outcome type "+schemaName+" version "+schemaVersion+" that does not exist in this centre.", "");
+
+ try {
+ validator = OutcomeValidator.getValidator(schema);
+ } catch (Exception e) {
+ throw new InvalidDataException("Could not create validator: "+e.getMessage(), "");
+ }
+ }
+
+ if(scriptName != null && scriptName.length() > 0 &&
+ (job.getPossibleTransition() == Transitions.DONE || job.getPossibleTransition() == Transitions.COMPLETE)) {
+ Logger.msg(3, "AgentProxy - executing script "+scriptName);
+ try {
+
+ // pre-validate outcome from script if there is one
+ if (job.getOutcomeString()!= null && validator != null) {
+ Logger.msg(5, "AgentProxy - validating outcome before script execution");
+ String error = validator.validate(job.getOutcomeString());
+ if (error.length() > 0) {
+ Logger.error("Outcome not valid: \n " + error);
+ throw new InvalidDataException(error, "");
+ }
+ }
+
+ // load script
+ ErrorInfo scriptErrors = (ErrorInfo)callScript(item, job);
+
+ if (scriptErrors.getFatal()) {
+ Logger.msg(3, "AgentProxy - fatal script error");
+ Logger.error(scriptErrors.getErrors());
+ throw new InvalidDataException("Fatal Script Error: \n"+scriptErrors.getErrors(), "");
+ }
+ if (scriptErrors.getErrors().length() > 0)
+ Logger.warning("Script errors: "+scriptErrors.getErrors());
+ } catch (ScriptingEngineException ex) {
+ Logger.error(ex);
+ throw new InvalidDataException(ex.getMessage(), "");
+ }
+ }
+
+ if (job.isOutcomeUsed()) {
+ Logger.msg(3, "AgentProxy - validating outcome");
+ String error = validator.validate(job.getOutcomeString());
+ if (error.length() > 0)
+ throw new InvalidDataException(error, "");
+ }
+
+ job.setAgentId(getSystemKey());
+ Logger.msg(3, "AgentProxy - submitting job to item proxy");
+ item.requestAction(job);
+ if (Logger.doLog(3)) {
+ Date timeNow = new Date();
+ long secsNow = (timeNow.getTime()-startTime.getTime())/1000;
+ Logger.msg(3, "Execution took "+secsNow+" seconds");
+ }
+ }
+
+ public Object callScript(ItemProxy item, Job job) throws ScriptingEngineException {
+ Script script = new Script(item, this, job);
+ return script.execute();
+ }
+
+ /**
+ * Standard execution of jobs. Note that this method should always be the one used from clients - all execution
+ * parameters are taken from the job where they're probably going to be correct.
+ *
+ * @param job
+ * @throws AccessRightsException
+ * @throws InvalidDataException
+ * @throws InvalidTransitionException
+ * @throws ObjectNotFoundException
+ * @throws PersistencyException
+ * @throws ObjectAlreadyExistsException
+ */
+ public void execute(Job job)
+ throws AccessRightsException,
+ InvalidDataException,
+ InvalidTransitionException,
+ ObjectNotFoundException,
+ PersistencyException,
+ ObjectAlreadyExistsException
+ {
+ try {
+ ItemProxy targetItem = (ItemProxy)Gateway.getProxyManager().getProxy(new EntityPath(job.getItemSysKey()));
+ execute(targetItem, job);
+ } catch (InvalidEntityPathException e) {
+ throw new ObjectNotFoundException("Job contained invalid item sysKey: "+job.getItemSysKey(), "");
+ }
+ }
+
+ public void execute(ItemProxy item, String predefStep, C2KLocalObject obj)
+ throws AccessRightsException,
+ InvalidDataException,
+ InvalidTransitionException,
+ ObjectNotFoundException,
+ PersistencyException,
+ ObjectAlreadyExistsException
+ {
+ String param;
+ try {
+ param = marshall(obj);
+ } catch (Exception ex) {
+ Logger.error(ex);
+ throw new InvalidDataException("Error on marshall", "");
+ }
+ execute(item, predefStep, param);
+ }
+
+ public void execute(ItemProxy item, String predefStep, String param)
+ throws AccessRightsException,
+ InvalidDataException,
+ InvalidTransitionException,
+ ObjectNotFoundException,
+ PersistencyException,
+ ObjectAlreadyExistsException
+ {
+ String[] params = new String[1];
+ params[0] = param;
+ execute(item, predefStep, params);
+ }
+
+ public void execute(ItemProxy item, String predefStep, String[] params)
+ throws AccessRightsException,
+ InvalidDataException,
+ InvalidTransitionException,
+ ObjectNotFoundException,
+ PersistencyException,
+ ObjectAlreadyExistsException
+ {
+ item.requestAction(getSystemKey(), "workflow/predefined/"+predefStep, Transitions.DONE, PredefinedStep.bundleData(params));
+ }
+
+ /** Wrappers for scripts */
+ public String marshall(Object obj) throws Exception {
+ return CastorXMLUtility.marshall(obj);
+ }
+
+ public Object unmarshall(String obj) throws Exception {
+ return CastorXMLUtility.unmarshall(obj);
+ }
+
+ /** Let scripts resolve items */
+ public ItemProxy searchItem(String name) throws ObjectNotFoundException {
+ Enumeration results = Gateway.getLDAPLookup().search(new DomainPath(""),name);
+
+ Path returnPath = null;
+ if (!results.hasMoreElements())
+ throw new ObjectNotFoundException(name, "");
+
+ while(results.hasMoreElements()) {
+ Path nextMatch = (Path)results.nextElement();
+ if (returnPath != null && nextMatch.getSysKey() != -1 && returnPath.getSysKey() != nextMatch.getSysKey())
+ throw new ObjectNotFoundException("Too many items with that name");
+ returnPath = nextMatch;
+ }
+
+ return (ItemProxy)Gateway.getProxyManager().getProxy(returnPath);
+ }
+
+ public ItemProxy getItem(String path) throws ObjectNotFoundException {
+ return (getItem(new DomainPath(path)));
+ }
+
+ public ItemProxy getItem(DomainPath path) throws ObjectNotFoundException {
+ return (ItemProxy)Gateway.getProxyManager().getProxy(path);
+ }
+
+ public ItemProxy getItemBySysKey(int sysKey) throws ObjectNotFoundException, InvalidEntityPathException {
+ return (ItemProxy)Gateway.getProxyManager().getProxy(new EntityPath(sysKey));
+ }
+}
diff --git a/source/com/c2kernel/entity/proxy/DomainPathSubscriber.java b/source/com/c2kernel/entity/proxy/DomainPathSubscriber.java
new file mode 100755
index 0000000..e09178d
--- /dev/null
+++ b/source/com/c2kernel/entity/proxy/DomainPathSubscriber.java
@@ -0,0 +1,18 @@
+package com.c2kernel.entity.proxy;
+
+import com.c2kernel.lookup.DomainPath;
+
+/**************************************************************************
+ *
+ * $Revision: 1.1 $
+ * $Date: 2004/02/05 16:11:57 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public interface DomainPathSubscriber {
+
+ public void pathAdded(DomainPath path);
+ public void pathRemoved(DomainPath path);
+}
diff --git a/source/com/c2kernel/entity/proxy/EntityProxy.java b/source/com/c2kernel/entity/proxy/EntityProxy.java
new file mode 100755
index 0000000..a5b6822
--- /dev/null
+++ b/source/com/c2kernel/entity/proxy/EntityProxy.java
@@ -0,0 +1,246 @@
+/**************************************************************************
+ * EntityProxy.java
+ *
+ * $Revision: 1.35 $
+ * $Date: 2005/05/10 11:40:09 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.entity.proxy;
+
+import java.util.*;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.*;
+import com.c2kernel.persistency.*;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.property.Property;
+import com.c2kernel.utils.*;
+
+
+/******************************************************************************
+* It is a wrapper for the connection and communication with Entities.
+* It can cache data loaded from the Entity to reduce communication with it.
+* This cache is syncronised with corresponding Entity through an event mechanism.
+*
+* @version $Revision: 1.35 $ $Date: 2005/05/10 11:40:09 $
+* @author $Author: abranson $
+******************************************************************************/
+
+abstract public class EntityProxy implements ManageableEntity
+{
+
+ protected ManageableEntity mEntity = null;
+ protected org.omg.CORBA.Object mIOR;
+ protected int mSystemKey;
+ private HashMap mSubscriptions;
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ protected EntityProxy( org.omg.CORBA.Object ior,
+ int systemKey)
+ throws ObjectNotFoundException
+ {
+ Logger.msg(8,"EntityProxy::EntityProxy() - Initialising '" +systemKey+ "' entity");
+
+ initialise( ior, systemKey);
+ }
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ private void initialise( org.omg.CORBA.Object ior,
+ int systemKey)
+ throws ObjectNotFoundException
+ {
+ Logger.msg(8, "EntityProxy::initialise() - Initialising '" +systemKey+ "' entity");
+
+ mIOR = ior;
+ mSystemKey = systemKey;
+ mSubscriptions = new HashMap();
+ }
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public ManageableEntity getEntity() throws ObjectNotFoundException
+ {
+ if (mEntity == null) {
+ mEntity = narrow();
+ }
+ return mEntity;
+ }
+
+ abstract public ManageableEntity narrow() throws ObjectNotFoundException;
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ //check who is using.. and if toString() is sufficient
+ public int getSystemKey()
+ {
+ return mSystemKey;
+ }
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public String queryData( String path )
+ throws ObjectNotFoundException
+ {
+
+ try {
+ Logger.msg(7, "EntityProxy.queryData() - "+mSystemKey+"/"+path);
+ if (path.endsWith("all")) {
+ Logger.msg(7, "EntityProxy.queryData() - listing contents");
+ String[] result = Gateway.getStorage().getClusterContents(mSystemKey, path.substring(0, path.length()-3));
+ StringBuffer retString = new StringBuffer();
+ for (int i = 0; i < result.length; i++) {
+ retString.append(result[i]);
+ if (i<result.length-1) retString.append(",");
+ }
+ Logger.msg(7, "EntityProxy.queryData() - "+retString.toString());
+ return retString.toString();
+ }
+ C2KLocalObject target = Gateway.getStorage().get(mSystemKey, path, null);
+ return CastorXMLUtility.marshall(target);
+ } catch (ObjectNotFoundException e) {
+ throw e;
+ } catch (Exception e) {
+ Logger.error(e);
+ return "<ERROR>"+e.getMessage()+"</ERROR>";
+ }
+ }
+
+ public String[] getContents( String path ) throws ObjectNotFoundException {
+ try {
+ return Gateway.getStorage().getClusterContents(mSystemKey, path.substring(0, path.length()));
+ } catch (ClusterStorageException e) {
+ throw new ObjectNotFoundException(e.toString());
+ }
+ }
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public C2KLocalObject getObject( String xpath )
+ throws ObjectNotFoundException
+ {
+ // load from storage, falling back to proxy loader if not found in others
+ try
+ {
+ return Gateway.getStorage().get( mSystemKey, xpath , this);
+ }
+ catch( ClusterStorageException ex )
+ {
+ Logger.msg(4, "Exception loading object :"+mSystemKey+"/"+xpath);
+ throw new ObjectNotFoundException( ex.toString() );
+ }
+ }
+
+
+
+ public String getProperty( String name )
+ throws ObjectNotFoundException
+ {
+ Logger.msg(5, "Get property "+name+" from syskey/"+mSystemKey);
+ Property prop = (Property)getObject("Property/"+name);
+ try
+ {
+ return prop.getValue();
+ }
+ catch (NullPointerException ex)
+ {
+ throw new ObjectNotFoundException();
+ }
+ }
+
+ public String getName()
+ {
+ try {
+ return getProperty("Name");
+ } catch (ObjectNotFoundException ex) {
+ return null;
+ }
+ }
+
+
+ /**************************************************************************
+ * Subscription methods
+ **************************************************************************/
+
+ public void subscribe (EntityProxyObserver observer,
+ String interest,
+ boolean preload)
+ {
+ MemberSubscription newSub = new MemberSubscription(this, interest, observer, preload);
+ synchronized (this){
+ mSubscriptions.put( newSub, observer );
+ }
+ new Thread(newSub).start();
+ Logger.msg(7, "Subscribed "+observer.getClass().getName()+" for "+interest);
+ }
+
+
+ public void unsubscribe(EntityProxyObserver observer)
+ {
+ synchronized (this){
+ for (Iterator e = mSubscriptions.keySet().iterator(); e.hasNext();) {
+ MemberSubscription thisSub = (MemberSubscription)e.next();
+ if (mSubscriptions.get( thisSub ) == observer) {
+ e.remove();
+ Logger.msg(7, "Unsubscribed "+observer.getClass().getName());
+ }
+ }
+ }
+ }
+
+ public void dumpSubscriptions(int logLevel) {
+ if (mSubscriptions.size() == 0) return;
+ Logger.msg(logLevel, "Subscriptions to proxy "+mSystemKey+":");
+ synchronized(this) {
+ for (Iterator iter = mSubscriptions.keySet().iterator(); iter.hasNext();) {
+ MemberSubscription element = (MemberSubscription)iter.next();
+ EntityProxyObserver obs = element.getObserver();
+ if (obs != null)
+ Logger.msg(logLevel, " "+element.getObserver().getClass().getName()+" subscribed to "+element.interest);
+ else
+ Logger.msg(logLevel, " Phantom subscription to "+element.interest);
+ }
+ }
+ }
+
+ public void notify(ProxyMessage message) {
+ Logger.msg(4, "EntityProxy.notify() - Received change notification for "+message.getPath()+" on "+mSystemKey);
+ synchronized (this){
+ if (!message.getServer().equals(EntityProxyManager.serverName))
+ Gateway.getStorage().clearCache(mSystemKey, message.getPath());
+ for (Iterator e = mSubscriptions.keySet().iterator(); e.hasNext();) {
+ MemberSubscription newSub = (MemberSubscription)e.next();
+ if (newSub.getObserver() == null) { // phantom
+ Logger.msg(4, "Removing phantom subscription to "+newSub.interest);
+ e.remove();
+ }
+ else
+ newSub.update(message.getPath(), message.getState());
+ }
+ }
+ }
+
+ /**
+ * If this is reaped, clear out the cache for it too.
+ */
+ protected void finalize() throws Throwable {
+ Logger.msg(7, "Proxy "+mSystemKey+" reaped");
+ Gateway.getStorage().clearCache(mSystemKey, null);
+ Gateway.getProxyManager().removeProxy(mSystemKey);
+ super.finalize();
+ }
+
+}
diff --git a/source/com/c2kernel/entity/proxy/EntityProxyManager.java b/source/com/c2kernel/entity/proxy/EntityProxyManager.java
new file mode 100755
index 0000000..386bc2c
--- /dev/null
+++ b/source/com/c2kernel/entity/proxy/EntityProxyManager.java
@@ -0,0 +1,341 @@
+/**************************************************************************
+ * EntityProxyFactory.java
+ *
+ * $Revision: 1.45 $
+ * $Date: 2005/05/10 11:40:09 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.entity.proxy;
+
+import java.util.*;
+
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.lookup.Path;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.property.Property;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.SoftCache;
+import com.c2kernel.utils.server.SimpleTCPIPServer;
+
+
+public class EntityProxyManager
+{
+ SoftCache proxyPool = new SoftCache(50);
+ HashMap treeSubscribers = new HashMap();
+ HashMap connections = new HashMap();
+
+ // server objects
+ static ArrayList proxyClients = new ArrayList();
+ static SimpleTCPIPServer proxyServer = null;
+ static String serverName = null;
+
+ /**
+ * Create an entity proxy manager to listen for proxy events and reap unused proxies
+ */
+ public EntityProxyManager()
+ {
+ Logger.msg(5, "EntityProxyManager - Starting.....");
+
+ Enumeration servers = Gateway.getLDAPLookup().searchEntities(new DomainPath("/servers"));
+ while(servers.hasMoreElements()) {
+ Path thisServerPath = (Path)servers.nextElement();
+ try {
+ int syskey = thisServerPath.getSysKey();
+ String remoteServer = ((Property)Gateway.getStorage().get(syskey, ClusterStorage.PROPERTY+"/Name", null)).getValue();
+ String portStr = ((Property)Gateway.getStorage().get(syskey, ClusterStorage.PROPERTY+"/ProxyPort", null)).getValue();
+ int remotePort = Integer.parseInt(portStr);
+ connectToProxyServer(remoteServer, remotePort);
+
+ } catch (Exception ex) {
+ Logger.error("Exception retrieving proxy server connection data for "+thisServerPath);
+ Logger.error(ex);
+ }
+ }
+ }
+
+ public void connectToProxyServer(String name, int port) {
+ ProxyServerConnection oldConn = (ProxyServerConnection)connections.get(name);
+ if (oldConn != null)
+ oldConn.shutdown();
+ connections.put(name, new ProxyServerConnection(name, port, this));
+ }
+
+
+ protected void resubscribe(ProxyServerConnection conn) {
+ synchronized (proxyPool) {
+ for (Iterator iter = proxyPool.keySet().iterator(); iter.hasNext();) {
+ Integer key = (Integer)iter.next();
+ ProxyMessage sub = new ProxyMessage(key.intValue(), ProxyMessage.ADDPATH, false);
+ Logger.msg(5, "Subscribing to entity "+key);
+ conn.sendMessage(sub);
+ }
+ }
+ }
+
+ /**
+ * @param sub
+ */
+ private void sendMessage(ProxyMessage sub) {
+ for (Iterator iter = connections.values().iterator(); iter.hasNext();) {
+ ProxyServerConnection element = (ProxyServerConnection) iter.next();
+ element.sendMessage(sub);
+ }
+
+ }
+
+ public void shutdown() {
+ Logger.msg("EntityProxyManager.shutdown() - flagging shutdown of server connections");
+ for (Iterator iter = connections.values().iterator(); iter.hasNext();) {
+ ProxyServerConnection element = (ProxyServerConnection) iter.next();
+ element.shutdown();
+ }
+ }
+
+ protected void processMessage(ProxyMessage thisMessage) throws InvalidDataException {
+ if (Logger.doLog(9)) Logger.msg(9, thisMessage.toString());
+
+ if (thisMessage.getPath().equals(ProxyMessage.PINGPATH)) // ping response
+ return;
+
+ if (thisMessage.getSysKey() == ProxyMessage.NA) // must be domain path info
+ informTreeSubscribers(thisMessage.getState(), thisMessage.getPath());
+ else {
+ // proper proxy message
+ Logger.msg(5, "Received proxy message: "+thisMessage.toString());
+ Integer key = new Integer(thisMessage.getSysKey());
+ EntityProxy relevant = (EntityProxy)proxyPool.get(key);
+ if (relevant == null)
+ Logger.warning("Received proxy message for sysKey "+thisMessage.getSysKey()+" which we don't have a proxy for.");
+ else
+ try {
+ relevant.notify(thisMessage);
+ } catch (Throwable ex) {
+ Logger.error("Error caught notifying proxy listener "+relevant.toString()+" of "+thisMessage.toString());
+ Logger.error(ex);
+ }
+ }
+ }
+
+ private void informTreeSubscribers(boolean state, String path) {
+ DomainPath last = new DomainPath(path);
+ DomainPath parent; boolean first = true;
+ synchronized(treeSubscribers) {
+ while((parent = last.getParent()) != null) {
+
+ for (Iterator iter = treeSubscribers.keySet().iterator(); iter.hasNext();) {
+ DomainPathSubscriber sub = (DomainPathSubscriber)iter.next();
+ DomainPath interest = (DomainPath)treeSubscribers.get(sub);
+ if (interest.equals(parent)) {
+ if (state == ProxyMessage.ADDED)
+ sub.pathAdded(last);
+ else if (first)
+ sub.pathRemoved(last);
+ }
+ }
+ last = parent;
+ first = false;
+ }
+ }
+ }
+
+ public void subscribeTree(DomainPathSubscriber sub, DomainPath interest) {
+ synchronized(treeSubscribers) {
+ treeSubscribers.put(sub, interest);
+ }
+ }
+
+ public void unsubscribeTree(DomainPathSubscriber sub) {
+ synchronized(treeSubscribers) {
+ treeSubscribers.remove(sub);
+ }
+ }
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ private EntityProxy createProxy( org.omg.CORBA.Object ior,
+ int systemKey,
+ boolean isItem )
+ throws ObjectNotFoundException
+ {
+
+ EntityProxy newProxy = null;
+
+ Logger.msg(5, "EntityProxyFactory::creating proxy on entity " + systemKey);
+
+ if( isItem )
+ {
+ newProxy = new ItemProxy(ior, systemKey);
+ }
+ else
+ {
+ newProxy = new AgentProxy(ior, systemKey);
+ }
+
+ // subscribe to changes from server
+ ProxyMessage sub = new ProxyMessage(systemKey, ProxyMessage.ADDPATH, false);
+ sendMessage(sub);
+ reportCurrentProxies(9);
+ return ( newProxy );
+ }
+
+ protected void removeProxy( int systemKey )
+ {
+ ProxyMessage sub = new ProxyMessage(systemKey, ProxyMessage.DELPATH, true);
+ Logger.msg(5,"EntityProxyManager.removeProxy() - Unsubscribing to proxy informer for "+systemKey);
+ sendMessage(sub);
+ }
+
+
+ /**************************************************************************
+ * EntityProxy getProxy( ManageableEntity, SystemKey)
+ *
+ * Called by the other GetProxy methods. Fills in either the ior or the
+ * SystemKey
+ **************************************************************************/
+ private EntityProxy getProxy( org.omg.CORBA.Object ior,
+ int systemKey,
+ boolean isItem )
+ throws ObjectNotFoundException
+ {
+ Integer key = new Integer(systemKey);
+
+ synchronized(proxyPool) {
+ EntityProxy newProxy;
+ // return it if it exists
+ newProxy = (EntityProxy)proxyPool.get(key);
+ if (newProxy == null) {
+ // create a new one
+ newProxy = createProxy(ior, systemKey, isItem );
+ proxyPool.put(key, newProxy);
+ }
+ return newProxy;
+
+ }
+ }
+
+ /**************************************************************************
+ * EntityProxy getProxy( String )
+ *
+ * Proxy from Alias
+ **************************************************************************/
+ public EntityProxy getProxy( Path path )
+ throws ObjectNotFoundException
+ {
+
+ //convert namePath to dn format
+ Logger.msg(8,"EntityProxyFactory::getProxy(" + path.toString() + ")");
+ boolean isItem = !(path.getEntity() instanceof AgentPath);
+ return getProxy( Gateway.getLDAPLookup().getIOR(path),
+ path.getSysKey(),
+ isItem );
+
+ }
+
+ /**************************************************************************
+ * void reportCurrentProxies()
+ *
+ * A utility to Dump the current proxies loaded
+ **************************************************************************/
+ public void reportCurrentProxies(int logLevel)
+ {
+ if (!Logger.doLog(logLevel)) return;
+ Logger.msg(logLevel, "Current proxies: ");
+ try {
+ synchronized(proxyPool) {
+ Iterator i = proxyPool.keySet().iterator();
+
+ for( int count=0; i.hasNext(); count++ )
+ {
+ Integer nextProxy = (Integer)i.next();
+ EntityProxy thisProxy = (EntityProxy)proxyPool.get(nextProxy);
+ if (thisProxy != null)
+ Logger.msg(logLevel,
+ "" + count + ": "
+ + proxyPool.get(nextProxy).getClass().getName()
+ + ": " + nextProxy);
+ }
+ }
+ } catch (ConcurrentModificationException ex) {
+ Logger.msg(logLevel, "Proxy cache modified. Aborting.");
+ }
+ }
+
+
+ /**************************************************************************
+ * Static Proxy Server methods
+ **************************************************************************/
+
+ /**
+ * Initialises the Proxy event UDP server listening on 'Host.Proxy.port' from c2kprops
+ * @param c2kProps
+ */
+ public static void initServer()
+ {
+ Logger.msg(5, "EntityProxyFactory::initServer - Starting.....");
+ String port = Gateway.getProperty("ItemServer.Proxy.port");
+ serverName = Gateway.getProperty("ItemServer.name");
+ if (port == null) {
+ Logger.error("ItemServer.Proxy.port not defined in connect file. Remote proxies will not be informed of entity changes.");
+ return;
+ }
+
+ // set up the proxy server
+ try {
+ int portNo = Integer.parseInt(port);
+ Logger.msg(5, "EntityProxyFactory::initServer - Initialising proxy informer on port "+port);
+ proxyServer = new SimpleTCPIPServer(portNo, ProxyClientConnection.class, 200);
+ proxyServer.startListening();
+ } catch (Exception ex) {
+ Logger.error("Error setting up Proxy Server. Remote proxies will not be informed of entity changes.");
+ Logger.error(ex);
+ }
+ }
+
+ public static void sendProxyEvent(ProxyMessage message) {
+ if (proxyServer != null && message.getPath() != null)
+ synchronized(proxyClients) {
+ for (Iterator iter = proxyClients.iterator(); iter.hasNext();) {
+ ProxyClientConnection client = (ProxyClientConnection)iter.next();
+ client.sendMessage(message);
+ }
+ }
+ }
+
+ public static void reportConnections(int logLevel) {
+ synchronized(proxyClients) {
+ Logger.msg(logLevel, "Currently connected proxy clients:");
+ for (Iterator iter = proxyClients.iterator(); iter.hasNext();) {
+ ProxyClientConnection client = (ProxyClientConnection)iter.next();
+ Logger.msg(logLevel, " "+client);
+ }
+ }
+ }
+
+ public static void shutdownServer() {
+ if (proxyServer != null) {
+ Logger.msg(1, "EntityProxyManager: Closing Server.");
+ proxyServer.stopListening();
+ }
+ }
+
+ public static void registerProxyClient(ProxyClientConnection client) {
+ synchronized(proxyClients) {
+ proxyClients.add(client);
+ }
+ }
+
+ public static void unRegisterProxyClient(ProxyClientConnection client) {
+ synchronized(proxyClients) {
+ proxyClients.remove(client);
+ }
+ }
+}
+
diff --git a/source/com/c2kernel/entity/proxy/EntityProxyObserver.java b/source/com/c2kernel/entity/proxy/EntityProxyObserver.java
new file mode 100755
index 0000000..985143d
--- /dev/null
+++ b/source/com/c2kernel/entity/proxy/EntityProxyObserver.java
@@ -0,0 +1,25 @@
+package com.c2kernel.entity.proxy;
+
+import com.c2kernel.entity.C2KLocalObject;
+
+
+
+public interface EntityProxyObserver
+{
+ /**************************************************************************
+ * Subscribed items are broken apart and fed one by one to these methods.
+ * Replacement after an event is done by feeding the new memberbase with the same id.
+ * ID could be an XPath?
+ **************************************************************************/
+ public void add(C2KLocalObject contents);
+
+ /**************************************************************************
+ * the 'type' parameter should be an indication of the type of object
+ * supplied so that the subscriber can associate the call back with
+ * one of its subscriptions. If we go with an Xpath subscription form,
+ * then the id will probably be sufficient.
+ * Should be comparable (substring whatever) with the parameter given to
+ * the subscribe method of ItemProxy.
+ **************************************************************************/
+ public void remove(String id);
+}
diff --git a/source/com/c2kernel/entity/proxy/ItemProxy.java b/source/com/c2kernel/entity/proxy/ItemProxy.java
new file mode 100755
index 0000000..e816a53
--- /dev/null
+++ b/source/com/c2kernel/entity/proxy/ItemProxy.java
@@ -0,0 +1,212 @@
+/**************************************************************************
+ * ItemProxy.java
+ *
+ * $Revision: 1.25 $
+ * $Date: 2005/05/10 11:40:09 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.entity.proxy;
+
+import java.util.ArrayList;
+
+import com.c2kernel.common.AccessRightsException;
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.InvalidTransitionException;
+import com.c2kernel.common.ObjectAlreadyExistsException;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.common.PersistencyException;
+import com.c2kernel.entity.*;
+import com.c2kernel.entity.agent.Job;
+import com.c2kernel.entity.agent.JobArrayList;
+import com.c2kernel.lifecycle.instance.stateMachine.Transitions;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.Logger;
+
+/******************************************************************************
+ * It is a wrapper for the connection and communication with Item
+ * It caches data loaded from the Item to reduce communication
+ *
+ * @version $Revision: 1.25 $ $Date: 2005/05/10 11:40:09 $
+ * @author $Author: abranson $
+ ******************************************************************************/
+public class ItemProxy extends EntityProxy
+{
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ protected ItemProxy( org.omg.CORBA.Object ior,
+ int systemKey)
+ throws ObjectNotFoundException
+ {
+ super(ior, systemKey);
+
+ }
+
+ public ManageableEntity narrow() throws ObjectNotFoundException
+ {
+ try {
+ return ItemHelper.narrow(mIOR);
+ } catch (org.omg.CORBA.BAD_PARAM ex) { }
+ throw new ObjectNotFoundException("CORBA Object was not an Item, or the server is down.");
+ }
+ /**************************************************************************
+ *
+ *
+ **************************************************************************/
+ public void initialise( int agentId,
+ String itemProps,
+ String workflow )
+ throws AccessRightsException,
+ InvalidDataException,
+ PersistencyException,
+ ObjectNotFoundException
+ {
+ Logger.msg(7, "ItemProxy::initialise - started");
+
+ ((Item)getEntity()).initialise( agentId, itemProps, workflow );
+ }
+
+ public void setProperty(AgentProxy agent, String name, String value)
+ throws AccessRightsException,
+ PersistencyException
+ {
+ String[] params = new String[2];
+ params[0] = name;
+ params[1] = value;
+ try {
+ agent.execute(this, "WriteProperty", params);
+ } catch (AccessRightsException e) {
+ throw (e);
+ } catch (PersistencyException e) {
+ throw (e);
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new PersistencyException("Could not store property");
+ }
+ }
+ /**************************************************************************
+ *
+ **************************************************************************/
+ protected void requestAction( Job thisJob )
+ throws AccessRightsException,
+ InvalidTransitionException,
+ ObjectNotFoundException,
+ InvalidDataException,
+ PersistencyException,
+ ObjectAlreadyExistsException
+ {
+ String outcome = thisJob.getOutcomeString();
+ // check fields that should have been filled in
+ if (outcome==null)
+ if (thisJob.isOutcomeUsed())
+ throw new InvalidDataException("Outcome is required.", "");
+ else
+ outcome="";
+
+ if (thisJob.getAgentId() == -1)
+ throw new InvalidDataException("No Agent specified.", "");
+
+ Logger.msg(7, "ItemProxy - executing "+thisJob.getStepPath()+" for "+thisJob.getAgentName());
+ requestAction (thisJob.getAgentId(), thisJob.getStepPath(),
+ thisJob.getPossibleTransition(), outcome);
+ }
+
+ //requestData is xmlString
+ public void requestAction( int agentId,
+ String stepPath,
+ int transitionID,
+ String requestData
+ )
+ throws AccessRightsException,
+ InvalidTransitionException,
+ ObjectNotFoundException,
+ InvalidDataException,
+ PersistencyException,
+ ObjectAlreadyExistsException
+ {
+ ((Item)getEntity()).requestAction( agentId,
+ stepPath,
+ transitionID,
+ requestData );
+ }
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public String queryLifeCycle( int agentId,
+ boolean filter
+ )
+ throws AccessRightsException,
+ ObjectNotFoundException,
+ PersistencyException
+ {
+ return ((Item)getEntity()).queryLifeCycle( agentId,
+ filter );
+ }
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ private ArrayList getJobList(int agentId, boolean filter)
+ throws AccessRightsException,
+ ObjectNotFoundException,
+ PersistencyException
+ {
+ JobArrayList thisJobList;
+ try {
+ String jobs = queryLifeCycle(agentId, filter);
+ thisJobList = (JobArrayList)CastorXMLUtility.unmarshall(jobs);
+ }
+ catch (Exception e) {
+ Logger.error("Exception::ItemProxy::getJobList() - Cannot unmarshall the jobs");
+ Logger.error(e);
+ return new ArrayList();
+ }
+ return thisJobList.list;
+ }
+
+ public ArrayList getJobList(AgentProxy agent)
+ throws AccessRightsException,
+ ObjectNotFoundException,
+ PersistencyException
+ {
+ return getJobList(agent.getSystemKey());
+ }
+
+ private ArrayList getJobList(int agentId)
+ throws AccessRightsException,
+ ObjectNotFoundException,
+ PersistencyException
+ {
+ return getJobList(agentId, true);
+ }
+
+ private Job getJobByName(String actName, int agentId)
+ throws AccessRightsException,
+ ObjectNotFoundException,
+ PersistencyException {
+
+ ArrayList jobList = getJobList(agentId);
+ for (Object jobObj : jobList) {
+ Job job = (Job)jobObj;
+ int transition = job.getPossibleTransition();
+ if (job.getStepName().equals(actName))
+ if (transition == Transitions.COMPLETE || transition == Transitions.DONE)
+ return job;
+ }
+ return null;
+
+ }
+
+ public Job getJobByName(String actName, AgentProxy agent)
+ throws AccessRightsException,
+ ObjectNotFoundException,
+ PersistencyException {
+ return getJobByName(actName, agent.getSystemKey());
+ }
+}
diff --git a/source/com/c2kernel/entity/proxy/MemberControl.java b/source/com/c2kernel/entity/proxy/MemberControl.java
new file mode 100755
index 0000000..5f483ae
--- /dev/null
+++ b/source/com/c2kernel/entity/proxy/MemberControl.java
@@ -0,0 +1,43 @@
+package com.c2kernel.entity.proxy;
+
+import com.c2kernel.entity.C2KLocalObject;
+
+
+/**
+ * @version $Revision: 1.2 $ $Date: 2004/02/04 11:02:44 $
+ * @author $Author: abranson $
+ */
+
+public class MemberControl implements C2KLocalObject {
+
+ public static final int ERROR = -1;
+ public static final int END = -2;
+ public static MemberControl theEND = new MemberControl(END, null);
+ private int id;
+ private String name;
+
+ public MemberControl(int code, String msg) {
+ this.setID(code);
+ switch (code) {
+ case MemberControl.ERROR:
+ this.setName("ERROR: The path "+msg+" was not found.");
+ break;
+ case MemberControl.END:
+ this.setName("END: End of preload");
+ break;
+ default:
+ this.setName("Unsupported control message code: "+code);
+ }
+ }
+
+ public String toString() {
+ return "MemberControl: "+this.getName();
+ }
+
+ public int getID() { return id; }
+ public void setID(int id) { this.id = id; }
+ public String getName() { return name; }
+ public void setName(String name) { this.name = name; }
+ public String getClusterType() { return null; }
+
+}
diff --git a/source/com/c2kernel/entity/proxy/MemberSubscription.java b/source/com/c2kernel/entity/proxy/MemberSubscription.java
new file mode 100755
index 0000000..fdd3e96
--- /dev/null
+++ b/source/com/c2kernel/entity/proxy/MemberSubscription.java
@@ -0,0 +1,121 @@
+
+package com.c2kernel.entity.proxy;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.utils.Logger;
+
+public class MemberSubscription implements Runnable {
+ EntityProxy subject;
+ String interest;
+ // keep the subscriber by weak reference, so it is not kept from the garbage collector if no longer used
+ WeakReference observerReference;
+ ArrayList contents = new ArrayList();
+ boolean preLoad;
+
+ public MemberSubscription(EntityProxy subject, String interest,
+ EntityProxyObserver observer, boolean preLoad) {
+ setObserver(observer);
+ this.interest = interest;
+ this.subject = subject;
+ this.preLoad = preLoad;
+ }
+
+ public void run() {
+ Thread.currentThread().setName("Member Subscription: "+subject.getSystemKey()+":"+interest);
+ if (preLoad) loadChildren();
+ }
+
+ private void loadChildren() {
+ C2KLocalObject newMember;
+ EntityProxyObserver observer = getObserver();
+ if (observer == null) return; //reaped
+ try {
+ // fetch contents of path
+ String children = subject.queryData(interest+"/all");
+ StringTokenizer tok = new StringTokenizer(children, ",");
+ ArrayList newContents = new ArrayList();
+ while (tok.hasMoreTokens())
+ newContents.add(tok.nextToken());
+
+ // look to see what's new
+ for (Iterator iter = newContents.iterator(); iter.hasNext();) {
+ String newChild = (String)iter.next();
+
+ // load child object
+ try {
+ newMember = subject.getObject(interest+"/"+newChild);
+ contents.remove(newChild);
+ } catch (ObjectNotFoundException ex) {
+ newMember = new MemberControl(MemberControl.ERROR, "Listed member "+newChild+" was not found.");
+ }
+ try {
+ observer.add(newMember);
+ } catch (Throwable ex) {
+ Logger.error("Error publishing member to "+observer);
+ Logger.error(ex);
+ }
+ }
+ // report what's left in old contents as deleted
+ for (Iterator iter = contents.iterator(); iter.hasNext();) {
+ String oldChild = (String)iter.next();
+ observer.remove(interest+"/"+oldChild);
+ }
+ //replace contents arraylist
+ contents = newContents;
+ //report that we're done
+ observer.add(MemberControl.theEND);
+ } catch (Exception ex) {
+ observer.add(new MemberControl(MemberControl.ERROR, "Query on "+interest+" failed with "+ex));
+ }
+ }
+
+ public boolean isRelevant(String path) {
+ Logger.msg(7, "Checking relevance of "+path+" to "+interest);
+ return (path.startsWith(interest));
+ }
+
+ public void update(String path, boolean deleted) {
+ EntityProxyObserver observer = getObserver();
+ if (observer == null) return; //reaped
+ Logger.msg(7, "Processing proxy message path "+path +" for "+observer+". Interest: "+interest+" Was Deleted:"+deleted);
+ if (!path.startsWith(interest)) // doesn't concern us
+ return;
+
+ if (path.equals(interest)) // refresh contents
+ loadChildren();
+ else {
+ String name = path.substring(interest.length());
+ if (deleted) {
+ Logger.msg(4, "Removing "+path);
+ contents.remove(name);
+ observer.remove(name);
+ }
+ else {
+ try {
+ C2KLocalObject newMember = subject.getObject(path);
+ Logger.msg(4, "Adding "+path);
+ contents.add(name);
+ observer.add(newMember);
+ } catch (ObjectNotFoundException e) {
+ Logger.error("Member Subscription: could not load "+path);
+ Logger.error(e);
+ }
+ }
+ }
+ }
+
+ public void setObserver(EntityProxyObserver observer) {
+ observerReference = new WeakReference(observer);
+ }
+
+ public EntityProxyObserver getObserver() {
+ EntityProxyObserver observer = (EntityProxyObserver)observerReference.get();
+ return observer;
+ }
+}
+
diff --git a/source/com/c2kernel/entity/proxy/ProxyClientConnection.java b/source/com/c2kernel/entity/proxy/ProxyClientConnection.java
new file mode 100755
index 0000000..46f1e3d
--- /dev/null
+++ b/source/com/c2kernel/entity/proxy/ProxyClientConnection.java
@@ -0,0 +1,179 @@
+package com.c2kernel.entity.proxy;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.InterruptedIOException;
+import java.io.PrintWriter;
+import java.net.Socket;
+import java.net.SocketException;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.server.SocketHandler;
+
+/**************************************************************************
+ *
+ * $Revision: 1.18 $
+ * $Date: 2005/05/10 11:40:09 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class ProxyClientConnection implements SocketHandler {
+
+ Socket clientSocket = null;
+ static int clientId = -1;
+ int thisClientId;
+ ArrayList sysKeys;
+ PrintWriter response;
+ BufferedReader request;
+ boolean closing = false;
+
+ public ProxyClientConnection() {
+ super();
+ thisClientId = ++clientId;
+ EntityProxyManager.registerProxyClient(this);
+ Logger.msg(1, "Proxy Client Connection Handler "+thisClientId+" ready.");
+ }
+
+
+ public String getName() {
+ return "Proxy Client Connection";
+ }
+
+ public boolean isBusy() {
+ return clientSocket != null;
+ }
+
+ public synchronized void setSocket(Socket newSocket) {
+ try {
+ Logger.msg(1, "Proxy Client Connection "+thisClientId+" connect from "+newSocket.getInetAddress()+":"+newSocket.getPort());
+ newSocket.setSoTimeout(500);
+ clientSocket = newSocket;
+ response = new PrintWriter(clientSocket.getOutputStream(), true);
+ sysKeys = new ArrayList();
+ } catch (SocketException ex) {
+ Logger.msg("Could not set socket timeout:");
+ Logger.error(ex);
+ closeSocket();
+ } catch (IOException ex) {
+ Logger.msg("Could not setup output stream:");
+ Logger.error(ex);
+ closeSocket();
+ }
+ }
+
+ /**
+ * Main loop. Reads proxy commands from the client and acts on them.
+ */
+ public void run() {
+ Thread.currentThread().setName("Proxy Client Connection: "+clientSocket.getInetAddress());
+ Logger.msg(7, "ProxyClientConnection "+thisClientId+" - Setting up proxy client connection with "+clientSocket.getInetAddress());
+ try {
+ request = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
+ String input = null;
+ ProxyMessage thisMessage;
+ while (clientSocket != null) {
+ try {
+ input = request.readLine();
+ Logger.msg(9, "ProxyClientConnection "+thisClientId+" - received "+input);
+ thisMessage = new ProxyMessage(input);
+ processMessage(thisMessage);
+ } catch (InterruptedIOException ex) { //timeout
+ } catch (InvalidDataException ex) { // invalid proxy message
+ Logger.error("ProxyClientConnection "+thisClientId+" - Invalid proxy message: "+input);
+ }
+
+ }
+ } catch (IOException ex) {
+ if (!closing)
+ Logger.error("ProxyClientConnection "+thisClientId+" - Error reading from socket.");
+ }
+ closeSocket();
+ Logger.msg(1, "ProxyClientConnection "+thisClientId+" closed.");
+ }
+
+ private void processMessage(ProxyMessage message) throws InvalidDataException {
+
+ // proxy disconnection
+ if (message.getPath().equals(ProxyMessage.BYEPATH)) {
+ Logger.msg(7, "ProxyClientConnection "+thisClientId+" disconnecting");
+ closeSocket();
+ }
+
+ // proxy checking connection
+ else if (message.getPath().equals(ProxyMessage.PINGPATH))
+ response.println(ProxyMessage.pingMessage);
+
+ // new subscription to entity changes
+ else if (message.getPath().equals(ProxyMessage.ADDPATH)) {
+ Logger.msg(7, "ProxyClientConnection "+thisClientId+" subscribed to "+message.getSysKey());
+ synchronized (sysKeys) {
+ sysKeys.add(new Integer(message.getSysKey()));
+ }
+ }
+
+ // remove of subscription to entity changes
+ else if (message.getPath().equals(ProxyMessage.DELPATH)) {
+ synchronized (sysKeys) {
+ sysKeys.remove(new Integer(message.getSysKey()));
+ }
+ Logger.msg(7, "ProxyClientConnection "+thisClientId+" unsubscribed from "+message.getSysKey());
+ }
+
+ else // unknown message
+ Logger.error("ProxyClientConnection "+thisClientId+" - Unknown message type: "+message);
+
+ }
+
+ public synchronized void sendMessage(ProxyMessage message) {
+ if (clientSocket==null) return; // idle
+ boolean relevant = message.getSysKey() == ProxyMessage.NA;
+ synchronized (sysKeys) {
+ for (Iterator iter = sysKeys.iterator(); iter.hasNext() && !relevant;) {
+ Integer thisKey = (Integer)iter.next();
+ if (thisKey.intValue() == message.getSysKey())
+ relevant = true;
+ }
+ }
+ if (!relevant) return; // not for our client
+
+ response.println(message);
+ }
+
+ public void shutdown() {
+ if (isBusy()) {
+ closing = true;
+ Logger.msg("ProxyClientConnection "+thisClientId+" closing.");
+ closeSocket();
+ }
+ }
+
+ public String toString() {
+ if (clientSocket == null) return thisClientId+": idle";
+ else return thisClientId+": "+clientSocket.getInetAddress();
+ }
+
+ private synchronized void closeSocket() {
+ if (clientSocket==null) return;
+ try {
+ request.close();
+ response.close();
+ clientSocket.close();
+ } catch (IOException e) {
+ Logger.error("ProxyClientConnection "+thisClientId+" - Could not close socket.");
+ Logger.error(e);
+ }
+ synchronized (sysKeys) {
+ sysKeys = null;
+ }
+
+ clientSocket = null;
+
+ }
+
+}
diff --git a/source/com/c2kernel/entity/proxy/ProxyMessage.java b/source/com/c2kernel/entity/proxy/ProxyMessage.java
new file mode 100755
index 0000000..66f1f34
--- /dev/null
+++ b/source/com/c2kernel/entity/proxy/ProxyMessage.java
@@ -0,0 +1,110 @@
+package com.c2kernel.entity.proxy;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.InetAddress;
+import java.util.StringTokenizer;
+
+import com.c2kernel.common.InvalidDataException;
+
+
+/**************************************************************************
+ *
+ * $Revision: 1.11 $
+ * $Date: 2005/05/10 11:40:09 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class ProxyMessage {
+
+ // special server message paths
+ public static final String BYEPATH = "bye";
+ public static final String ADDPATH = "add";
+ public static final String DELPATH = "del";
+ public static final String PINGPATH = "ping";
+ public static final boolean ADDED = false;
+ public static final boolean DELETED = true;
+ public static final int NA = -1;
+
+ static ProxyMessage byeMessage = new ProxyMessage(NA, BYEPATH, ADDED);
+ static ProxyMessage pingMessage = new ProxyMessage(NA, PINGPATH, ADDED);
+
+ private int sysKey = NA;
+ private String path = "";
+ private String server = null;
+ private boolean state = ADDED;
+
+ public ProxyMessage() {
+ super();
+ }
+ public ProxyMessage(int sysKey, String path, boolean state) {
+ this();
+ setSysKey(sysKey);
+ setPath(path);
+ setState(state);
+ }
+
+ public ProxyMessage(String line) throws InvalidDataException, IOException {
+ if (line == null)
+ throw new IOException("Null proxy message");
+ StringTokenizer tok = new StringTokenizer(line,":");
+ if (tok.countTokens()!=2)
+ throw new InvalidDataException("String '"+line+"' does not constitute a valid proxy message.", "");
+ sysKey = Integer.parseInt(tok.nextToken());
+ path = tok.nextToken();
+ if (path.startsWith("-")) {
+ state = DELETED;
+ path = path.substring(1);
+ }
+ }
+
+ public ProxyMessage(DatagramPacket packet) throws InvalidDataException, IOException {
+ this(new String(packet.getData()));
+ }
+
+ public int getSysKey() {
+ return sysKey;
+ }
+
+ public void setSysKey(int sysKey) {
+ this.sysKey = sysKey;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String newPath) {
+ this.path = newPath;
+ }
+
+ public boolean getState() {
+ return state;
+ }
+
+ public void setState(boolean state) {
+ this.state = state;
+ }
+
+ public String toString() {
+ return sysKey+":"+(state?"-":"")+path;
+ }
+ public DatagramPacket getPacket(ProxySubscriber host) {
+ return getPacket(host.getHost(), host.getPort());
+ }
+
+ public DatagramPacket getPacket(InetAddress host, int port) {
+ byte[] packetString = toString().getBytes();
+ return new DatagramPacket(packetString, packetString.length, host, port);
+ }
+
+ public String getServer() {
+ return server;
+ }
+
+ public void setServer(String server) {
+ this.server = server;
+ }
+}
diff --git a/source/com/c2kernel/entity/proxy/ProxyServerConnection.java b/source/com/c2kernel/entity/proxy/ProxyServerConnection.java
new file mode 100755
index 0000000..191492f
--- /dev/null
+++ b/source/com/c2kernel/entity/proxy/ProxyServerConnection.java
@@ -0,0 +1,129 @@
+/**************************************************************************
+ * EntityProxyFactory.java
+ *
+ * $Revision: 1.3 $
+ * $Date: 2005/05/25 12:11:44 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.entity.proxy;
+
+import java.io.*;
+import java.net.Socket;
+
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.utils.Logger;
+
+
+public class ProxyServerConnection extends Thread
+{
+
+ public boolean serverIsActive = true;
+ // proxy client details
+ String serverName;
+ int serverPort;
+ Socket serverConnection;
+ EntityProxyManager manager;
+ // for talking to the proxy server
+ PrintWriter serverStream;
+ boolean listening = false;
+ static boolean isServer = false;
+
+ /**
+ * Create an entity proxy manager to listen for proxy events and reap unused proxies
+ */
+ public ProxyServerConnection(String host, int port, EntityProxyManager manager)
+ {
+ Logger.msg(5, "ProxyServerConnection - Initialising connection to "+host+":"+port);
+ serverName = host;
+ serverPort = port;
+ this.manager = manager;
+ listening = true;
+ start();
+ }
+
+ public void run() {
+ Thread.currentThread().setName("Proxy Client Connection Listener to "+serverName+":"+serverPort);
+ while (listening) {
+ try {
+ if (serverConnection == null) connect();
+ if (serverConnection != null) {
+ BufferedReader request = new BufferedReader(new InputStreamReader(serverConnection.getInputStream()));
+ String input = null;
+ ProxyMessage thisMessage;
+ while (listening && serverConnection != null) {
+ try {
+ input = request.readLine();
+ thisMessage = new ProxyMessage(input);
+ thisMessage.setServer(serverName);
+ manager.processMessage(thisMessage);
+ } catch (InterruptedIOException ex) { // timeout - send a ping
+ sendMessage(ProxyMessage.pingMessage);
+ } catch (InvalidDataException ex) { // invalid proxy message
+ if (input != null)
+ Logger.error("EntityProxyManager - Invalid proxy message: "+input);
+ }
+ }
+ }
+ } catch (IOException ex) {
+ Logger.error("ProxyServerConnection - Disconnected from "+serverName+":"+serverPort);
+ try {
+ serverStream.close();
+ serverConnection.close();
+ } catch (IOException e1) { }
+
+
+ serverStream = null;
+ serverConnection = null;
+ }
+ }
+
+ if (serverStream != null) {
+ try {
+ Logger.msg(1, "Disconnecting from proxy server on "+serverName+":"+serverPort);
+ serverStream.println(ProxyMessage.byeMessage.toString());
+ serverStream.close();
+ serverConnection.close();
+ serverConnection = null;
+ } catch (Exception e) {
+ Logger.error("Error disconnecting from proxy server.");
+ }
+ }
+ }
+
+ public void connect() {
+ Logger.msg(3, "ProxyServerConnection - connecting to proxy server on "+serverName+":"+serverPort);
+ try {
+ serverConnection = new Socket(serverName, serverPort);
+ serverConnection.setKeepAlive(true);
+ serverIsActive = true;
+ serverConnection.setSoTimeout(5000);
+ serverStream = new PrintWriter(serverConnection.getOutputStream(), true);
+ Logger.msg("Connected to proxy server on "+serverName+":"+serverPort);
+ manager.resubscribe(this);
+ } catch (Exception e) {
+ Logger.msg(3, "Could not connect to proxy server. Retrying in 5s");
+ try { Thread.sleep(5000); } catch (InterruptedException ex) { }
+ serverStream = null;
+ serverConnection = null;
+ serverIsActive = false;
+ }
+ }
+
+ public void shutdown() {
+ Logger.msg("Proxy Client: flagging shutdown.");
+ listening = false;
+ }
+
+ /**
+ * @param sub
+ */
+ public void sendMessage(ProxyMessage sub) {
+ if (serverStream != null)
+ serverStream.println(sub);
+ }
+
+}
+
diff --git a/source/com/c2kernel/entity/proxy/ProxySubscriber.java b/source/com/c2kernel/entity/proxy/ProxySubscriber.java
new file mode 100755
index 0000000..67d0a60
--- /dev/null
+++ b/source/com/c2kernel/entity/proxy/ProxySubscriber.java
@@ -0,0 +1,36 @@
+package com.c2kernel.entity.proxy;
+
+import java.net.DatagramPacket;
+import java.net.InetAddress;
+import java.util.ArrayList;
+
+import com.c2kernel.common.InvalidDataException;
+
+/**************************************************************************
+ *
+ * $Revision: 1.1 $
+ * $Date: 2003/04/24 10:12:40 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class ProxySubscriber {
+
+ private InetAddress host;
+ private int port;
+ public ArrayList sysKeys = new ArrayList();
+
+ public ProxySubscriber(DatagramPacket packet) throws InvalidDataException {
+ host = packet.getAddress();
+ port = packet.getPort();
+ }
+
+ public InetAddress getHost() {
+ return host;
+ }
+
+ public int getPort() {
+ return port;
+ }
+}
diff --git a/source/com/c2kernel/entity/transfer/TransferItem.java b/source/com/c2kernel/entity/transfer/TransferItem.java
new file mode 100755
index 0000000..a869741
--- /dev/null
+++ b/source/com/c2kernel/entity/transfer/TransferItem.java
@@ -0,0 +1,131 @@
+package com.c2kernel.entity.transfer;
+
+import java.io.File;
+import java.util.*;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.*;
+import com.c2kernel.lifecycle.instance.Workflow;
+import com.c2kernel.lookup.*;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.persistency.outcome.Outcome;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.property.*;
+import com.c2kernel.utils.*;
+
+public class TransferItem {
+ public ArrayList domainPaths;
+ public int sysKey;
+ static int importAgentId;
+
+ public TransferItem() throws Exception {
+ try {
+ importAgentId = Gateway.getLDAPLookup().getRoleManager().getAgentPath("system").getSysKey();
+ } catch (ObjectNotFoundException e) {
+ Logger.error("TransferItem - System user not found!");
+ throw e;
+ }
+ }
+
+ public TransferItem(int sysKey) throws Exception {
+ this.sysKey = sysKey;
+ domainPaths = new ArrayList();
+ Property name = (Property)Gateway.getStorage().get(sysKey, ClusterStorage.PROPERTY + "/Name", null);
+ Enumeration paths = Gateway.getLDAPLookup().search(new DomainPath(), name.getValue());
+ while (paths.hasMoreElements()) {
+ DomainPath thisPath = (DomainPath)paths.nextElement();
+ domainPaths.add(thisPath.toString());
+ }
+ }
+
+ public void exportItem(File dir, String path) throws Exception {
+ Logger.msg("Path " + path + " in " + sysKey);
+ String[] contents = Gateway.getStorage().getClusterContents(sysKey, path);
+ if (contents.length > 0) {
+ FileStringUtility.createNewDir(dir.getCanonicalPath());
+ for (int i = 0; i < contents.length; i++) {
+ exportItem(new File(dir, contents[i]), path + "/" + contents[i]);
+ }
+ } else { //no children, try to dump object
+ try {
+ C2KLocalObject obj = Gateway.getStorage().get(sysKey, path, null);
+ Logger.msg("Dumping object " + path + " in " + sysKey);
+ File dumpPath = new File(dir.getCanonicalPath() + ".xml");
+ FileStringUtility.string2File(dumpPath, CastorXMLUtility.marshall(obj));
+ return;
+ } catch (ObjectNotFoundException ex) {
+ } // not an object
+ }
+ }
+
+ public void importItem(File dir) throws Exception {
+ // check if already exists
+ try {
+ Property name = (Property)Gateway.getStorage().get(sysKey, ClusterStorage.PROPERTY + "/Name", null);
+ throw new Exception("Syskey " + sysKey + " already in use as " + name.getValue());
+ } catch (Exception ex) {
+ }
+
+ ArrayList events, outcomes, viewpoints = new ArrayList();
+ // retrieve objects
+ ArrayList objectFiles = FileStringUtility.listDir(dir.getCanonicalPath(), false, true);
+ ArrayList objects = new ArrayList();
+ for (Iterator iter = objectFiles.iterator(); iter.hasNext();) {
+ String element = (String)iter.next();
+ String xmlFile = FileStringUtility.file2String(element);
+ C2KLocalObject newObj;
+ String choppedPath = element.substring(dir.getCanonicalPath().length()+1, element.length()-4);
+ Logger.msg(choppedPath);
+ if (choppedPath.startsWith(ClusterStorage.OUTCOME))
+ newObj = new Outcome(choppedPath, xmlFile);
+ else
+ newObj = (C2KLocalObject)CastorXMLUtility.unmarshall(xmlFile);
+
+ objects.add(newObj);
+ }
+
+ // create item
+ EntityPath entityPath = new EntityPath(sysKey);
+ TraceableEntity newItem = (TraceableEntity)Gateway.getCorbaServer().createEntity(entityPath);
+ Gateway.getLDAPLookup().add(entityPath);
+
+ PropertyArrayList props = new PropertyArrayList();
+ Workflow wf = null;
+ // put objects
+ for (Iterator iter = objects.iterator(); iter.hasNext();) {
+ C2KLocalObject obj = (C2KLocalObject)iter.next();
+ if (obj instanceof Property)
+ props.list.add(obj);
+ else if (obj instanceof Workflow)
+ wf = (Workflow)obj;
+ }
+
+ if (wf == null)
+ throw new Exception("No workflow found in import for "+sysKey);
+
+ // init item
+ newItem.initialise(importAgentId, CastorXMLUtility.marshall(props), CastorXMLUtility.marshall(wf.search("workflow/domain")));
+
+ // store objects
+ importByType(ClusterStorage.COLLECTION, objects);
+ importByType(ClusterStorage.HISTORY, objects);
+ importByType(ClusterStorage.OUTCOME, objects);
+ importByType(ClusterStorage.VIEWPOINT, objects);
+ Gateway.getStorage().commit(this);
+ // add domPaths
+ for (Iterator iter = domainPaths.iterator(); iter.hasNext();) {
+ String element = (String)iter.next();
+ DomainPath newPath = new DomainPath(element, entityPath);
+ Gateway.getLDAPLookup().add(newPath);
+ }
+ }
+
+ private void importByType(String type, ArrayList objects) throws Exception {
+ for (Iterator iter = objects.iterator(); iter.hasNext();) {
+ C2KLocalObject element = (C2KLocalObject)iter.next();
+ if (element.getClusterType().equals(type))
+ Gateway.getStorage().put(sysKey, element, this);
+ }
+
+ }
+} \ No newline at end of file
diff --git a/source/com/c2kernel/entity/transfer/TransferSet.java b/source/com/c2kernel/entity/transfer/TransferSet.java
new file mode 100755
index 0000000..ee98f8d
--- /dev/null
+++ b/source/com/c2kernel/entity/transfer/TransferSet.java
@@ -0,0 +1,107 @@
+package com.c2kernel.entity.transfer;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.lookup.NextKeyManager;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.FileStringUtility;
+import com.c2kernel.utils.Logger;
+
+/**************************************************************************
+ *
+ * $Revision: 1.5 $
+ * $Date: 2005/04/26 06:48:13 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class TransferSet {
+
+ public ArrayList items;
+
+ public TransferSet() {
+ }
+
+ public TransferSet(int[] sysKeys) {
+ items = new ArrayList();
+ for (int i = 0; i < sysKeys.length; i++) {
+ try {
+ items.add(new TransferItem(sysKeys[i]));
+ } catch (Exception ex) {
+ Logger.error("Could not add item "+sysKeys[i]);
+ Logger.error(ex);
+ }
+ }
+ }
+
+ public void exportPackage(File dir) throws Exception {
+ if (items==null || items.size() == 0)
+ throw new Exception("Nothing to dump");
+ FileStringUtility.createNewDir(dir.getAbsolutePath());
+ for (Iterator iter = items.iterator(); iter.hasNext();) {
+ TransferItem element = (TransferItem)iter.next();
+ try {
+ element.exportItem(new File(dir, String.valueOf(element.sysKey)), "/");
+ } catch (Exception ex) {
+ Logger.error("Error dumping item "+element.sysKey);
+ Logger.error(ex);
+ }
+ }
+
+ try {
+ String self = CastorXMLUtility.marshall(this);
+ FileStringUtility.string2File(new File(dir, "transferSet.xml"), self);
+ } catch (Exception ex) {
+ Logger.error("Error writing header file");
+ Logger.error(ex);
+ }
+ }
+
+ public void importPackage(File rootDir) {
+ for (Iterator iter = items.iterator(); iter.hasNext();) {
+ TransferItem element = (TransferItem)iter.next();
+ Logger.msg(5, "Importing "+element.sysKey);
+ try {
+ element.importItem(new File(rootDir, String.valueOf(element.sysKey)));
+ } catch (Exception ex) {
+ Logger.error("Import of item "+element.sysKey+" failed. Rolling back");
+ Logger.error(ex);
+ Gateway.getStorage().abort(element);
+ }
+ }
+ checkLastKey();
+ }
+
+ private void checkLastKey()
+ {
+ // find highest key in out import set
+ int packageLastKey = 0;
+ for (Iterator iter = items.iterator(); iter.hasNext();) {
+ TransferItem element = (TransferItem)iter.next();
+ if (element.sysKey > packageLastKey)
+ packageLastKey = element.sysKey;
+ }
+
+ try
+ { // find the current last key
+ NextKeyManager nextKeyMan = Gateway.getLDAPLookup().getNextKeyManager();
+ EntityPath lastKey = nextKeyMan.getLastEntityPath();
+ Logger.msg(1, "Last key imported was "+packageLastKey+". LDAP lastkey was "+lastKey.getSysKey());
+
+
+ if (packageLastKey > lastKey.getSysKey()) { // set new last
+ Logger.msg(1, "Updating lastKey to "+packageLastKey);
+ nextKeyMan.writeLastEntityKey(packageLastKey);
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.error("Exception::LoadKeys::processFile() " + ex);
+ }
+ }
+}
diff --git a/source/com/c2kernel/events/Event.java b/source/com/c2kernel/events/Event.java
new file mode 100755
index 0000000..e3ab8b3
--- /dev/null
+++ b/source/com/c2kernel/events/Event.java
@@ -0,0 +1,296 @@
+/*
+ * $Revision: 1.13 $
+ *
+ * $Date: 2004/11/22 09:12:28 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ */
+
+package com.c2kernel.events;
+
+import java.util.Calendar;
+
+import com.c2kernel.common.GTimeStamp;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.persistency.ClusterStorage;
+
+
+/**
+ * The data structure of events, which are passed over the event service.
+ *
+ * Events are incrementaly numbered objects maintained by the History.
+ *
+ * @version $Revision: 1.13 $ $Date: 2004/11/22 09:12:28 $
+ * @author $Author: abranson $
+ */
+public class Event implements C2KLocalObject
+{
+
+ int mID, mEntitySystemKey, mType, mCurrentState, mTransition;
+ String mName, mStepName, mStepPath, mStepType, mAgentName, mAgentCentre, mAgentRole;
+ GTimeStamp mTimeStamp;
+
+ public void setID( int id ) {
+ mID = id;
+ mName = String.valueOf(id);
+ }
+ /**
+ */
+ public void setEntitySystemKey( int systemKey )
+ {
+ mEntitySystemKey = systemKey;
+ }
+
+
+ /**
+ * Set the Event Type, in parameter is an integer.
+ */
+ public void setType(int type)
+ {
+ mType = type;
+ }
+
+ /**
+ * Set the Event Name, in parameter is a String
+ */
+ public void setName(String name)
+ {
+ mName = name;
+ try {
+ mID = Integer.parseInt(name);
+ } catch (NumberFormatException ex) {
+ mID = -1;
+ }
+ }
+
+ /**
+ * Set the StepPath of the Event, in parameter is a String
+ */
+ public void setStepName(String name)
+ {
+ mStepName = name;
+ }
+
+ /**
+ * Set the StepPath of the Event, in parameter is a String
+ */
+ public void setStepPath(String path)
+ {
+ mStepPath = path;
+ }
+
+ /**
+ * Set the StepType of the Event, in parameter is a String
+ */
+ public void setStepType(String type)
+ {
+ mStepType = type;
+ }
+
+ public void setCurrentState(int state)
+ {
+ mCurrentState = state;
+ }
+
+ /**
+ * Set the AgentInfo in the Event, in parameter is an AgentInfo
+ */
+ public void setAgentName(String agentName)
+ {
+ mAgentName = agentName;
+ }
+
+ public void setAgentCentre(String agentCentre)
+ {
+ mAgentCentre = agentCentre;
+ }
+
+ public void setAgentRole(String agentRole)
+ {
+ mAgentRole = agentRole;
+ }
+
+ /**
+ * Set the TimeStamp in the Event, in parameter is an GTimeStamp
+ */
+ public void setTimeStamp(GTimeStamp inTimeStamp)
+ {
+ mTimeStamp = inTimeStamp;
+ }
+
+
+ /**
+ * Return the Event's ID
+ */
+ public int getID()
+ {
+ return mID;
+ }
+
+ /**
+ */
+ public int getEntitySystemKey()
+ {
+ return mEntitySystemKey;
+ }
+
+ /**
+ * Return the Event Type
+ */
+ public int getType()
+ {
+ return mType;
+ }
+
+ /**
+ * Return the Event Name
+ */
+ public String getName()
+ {
+ return mName;
+ }
+
+ /**
+ * Return the StepPath of the Event.
+ */
+ public String getStepName()
+ {
+ return mStepName;
+ }
+
+ /**
+ * Return the StepPath of the Event.
+ */
+ public String getStepPath()
+ {
+ return mStepPath;
+ }
+
+ /**
+ * Return the StepPath of the Event.
+ */
+ public String getStepType()
+ {
+ return mStepType;
+ }
+
+ public int getCurrentState()
+ {
+ return mCurrentState;
+ }
+
+ /**
+ * Return the AgentInfo of the Event.
+ */
+ public String getAgentName()
+ {
+ if (mAgentCentre != null)
+ return mAgentCentre+"/"+mAgentName;
+ return mAgentName;
+ }
+
+ public String getAgentRole()
+ {
+ return mAgentRole;
+ }
+
+ /**
+ * Return the Event's TimeStamp.
+ */
+ public GTimeStamp getTimeStamp()
+ {
+ return mTimeStamp;
+ }
+
+ /**
+ * Return the TimeStamp in a form that will
+ * convert nicely to a String
+ * YYYY-MM-DD HH:MI:SS
+ */
+ public String getTimeString()
+ {
+ return Event.timeToString(mTimeStamp);
+ }
+
+ public static String timeToString(GTimeStamp timeStamp) {
+ StringBuffer time = new StringBuffer().append(timeStamp.mYear).append("-");
+
+ if (timeStamp.mMonth<10) time.append("0");
+ time.append(timeStamp.mMonth).append("-");
+
+ if (timeStamp.mDay<10) time.append("0");
+ time.append(timeStamp.mDay).append(" ");
+
+ if (timeStamp.mHour<10) time.append("0");
+ time.append(timeStamp.mHour).append(":");
+
+ if (timeStamp.mMinute<10) time.append("0");
+ time.append(timeStamp.mMinute).append(":");
+
+ if (timeStamp.mSecond<10) time.append("0");
+ time.append(timeStamp.mSecond);
+
+ return time.toString();
+ }
+
+ public void setTimeString(String time) throws Exception
+ {
+ if (time.length() == 19)
+ mTimeStamp = new GTimeStamp(
+ Integer.parseInt(time.substring(0,4)),
+ Integer.parseInt(time.substring(5,7)),
+ Integer.parseInt(time.substring(8,10)),
+ Integer.parseInt(time.substring(11,13)),
+ Integer.parseInt(time.substring(14,16)),
+ Integer.parseInt(time.substring(17,19)),
+ Calendar.getInstance().get(Calendar.ZONE_OFFSET));
+ else if (time.length() == 14) // support for some sql formats
+ mTimeStamp = new GTimeStamp(
+ Integer.parseInt(time.substring(0,4)),
+ Integer.parseInt(time.substring(4,6)),
+ Integer.parseInt(time.substring(6,8)),
+ Integer.parseInt(time.substring(8,10)),
+ Integer.parseInt(time.substring(10,12)),
+ Integer.parseInt(time.substring(12,14)),
+ Calendar.getInstance().get(Calendar.ZONE_OFFSET));
+ else
+ throw new Exception("Unknown time format: "+time);
+ }
+
+
+
+ static public GTimeStamp getGMT()
+ {
+ java.util.Calendar now = Calendar.getInstance();
+
+ return new GTimeStamp( now.get(Calendar.YEAR),
+ now.get(Calendar.MONTH)+1,
+ now.get(Calendar.DAY_OF_MONTH),
+ now.get(Calendar.HOUR_OF_DAY),
+ now.get(Calendar.MINUTE),
+ now.get(Calendar.SECOND),
+ now.get(Calendar.ZONE_OFFSET) );
+ }
+ /**
+ * @see com.c2kernel.entity.C2KLocalObject#getClusterType()
+ */
+ public String getClusterType() {
+ return ClusterStorage.HISTORY;
+ }
+
+ /**
+ * @return
+ */
+ public int getTransition() {
+ return mTransition;
+ }
+
+ /**
+ * @param i
+ */
+ public void setTransition(int i) {
+ mTransition = i;
+ }
+
+}
diff --git a/source/com/c2kernel/events/History.java b/source/com/c2kernel/events/History.java
new file mode 100755
index 0000000..bc806dd
--- /dev/null
+++ b/source/com/c2kernel/events/History.java
@@ -0,0 +1,94 @@
+package com.c2kernel.events;
+
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.lookup.InvalidEntityPathException;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.persistency.RemoteMap;
+import com.c2kernel.utils.Logger;
+
+/**
+ * @author Andrew Branson
+ *
+ * $Revision: 1.20 $
+ * $Date: 2004/07/21 09:55:11 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ */
+
+public class History extends RemoteMap {
+
+ int lastID = -1;
+
+ public History(int sysKey, Object locker)
+ throws ObjectNotFoundException, InvalidEntityPathException {
+ super(sysKey, ClusterStorage.HISTORY, locker);
+ }
+
+ public Event addEvent(String agentName, String agentRole,
+ int stepTransitionId,
+ String stepName,
+ String stepPath,
+ String stepType,
+ int stepCurrentState) {
+ Logger.msg(7, "History.addEvent() - creating new event for "+stepTransitionId+" on "+stepName+" in "+mSysKey);
+ Event newEvent = new Event();
+ newEvent.setEntitySystemKey(mSysKey);
+ newEvent.setAgentName(agentName);
+ newEvent.setAgentRole(agentRole);
+ newEvent.setTransition(stepTransitionId);
+ newEvent.setStepName(stepName);
+ newEvent.setStepPath(stepPath);
+ newEvent.setStepType(stepType);
+ newEvent.setCurrentState(stepCurrentState);
+ newEvent.setTimeStamp(Event.getGMT());
+ return storeNewEvent(newEvent);
+ }
+
+ public Event addEvent(String agentName, String agentRole,
+ int stepTransitionId,
+ String stepName,
+ String stepPath,
+ String stepType,
+ int stepCurrentState,
+ String timeString) throws Exception {
+ Logger.msg(7, "History.addEvent() - creating new event for "+stepTransitionId+" on "+stepName+" in "+mSysKey);
+ Event newEvent = new Event();
+ newEvent.setEntitySystemKey(mSysKey);
+ newEvent.setAgentName(agentName);
+ newEvent.setAgentRole(agentRole);
+ newEvent.setTransition(stepTransitionId);
+ newEvent.setStepName(stepName);
+ newEvent.setStepPath(stepPath);
+ newEvent.setStepType(stepType);
+ newEvent.setCurrentState(stepCurrentState);
+ newEvent.setTimeString(timeString);
+ return storeNewEvent(newEvent);
+ }
+
+ private Event storeNewEvent(Event newEvent) {
+ synchronized (this) {
+ int newEventID = getLastId()+1;
+ newEvent.setID(newEventID);
+ if (put(newEvent.getName(), newEvent) != null) {
+ lastID = newEventID;
+ return newEvent;
+ }
+ else {
+ Logger.error("History.addEvent() - Event storage failed!");
+ return null;
+ }
+ }
+ }
+
+ public Event getEvent(int id) {
+ return (Event)get(String.valueOf(id));
+ }
+
+ public Object remove(Object key) {
+ // forbidden
+ return null;
+ }
+
+}
diff --git a/source/com/c2kernel/graph/controller/AutoScrollController.java b/source/com/c2kernel/graph/controller/AutoScrollController.java
new file mode 100755
index 0000000..d1e0d8d
--- /dev/null
+++ b/source/com/c2kernel/graph/controller/AutoScrollController.java
@@ -0,0 +1,39 @@
+package com.c2kernel.graph.controller;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionListener;
+
+import com.c2kernel.graph.view.GraphPanel;
+
+
+public class AutoScrollController implements MouseMotionListener
+{
+ private GraphPanel mGraphPanel = null;
+
+
+ public void setGraphPanel(GraphPanel graphPanel)
+ {
+ mGraphPanel = graphPanel;
+ mGraphPanel.addMouseMotionListener(this);
+ }
+
+
+ public void mouseDragged(MouseEvent me)
+ {
+ Point mousePoint = null;
+
+
+ if(mGraphPanel != null)
+ {
+ mousePoint = me.getPoint();
+ mGraphPanel.scrollRectToVisible(new Rectangle(mousePoint.x, mousePoint.y, 1, 1));
+ }
+ }
+
+
+ public void mouseMoved(MouseEvent me)
+ {
+ }
+}
diff --git a/source/com/c2kernel/graph/controller/DeletionController.java b/source/com/c2kernel/graph/controller/DeletionController.java
new file mode 100755
index 0000000..38e8347
--- /dev/null
+++ b/source/com/c2kernel/graph/controller/DeletionController.java
@@ -0,0 +1,89 @@
+package com.c2kernel.graph.controller;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.util.Observable;
+import java.util.Observer;
+
+import javax.swing.JButton;
+
+import com.c2kernel.graph.event.SelectionChangedEvent;
+import com.c2kernel.graph.model.DirectedEdge;
+import com.c2kernel.graph.model.GraphModelManager;
+import com.c2kernel.graph.model.Vertex;
+
+
+// The deletion controller is responsible for deleting the present
+// selection within the graph.
+//
+// The controller listens to:
+// * The graph model to determine if there is a selection
+// * The delete button
+// * The graph panel for the typing of the delete key
+//
+// The controller modifies:
+// * The graph model to delete the current selection
+// * The delete button to enable it only when there is a selection
+public class DeletionController extends KeyAdapter implements Observer, ActionListener
+{
+ private GraphModelManager mGraphModelManager = null;
+ private JButton mDeleteButton = null;
+
+
+ public void setGraphModelManager(GraphModelManager graphModelManager)
+ {
+ mGraphModelManager = graphModelManager;
+ mGraphModelManager.addObserver(this);
+ }
+
+
+ public void setDeleteButton(JButton deleteButton)
+ {
+ mDeleteButton = deleteButton;
+ mDeleteButton.addActionListener(this);
+ }
+
+
+ // Invoked by the graph model
+ public void update(Observable o, Object arg)
+ {
+ SelectionChangedEvent event = null;
+ DirectedEdge selectedEdge = null;
+ Vertex[] selectedVertices = null;
+
+
+ // If the selected edge has changed
+ if(arg instanceof SelectionChangedEvent && mDeleteButton != null && mGraphModelManager.isEditable())
+ {
+ // Enable the button if a single edge or single vertex is selected
+ event = (SelectionChangedEvent)arg;
+
+ selectedEdge = event.mSelection.mEdge;
+ selectedVertices = event.mSelection.mVertices;
+
+ mDeleteButton.setEnabled((selectedEdge != null) || (selectedVertices != null));
+ }
+ }
+
+
+ // Invoked by the graph panel
+ public void keyPressed(KeyEvent e)
+ {
+ if(e.getKeyCode() == KeyEvent.VK_DELETE && mGraphModelManager.isEditable())
+ {
+ mGraphModelManager.getModel().deleteSelection();
+ }
+ }
+
+
+ // Invoked by the delete button
+ public void actionPerformed(ActionEvent ae)
+ {
+ if(mGraphModelManager != null && mGraphModelManager.isEditable())
+ {
+ mGraphModelManager.getModel().deleteSelection();
+ }
+ }
+}
diff --git a/source/com/c2kernel/graph/controller/EdgeConstructionController.java b/source/com/c2kernel/graph/controller/EdgeConstructionController.java
new file mode 100755
index 0000000..fdf52bf
--- /dev/null
+++ b/source/com/c2kernel/graph/controller/EdgeConstructionController.java
@@ -0,0 +1,244 @@
+package com.c2kernel.graph.controller;
+
+import java.awt.Point;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionListener;
+
+import com.c2kernel.graph.model.GraphModelManager;
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.graph.view.EditorModeListener;
+import com.c2kernel.graph.view.EditorToolBar;
+
+
+public class EdgeConstructionController extends MouseAdapter implements MouseMotionListener, EditorModeListener
+{
+ private GraphModelManager mGraphModelManager = null;
+ private EditorToolBar mEditorToolBar = null;
+
+
+ /**********/
+ /* States */
+ /**********/
+ private final Integer kOtherMode = new Integer(0);
+ private final Integer kWaitOrigin = new Integer(1);
+ private final Integer kWaitTerminus = new Integer(2);
+
+
+ /**********/
+ /* Events */
+ /**********/
+ private final int kEdgeEntered = 0;
+ private final int kOtherEntered = 1;
+ private final int kPressOnVertex = 2;
+ private final int kDrag = 3;
+ private final int kReleaseOnTerminus = 4;
+ private final int kReleaseOnNothing = 5;
+
+
+ /***********/
+ /* Actions */
+ /***********/
+
+ private interface Action
+ {
+ public void doIt(Object data);
+ }
+
+
+ private Action mSetOriginVertex = new Action()
+ {
+ public void doIt(Object data)
+ {
+ if(mGraphModelManager != null)
+ {
+ mGraphModelManager.getModel().setNewEdgeOriginVertex((Vertex)data);
+ }
+ }
+ };
+
+
+ private Action mSetEndPoint = new Action()
+ {
+ public void doIt(Object data)
+ {
+ if(mGraphModelManager != null)
+ {
+ mGraphModelManager.getModel().setNewEdgeEndPoint((Point)data);
+ }
+ }
+ };
+
+
+ private Action mClearEdge = new Action()
+ {
+ public void doIt(Object data)
+ {
+ if(mGraphModelManager != null)
+ {
+ mGraphModelManager.getModel().setNewEdgeOriginVertex(null);
+ mGraphModelManager.getModel().setNewEdgeEndPoint(null);
+ }
+ }
+ };
+
+
+ private Action mCreateEdge = new Action()
+ {
+ public void doIt(Object data)
+ {
+ if((mGraphModelManager != null) && (mEditorToolBar != null) && mGraphModelManager.isEditable())
+ {
+ mGraphModelManager.getModel().createDirectedEdge
+ (
+ mGraphModelManager.getModel().getNewEdgeOriginVertex(),
+ (Vertex)data,
+ mEditorToolBar.getSelectedEdgeType()
+ );
+ mGraphModelManager.getModel().setNewEdgeOriginVertex(null);
+ mGraphModelManager.getModel().setNewEdgeEndPoint(null);
+ }
+ }
+ };
+
+
+ /***********************************/
+ /* Finite State Transition Network */
+ /***********************************/
+
+ private Object[][][] mFSTN =
+ {// OtherMode WaitOrigin WaitTerminus
+ /* EdgeEntered */ {{null, kWaitOrigin}, null , null },
+ /* OtherEntered */ { null , {null , kOtherMode} , null },
+ /* PressOnVertex */ { null , {mSetOriginVertex, kWaitTerminus}, null },
+ /* Drag */ { null , null , {mSetEndPoint, null} },
+ /* ReleaseOnTerminus */ { null , null , {mCreateEdge , kWaitOrigin}},
+ /* ReleaseOnNothing */ { null , null , {mClearEdge , kWaitOrigin}}
+ };
+
+
+ /*****************/
+ /* Current state */
+ /*****************/
+
+ private Integer mState = kOtherMode;
+
+
+ /**************************/
+ /* Event processing logic */
+ /**************************/
+
+ private void processEvent(int event, Object data)
+ {
+ Object[] transition = mFSTN[event][mState.intValue()];
+ Action action = null;
+ Integer nextState = null;
+
+ if(transition != null)
+ {
+ action = (Action)transition[0];
+ nextState = (Integer)transition[1];
+
+ if(action != null)
+ {
+ action.doIt(data);
+ }
+
+ if(nextState != null)
+ {
+ mState = nextState;
+ }
+ }
+ }
+
+
+ /********************/
+ /* Public interface */
+ /********************/
+
+ public void setGraphModelManager(GraphModelManager graphModelManager)
+ {
+ mGraphModelManager = graphModelManager;
+ }
+
+
+ public void setEditorToolBar(EditorToolBar editorToolBar)
+ {
+ mEditorToolBar = editorToolBar;
+ mEditorToolBar.addEditorModeListener(this);
+ }
+
+
+ public void editorModeChanged(String idOfNewMode)
+ {
+ if(idOfNewMode.equals("Edge"))
+ {
+ processEvent(kEdgeEntered, null);
+ }
+ else
+ {
+ processEvent(kOtherEntered, null);
+ }
+ }
+
+
+ public void mousePressed(MouseEvent me)
+ {
+ Vertex vertex = null;
+ Point mousePoint = null;
+
+ if(mGraphModelManager != null)
+ {
+ // Determine if there is a vertex under the mouse cursor
+ mousePoint = me.getPoint();
+ vertex = mGraphModelManager.getModel().getVertex(new GraphPoint(mousePoint.x, mousePoint.y));
+
+ // If the mouse has been pressed on a vertex
+ if(vertex != null)
+ {
+ processEvent(kPressOnVertex, vertex);
+ }
+ }
+ }
+
+
+ public void mouseReleased(MouseEvent me)
+ {
+ Vertex vertex = null;
+ Point mousePoint = null;
+
+ if(mGraphModelManager != null)
+ {
+ // Determine if there is a vertex under the mouse cursor
+ mousePoint = me.getPoint();
+ vertex = mGraphModelManager.getModel().getVertex(new GraphPoint(mousePoint.x, mousePoint.y));
+
+ // If the mouse has been released on a vertex which is not the origin vertex
+ if((vertex != null) && (vertex != mGraphModelManager.getModel().getNewEdgeOriginVertex()))
+ {
+ processEvent(kReleaseOnTerminus, vertex);
+ }
+ else
+ {
+ processEvent(kReleaseOnNothing, null);
+ }
+ }
+ }
+
+
+ public void mouseExited(MouseEvent me)
+ {
+ }
+
+
+ public void mouseDragged(MouseEvent me)
+ {
+ processEvent(kDrag, me.getPoint());
+ }
+
+
+ public void mouseMoved(MouseEvent me)
+ {
+ }
+}
diff --git a/source/com/c2kernel/graph/controller/MultiSelectionDragController.java b/source/com/c2kernel/graph/controller/MultiSelectionDragController.java
new file mode 100755
index 0000000..8e9a2b3
--- /dev/null
+++ b/source/com/c2kernel/graph/controller/MultiSelectionDragController.java
@@ -0,0 +1,551 @@
+package com.c2kernel.graph.controller;
+
+import java.awt.Point;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionListener;
+
+import com.c2kernel.graph.model.DirectedEdge;
+import com.c2kernel.graph.model.ElasticBand;
+import com.c2kernel.graph.model.GraphModelManager;
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.graph.model.GraphableVertex;
+import com.c2kernel.graph.model.Selection;
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.graph.view.EditorModeListener;
+
+
+public class MultiSelectionDragController
+extends MouseAdapter
+implements EditorModeListener, MouseMotionListener, KeyListener
+{
+ private class ResizeInf
+ {
+ public int mMousePressedX = 0;
+ public int mMousePressedY = 0;
+ public Vertex mSelectedVertex = null;
+ public GraphPoint[] mOldOutline = null;
+ public int mCentreX = 0;
+ public int mCentreY = 0;
+ public int mOldHeight = 0;
+ public int mOldWidth = 0;
+ }
+ private ResizeInf mResizeInf = new ResizeInf();
+
+ private class DispForSelection
+ {
+ public int mXDisp = 0;
+ public int mYDisp = 0;
+ }
+ private DispForSelection mDispForSelection = null;
+
+ private class VertexAndDisp
+ {
+ public Vertex mVertex = null;
+ public int mXDisp = 0;
+ public int mYDisp = 0;
+ }
+
+ protected GraphModelManager mGraphModelManager = null;
+
+
+ /**********/
+ /* States */
+ /**********/
+ protected final Integer kOtherMode = new Integer(0);
+ protected final Integer kWaiting = new Integer(1);
+ protected final Integer kResizing = new Integer(2);
+ protected final Integer kDraggingSelection = new Integer(3);
+ protected final Integer kStretching = new Integer(4);
+
+
+ /**********/
+ /* Events */
+ /**********/
+ protected final int kSelectEntered = 0;
+ protected final int kOtherEntered = 1;
+ protected final int kPressOnEdge = 2;
+ protected final int kPressOnVertex = 3;
+ protected final int kPressOnSelection = 4;
+ protected final int kPressOnResizePad = 5;
+ protected final int kCTRLPressOnVertex = 6;
+ protected final int kCTRL_A = 7;
+ protected final int kPressOnNothing = 8;
+ protected final int kDrag = 9;
+ protected final int kRelease = 10;
+ protected final int kZoomIn = 11;
+
+ /***********/
+ /* Actions */
+ /***********/
+
+ protected interface Action
+ {
+ public void doIt(Object data);
+ }
+
+
+ protected Action mStoreResizeInf = new Action()
+ {
+ public void doIt(Object data)
+ {
+ Point mousePoint = (Point)data;
+ GraphPoint centre = null;
+
+ mResizeInf.mMousePressedX = mousePoint.x;
+ mResizeInf.mMousePressedY = mousePoint.y;
+ mResizeInf.mSelectedVertex = mGraphModelManager.getModel().getSelection().mVertices[0];
+ mResizeInf.mOldOutline = mResizeInf.mSelectedVertex.getOutlinePoints();
+ centre = mResizeInf.mSelectedVertex.getCentrePoint();
+ mResizeInf.mCentreX = centre.x;
+ mResizeInf.mCentreY = centre.y;
+ mResizeInf.mOldHeight = mResizeInf.mSelectedVertex.getHeight();
+ mResizeInf.mOldWidth = mResizeInf.mSelectedVertex.getWidth();
+ }
+ };
+
+
+ protected Action mResizeVertex = new Action()
+ {
+ public void doIt(Object data)
+ {
+ Point mousePoint = (Point)data;
+ int resizeX = 0;
+ int resizeY = 0;
+
+
+ // Calculate how much the old outline should be resized
+ resizeX = mousePoint.x - mResizeInf.mMousePressedX;
+ resizeY = mousePoint.y - mResizeInf.mMousePressedY;
+
+ // Clip the resize so that outline does not get any
+ // smaller than 10 x 10 pixels
+ if(resizeX < -mResizeInf.mOldWidth/2 + 10)
+ {
+ resizeX = -mResizeInf.mOldWidth/2 + 10;
+ }
+
+ if(resizeY < -mResizeInf.mOldHeight/2 + 10)
+ {
+ resizeY = -mResizeInf.mOldHeight/2 + 10;
+ }
+
+ if (mGraphModelManager.isEditable()) {
+ mResizeInf.mSelectedVertex.setOutlinePoints(newOutline(resizeX, resizeY));
+ mGraphModelManager.forceNotify();
+ }
+ }
+
+
+ private GraphPoint[] newOutline(int resizeX, int resizeY)
+ {
+ GraphPoint[] newOutline = new GraphPoint[mResizeInf.mOldOutline.length];
+ int x = 0;
+ int y = 0;
+ int i = 0;
+
+
+ for(i=0; i<newOutline.length; i++)
+ {
+ if(mResizeInf.mOldOutline[i].x > mResizeInf.mCentreX)
+ {
+ x = mResizeInf.mOldOutline[i].x + resizeX;
+ }
+ else if(mResizeInf.mOldOutline[i].x < mResizeInf.mCentreX)
+ {
+ x = mResizeInf.mOldOutline[i].x - resizeX;
+ }
+ else
+ {
+ x = mResizeInf.mOldOutline[i].x;
+ }
+
+ if(mResizeInf.mOldOutline[i].y > mResizeInf.mCentreY)
+ {
+ y = mResizeInf.mOldOutline[i].y + resizeY;
+ }
+ else if(mResizeInf.mOldOutline[i].y < mResizeInf.mCentreY)
+ {
+ y = mResizeInf.mOldOutline[i].y - resizeY;
+ }
+ else
+ {
+ y = mResizeInf.mOldOutline[i].y;
+ }
+
+ newOutline[i] = new GraphPoint(x, y);
+ }
+
+ return newOutline;
+ }
+ };
+
+
+ protected Action mSelectEdge = new Action()
+ {
+ public void doIt(Object data)
+ {
+ Selection selection = new Selection((DirectedEdge)data, null, 0, 0, 0, 0);
+
+ mGraphModelManager.getModel().setSelection(selection);
+ }
+ };
+
+
+ protected Action mSelectVertexAndStoreDisp = new Action()
+ {
+ public void doIt(Object data)
+ {
+ VertexAndDisp vertexAndDisp = (VertexAndDisp)data;
+ GraphPoint centrePoint = vertexAndDisp.mVertex.getCentrePoint();
+ Selection selection = new Selection(null,
+ new Vertex[] {vertexAndDisp.mVertex},
+ centrePoint.x,
+ centrePoint.y,
+ centrePoint.x,
+ centrePoint.y);
+
+ mGraphModelManager.getModel().setSelection(selection);
+ mDispForSelection = new DispForSelection();
+ mDispForSelection.mXDisp = vertexAndDisp.mXDisp;
+ mDispForSelection.mYDisp = vertexAndDisp.mYDisp;
+ }
+ };
+
+
+ protected Action mStoreDisp = new Action()
+ {
+ public void doIt(Object data)
+ {
+ mDispForSelection = (DispForSelection)data;
+ }
+ };
+
+
+ protected Action mToggleVertex = new Action()
+ {
+ public void doIt(Object data)
+ {
+ Vertex vertex = (Vertex)data;
+
+ if(mGraphModelManager.getModel().inSelection(vertex))
+ {
+ mGraphModelManager.getModel().removeFromSelection(vertex);
+ }
+ else
+ {
+ mGraphModelManager.getModel().addToSelection(vertex);
+ }
+ }
+ };
+
+
+ protected Action mSelectAll = new Action()
+ {
+ public void doIt(Object data)
+ {
+ mGraphModelManager.getModel().selectAll();
+ }
+ };
+
+
+ protected Action mCreateBand = new Action()
+ {
+ public void doIt(Object data)
+ {
+ Point fixedCorner = (Point)data;
+
+ mGraphModelManager.getModel().setElasticBand(new ElasticBand(fixedCorner, fixedCorner));
+ }
+ };
+
+
+ protected Action mMoveSelection = new Action()
+ {
+ public void doIt(Object data)
+ {
+ Point mousePoint = (Point)data;
+ int topLeftX = mousePoint.x - mDispForSelection.mXDisp;
+ int topLeftY = mousePoint.y - mDispForSelection.mYDisp;
+ if (mGraphModelManager.isEditable()) {
+ mGraphModelManager.getModel().moveAbsoluteSelection(topLeftX, topLeftY);
+ }
+ }
+ };
+
+
+ protected Action mResizeBand = new Action()
+ {
+ public void doIt(Object data)
+ {
+ mGraphModelManager.getModel().resizeElasticBand((Point)data);
+ }
+ };
+
+
+ protected Action mSelectContents = new Action()
+ {
+ public void doIt(Object data)
+ {
+ mGraphModelManager.getModel().selectContentsOfElasticBand();
+ }
+ };
+
+ protected Action mZoomIn = new Action()
+ {
+ public void doIt(Object data) // data is the clicked vertex
+ {
+ // Need to get child graph model out of the vertex before we can zoom in
+ if (data instanceof Vertex) {
+ Vertex zoomTo = (Vertex)data;
+ if (((GraphableVertex)zoomTo).getIsComposite()) mGraphModelManager.zoomIn(zoomTo);
+ }
+ }
+ };
+
+ /***********************************/
+ /* Finite State Transition Network */
+ /***********************************/
+
+ protected Object[][][] mFSTN =
+ {// OtherMode Waiting Resizing DraggingSelection Stretching
+ /* SelectEntered */ {{null, kWaiting}, null , null , null , null },
+ /* OtherEntered */ { null , {null , kOtherMode }, null , null , null },
+ /* PressOnEdge */ { null , {mSelectEdge , null }, null , null , null },
+ /* PressOnVertex */ { null , {mSelectVertexAndStoreDisp, kDraggingSelection}, null , null , null },
+ /* PressOnSelection */ { null , {mStoreDisp , kDraggingSelection}, null , null , null },
+ /* PressOnResizePad */ { null , {mStoreResizeInf , kResizing }, null , null , null },
+ /* CTRLPressOnVertex */ { null , {mToggleVertex , null }, null , null , null },
+ /* CTRL_A */ { null , {mSelectAll , null }, null , null , null },
+ /* PressOnNothing */ { null , {mCreateBand , kStretching }, null , null , null },
+ /* Drag */ { null , null , {mResizeVertex, null }, {mMoveSelection, null }, {mResizeBand , null }},
+ /* Release */ { null , null , {null , kWaiting}, {null , kWaiting}, {mSelectContents, kWaiting}},
+ /* Double Click */ { null , {mZoomIn , null }, null , null , null },
+ };
+
+
+ /*****************/
+ /* Current state */
+ /*****************/
+
+ private Integer mState = kWaiting;
+
+
+ /**************************/
+ /* Event processing logic */
+ /**************************/
+
+ protected void processEvent(int event, Object data)
+ {
+ Object[] transition = mFSTN[event][mState.intValue()];
+ Action action = null;
+ Integer nextState = null;
+
+ if(transition != null)
+ {
+ action = (Action)transition[0];
+ nextState = (Integer)transition[1];
+
+ if(action != null)
+ {
+ action.doIt(data);
+ }
+
+ if(nextState != null)
+ {
+ mState = nextState;
+ }
+ }
+ }
+
+
+ /********************/
+ /* Public interface */
+ /********************/
+
+ public void setGraphModelManager(GraphModelManager graphModelManager)
+ {
+ mGraphModelManager = graphModelManager;
+ }
+
+
+ public void editorModeChanged(String idOfNewMode)
+ {
+ if(idOfNewMode.equals("Select"))
+ {
+ processEvent(kSelectEntered, null);
+ }
+ else
+ {
+ processEvent(kOtherEntered, null);
+ }
+ }
+
+
+ public void mousePressed(MouseEvent me)
+ {
+ int modifiers = me.getModifiers();
+
+ if(mGraphModelManager != null)
+ {
+ if((modifiers & InputEvent.CTRL_MASK) == 0)
+ {
+ mousePressedWithoutCTRL(me.getPoint());
+ }
+ else
+ {
+ mousePressedWithCTRL(me.getPoint());
+ }
+ }
+ }
+
+ public void mouseClicked(MouseEvent me)
+ {
+ if (me.getClickCount() == 2) { // want double click
+ Point clickedSpot = me.getPoint();
+ GraphPoint mouseGPoint = new GraphPoint(clickedSpot.x, clickedSpot.y);
+ Vertex clicked = mGraphModelManager.getModel().getVertex(mouseGPoint);
+ if (clicked != null)
+ processEvent(kZoomIn, clicked);
+ }
+ }
+
+ private void mousePressedWithoutCTRL(Point mousePoint)
+ {
+ GraphPoint mouseGPoint = new GraphPoint(mousePoint.x, mousePoint.y);
+ DirectedEdge edge = mGraphModelManager.getModel().getEdge(mouseGPoint);
+ Vertex vertex = mGraphModelManager.getModel().getVertex(mouseGPoint);
+ GraphPoint vertexCentrePoint = null;
+ VertexAndDisp vertexAndDisp = null;
+ Selection selection = null;
+ DispForSelection dispForSelection = null;
+
+
+ // In order of priority:
+ // 1. Click on resize pad
+ // 2. Click on vertex
+ // 3. Click on edge
+ if(onResizePad(mouseGPoint))
+ {
+ processEvent(kPressOnResizePad, mousePoint);
+ }
+ else if(vertex != null)
+ {
+ if(mGraphModelManager.getModel().inSelection(vertex))
+ {
+ selection = mGraphModelManager.getModel().getSelection();
+ dispForSelection = new DispForSelection();
+ dispForSelection.mXDisp = mousePoint.x - selection.mTopLeftX;
+ dispForSelection.mYDisp = mousePoint.y - selection.mTopLeftY;
+
+ processEvent(kPressOnSelection, dispForSelection);
+ }
+ else
+ {
+ vertexCentrePoint = vertex.getCentrePoint();
+
+ vertexAndDisp = new VertexAndDisp();
+ vertexAndDisp.mVertex = vertex;
+ vertexAndDisp.mXDisp = mousePoint.x - vertexCentrePoint.x;
+ vertexAndDisp.mYDisp = mousePoint.y - vertexCentrePoint.y;
+
+ processEvent(kPressOnVertex, vertexAndDisp);
+ }
+ }
+ // vertex == null
+ else
+ {
+ if(edge == null)
+ {
+ processEvent(kPressOnNothing, mousePoint);
+ }
+ else
+ {
+ processEvent(kPressOnEdge, edge);
+ }
+ }
+ }
+
+
+ private boolean onResizePad(GraphPoint mouseGPoint)
+ {
+ Selection selection = mGraphModelManager.getModel().getSelection();
+ GraphPoint vertexCentre = null;
+ int bottomRightX = 0;
+ int bottomRightY = 0;
+
+
+ if(selection.mVertices == null) return false;
+
+ if(selection.mVertices.length == 1)
+ {
+ vertexCentre = selection.mVertices[0].getCentrePoint();
+ if (vertexCentre == null) return false;
+ bottomRightX = vertexCentre.x + selection.mVertices[0].getWidth()/2;
+ bottomRightY = vertexCentre.y + selection.mVertices[0].getHeight()/2;
+
+ return
+ (
+ (mouseGPoint.x > bottomRightX) &&
+ (mouseGPoint.x < bottomRightX + 10) &&
+ (mouseGPoint.y > bottomRightY) &&
+ (mouseGPoint.y < bottomRightY + 10)
+ );
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+
+ private void mousePressedWithCTRL(Point mousePoint)
+ {
+ Vertex vertex = mGraphModelManager.getModel().getVertex(new GraphPoint(mousePoint.x, mousePoint.y));
+
+ if(vertex != null)
+ {
+ processEvent(kCTRLPressOnVertex, vertex);
+ }
+ }
+
+
+ public void mouseReleased(MouseEvent me)
+ {
+ processEvent(kRelease, null);
+ }
+
+
+ public void mouseMoved(MouseEvent me)
+ {
+ }
+
+
+ public void mouseDragged(MouseEvent e)
+ {
+ processEvent(kDrag, e.getPoint());
+ }
+
+
+ public void keyPressed(KeyEvent e)
+ {
+ if((e.getKeyCode() == KeyEvent.VK_A) && e.isControlDown())
+ {
+ processEvent(kCTRL_A, null);
+ }
+ }
+
+
+ public void keyReleased(KeyEvent e)
+ {
+ }
+
+
+ public void keyTyped(KeyEvent e)
+ {
+ }
+
+}
diff --git a/source/com/c2kernel/graph/controller/StartVertexController.java b/source/com/c2kernel/graph/controller/StartVertexController.java
new file mode 100755
index 0000000..0dc959c
--- /dev/null
+++ b/source/com/c2kernel/graph/controller/StartVertexController.java
@@ -0,0 +1,77 @@
+package com.c2kernel.graph.controller;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Observable;
+import java.util.Observer;
+
+import javax.swing.JButton;
+
+import com.c2kernel.graph.event.SelectionChangedEvent;
+import com.c2kernel.graph.model.GraphModelManager;
+import com.c2kernel.graph.model.Vertex;
+
+
+// The start vertex controller is responsible for selecting
+// the vertex at the start of the graph.
+//
+// The controller listens to:
+// * The graph model to determine if there is a single
+// vertex selected
+// * The start vertex button
+//
+// The controller modifies:
+// * The graph model to select the start vertex
+// * The start button to enable it only when there is a
+// single vertex selected
+public class StartVertexController implements Observer, ActionListener
+{
+ private GraphModelManager mGraphModelManager = null;
+ private JButton mStartButton = null;
+
+
+ public void setGraphModelManager(GraphModelManager graphModelManager)
+ {
+ mGraphModelManager = graphModelManager;
+ mGraphModelManager.addObserver(this);
+ }
+
+
+ public void setStartButton(JButton startButton)
+ {
+ mStartButton = startButton;
+ mStartButton.addActionListener(this);
+ }
+
+
+ public void update(Observable o, Object arg)
+ {
+ SelectionChangedEvent event = null;
+ Vertex[] selectedVertices = null;
+
+ // If the selected vertex has changed
+ if(arg instanceof SelectionChangedEvent && mStartButton != null)
+ {
+ event = (SelectionChangedEvent)arg;
+ selectedVertices = event.mSelection.mVertices;
+
+ if(selectedVertices == null)
+ {
+ mStartButton.setEnabled(false);
+ }
+ else if (mGraphModelManager.isEditable())
+ {
+ mStartButton.setEnabled(selectedVertices.length == 1);
+ }
+ }
+ }
+
+
+ public void actionPerformed(ActionEvent ae)
+ {
+ if(mGraphModelManager != null)
+ {
+ mGraphModelManager.getModel().setSelectedVertexToBeStart();
+ }
+ }
+}
diff --git a/source/com/c2kernel/graph/controller/VertexConstructionController.java b/source/com/c2kernel/graph/controller/VertexConstructionController.java
new file mode 100755
index 0000000..d351b0a
--- /dev/null
+++ b/source/com/c2kernel/graph/controller/VertexConstructionController.java
@@ -0,0 +1,45 @@
+package com.c2kernel.graph.controller;
+
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+import com.c2kernel.graph.model.GraphModelManager;
+import com.c2kernel.graph.view.EditorModeListener;
+import com.c2kernel.graph.view.EditorToolBar;
+
+
+public class VertexConstructionController extends MouseAdapter implements EditorModeListener
+{
+ private GraphModelManager mGraphModelManager = null;
+ private EditorToolBar mEditorToolBar = null;
+ private boolean mCreatingVertices = false;
+
+
+ public void setGraphModelManager(GraphModelManager graphModelManager)
+ {
+ mGraphModelManager = graphModelManager;
+ }
+
+
+ public void setEditorToolBar(EditorToolBar editorToolBar)
+ {
+ mEditorToolBar = editorToolBar;
+ mEditorToolBar.addEditorModeListener(this);
+ }
+
+
+ public void editorModeChanged(String idOfNewMode)
+ {
+ mCreatingVertices = idOfNewMode.equals("Vertex");
+ }
+
+
+ public void mouseClicked(MouseEvent me)
+ {
+ if(mCreatingVertices && (mGraphModelManager != null) && (mEditorToolBar != null) && mGraphModelManager.isEditable())
+ {
+ mGraphModelManager.getModel().createVertex(me.getPoint(), mEditorToolBar.getSelectedVertexType());
+ mEditorToolBar.enterSelectMode();
+ }
+ }
+}
diff --git a/source/com/c2kernel/graph/event/ClearedEvent.java b/source/com/c2kernel/graph/event/ClearedEvent.java
new file mode 100755
index 0000000..128e671
--- /dev/null
+++ b/source/com/c2kernel/graph/event/ClearedEvent.java
@@ -0,0 +1,6 @@
+package com.c2kernel.graph.event;
+
+
+public class ClearedEvent extends GraphModelEvent
+{
+}
diff --git a/source/com/c2kernel/graph/event/EdgeRemovedEvent.java b/source/com/c2kernel/graph/event/EdgeRemovedEvent.java
new file mode 100755
index 0000000..d895132
--- /dev/null
+++ b/source/com/c2kernel/graph/event/EdgeRemovedEvent.java
@@ -0,0 +1,6 @@
+package com.c2kernel.graph.event;
+
+
+public class EdgeRemovedEvent extends GraphModelEvent
+{
+}
diff --git a/source/com/c2kernel/graph/event/EdgesChangedEvent.java b/source/com/c2kernel/graph/event/EdgesChangedEvent.java
new file mode 100755
index 0000000..7835836
--- /dev/null
+++ b/source/com/c2kernel/graph/event/EdgesChangedEvent.java
@@ -0,0 +1,6 @@
+package com.c2kernel.graph.event;
+
+
+public class EdgesChangedEvent extends GraphModelEvent
+{
+}
diff --git a/source/com/c2kernel/graph/event/ElasticBandResizedEvent.java b/source/com/c2kernel/graph/event/ElasticBandResizedEvent.java
new file mode 100755
index 0000000..cb8ae3e
--- /dev/null
+++ b/source/com/c2kernel/graph/event/ElasticBandResizedEvent.java
@@ -0,0 +1,6 @@
+package com.c2kernel.graph.event;
+
+
+public class ElasticBandResizedEvent extends GraphModelEvent
+{
+}
diff --git a/source/com/c2kernel/graph/event/ElasticBandSetEvent.java b/source/com/c2kernel/graph/event/ElasticBandSetEvent.java
new file mode 100755
index 0000000..6211513
--- /dev/null
+++ b/source/com/c2kernel/graph/event/ElasticBandSetEvent.java
@@ -0,0 +1,6 @@
+package com.c2kernel.graph.event;
+
+
+public class ElasticBandSetEvent extends GraphModelEvent
+{
+}
diff --git a/source/com/c2kernel/graph/event/EntireModelChangedEvent.java b/source/com/c2kernel/graph/event/EntireModelChangedEvent.java
new file mode 100755
index 0000000..6e13e8b
--- /dev/null
+++ b/source/com/c2kernel/graph/event/EntireModelChangedEvent.java
@@ -0,0 +1,6 @@
+package com.c2kernel.graph.event;
+
+
+public class EntireModelChangedEvent extends GraphModelEvent
+{
+}
diff --git a/source/com/c2kernel/graph/event/ForcedNotifyEvent.java b/source/com/c2kernel/graph/event/ForcedNotifyEvent.java
new file mode 100755
index 0000000..d8dd646
--- /dev/null
+++ b/source/com/c2kernel/graph/event/ForcedNotifyEvent.java
@@ -0,0 +1,6 @@
+package com.c2kernel.graph.event;
+
+
+public class ForcedNotifyEvent extends GraphModelEvent
+{
+}
diff --git a/source/com/c2kernel/graph/event/GraphModelEvent.java b/source/com/c2kernel/graph/event/GraphModelEvent.java
new file mode 100755
index 0000000..95cd6fb
--- /dev/null
+++ b/source/com/c2kernel/graph/event/GraphModelEvent.java
@@ -0,0 +1,7 @@
+package com.c2kernel.graph.event;
+
+import java.io.Serializable;
+
+public abstract class GraphModelEvent implements Serializable
+{
+}
diff --git a/source/com/c2kernel/graph/event/GraphModelResizedEvent.java b/source/com/c2kernel/graph/event/GraphModelResizedEvent.java
new file mode 100755
index 0000000..20980c3
--- /dev/null
+++ b/source/com/c2kernel/graph/event/GraphModelResizedEvent.java
@@ -0,0 +1,6 @@
+package com.c2kernel.graph.event;
+
+
+public class GraphModelResizedEvent extends GraphModelEvent
+{
+}
diff --git a/source/com/c2kernel/graph/event/NewEdgeEndPointChangedEvent.java b/source/com/c2kernel/graph/event/NewEdgeEndPointChangedEvent.java
new file mode 100755
index 0000000..d1bb6f2
--- /dev/null
+++ b/source/com/c2kernel/graph/event/NewEdgeEndPointChangedEvent.java
@@ -0,0 +1,6 @@
+package com.c2kernel.graph.event;
+
+
+public class NewEdgeEndPointChangedEvent extends GraphModelEvent
+{
+}
diff --git a/source/com/c2kernel/graph/event/SelectionChangedEvent.java b/source/com/c2kernel/graph/event/SelectionChangedEvent.java
new file mode 100755
index 0000000..f95e6d3
--- /dev/null
+++ b/source/com/c2kernel/graph/event/SelectionChangedEvent.java
@@ -0,0 +1,9 @@
+package com.c2kernel.graph.event;
+
+import com.c2kernel.graph.model.Selection;
+
+
+public class SelectionChangedEvent extends GraphModelEvent
+{
+ public Selection mSelection = null;
+}
diff --git a/source/com/c2kernel/graph/event/SelectionMovedEvent.java b/source/com/c2kernel/graph/event/SelectionMovedEvent.java
new file mode 100755
index 0000000..2d892a9
--- /dev/null
+++ b/source/com/c2kernel/graph/event/SelectionMovedEvent.java
@@ -0,0 +1,7 @@
+package com.c2kernel.graph.event;
+
+
+
+public class SelectionMovedEvent extends GraphModelEvent
+{
+}
diff --git a/source/com/c2kernel/graph/event/StartVertexIdChangedEvent.java b/source/com/c2kernel/graph/event/StartVertexIdChangedEvent.java
new file mode 100755
index 0000000..f875626
--- /dev/null
+++ b/source/com/c2kernel/graph/event/StartVertexIdChangedEvent.java
@@ -0,0 +1,6 @@
+package com.c2kernel.graph.event;
+
+
+public class StartVertexIdChangedEvent extends GraphModelEvent
+{
+}
diff --git a/source/com/c2kernel/graph/event/VertexAddedEvent.java b/source/com/c2kernel/graph/event/VertexAddedEvent.java
new file mode 100755
index 0000000..353aacb
--- /dev/null
+++ b/source/com/c2kernel/graph/event/VertexAddedEvent.java
@@ -0,0 +1,6 @@
+package com.c2kernel.graph.event;
+
+
+public class VertexAddedEvent extends GraphModelEvent
+{
+}
diff --git a/source/com/c2kernel/graph/event/VertexCreatedEvent.java b/source/com/c2kernel/graph/event/VertexCreatedEvent.java
new file mode 100755
index 0000000..e72ca4a
--- /dev/null
+++ b/source/com/c2kernel/graph/event/VertexCreatedEvent.java
@@ -0,0 +1,6 @@
+package com.c2kernel.graph.event;
+
+
+public class VertexCreatedEvent extends GraphModelEvent
+{
+}
diff --git a/source/com/c2kernel/graph/event/VertexMovedEvent.java b/source/com/c2kernel/graph/event/VertexMovedEvent.java
new file mode 100755
index 0000000..807ca36
--- /dev/null
+++ b/source/com/c2kernel/graph/event/VertexMovedEvent.java
@@ -0,0 +1,6 @@
+package com.c2kernel.graph.event;
+
+
+public class VertexMovedEvent extends GraphModelEvent
+{
+}
diff --git a/source/com/c2kernel/graph/event/VertexRemovedEvent.java b/source/com/c2kernel/graph/event/VertexRemovedEvent.java
new file mode 100755
index 0000000..e24700d
--- /dev/null
+++ b/source/com/c2kernel/graph/event/VertexRemovedEvent.java
@@ -0,0 +1,6 @@
+package com.c2kernel.graph.event;
+
+
+public class VertexRemovedEvent extends GraphModelEvent
+{
+}
diff --git a/source/com/c2kernel/graph/event/VerticesChangedEvent.java b/source/com/c2kernel/graph/event/VerticesChangedEvent.java
new file mode 100755
index 0000000..5d83834
--- /dev/null
+++ b/source/com/c2kernel/graph/event/VerticesChangedEvent.java
@@ -0,0 +1,6 @@
+package com.c2kernel.graph.event;
+
+
+public class VerticesChangedEvent extends GraphModelEvent
+{
+}
diff --git a/source/com/c2kernel/graph/layout/DefaultGraphLayoutGenerator.java b/source/com/c2kernel/graph/layout/DefaultGraphLayoutGenerator.java
new file mode 100755
index 0000000..e243817
--- /dev/null
+++ b/source/com/c2kernel/graph/layout/DefaultGraphLayoutGenerator.java
@@ -0,0 +1,116 @@
+package com.c2kernel.graph.layout;
+
+import java.util.Vector;
+
+import com.c2kernel.graph.model.DirectedEdge;
+import com.c2kernel.graph.model.GraphModel;
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.utils.Logger;
+
+public class DefaultGraphLayoutGenerator {
+ private static int mTopMargin = 100;
+ private static int mLeftMargin = 100;
+ private static int mHorzGap = 180;
+ private static int mVertGap = 100;
+
+ private DefaultGraphLayoutGenerator() {
+ }
+
+ public static void layoutGraph(GraphModel graphModel) {
+ Vertex start = graphModel.getStartVertex();
+ Vector rowVector = new Vector(10, 10);
+ int[] midPoints = null;
+ IntegerWrapper valueOfLargestMidPoint = new IntegerWrapper(0);
+ if (start == null) {
+ Logger.msg(1,"Error graph must have a starting vertex to be layed out");
+ return;
+ }
+ graphModel.clearTags(start);
+ visitVertex(graphModel, start, 0, rowVector, start);
+ midPoints = new int[rowVector.size()];
+ calculateRowMidPoints(rowVector, midPoints, valueOfLargestMidPoint);
+ fillInVertexLocations(graphModel, rowVector, valueOfLargestMidPoint, midPoints);
+ fillInEdgeLocations(graphModel);
+ graphModel.forceNotify();
+ }
+
+ private static void visitVertex(GraphModel graphModel, Vertex vertex, int rowIndex, Vector rowVector, Object tag) {
+ int i = 0;
+ Vertex[] children = graphModel.getOutVertices(vertex);
+ vertex.setTag(tag);
+ addVertexToRow(vertex, rowIndex, rowVector);
+ for (i = 0; i < children.length; i++) {
+ if (!(children[i].hasTag(tag))) {
+ visitVertex(graphModel, children[i], rowIndex + 1, rowVector, tag);
+ }
+ }
+ }
+
+ private static void addVertexToRow(Vertex vertex, int rowIndex, Vector rowVector) {
+ Vector rowsVertices = null;
+ // If there is no vector of vertices already created for this row,
+ // then create one
+ if (rowVector.size() == rowIndex) {
+ rowVector.add(new Vector(10, 10));
+ }
+ // Add the vertex to the row's vector of vertices
+ rowsVertices = (Vector)rowVector.elementAt(rowIndex);
+ rowsVertices.add(vertex);
+ }
+
+ private static void calculateRowMidPoints(Vector rowVector, int[] midPoints, IntegerWrapper valueOfLargestMidPoint) {
+ Vector rowsVertices = null;
+ int rowsWidth = 0;
+ int i = 0;
+ for (i = 0; i < midPoints.length; i++) {
+ rowsVertices = (Vector)rowVector.elementAt(i);
+ rowsWidth = mHorzGap * (rowsVertices.size() - 1);
+ midPoints[i] = rowsWidth / 2;
+ if (midPoints[i] > valueOfLargestMidPoint.mValue) {
+ valueOfLargestMidPoint.mValue = midPoints[i];
+ }
+ }
+ }
+
+ private static void fillInVertexLocations(GraphModel graphModel, Vector rowVector,
+ IntegerWrapper valueOfLargestMidPoint, int[] midPoints) {
+ Vector rowsVertices = null;
+ Vertex vertex = null;
+ int rowIndex = 0;
+ int column = 0;
+ int rowsLeftMargin = 0;
+ GraphPoint point = new GraphPoint(0, 0);
+ for (rowIndex = 0; rowIndex < rowVector.size(); rowIndex++) {
+ rowsVertices = (Vector)rowVector.elementAt(rowIndex);
+ rowsLeftMargin = mLeftMargin + valueOfLargestMidPoint.mValue - midPoints[rowIndex];
+ for (column = 0; column < rowsVertices.size(); column++) {
+ vertex = (Vertex)rowsVertices.elementAt(column);
+ point.x = rowsLeftMargin + column * mHorzGap;
+ point.y = mTopMargin + rowIndex * mVertGap;
+ vertex.moveAbsolute(point);
+ graphModel.checkSize(vertex);
+ }
+ }
+ }
+
+ private static void fillInEdgeLocations(GraphModel graphModel) {
+ Vertex[] vertices = graphModel.getVertices();
+ GraphPoint centrePoint = null;
+ DirectedEdge[] inEdges = null;
+ DirectedEdge[] outEdges = null;
+ int i = 0;
+ int j = 0;
+ for (i = 0; i < vertices.length; i++) {
+ centrePoint = vertices[i].getCentrePoint();
+ inEdges = graphModel.getInEdges(vertices[i]);
+ outEdges = graphModel.getOutEdges(vertices[i]);
+ for (j = 0; j < inEdges.length; j++) {
+ inEdges[j].setTerminusPoint(centrePoint);
+ }
+ for (j = 0; j < outEdges.length; j++) {
+ outEdges[j].setOriginPoint(centrePoint);
+ }
+ }
+ }
+}
diff --git a/source/com/c2kernel/graph/layout/IntegerWrapper.java b/source/com/c2kernel/graph/layout/IntegerWrapper.java
new file mode 100755
index 0000000..aaee858
--- /dev/null
+++ b/source/com/c2kernel/graph/layout/IntegerWrapper.java
@@ -0,0 +1,13 @@
+package com.c2kernel.graph.layout;
+
+
+public class IntegerWrapper
+{
+ public int mValue = 0;
+
+
+ public IntegerWrapper(int value)
+ {
+ mValue = value;
+ }
+}
diff --git a/source/com/c2kernel/graph/model/DirectedEdge.java b/source/com/c2kernel/graph/model/DirectedEdge.java
new file mode 100755
index 0000000..3848373
--- /dev/null
+++ b/source/com/c2kernel/graph/model/DirectedEdge.java
@@ -0,0 +1,99 @@
+package com.c2kernel.graph.model;
+
+import java.io.Serializable;
+
+
+
+public abstract class DirectedEdge implements Serializable
+{
+ // Persistent data
+ private int mId = -1;
+ private GraphPoint mOriginPoint = new GraphPoint(0, 0);
+ private GraphPoint mTerminusPoint = new GraphPoint(0, 0);
+ private int mOriginVertexId = -1;
+ private int mTerminusVertexId = -1;
+
+
+ public void setID(int id)
+ {
+ mId = id;
+ }
+
+
+ public int getID()
+ {
+ return mId;
+ }
+
+
+ public void setOriginPoint(GraphPoint p)
+ {
+ mOriginPoint = p;
+ }
+
+
+ public GraphPoint getOriginPoint()
+ {
+ return mOriginPoint;
+ }
+
+
+ public void setTerminusPoint(GraphPoint p)
+ {
+ mTerminusPoint = p;
+ }
+
+
+ public GraphPoint getTerminusPoint()
+ {
+ return mTerminusPoint;
+ }
+
+
+ public boolean containsPoint(GraphPoint p)
+ {
+ int midX = mOriginPoint.x + (mTerminusPoint.x - mOriginPoint.x)/2;
+ int midY = mOriginPoint.y + (mTerminusPoint.y - mOriginPoint.y)/2;
+ int minX = midX - 10;
+ int minY = midY - 10;
+ int maxX = midX + 10;
+ int maxY = midY + 10;
+
+ return (p.x >= minX) && (p.x <= maxX) && (p.y >= minY) && (p.y <= maxY);
+ }
+
+
+ public void setOriginVertexId(int id)
+ {
+ mOriginVertexId = id;
+ }
+
+
+ public int getOriginVertexId()
+ {
+ return mOriginVertexId;
+ }
+
+
+ public void setTerminusVertexId(int id)
+ {
+ mTerminusVertexId = id;
+ }
+
+
+ public int getTerminusVertexId()
+ {
+ return mTerminusVertexId;
+ }
+
+
+ public void setName(String name)
+ {
+ }
+
+
+ public String getName()
+ {
+ return null;
+ }
+}
diff --git a/source/com/c2kernel/graph/model/EdgeFactory.java b/source/com/c2kernel/graph/model/EdgeFactory.java
new file mode 100755
index 0000000..083f616
--- /dev/null
+++ b/source/com/c2kernel/graph/model/EdgeFactory.java
@@ -0,0 +1,14 @@
+package com.c2kernel.graph.model;
+
+
+
+public interface EdgeFactory
+{
+ public void create
+ (
+ GraphModelManager graphModelManager,
+ Vertex origin,
+ Vertex terminus,
+ TypeNameAndConstructionInfo typeNameAndConstructionInfo
+ );
+}
diff --git a/source/com/c2kernel/graph/model/ElasticBand.java b/source/com/c2kernel/graph/model/ElasticBand.java
new file mode 100755
index 0000000..38497ef
--- /dev/null
+++ b/source/com/c2kernel/graph/model/ElasticBand.java
@@ -0,0 +1,17 @@
+package com.c2kernel.graph.model;
+
+import java.awt.Point;
+
+
+public class ElasticBand
+{
+ public Point mFixedCorner = null;
+ public Point mMovingCorner = null;
+
+
+ public ElasticBand(Point fixedCorner, Point movingCorner)
+ {
+ mFixedCorner = fixedCorner;
+ mMovingCorner = movingCorner;
+ }
+}
diff --git a/source/com/c2kernel/graph/model/GraphModel.java b/source/com/c2kernel/graph/model/GraphModel.java
new file mode 100755
index 0000000..7a546eb
--- /dev/null
+++ b/source/com/c2kernel/graph/model/GraphModel.java
@@ -0,0 +1,884 @@
+package com.c2kernel.graph.model;
+
+import java.awt.Point;
+import java.awt.Polygon;
+import java.io.Serializable;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import com.c2kernel.graph.event.*;
+import com.c2kernel.utils.Logger;
+
+public class GraphModel implements Serializable{
+ /* Persistant data */
+
+ private int mWidth = 0;
+ private int mHeight = 0;
+ private int mNextId = 0;
+ protected int mStartVertexId = -1;
+ protected Hashtable mVertexHashtable = new Hashtable();
+ protected Hashtable mEdgeHashtable = new Hashtable();
+ private GraphableVertex mContainingVertex;
+
+ /* Transient data */
+
+ // There should always be a Selection object
+ protected Selection mSelection = new Selection(null, null, 0, 0, 0, 0);
+ protected Vertex mNewEdgeOriginVertex = null;
+ protected Point mNewEdgeEndPoint = null;
+ private ElasticBand mElasticBand = null;
+ private GraphModelManager mManager = null;
+
+ /* External factories */
+
+ private VertexFactory mExternalVertexFactory = null;
+ private EdgeFactory mExternalEdgeFactory = null;
+
+ /* Vertex outline creator */
+
+ private VertexOutlineCreator mVertexOutlineCreator = null;
+
+ /* Notification Events */
+
+ private ClearedEvent mClearedEvent = new ClearedEvent();
+ private EdgeRemovedEvent mEdgeRemovedEvent = new EdgeRemovedEvent();
+ private EdgesChangedEvent mEdgesChangedEvent = new EdgesChangedEvent();
+ private ForcedNotifyEvent mForcedNotifyEvent = new ForcedNotifyEvent();
+ private NewEdgeEndPointChangedEvent mNewEdgeEndPointChangedEvent = new NewEdgeEndPointChangedEvent();
+ private SelectionChangedEvent mSelectionChangedEvent = new SelectionChangedEvent();
+ private StartVertexIdChangedEvent mStartVertexIdChangedEvent = new StartVertexIdChangedEvent();
+ private VertexAddedEvent mVertexAddedEvent = new VertexAddedEvent();
+ private VertexCreatedEvent mVertexCreatedEvent = new VertexCreatedEvent();
+ private VertexMovedEvent mVertexMovedEvent = new VertexMovedEvent();
+ private SelectionMovedEvent mSelectionMovedEvent = new SelectionMovedEvent();
+ private VertexRemovedEvent mVertexRemovedEvent = new VertexRemovedEvent();
+ private VerticesChangedEvent mVerticesChangedEvent = new VerticesChangedEvent();
+ private ElasticBandSetEvent mElasticBandSetEvent = new ElasticBandSetEvent();
+ private ElasticBandResizedEvent mElasticBandResizedEvent = new ElasticBandResizedEvent();
+ private GraphModelResizedEvent mGraphModelResizedEvent = new GraphModelResizedEvent();
+
+ // Calling this constructor does not create a vertex outline creator
+ // which is required by the method addVertexAndCreateId()
+
+ private static int count=0;
+
+ // count instances for debugging
+ private int number;
+
+ public GraphModel() {
+ number=++count;
+
+ }
+
+ public int getNumber() {
+ return number;
+ }
+
+ private void setChanged() {
+ if (mManager != null)
+ mManager.setChanged();
+ }
+
+ private void notifyObservers(GraphModelEvent ev) {
+ if (mManager != null)
+ mManager.notifyObservers(ev);
+ }
+
+ public void setNextId(int id) {
+ mNextId = id;
+ }
+
+ public int getNextId() {
+ return mNextId;
+ }
+
+ public void setManager(GraphModelManager mgr) {
+ mManager = mgr;
+ }
+
+ public GraphModelManager getManager() {
+ return mManager;
+ }
+
+ public GraphModel(VertexOutlineCreator vertexOutlineCreator) {
+ mVertexOutlineCreator = vertexOutlineCreator;
+ }
+
+ public void setWidth(int width) {
+
+ mWidth = width;
+ }
+
+ public int getWidth() {
+ return mWidth;
+ }
+
+ public void setHeight(int height) {
+
+ mHeight = height;
+ }
+
+ public int getHeight() {
+ return mHeight;
+ }
+
+ public void checkSize(Vertex v) {
+ boolean resized = false;
+ GraphPoint centre = v.getCentrePoint();
+ if (getWidth() < centre.x + v.getWidth()/2 +10 ) {
+ setWidth( centre.x + v.getWidth()/2 +10 );
+ resized = true;
+ }
+
+ if (getHeight() < centre.y + v.getHeight()/2 +10 ) {
+ setHeight(centre.y + v.getHeight()/2 +10 );
+ resized = true;
+ }
+
+ if (resized) {
+ setChanged();
+ notifyObservers(mGraphModelResizedEvent);
+ }
+
+ }
+
+ public void setStartVertexId(int id) {
+ mStartVertexId = id;
+ }
+
+ public int getStartVertexId() {
+ return mStartVertexId;
+ }
+
+ public Vertex getStartVertex() {
+ return resolveVertex(getStartVertexId());
+ }
+
+ /**
+ * @return Returns the mParentVertex.
+ */
+ public GraphableVertex getContainingVertex() {
+ return mContainingVertex;
+ }
+ /**
+ * @param parentVertex The mParentVertex to set.
+ */
+ public void setContainingVertex(GraphableVertex vertex) {
+ mContainingVertex = vertex;
+ }
+
+ public void setVertices(Vertex[] vertices) {
+ mVertexHashtable = new Hashtable();
+ for (int i = 0; i < vertices.length; i++) {
+ mVertexHashtable.put(String.valueOf(vertices[i].getID()), vertices[i]);
+ checkSize(vertices[i]);
+
+ }
+ setChanged();
+ notifyObservers(mVerticesChangedEvent);
+ }
+
+ public Vertex[] getVertices() {
+ Object[] vertexObjs = mVertexHashtable.values().toArray();
+ Vertex[] vertices = new Vertex[vertexObjs.length];
+ int i = 0;
+ for (i = 0; i < vertices.length; i++) {
+ vertices[i] = (Vertex)vertexObjs[i];
+ }
+ return vertices;
+ }
+
+ public void setEdges(DirectedEdge[] edges) {
+ mEdgeHashtable = new Hashtable();
+ for (int i = 0; i < edges.length; i++) {
+ mEdgeHashtable.put(String.valueOf(edges[i].getID()), edges[i]);
+ }
+ setChanged();
+ notifyObservers(mEdgesChangedEvent);
+ }
+
+ public DirectedEdge[] getEdges() {
+ Object[] edgeObjs = mEdgeHashtable.values().toArray();
+ DirectedEdge[] edges = new DirectedEdge[edgeObjs.length];
+ int i = 0;
+ for (i = 0; i < edges.length; i++) {
+ edges[i] = (DirectedEdge)edgeObjs[i];
+ }
+ return edges;
+ }
+
+ // If the specified point is within more than one vertex,
+ // then the smallest vertex is returned.
+ public Vertex getVertex(GraphPoint p) {
+ Object[] vertexObjs = mVertexHashtable.values().toArray();
+ Vertex vertex = null;
+ Vector vertexVector = new Vector(10, 10);
+ int numVerticesFound = 0;
+ Vertex smallestVertex = null;
+ int sizeOfSmallestVertex = 0;
+ int sizeOfVertex = 0;
+ int i = 0;
+ for (i = 0; i < vertexObjs.length; i++) {
+ vertex = (Vertex)vertexObjs[i];
+ if (vertex.containsPoint(p)) {
+ vertexVector.add(vertex);
+ }
+ }
+ numVerticesFound = vertexVector.size();
+ if (numVerticesFound == 0) {
+ return null;
+ }
+ else {
+ smallestVertex = (Vertex)vertexVector.elementAt(0);
+ sizeOfSmallestVertex = smallestVertex.getHeight() * smallestVertex.getWidth();
+ // Determine the smallest vertex
+ for (i = 1; i < numVerticesFound; i++) {
+ vertex = (Vertex)vertexVector.elementAt(i);
+ sizeOfVertex = vertex.getHeight() * vertex.getWidth();
+ if (sizeOfVertex < sizeOfSmallestVertex) {
+ smallestVertex = vertex;
+ sizeOfSmallestVertex = sizeOfVertex;
+ }
+ }
+ return smallestVertex;
+ }
+ }
+
+ public Vertex getVertexById(int id) {
+ return (Vertex)mVertexHashtable.get(String.valueOf(id));
+ }
+
+ public DirectedEdge getEdge(GraphPoint p) {
+ Object[] edgeObjs = mEdgeHashtable.values().toArray();
+ DirectedEdge edge = null;
+ int i = 0;
+ for (i = 0; i < edgeObjs.length; i++) {
+ edge = (DirectedEdge)edgeObjs[i];
+ if (edge.containsPoint(p)) {
+ return edge;
+ }
+ }
+ return null;
+ }
+
+ public int addEdgeAndCreateId(DirectedEdge e, int originId, int terminusId) {
+ return addEdgeAndCreateId(e, resolveVertex(originId), resolveVertex(terminusId));
+ }
+
+ public int addEdgeAndCreateId(DirectedEdge e, Vertex origin, Vertex terminus) {
+ e.setID(mNextId);
+ e.setOriginVertexId(origin.getID());
+ e.setOriginPoint(origin.getCentrePoint());
+ e.setTerminusVertexId(terminus.getID());
+ e.setTerminusPoint(terminus.getCentrePoint());
+ origin.addOutEdgeId(mNextId);
+ terminus.addInEdgeId(mNextId);
+ mEdgeHashtable.put(String.valueOf(mNextId), e);
+ mNextId++;
+ return mNextId - 1;
+ }
+
+ // Removes an edge, but does not modify the selection
+ public void removeEdge(DirectedEdge e) {
+ Vertex origin = getOrigin(e);
+ Vertex terminus = getTerminus(e);
+ int edgeId = e.getID();
+ // Remove the id of the edge from the origin and terminus vertices
+ origin.removeOutEdgeId(edgeId);
+ terminus.removeInEdgeId(edgeId);
+ // Remove the edge
+ mEdgeHashtable.remove(String.valueOf(e.getID()));
+ setChanged();
+ notifyObservers(mEdgeRemovedEvent);
+ }
+
+ public int addVertexAndCreateId(Vertex v, Point location) {
+ return addVertexAndCreateId(v, new GraphPoint(location.x, location.y));
+ }
+
+ public int addVertexAndCreateId(Vertex v, GraphPoint location) {
+ if (location!= null)
+ {
+ if (mVertexOutlineCreator == null) {
+ Logger.msg(1,"You cannot add a vertex with no outline creator");
+ return -1;
+
+ }
+ mVertexHashtable.put(String.valueOf(mNextId), v);
+ placeVertex(v, location);
+ }
+ v.setID(mNextId);
+ return mNextId++;
+ }
+
+ public void placeVertex(Vertex v, GraphPoint location) {
+ v.setCentrePoint(location);
+ if (mVertexOutlineCreator != null) {
+ mVertexOutlineCreator.setOutline(v);
+ }
+ setChanged();
+ notifyObservers(mVertexAddedEvent);
+ checkSize(v);
+ }
+
+ // Removes a vertex, but does not modify the selection
+ public void removeVertex(Vertex v) {
+ DirectedEdge[] inEdges = getInEdges(v);
+ DirectedEdge[] outEdges = getOutEdges(v);
+ Vertex origin = null;
+ Vertex terminus = null;
+ int edgeId = -1;
+ int i = 0;
+ // For each in edge
+ for (i = 0; i < inEdges.length; i++) {
+ edgeId = inEdges[i].getID();
+ origin = getOrigin(inEdges[i]);
+ // Remove the id of the edge from the origin vertex
+ origin.removeOutEdgeId(edgeId);
+ // Remove the edge
+ mEdgeHashtable.remove(String.valueOf(edgeId));
+ }
+ // Remove all the out edges
+ for (i = 0; i < outEdges.length; i++) {
+ edgeId = outEdges[i].getID();
+ terminus = getTerminus(outEdges[i]);
+ // Remove the id of the edge from the terminus vertex
+ terminus.removeInEdgeId(edgeId);
+ // Remove the edge
+ mEdgeHashtable.remove(String.valueOf(edgeId));
+ }
+ // Remove the vertex
+ mVertexHashtable.remove(String.valueOf(v.getID()));
+ setChanged();
+ notifyObservers(mVertexRemovedEvent);
+ }
+
+ public void moveAbsoluteVertex(Vertex v, GraphPoint p) {
+ // Make sure the new position stays within the graph
+ if (p.x < 0) p.x = 0;
+ if (p.y < 0) p.y = 0;
+ if (p.x > mWidth) p.x = mWidth;
+ if (p.y > mHeight) p.y = mHeight;
+ moveAbsoluteVertexAndConnectingEdges(v, p);
+ setChanged();
+ notifyObservers(mVertexMovedEvent);
+ }
+
+ private void moveAbsoluteVertexAndConnectingEdges(Vertex v, GraphPoint p) {
+ DirectedEdge[] inEdges = getInEdges(v);
+ DirectedEdge[] outEdges = getOutEdges(v);
+ int i = 0;
+ // Move the vertex to the new position
+ v.moveAbsolute(p);
+ // Move the ends of the incoming edges to the new position
+ for (i = 0; i < inEdges.length; i++) {
+ inEdges[i].setTerminusPoint(p);
+ }
+ // Move the ends of the outgoing edges to the new position
+ for (i = 0; i < outEdges.length; i++) {
+ outEdges[i].setOriginPoint(p);
+ }
+ checkSize(v);
+ }
+
+ public void moveAbsoluteSelection(int newTopLeftX, int newTopLeftY) {
+ int selectionHeight = mSelection.mBottomRightY - mSelection.mTopLeftY;
+ int selectionWidth = mSelection.mBottomRightX - mSelection.mTopLeftX;
+ int bottomRightX = newTopLeftX + selectionWidth;
+ int bottomRightY = newTopLeftY + selectionHeight;
+ GraphPoint oldCentrePoint = null;
+ GraphPoint newCentrePoint = null;
+ int distXFromTopLeft = 0;
+ int distYFromTopLeft = 0;
+ int i = 0;
+ // Make sure the selection does not move
+ // outside the boundaries of the graph
+ if (newTopLeftX < 0) newTopLeftX = 0;
+ if (newTopLeftY < 0) newTopLeftY = 0;
+ if (bottomRightX > mWidth) newTopLeftX = mWidth - selectionWidth;
+ if (bottomRightY > mHeight) newTopLeftY = mHeight - selectionHeight;
+ // For each selected vertex
+ for (i = 0; i < mSelection.mVertices.length; i++) {
+ // Calculate the new centre point of the vertex.
+ // First calculate the distance of the centre point
+ // from the old top left hand corner of the selection,
+ // then move the point to the new top left hand
+ // corner plus the distance.
+ oldCentrePoint = mSelection.mVertices[i].getCentrePoint();
+ distXFromTopLeft = oldCentrePoint.x - mSelection.mTopLeftX;
+ distYFromTopLeft = oldCentrePoint.y - mSelection.mTopLeftY;
+ newCentrePoint = new GraphPoint(newTopLeftX + distXFromTopLeft, newTopLeftY + distYFromTopLeft);
+ moveAbsoluteVertexAndConnectingEdges(mSelection.mVertices[i], newCentrePoint);
+ }
+ // Update the top left and bottom right corners
+ mSelection.mTopLeftX = newTopLeftX;
+ mSelection.mTopLeftY = newTopLeftY;
+ mSelection.mBottomRightX = newTopLeftX + selectionWidth;
+ mSelection.mBottomRightY = newTopLeftY + selectionHeight;
+ setChanged();
+ notifyObservers(mSelectionMovedEvent);
+ }
+
+ public Vertex resolveVertex(int id) {
+ return (Vertex)mVertexHashtable.get(String.valueOf(id));
+ }
+
+ public DirectedEdge resolveEdge(int id) {
+ return (DirectedEdge)mEdgeHashtable.get(String.valueOf(id));
+ }
+
+ public DirectedEdge[] getInEdges(Vertex v) {
+ int[] ids = v.getInEdgeIds();
+ return resolveEdges(ids);
+ }
+
+ public DirectedEdge[] getOutEdges(Vertex v) {
+ int[] ids = v.getOutEdgeIds();
+ return resolveEdges(ids);
+ }
+
+ private DirectedEdge[] resolveEdges(int[] ids) {
+ DirectedEdge[] edges = new DirectedEdge[ids.length];
+ int i = 0;
+ for (i = 0; i < ids.length; i++) {
+ edges[i] = resolveEdge(ids[i]);
+ }
+ return edges;
+ }
+
+ public Vertex getOrigin(DirectedEdge e) {
+ return resolveVertex(e.getOriginVertexId());
+ }
+
+ public Vertex getTerminus(DirectedEdge e) {
+ return resolveVertex(e.getTerminusVertexId());
+ }
+
+ public Vertex[] getInVertices(Vertex v) {
+ DirectedEdge[] inEdges = getInEdges(v);
+ Vertex[] inVertices = new Vertex[inEdges.length];
+ int i = 0;
+ for (i = 0; i < inEdges.length; i++) {
+ inVertices[i] = getOrigin(inEdges[i]);
+ }
+ return inVertices;
+ }
+
+ public Vertex[] getOutVertices(Vertex v) {
+ DirectedEdge[] outEdges = getOutEdges(v);
+ Vertex[] outVertices = new Vertex[outEdges.length];
+ int i = 0;
+ for (i = 0; i < outEdges.length; i++) {
+ outVertices[i] = getTerminus(outEdges[i]);
+ }
+ return outVertices;
+ }
+
+ public DirectedEdge[] getConnectingEdges(int originVertexId, int terminusVertexId) {
+ Vertex origin = resolveVertex(originVertexId);
+ DirectedEdge[] outEdges = null;
+ int numEdgesFound = 0;
+ DirectedEdge[] edgesFound = null;
+ int i = 0;
+ int j = 0;
+ if (origin == null) return null;
+ outEdges = getOutEdges(origin);
+ for (i = 0; i < outEdges.length; i++) {
+ if (outEdges[i].getTerminusVertexId() == terminusVertexId) {
+ numEdgesFound++;
+ }
+ }
+ edgesFound = new DirectedEdge[numEdgesFound];
+ for (i = 0; i < outEdges.length; i++) {
+ if (outEdges[i].getTerminusVertexId() == terminusVertexId) {
+ edgesFound[j] = outEdges[i];
+ j++;
+ }
+ }
+ return edgesFound;
+ }
+
+ public void clearTags(Object tag) {
+ Vertex vertex = null;
+ Object[] vertexObjs = mVertexHashtable.values().toArray();
+ int i = 0;
+ for (i = 0; i < vertexObjs.length; i++) {
+ vertex = (Vertex)vertexObjs[i];
+ vertex.clearTag(tag);
+ }
+ }
+
+ public void forceNotify() {
+ setChanged();
+ notifyObservers(mForcedNotifyEvent);
+ }
+
+ public void clear() {
+ mVertexHashtable = new Hashtable();
+ mEdgeHashtable = new Hashtable();
+ mStartVertexId = -1;
+ setChanged();
+ notifyObservers(mClearedEvent);
+ }
+
+ public void setSelection(Selection s) {
+ // If the there is a change
+ if (selectionChanged(s)) {
+ mSelection = s;
+ mSelectionChangedEvent.mSelection = s;
+ setChanged();
+ notifyObservers(mSelectionChangedEvent);
+ }
+ }
+
+ private boolean selectionChanged(Selection newValue) {
+ int i = 0;
+ if (mSelection.mEdge != newValue.mEdge) {
+ return true;
+ }
+ if (mSelection.mVertices == null) {
+ if (newValue.mVertices == null) {
+ return false;
+ }
+ else {
+ return true;
+ }
+ }
+ else {
+ if (newValue.mVertices == null) {
+ return true;
+ }
+ else {
+ if (mSelection.mVertices.length != newValue.mVertices.length) {
+ return true;
+ }
+ for (i = 0; i < mSelection.mVertices.length; i++) {
+ if (mSelection.mVertices[i] != newValue.mVertices[i]) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+ }
+
+ public Selection getSelection() {
+ return mSelection;
+ }
+
+ public void setNewEdgeOriginVertex(Vertex v) {
+ mNewEdgeOriginVertex = v;
+ }
+
+ public Vertex getNewEdgeOriginVertex() {
+ return mNewEdgeOriginVertex;
+ }
+
+ public void setNewEdgeEndPoint(Point p) {
+ mNewEdgeEndPoint = p;
+ setChanged();
+ notifyObservers(mNewEdgeEndPointChangedEvent);
+ }
+
+ public Point getNewEdgeEndPoint() {
+ return mNewEdgeEndPoint;
+ }
+
+ public void setExternalVertexFactory(VertexFactory factory) {
+ mExternalVertexFactory = factory;
+ }
+
+ public void createVertex(Point location, TypeNameAndConstructionInfo typeNameAndConstructionInfo) {
+ if (mExternalVertexFactory != null) {
+ mExternalVertexFactory.create(mManager, location, typeNameAndConstructionInfo);
+ setChanged();
+ notifyObservers(mVertexCreatedEvent);
+ }
+ }
+
+ public void setExternalEdgeFactory(EdgeFactory factory) {
+ mExternalEdgeFactory = factory;
+ }
+
+ public void setVertexOutlineCreator(VertexOutlineCreator outlineCreator) {
+ mVertexOutlineCreator = outlineCreator;
+ }
+
+ public void createDirectedEdge(Vertex origin, Vertex terminus, TypeNameAndConstructionInfo typeNameAndConstructionInfo) {
+ if (mExternalEdgeFactory != null) {
+ mExternalEdgeFactory.create(mManager, origin, terminus, typeNameAndConstructionInfo);
+ }
+ }
+
+ public void selectAll() {
+ Vertex[] allVertices = getVertices();
+ if (allVertices.length > 0) {
+ mSelection.mEdge = null;
+ mSelection.mVertices = allVertices;
+ updateSelectionCorners();
+ mSelectionChangedEvent.mSelection = mSelection;
+ setChanged();
+ notifyObservers(mSelectionChangedEvent);
+ }
+ }
+
+ public void selectContentsOfElasticBand() {
+ if (mElasticBand == null) return;
+ Polygon bandPolygon = new Polygon();
+ Vertex[] allVertices = getVertices();
+ GraphPoint centrePoint = null;
+ Vector verticesInside = new Vector(10, 10);
+ int i = 0;
+ // Create a polygon representing the elastic band
+ bandPolygon.addPoint(mElasticBand.mFixedCorner.x, mElasticBand.mFixedCorner.y);
+ bandPolygon.addPoint(mElasticBand.mMovingCorner.x, mElasticBand.mFixedCorner.y);
+ bandPolygon.addPoint(mElasticBand.mMovingCorner.x, mElasticBand.mMovingCorner.y);
+ bandPolygon.addPoint(mElasticBand.mFixedCorner.x, mElasticBand.mMovingCorner.y);
+ // Create a vector of all of the vertices within the elastic band polygon
+ for (i = 0; i < allVertices.length; i++) {
+ centrePoint = allVertices[i].getCentrePoint();
+ if (bandPolygon.contains(centrePoint.x, centrePoint.y)) {
+ verticesInside.add(allVertices[i]);
+ }
+ }
+
+ // Select the vertices found within the elastic band polygon
+ if (verticesInside.size() == 0) {
+ mSelection.mTopLeftX = 0;
+ mSelection.mTopLeftY = 0;
+ mSelection.mBottomRightX = 0;
+ mSelection.mBottomRightY = 0;
+ mSelection.mEdge = null;
+ if (mContainingVertex != null)
+ verticesInside.add(mContainingVertex);
+ else
+ mSelection.mVertices = null;
+ }
+
+ if (verticesInside.size() > 0) {
+ mSelection.mEdge = null;
+ mSelection.mVertices = new Vertex[verticesInside.size()];
+ for (i = 0; i < verticesInside.size(); i++) {
+ mSelection.mVertices[i] = (Vertex)verticesInside.elementAt(i);
+ }
+ updateSelectionCorners();
+ }
+ // Remove the elastic band
+ mElasticBand = null;
+ mSelectionChangedEvent.mSelection = mSelection;
+ setChanged();
+ notifyObservers(mSelectionChangedEvent);
+ }
+
+ // Updates the top left and bottom right corners of the selection
+ private void updateSelectionCorners() {
+ Vertex vertex = mSelection.mVertices[0];
+ GraphPoint centrePoint = vertex.getCentrePoint();
+ if (centrePoint == null) return;
+ mSelection.mTopLeftX = centrePoint.x;
+ mSelection.mTopLeftY = centrePoint.y;
+ mSelection.mBottomRightX = centrePoint.x;
+ mSelection.mBottomRightY = centrePoint.y;
+ for (int i = 0; i < mSelection.mVertices.length; i++) {
+ vertex = mSelection.mVertices[i];
+ centrePoint = vertex.getCentrePoint();
+ if (centrePoint.x < mSelection.mTopLeftX) {
+ mSelection.mTopLeftX = centrePoint.x;
+ }
+ if (centrePoint.y < mSelection.mTopLeftY) {
+ mSelection.mTopLeftY = centrePoint.y;
+ }
+ if (centrePoint.x > mSelection.mBottomRightX) {
+ mSelection.mBottomRightX = centrePoint.x;
+ }
+ if (centrePoint.y > mSelection.mBottomRightY) {
+ mSelection.mBottomRightY = centrePoint.y;
+ }
+ }
+ }
+
+ public void deleteSelection() {
+ int i = 0;
+ if (mSelection.mVertices != null) {
+ for (i = 0; i < mSelection.mVertices.length; i++) {
+ removeVertex(mSelection.mVertices[i]);
+ }
+ }
+ else if (mSelection.mEdge != null) {
+ removeEdge(mSelection.mEdge);
+ }
+ // Make sure nothing is selected
+ if ((mSelection.mEdge != null) || (mSelection.mVertices != null)) {
+ mSelection.mEdge = null;
+ mSelection.mVertices = null;
+ mSelectionChangedEvent.mSelection = mSelection;
+ setChanged();
+ notifyObservers(mSelectionChangedEvent);
+ }
+ }
+
+ public void setSelectedVertexToBeStart() {
+ if (mSelection.mVertices != null) {
+ if (mSelection.mVertices.length == 1) {
+ setStartVertexId(mSelection.mVertices[0].getID());
+ setChanged();
+ notifyObservers(mStartVertexIdChangedEvent);
+ }
+ }
+ }
+
+ public void setElasticBand(ElasticBand elasticBand) {
+ mElasticBand = elasticBand;
+ setChanged();
+ notifyObservers(mElasticBandSetEvent);
+ }
+
+ public ElasticBand getElasticBand() {
+ return mElasticBand;
+ }
+
+ public void resizeElasticBand(Point movingCorner) {
+ mElasticBand.mMovingCorner = movingCorner;
+ setChanged();
+ notifyObservers(mElasticBandResizedEvent);
+ }
+
+ public boolean inSelection(Vertex v) {
+ int i = 0;
+ if (mSelection.mVertices == null) {
+ return false;
+ }
+ else {
+ for (i = 0; i < mSelection.mVertices.length; i++) {
+ if (mSelection.mVertices[i] == v) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ // Only use this method to remove one vertex.
+ // If you wish to remove more, it would
+ // propably be more efficient to create a
+ // new Selection object.
+ public void removeFromSelection(Vertex v) {
+ Vertex[] vertices = null;
+ int i = 0;
+ int j = 0;
+ if (mSelection.mVertices.length == 1) {
+ mSelection.mVertices = null;
+ mSelection.mTopLeftX = 0;
+ mSelection.mTopLeftY = 0;
+ mSelection.mBottomRightX = 0;
+ mSelection.mBottomRightY = 0;
+ }
+ else {
+ vertices = new Vertex[mSelection.mVertices.length - 1];
+ for (i = 0; i < mSelection.mVertices.length; i++) {
+ if (mSelection.mVertices[i] != v) {
+ vertices[j] = mSelection.mVertices[i];
+ j++;
+ }
+ }
+ mSelection.mVertices = vertices;
+ updateSelectionCorners();
+ }
+ setChanged();
+ notifyObservers(mSelectionChangedEvent);
+ }
+
+ // Only use this method to add one vertex.
+ // If you wish to add more, it would
+ // propably be more efficient to create a
+ // new Selection object.
+ public void addToSelection(Vertex v) {
+ Vertex[] vertices = new Vertex[mSelection.mVertices.length + 1];
+ GraphPoint centrePoint = null;
+ int i = 0;
+ if (mSelection.mVertices == null) {
+ centrePoint = v.getCentrePoint();
+ mSelection.mVertices = new Vertex[] { v };
+ mSelection.mTopLeftX = centrePoint.x;
+ mSelection.mTopLeftY = centrePoint.y;
+ mSelection.mBottomRightX = centrePoint.x;
+ mSelection.mBottomRightY = centrePoint.y;
+ }
+ else {
+ for (i = 0; i < mSelection.mVertices.length; i++) {
+ vertices[i] = mSelection.mVertices[i];
+ }
+ vertices[mSelection.mVertices.length] = v;
+ mSelection.mVertices = vertices;
+ updateSelectionCorners();
+ }
+ setChanged();
+ notifyObservers(mSelectionChangedEvent);
+ }
+
+ public void resetVertexOutlines() {
+ Vertex[] vertices = getVertices();
+ int i = 0;
+ for (i = 0; i < vertices.length; i++) {
+ mVertexOutlineCreator.setOutline(vertices[i]);
+ }
+ }
+
+ public void setGraphModelCastorData(GraphModelCastorData data) {
+ Class vertexOutlineCreatorClass = null;
+ int i = 0;
+ // Create the vertex outline creator
+ if (data.mClassNameOfVertexOutlineCreator.equals("")) {
+ mVertexOutlineCreator = null;
+ }
+ else {
+ try {
+ vertexOutlineCreatorClass = Class.forName(data.mClassNameOfVertexOutlineCreator);
+ mVertexOutlineCreator = (VertexOutlineCreator)vertexOutlineCreatorClass.newInstance();
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ mVertexOutlineCreator = null;
+ }
+ }
+ // Create and populate the vertex hashtable
+ mVertexHashtable = new Hashtable();
+ for (i = 0; i < data.mVertexImpls.length; i++) {
+ mVertexHashtable.put(String.valueOf(data.mVertexImpls[i].getID()), data.mVertexImpls[i]);
+ checkSize(data.mVertexImpls[i]);
+ }
+ // Create and populate the edge hastable
+ mEdgeHashtable = new Hashtable();
+ for (i = 0; i < data.mEdgeImpls.length; i++) {
+ mEdgeHashtable.put(String.valueOf(data.mEdgeImpls[i].getID()), data.mEdgeImpls[i]);
+ }
+ // Set the start vertex id and the id generation counter
+ mStartVertexId = data.mStartVertexId;
+ mNextId = data.mNextId;
+ }
+
+ public GraphModelCastorData getGraphModelCastorData() {
+ Object[] vertexObjs = mVertexHashtable.values().toArray();
+ Vertex[] vertexImpls = new Vertex[vertexObjs.length];
+ Object[] edgeObjs = mEdgeHashtable.values().toArray();
+ DirectedEdge[] directedEdgeImpls = new DirectedEdge[edgeObjs.length];
+ String className = null;
+ int i = 0;
+ // Put in the vertices
+ for (i = 0; i < vertexImpls.length; i++) {
+ vertexImpls[i] = (Vertex)vertexObjs[i];
+ }
+ // Put in the edges
+ for (i = 0; i < directedEdgeImpls.length; i++) {
+ directedEdgeImpls[i] = (DirectedEdge)edgeObjs[i];
+ }
+ // Determine the class name of the vertex outline creator
+ if (mVertexOutlineCreator == null) {
+ className = "";
+ }
+ else {
+ className = mVertexOutlineCreator.getClass().getName();
+ }
+ return new GraphModelCastorData(className, vertexImpls, directedEdgeImpls, mStartVertexId, mNextId);
+ }
+}
diff --git a/source/com/c2kernel/graph/model/GraphModelCastorData.java b/source/com/c2kernel/graph/model/GraphModelCastorData.java
new file mode 100755
index 0000000..7717c33
--- /dev/null
+++ b/source/com/c2kernel/graph/model/GraphModelCastorData.java
@@ -0,0 +1,29 @@
+package com.c2kernel.graph.model;
+
+
+public class GraphModelCastorData
+{
+ public String mClassNameOfVertexOutlineCreator = "";
+ public Vertex[] mVertexImpls = {};
+ public DirectedEdge[] mEdgeImpls = {};
+ public int mStartVertexId = 0;
+ public int mNextId = 0;
+
+
+ public GraphModelCastorData()
+ {
+ }
+
+ public GraphModelCastorData(String classNameOfVertexOutlineCreator,
+ Vertex[] vertexImpls,
+ DirectedEdge[] edgeImpls,
+ int startVertexId,
+ int nextId)
+ {
+ mClassNameOfVertexOutlineCreator = classNameOfVertexOutlineCreator;
+ mVertexImpls = vertexImpls;
+ mEdgeImpls = edgeImpls;
+ mStartVertexId = startVertexId;
+ mNextId = nextId;
+ }
+}
diff --git a/source/com/c2kernel/graph/model/GraphModelManager.java b/source/com/c2kernel/graph/model/GraphModelManager.java
new file mode 100755
index 0000000..19f2dc3
--- /dev/null
+++ b/source/com/c2kernel/graph/model/GraphModelManager.java
@@ -0,0 +1,142 @@
+package com.c2kernel.graph.model;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Observable;
+import java.util.Stack;
+
+import com.c2kernel.graph.event.EntireModelChangedEvent;
+import com.c2kernel.graph.event.ForcedNotifyEvent;
+import com.c2kernel.graph.event.GraphModelEvent;
+import com.c2kernel.utils.Logger;
+
+
+public class GraphModelManager extends Observable
+{
+
+ private GraphModel mGraphModel;
+ private EdgeFactory mEdgeFactory;
+ private VertexFactory mVertexFactory;
+ private VertexOutlineCreator mVertexOutlineCreator;
+ private EntireModelChangedEvent mEntireModelChangedEvent = new EntireModelChangedEvent();
+ private ForcedNotifyEvent mForcedNotifyEvent = new ForcedNotifyEvent();
+ private Stack mParentModels = new Stack();
+ private ArrayList mParentIds = new ArrayList();
+ private boolean mEditable = true;
+
+ // Calling this constructor does not create a vertex outline creator
+ // which is required by the method addVertexAndCreateId()
+ public GraphModelManager()
+ {
+ mGraphModel = new GraphModel();
+ mGraphModel.setManager(this);
+ }
+
+ public GraphModelManager(GraphModel newModel) {
+ newModel.setManager(this);
+ mGraphModel = newModel;
+ }
+
+ public void replace(GraphModel newModel) {
+ mParentModels.clear();
+
+ //zoom back to where we were
+ for (Iterator iter = mParentIds.iterator(); iter.hasNext();) {
+ Integer parentId = (Integer) iter.next();
+ GraphableVertex childModelVertex = (GraphableVertex)newModel.getVertexById(parentId.intValue());
+ if (childModelVertex == null) { // we've been deleted, stay here
+ Logger.msg(7, "Didn't find "+parentId+" in new model tree. Stopping here.");
+ do { iter.remove(); } while (iter.hasNext());
+ break;
+ }
+ else {
+ mParentModels.push(newModel);
+ Logger.msg(7, "Pushing model and switching to "+parentId);
+ newModel = childModelVertex.getChildGraphModel();
+ }
+ }
+ setModel(newModel);
+ }
+
+ public void setModel(GraphModel newModel) {
+ // reset transient data
+ newModel.mSelection = new Selection(null, null, 0, 0, 0, 0);
+ newModel.mNewEdgeOriginVertex = null;
+ newModel.mNewEdgeEndPoint = null;
+
+ // copy factories over
+ newModel.setExternalEdgeFactory(mEdgeFactory);
+ newModel.setExternalVertexFactory(mVertexFactory);
+ newModel.setVertexOutlineCreator(mVertexOutlineCreator);
+ mVertexFactory.setCreationContext(newModel.getContainingVertex());
+ newModel.setManager(this);
+ mGraphModel.setManager(null);
+ mGraphModel = newModel;
+
+ // notify
+ setChanged();
+ notifyObservers(mEntireModelChangedEvent);
+ }
+
+ public void zoomIn(Vertex child) {
+ GraphModel childModel = child.getChildGraphModel();
+ if (childModel != null) {
+ mParentModels.push(mGraphModel);
+ mParentIds.add(new Integer(child.getID()));
+ setModel(childModel);
+ Logger.msg(7, "ZoomIn - Stack size: "+mParentModels.size()+" ids:"+mParentIds.size());
+ }
+ }
+
+ public void zoomOut() {
+ if (!mParentModels.empty()) {
+ setModel((GraphModel)mParentModels.pop());
+ mParentIds.remove(mParentIds.size()-1);
+ }
+ Logger.msg(7, "ZoomOut - Stack size: "+mParentModels.size()+" ids:"+mParentIds.size());
+
+ }
+
+ public void forceNotify()
+ {
+ setChanged();
+ notifyObservers(mForcedNotifyEvent);
+ }
+
+ public GraphModel getModel() {
+ return mGraphModel;
+ }
+
+ public void setExternalEdgeFactory(EdgeFactory newEdgeFactory) {
+ mEdgeFactory = newEdgeFactory;
+ mGraphModel.setExternalEdgeFactory(newEdgeFactory);
+ }
+
+ public void setExternalVertexFactory(VertexFactory newVertexFactory) {
+ mVertexFactory = newVertexFactory;
+ mGraphModel.setExternalVertexFactory(newVertexFactory);
+ }
+
+ public void setVertexOutlineCreator(VertexOutlineCreator newVertexOutlineCreator) {
+ mVertexOutlineCreator = newVertexOutlineCreator;
+ mGraphModel.setVertexOutlineCreator(newVertexOutlineCreator);
+ }
+
+ protected void setChanged() {
+ super.setChanged();
+ }
+
+ protected void notifyObservers(GraphModelEvent ev) {
+ super.notifyObservers(ev);
+ }
+
+ public void setEditable(boolean editable) {
+ mEditable = editable;
+ }
+
+ public boolean isEditable() {
+ return mEditable;
+ }
+
+
+}
diff --git a/source/com/c2kernel/graph/model/GraphPoint.java b/source/com/c2kernel/graph/model/GraphPoint.java
new file mode 100755
index 0000000..c1c6ccc
--- /dev/null
+++ b/source/com/c2kernel/graph/model/GraphPoint.java
@@ -0,0 +1,18 @@
+package com.c2kernel.graph.model;
+
+import java.io.Serializable;
+
+public class GraphPoint implements Serializable{
+
+ public int x;
+ public int y;
+
+ public GraphPoint() {
+ x=0; y=0;
+ }
+
+ public GraphPoint(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+}
diff --git a/source/com/c2kernel/graph/model/Graphable.java b/source/com/c2kernel/graph/model/Graphable.java
new file mode 100755
index 0000000..5dde105
--- /dev/null
+++ b/source/com/c2kernel/graph/model/Graphable.java
@@ -0,0 +1,53 @@
+package com.c2kernel.graph.model;
+
+/**
+* @version $Revision: 1.6 $ $Date: 2003/05/12 13:10:20 $
+* @author $Author: abranson $
+*/
+
+import com.c2kernel.utils.CastorHashMap;
+
+abstract public class Graphable extends Vertex
+{
+
+ protected CastorHashMap mProperties = null;
+ public GraphModel children;
+
+ public void setProperties(CastorHashMap props)
+ {
+ mProperties = props;
+ }
+
+ public CastorHashMap getProperties()
+ {
+ return mProperties;
+ }
+ /** @associates Graphable that is directly containing it*/
+ private Graphable parent;
+
+ /**
+ * Returns the parent.
+ * @return Graphable
+ */
+ public Graphable getParent()
+ {
+ return parent;
+ }
+
+ /**
+ * Sets the parent.
+ * @param parent The parent to set
+ */
+ public void setParent(Graphable parent)
+ {
+ this.parent = parent;
+ }
+ public GraphModel getChildGraphModel() {
+ return children;
+ }
+
+ public Object getCreationContext() {
+ return this;
+ }
+
+}
diff --git a/source/com/c2kernel/graph/model/GraphableEdge.java b/source/com/c2kernel/graph/model/GraphableEdge.java
new file mode 100755
index 0000000..a6d9a63
--- /dev/null
+++ b/source/com/c2kernel/graph/model/GraphableEdge.java
@@ -0,0 +1,71 @@
+package com.c2kernel.graph.model;
+
+import com.c2kernel.utils.CastorHashMap;
+import com.c2kernel.utils.KeyValuePair;
+
+/**
+* @version $Revision: 1.2 $ $Date: 2003/05/12 13:10:20 $
+* @author $Author: abranson $
+*/
+public abstract class GraphableEdge extends DirectedEdge
+{
+
+ private GraphableVertex mParent;
+ private CastorHashMap mProperties = null;
+
+ public GraphableEdge()
+ {
+ mProperties = new CastorHashMap();
+ }
+
+ public GraphableEdge(GraphableVertex pre, GraphableVertex nex)
+ {
+ mProperties = new CastorHashMap();
+ setParent(pre.getParent());
+ pre.getParent().getChildrenGraphModel().addEdgeAndCreateId(this, pre, nex);
+ }
+
+ /**
+ * Returns the parent.
+ * @return GraphableVertex
+ */
+ public GraphableVertex getParent()
+ {
+ return mParent;
+ }
+
+ /**
+ * Sets the parent.
+ * @param parent The parent to set
+ */
+ public void setParent(GraphableVertex parent)
+ {
+ mParent = parent;
+ }
+
+ /**
+ * Returns the properties.
+ * @return CastorHashMap
+ */
+ public CastorHashMap getProperties()
+ {
+ return mProperties;
+ }
+
+ /**
+ * Sets the properties.
+ * @param properties The properties to set
+ */
+ public void setProperties(CastorHashMap properties)
+ {
+ mProperties = properties;
+ }
+
+ public KeyValuePair[] getKeyValuePairs() {
+ return mProperties.getKeyValuePairs();
+ }
+
+ public void setKeyValuePairs(KeyValuePair[] pairs) {
+ mProperties.setKeyValuePairs(pairs);
+ }
+}
diff --git a/source/com/c2kernel/graph/model/GraphableVertex.java b/source/com/c2kernel/graph/model/GraphableVertex.java
new file mode 100755
index 0000000..6efd298
--- /dev/null
+++ b/source/com/c2kernel/graph/model/GraphableVertex.java
@@ -0,0 +1,254 @@
+package com.c2kernel.graph.model;
+/**
+* @version $Revision: 1.24 $ $Date: 2005/10/05 07:39:37 $
+* @author $Author: abranson $
+*/
+import java.awt.Point;
+import com.c2kernel.utils.CastorHashMap;
+import com.c2kernel.utils.KeyValuePair;
+public abstract class GraphableVertex extends Vertex
+{
+ private CastorHashMap mProperties = null;
+ private boolean mIsLayoutable;
+ protected boolean mIsComposite;
+ private GraphModel mChildrenGraphModel;
+ public GraphableVertex()
+ {
+ mProperties = new CastorHashMap();
+ }
+ public void setProperties(CastorHashMap props)
+ {
+ mProperties = props;
+ }
+ public CastorHashMap getProperties()
+ {
+ return mProperties;
+ }
+ public KeyValuePair[] getKeyValuePairs()
+ {
+ return mProperties.getKeyValuePairs();
+ }
+ public void setKeyValuePairs(KeyValuePair[] pairs)
+ {
+ mProperties.setKeyValuePairs(pairs);
+ }
+ /** @associates Graphable that is directly containing it*/
+ private GraphableVertex parent;
+ /**
+ * Returns the parent.
+ * @return Graphable
+ */
+ public GraphableVertex getParent()
+ {
+ return parent;
+ }
+ /**
+ * Sets the parent.
+ * @param parent The parent to set
+ */
+ public void setParent(GraphableVertex parent)
+ {
+ if (this.equals(parent))
+ throw new ExceptionInInitializerError();
+ this.parent = parent;
+ }
+ public GraphModel getChildGraphModel()
+ {
+ return mChildrenGraphModel;
+ }
+ public Object getCreationContext()
+ {
+ return this;
+ }
+ public Vertex[] getOutGraphables()
+ {
+ if (parent == null)
+ return new Vertex[0]; // none if no parent
+ return parent.mChildrenGraphModel.getOutVertices(this);
+ }
+ public DirectedEdge[] getOutEdges()
+ {
+ if (parent == null)
+ return new DirectedEdge[0]; // none if no parent
+ return parent.mChildrenGraphModel.getOutEdges(this);
+ }
+ public DirectedEdge[] getInEdges()
+ {
+ if (parent == null)
+ return new DirectedEdge[0]; // none if no parent
+ DirectedEdge[] edges = getParent().mChildrenGraphModel.getInEdges(this);
+ if (edges != null)
+ return edges;
+ else
+ return new DirectedEdge[0];
+ }
+ public GraphableVertex[] getChildren()
+ {
+ return getLayoutableChildren();
+ }
+
+ public DirectedEdge[] getChildrenEdges()
+ {
+ if (getIsComposite())
+ {
+ return getChildGraphModel().getEdges();
+ }
+ return null;
+ }
+
+ public GraphableVertex[] getLayoutableChildren()
+ {
+ if (getIsComposite())
+ {
+ Vertex[] vs = mChildrenGraphModel.getVertices();
+ GraphableVertex[] gvs = new GraphableVertex[vs.length];
+ for (int i = 0; i < vs.length; i++)
+ {
+ gvs[i] = (GraphableVertex) vs[i];
+ }
+ return gvs;
+ }
+ return null;
+ }
+ // deprecated methods
+ public GraphableVertex[] getCNonLayoutableChildren() {
+ return new GraphableVertex[0];
+ }
+ public void setCNonLayoutableChildren(GraphableVertex[] dummy) { }
+
+ /**@returns the Graphable searched or null if not this or children*/
+ public GraphableVertex search(String ids)
+ {
+ if (getName().equals(ids))
+ return this;
+ if (String.valueOf(getID()).equals(ids))
+ return this;
+ if (getIsComposite())
+ {
+ GraphableVertex[] graphables = getChildren();
+ if (ids.startsWith(String.valueOf(getID())))
+ ids = ids.substring(ids.indexOf("/") + 1);
+ else if (ids.startsWith(getName()))
+ ids = ids.substring(getName().length() + 1);
+ else if (ids.startsWith(getPath()))
+ ids = ids.substring(getPath().length() + 1);
+ else
+ return null;
+
+ for (int i = 0; i < graphables.length; i++) {
+ GraphableVertex grap = graphables[i].search(ids);
+ if (grap != null) return grap;
+ }
+ }
+ return null;
+ }
+ /**
+ * Returns the isLayoutable.
+ * @return boolean
+ */
+ public boolean getIsLayoutable()
+ {
+ return mIsLayoutable;
+ }
+ /**
+ * Sets the isLayoutable.
+ * @param isLayoutable The isLayoutable to set
+ */
+ public void setIsLayoutable(boolean isLayoutable)
+ {
+ mIsLayoutable = isLayoutable;
+ }
+ /**
+ * Returns the isComposite.
+ * @return boolean
+ */
+ public boolean getIsComposite()
+ {
+ return mIsComposite;
+ }
+ /**
+ * Sets the isComposite.
+ * @param isComposite The isComposite to set
+ */
+ public void setIsComposite(boolean isComposite)
+ {
+ mIsComposite = isComposite;
+ }
+ public void addChild(GraphableVertex graphableVertex, Point p)
+ {
+ addChild(graphableVertex, new GraphPoint(p.x, p.y));
+ }
+ public void addChild(GraphableVertex graphableVertex, GraphPoint g)
+ {
+ getChildGraphModel().addVertexAndCreateId(graphableVertex, g);
+ graphableVertex.setParent(this);
+ }
+ /**
+ * Returns the childrenGraph.
+ * @return GraphModel
+ */
+ public GraphModel getChildrenGraphModel()
+ {
+ return mChildrenGraphModel;
+ }
+ /**
+ * Sets the childrenGraph.
+ * @param childrenGraph The childrenGraph to set
+ */
+ public void setChildrenGraphModel(GraphModel childrenGraph)
+ {
+ mChildrenGraphModel = childrenGraph;
+ DirectedEdge[] edges = mChildrenGraphModel.getEdges();
+ GraphableVertex[] graphables = this.getLayoutableChildren();
+ if (graphables != null)
+ for (int i = 0; i < graphables.length; i++)
+ graphables[i].setParent(this);
+ if (edges != null)
+ for (int i = 0; i < edges.length; i++)
+ ((GraphableEdge) edges[i]).setParent(this);
+ childrenGraph.setContainingVertex(this);
+ }
+
+ /**
+ * @see com.c2kernel.graph.model.Vertex#getCentrePoint()
+ */
+ public GraphPoint getCentrePoint()
+ {
+ if (!getIsLayoutable())
+ return null;
+ return super.getCentrePoint();
+ }
+ /**
+ * @see com.c2kernel.graph.model.Vertex#getInEdgeIds()
+ */
+ public int[] getInEdgeIds()
+ {
+ if (!getIsLayoutable())
+ return null;
+ return super.getInEdgeIds();
+ }
+ /**
+ * @see com.c2kernel.graph.model.Vertex#getOutEdgeIds()
+ */
+ public int[] getOutEdgeIds()
+ {
+ if (!getIsLayoutable())
+ return null;
+ return super.getOutEdgeIds();
+ }
+ /**
+ * @see com.c2kernel.graph.model.Vertex#getOutlinePoints()
+ */
+ public GraphPoint[] getOutlinePoints()
+ {
+ if (!getIsLayoutable())
+ return null;
+ return super.getOutlinePoints();
+ }
+ public String getPath()
+ {
+ if (getName() != null && !getName().equals(""))
+ return getParent().getPath() + "/" + getName();
+ return getParent().getPath() + "/" + getID();
+ }
+} \ No newline at end of file
diff --git a/source/com/c2kernel/graph/model/Selection.java b/source/com/c2kernel/graph/model/Selection.java
new file mode 100755
index 0000000..dcc7b46
--- /dev/null
+++ b/source/com/c2kernel/graph/model/Selection.java
@@ -0,0 +1,35 @@
+package com.c2kernel.graph.model;
+
+import java.io.Serializable;
+
+
+
+public class Selection implements Serializable
+{
+ // Either a single edge can be selected or
+ // one or more vertices can be selected.
+ // It is impossible to select an edge and a
+ // vertex at the same time.
+ public DirectedEdge mEdge = null;
+ public Vertex[] mVertices = null;
+ public int mTopLeftX = 0;
+ public int mTopLeftY = 0;
+ public int mBottomRightX = 0;
+ public int mBottomRightY = 0;
+
+
+ public Selection(DirectedEdge edge,
+ Vertex[] vertices,
+ int topLeftX,
+ int topLeftY,
+ int bottomRightX,
+ int bottomRightY)
+ {
+ mEdge = edge;
+ mVertices = vertices;
+ mTopLeftX = topLeftX;
+ mTopLeftY = topLeftY;
+ mBottomRightX = bottomRightX;
+ mBottomRightY = bottomRightY;
+ }
+}
diff --git a/source/com/c2kernel/graph/model/TypeNameAndConstructionInfo.java b/source/com/c2kernel/graph/model/TypeNameAndConstructionInfo.java
new file mode 100755
index 0000000..6443064
--- /dev/null
+++ b/source/com/c2kernel/graph/model/TypeNameAndConstructionInfo.java
@@ -0,0 +1,23 @@
+package com.c2kernel.graph.model;
+
+import java.io.Serializable;
+
+
+public class TypeNameAndConstructionInfo implements Serializable
+{
+ public String mName = null;
+ public Object mInfo = null;
+
+
+ public TypeNameAndConstructionInfo(String name, Object info)
+ {
+ mName = name;
+ mInfo = info;
+ }
+
+
+ public String toString()
+ {
+ return mName;
+ }
+}
diff --git a/source/com/c2kernel/graph/model/Vertex.java b/source/com/c2kernel/graph/model/Vertex.java
new file mode 100755
index 0000000..1e8399b
--- /dev/null
+++ b/source/com/c2kernel/graph/model/Vertex.java
@@ -0,0 +1,308 @@
+package com.c2kernel.graph.model;
+
+import java.awt.Polygon;
+import java.io.Serializable;
+import java.util.Vector;
+
+
+public class Vertex implements Serializable
+{
+ private int mId = -1;
+ private String mName = "";
+ private GraphPoint mCentrePoint = new GraphPoint(0, 0);
+ private int mHeight = 0;
+ private int mWidth = 0;
+ private Vector mInEdgeIdVector = new Vector();
+ private Vector mOutEdgeIdVector = new Vector();
+ private Vector mTags = new Vector();
+
+ // The Java Polygon class is used to determine if a point
+ // lies within the outline of a vertex. Unfortunately
+ // both the polygon and the set of outline points need to
+ // kept in memory because a polygon never has 0 points
+ // which is required by Castor's unmarshall object mechanism
+ private Polygon mOutlinePolygon = new Polygon();
+ private GraphPoint[] mOutlinePoints = new GraphPoint[0];
+
+
+ private GraphModel graphModel;
+
+ public void setID(int id)
+ {
+ mId = id;
+ }
+
+
+ public int getID()
+ {
+ return mId;
+ }
+
+
+ public void setName(String n)
+ {
+ mName = n;
+ }
+
+
+ public String getName()
+ {
+ return mName;
+ }
+
+
+ public void setCentrePoint(GraphPoint p)
+ {
+ mCentrePoint = p;
+ }
+
+
+ public GraphPoint getCentrePoint()
+ {
+ return mCentrePoint;
+ }
+
+
+ public void setHeight(int h)
+ {
+ mHeight = h;
+ }
+
+
+ public int getHeight()
+ {
+ return mHeight;
+ }
+
+
+ public void setWidth(int w)
+ {
+ mWidth = w;
+ }
+
+
+ public int getWidth()
+ {
+ return mWidth;
+ }
+
+
+ // Sets the outline points and re-calculates the
+ // height and width
+ public void setOutlinePoints(GraphPoint[] outline)
+ {
+ int topLeftX = outline[0].x;
+ int topLeftY = outline[0].y;
+ int bottomRightX = 0;
+ int bottomRightY = 0;
+ int i = 0;
+
+ mOutlinePoints = outline;
+
+ // Construct a polygon in the outline of the vertex
+ // and calculate the top left and bottom right corners
+ mOutlinePolygon = new Polygon();
+
+ for(i=0; i<outline.length; i++)
+ {
+ mOutlinePolygon.addPoint(outline[i].x, outline[i].y);
+
+ if(outline[i].x < topLeftX)
+ {
+ topLeftX = outline[i].x;
+ }
+
+ if(outline[i].y < topLeftY)
+ {
+ topLeftY = outline[i].y;
+ }
+
+ if(outline[i].x > bottomRightX)
+ {
+ bottomRightX = outline[i].x;
+ }
+
+
+ if(outline[i].y > bottomRightY)
+ {
+ bottomRightY = outline[i].y;
+ }
+ }
+
+ // Set the height and width
+ mHeight = bottomRightY - topLeftY;
+ mWidth = bottomRightX - topLeftX;
+ }
+
+
+ public GraphPoint[] getOutlinePoints()
+ {
+ return mOutlinePoints;
+ }
+
+ public void moveAbsolute(GraphPoint p)
+ {
+ int deltaX = p.x - mCentrePoint.x;
+ int deltaY = p.y - mCentrePoint.y;
+ int i = 0;
+
+ // Update the outline points and the polygon
+ for(i=0; i<mOutlinePoints.length; i++)
+ {
+ mOutlinePoints[i].x += deltaX;
+ mOutlinePoints[i].y += deltaY;
+ }
+
+ mOutlinePolygon.translate(deltaX, deltaY);
+
+ mCentrePoint.x = p.x;
+ mCentrePoint.y = p.y;
+ }
+
+
+ public boolean containsPoint(GraphPoint p)
+ {
+ return mOutlinePolygon.contains(p.x, p.y);
+ }
+
+
+ public void setInEdgeIds(int[] ids)
+ {
+ int i = 0;
+
+ mInEdgeIdVector = new Vector(10, 10);
+ for(i=0; i<ids.length; i++)
+ mInEdgeIdVector.add(new Integer(ids[i]));
+ }
+
+
+ public int[] getInEdgeIds()
+ {
+ return integerVectorToIntArray(mInEdgeIdVector);
+ }
+
+
+ public void setOutEdgeIds(int[] ids)
+ {
+ int i = 0;
+
+ mOutEdgeIdVector = new Vector(10, 10);
+ for(i=0; i<ids.length; i++)
+ mOutEdgeIdVector.add(new Integer(ids[i]));
+ }
+
+
+ public int[] getOutEdgeIds()
+ {
+ return integerVectorToIntArray(mOutEdgeIdVector);
+ }
+
+
+ private int[] integerVectorToIntArray(Vector vector)
+ {
+ int[] array = new int[vector.size()];
+ Integer integer = null;
+ int i = 0;
+
+ for(i=0; i<array.length; i++)
+ {
+ integer = (Integer)vector.elementAt(i);
+ array[i] = integer.intValue();
+ }
+
+ return array;
+ }
+
+
+ public void addInEdgeId(int id)
+ {
+ mInEdgeIdVector.add(new Integer(id));
+ }
+
+
+ public void removeInEdgeId(int id)
+ {
+ Integer integer = null;
+ int i = 0;
+
+ for(i=0; i<mInEdgeIdVector.size(); i++)
+ {
+ integer = (Integer)mInEdgeIdVector.elementAt(i);
+
+ if(integer.intValue() == id)
+ {
+ mInEdgeIdVector.removeElementAt(i);
+ return;
+ }
+ }
+ }
+
+
+ public void addOutEdgeId(int id)
+ {
+ mOutEdgeIdVector.add(new Integer(id));
+ }
+
+
+ public void removeOutEdgeId(int id)
+ {
+ Integer integer = null;
+ int i = 0;
+
+ for(i=0; i<mOutEdgeIdVector.size(); i++)
+ {
+ integer = (Integer)mOutEdgeIdVector.elementAt(i);
+
+ if(integer.intValue() == id)
+ {
+ mOutEdgeIdVector.removeElementAt(i);
+ return;
+ }
+ }
+ }
+
+
+ public void setTag(Object o)
+ {
+ mTags.add(o);
+ }
+
+
+ public boolean hasTag(Object o)
+ {
+ return mTags.contains(o);
+ }
+
+ public void clearTag(Object o)
+ {
+ mTags.remove(o);
+ }
+
+
+ public GraphModel getChildGraphModel() {
+ return null;
+ }
+
+ public Object getCreationContext() {
+ return null;
+ }
+
+
+ public GraphModel getGraphModel()
+ {
+ return graphModel;
+ }
+
+ public void setGraphModel(GraphModel graphModel)
+ {
+ this.graphModel = graphModel;
+ }
+
+ public boolean isJoin() {
+ return false;
+ }
+ public boolean isLoop() {
+ return false;
+ }
+
+}
diff --git a/source/com/c2kernel/graph/model/VertexFactory.java b/source/com/c2kernel/graph/model/VertexFactory.java
new file mode 100755
index 0000000..f47d9a6
--- /dev/null
+++ b/source/com/c2kernel/graph/model/VertexFactory.java
@@ -0,0 +1,16 @@
+package com.c2kernel.graph.model;
+
+import java.awt.Point;
+
+
+public interface VertexFactory
+{
+ public void create
+ (
+ GraphModelManager graphModelManager,
+ Point location,
+ TypeNameAndConstructionInfo typeNameAndConstructionInfo
+ );
+
+ public void setCreationContext(Object newContext);
+}
diff --git a/source/com/c2kernel/graph/model/VertexOutlineCreator.java b/source/com/c2kernel/graph/model/VertexOutlineCreator.java
new file mode 100755
index 0000000..627395e
--- /dev/null
+++ b/source/com/c2kernel/graph/model/VertexOutlineCreator.java
@@ -0,0 +1,10 @@
+package com.c2kernel.graph.model;
+
+
+
+// Classes that implement this interface must
+// have a parameter less constructor
+public interface VertexOutlineCreator
+{
+ public void setOutline(Vertex vertex);
+}
diff --git a/source/com/c2kernel/graph/traversal/GraphTraversal.java b/source/com/c2kernel/graph/traversal/GraphTraversal.java
new file mode 100755
index 0000000..abf30f7
--- /dev/null
+++ b/source/com/c2kernel/graph/traversal/GraphTraversal.java
@@ -0,0 +1,85 @@
+package com.c2kernel.graph.traversal;
+
+
+import java.util.Vector;
+
+import com.c2kernel.graph.model.GraphModel;
+import com.c2kernel.graph.model.Vertex;
+
+
+public class GraphTraversal
+{
+ public static final int kUp = 1;
+ public static final int kDown = 2;
+
+
+ private GraphTraversal()
+ {
+ }
+
+
+ public static Vertex[] getTraversal(GraphModel graphModel, Vertex startVertex, int direction, boolean ignoreBackLinks)
+ {
+ Vector path = new Vector(10, 10);
+
+ graphModel.clearTags(startVertex);
+ visitVertex(startVertex, graphModel, path, direction, startVertex, ignoreBackLinks);
+
+ return vectorToVertexArray(path);
+ }
+
+
+ private static void visitVertex(Vertex vertex, GraphModel graphModel, Vector path, int direction, Object tag, boolean ignoreBackLinks)
+ {
+ Vertex[] children = null;
+ int i = 0;
+
+ if(direction == kDown)
+ {
+ children = graphModel.getOutVertices(vertex);
+ }
+ else
+ {
+ children = graphModel.getInVertices(vertex);
+ }
+
+ vertex.setTag(tag);
+ path.add(vertex);
+
+ for(i=0; i<children.length; i++)
+ {
+ if(!(children[i].hasTag(tag)))
+ {
+ boolean skipBackLink = false;
+ if ( ignoreBackLinks &&
+ ((vertex.isJoin() && direction == kUp) ||
+ (vertex.isLoop() && direction == kDown))) {
+ Vertex[] following = getTraversal(graphModel, children[i], direction, false);
+ for (int j = 0; j < following.length; j++) {
+ if (following[j] == vertex) {
+ skipBackLink = true;
+ break;
+ }
+ }
+ }
+ if (!skipBackLink)
+ visitVertex(children[i], graphModel, path, direction, tag, ignoreBackLinks);
+ }
+ }
+ }
+
+
+ private static Vertex[] vectorToVertexArray(Vector vector)
+ {
+ Vertex[] vertices = new Vertex[vector.size()];
+ int i = 0;
+
+
+ for(i=0; i<vertices.length; i++)
+ {
+ vertices[i] = (Vertex)vector.elementAt(i);
+ }
+
+ return vertices;
+ }
+}
diff --git a/source/com/c2kernel/graph/view/DefaultDirectedEdgeRenderer.java b/source/com/c2kernel/graph/view/DefaultDirectedEdgeRenderer.java
new file mode 100755
index 0000000..b8c4081
--- /dev/null
+++ b/source/com/c2kernel/graph/view/DefaultDirectedEdgeRenderer.java
@@ -0,0 +1,75 @@
+package com.c2kernel.graph.view;
+
+import java.awt.Graphics2D;
+import java.awt.Paint;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.GeneralPath;
+
+import com.c2kernel.graph.model.DirectedEdge;
+import com.c2kernel.graph.model.GraphPoint;
+
+
+public class DefaultDirectedEdgeRenderer implements DirectedEdgeRenderer
+{
+ private GeneralPath mArrowTemplate = new GeneralPath();
+ private Paint mLinePaint = null;
+
+
+ public DefaultDirectedEdgeRenderer(Paint linePaint)
+ {
+ mLinePaint = linePaint;
+
+ mArrowTemplate.moveTo(-5, 5);
+ mArrowTemplate.lineTo( 0, 0);
+ mArrowTemplate.lineTo( 5, 5);
+ }
+
+
+ public void draw(Graphics2D g2d, DirectedEdge directedEdge)
+ {
+ GraphPoint originPoint = directedEdge.getOriginPoint();
+ GraphPoint terminusPoint = directedEdge.getTerminusPoint();
+ GraphPoint midPoint = new GraphPoint();
+ AffineTransform transform = new AffineTransform();
+ Shape arrow = null;
+
+ g2d.setPaint(mLinePaint);
+ g2d.drawLine(originPoint.x, originPoint.y, terminusPoint.x, terminusPoint.y);
+
+ midPoint.x = originPoint.x + (terminusPoint.x - originPoint.x)/2;
+ midPoint.y = originPoint.y + (terminusPoint.y - originPoint.y)/2;
+
+ transform.translate(midPoint.x, midPoint.y);
+ transform.rotate(calcArrowAngle(originPoint.x, originPoint.y, terminusPoint.x, terminusPoint.y));
+
+ arrow = mArrowTemplate.createTransformedShape(transform);
+
+ g2d.draw(arrow);
+ }
+
+
+ private double calcArrowAngle(int originX, int originY, int terminusX, int terminusY) {
+ double width = terminusX - originX;
+ double height = terminusY - originY;
+ double theta = 0;
+
+ if((width == 0) && (height > 0)) return Math.PI;
+
+ if((width == 0) && (height < 0)) return 0;
+
+ if((width > 0) && (height == 0)) return Math.PI/2.0;
+
+ if((width < 0) && (height == 0)) return -1.0 * Math.PI/2.0;
+
+ if((width > 0) && (height > 0)) return Math.PI/2.0 + Math.atan(Math.abs(height)/Math.abs(width));
+
+ if((width > 0) && (height < 0)) return Math.atan(Math.abs(width)/Math.abs(height));
+
+ if((width < 0) && (height < 0)) return -1.0 * Math.atan(Math.abs(width)/Math.abs(height));
+
+ if((width < 0) && (height > 0)) return -1.0 * (Math.PI/2.0 + Math.atan(Math.abs(height)/Math.abs(width)));
+
+ return 0.0;
+ }
+}
diff --git a/source/com/c2kernel/graph/view/DefaultVertexRenderer.java b/source/com/c2kernel/graph/view/DefaultVertexRenderer.java
new file mode 100755
index 0000000..6f57185
--- /dev/null
+++ b/source/com/c2kernel/graph/view/DefaultVertexRenderer.java
@@ -0,0 +1,59 @@
+package com.c2kernel.graph.view;
+
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.Paint;
+import java.awt.Polygon;
+
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.graph.model.Vertex;
+
+
+public class DefaultVertexRenderer implements VertexRenderer
+{
+ private Paint mLinePaint = null;
+ private Paint mTextPaint = null;
+ private Paint mFillPaint = null;
+
+
+ public DefaultVertexRenderer(Paint linePaint, Paint textPaint, Paint fillPaint)
+ {
+ mLinePaint = linePaint;
+ mTextPaint = textPaint;
+ mFillPaint = fillPaint;
+ }
+
+
+ public void draw(Graphics2D g2d, Vertex vertex)
+ {
+ GraphPoint[] outlinePoints = vertex.getOutlinePoints();
+ GraphPoint centrePoint = vertex.getCentrePoint();
+ Polygon outline = new Polygon();
+
+ String vertexName = vertex.getName();
+ FontMetrics metrics = g2d.getFontMetrics();
+ int textWidth = metrics.stringWidth(vertexName);
+ int textHeight = metrics.getHeight();
+ int textX = centrePoint.x - textWidth/2;
+ int textY = centrePoint.y + textHeight/3;
+
+ int i = 0;
+
+
+ // Construct a shape in the outline of the vertex
+ for(i=0; i<outlinePoints.length; i++)
+ {
+ outline.addPoint(outlinePoints[i].x, outlinePoints[i].y);
+ }
+
+ // Fill and then draw the outline
+ g2d.setPaint(mFillPaint);
+ g2d.fill(outline);
+ g2d.setPaint(mLinePaint);
+ g2d.draw(outline);
+
+ // Write the name of the vertex in the centre of the outline
+ g2d.setPaint(mTextPaint);
+ g2d.drawString(vertexName, textX, textY);
+ }
+}
diff --git a/source/com/c2kernel/graph/view/DirectedEdgeRenderer.java b/source/com/c2kernel/graph/view/DirectedEdgeRenderer.java
new file mode 100755
index 0000000..6937922
--- /dev/null
+++ b/source/com/c2kernel/graph/view/DirectedEdgeRenderer.java
@@ -0,0 +1,11 @@
+package com.c2kernel.graph.view;
+
+import java.awt.Graphics2D;
+
+import com.c2kernel.graph.model.DirectedEdge;
+
+
+public interface DirectedEdgeRenderer
+{
+ public void draw(Graphics2D g2d, DirectedEdge directedEdge);
+}
diff --git a/source/com/c2kernel/graph/view/EditorModeListener.java b/source/com/c2kernel/graph/view/EditorModeListener.java
new file mode 100755
index 0000000..c3a4a8a
--- /dev/null
+++ b/source/com/c2kernel/graph/view/EditorModeListener.java
@@ -0,0 +1,8 @@
+package com.c2kernel.graph.view;
+
+
+
+public interface EditorModeListener
+{
+ public void editorModeChanged(String idOfNewMode);
+}
diff --git a/source/com/c2kernel/graph/view/EditorPanel.java b/source/com/c2kernel/graph/view/EditorPanel.java
new file mode 100755
index 0000000..78fb5c9
--- /dev/null
+++ b/source/com/c2kernel/graph/view/EditorPanel.java
@@ -0,0 +1,100 @@
+package com.c2kernel.graph.view;
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+
+import javax.swing.JButton;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+
+import com.c2kernel.graph.controller.AutoScrollController;
+import com.c2kernel.graph.controller.EdgeConstructionController;
+import com.c2kernel.graph.controller.MultiSelectionDragController;
+import com.c2kernel.graph.controller.VertexConstructionController;
+import com.c2kernel.graph.model.*;
+public class EditorPanel extends JPanel
+{
+ // Graph Model
+ public final GraphModelManager mGraphModelManager = new GraphModelManager();
+ // Graph View
+ public GraphPanel mGraphPanel = null;
+ protected JScrollPane mGraphScrollPane = null;
+ // Graph Controllers
+ protected MultiSelectionDragController mMultiSelectionDragController = new MultiSelectionDragController();
+ protected VertexConstructionController mVertexConstructionController = new VertexConstructionController();
+ protected EdgeConstructionController mEdgeConstructionController = new EdgeConstructionController();
+ protected AutoScrollController mAutoScrollController = new AutoScrollController();
+ // Tool bar
+ protected EditorToolBar mEditorToolBar = null;
+ protected EditorPanel()
+ {
+ }
+ public EditorPanel(EdgeFactory eFactory, VertexFactory vFactory, VertexOutlineCreator vOutlineCreator, boolean edgeCreationMode, // True
+ // if
+ // edges
+ // can
+ // be
+ // created
+ JButton[] otherButtons, GraphPanel graphPanel)
+ {
+ // Create the graph panel and editor tool bar
+ setDoubleBuffered(true);
+ mGraphPanel = graphPanel;
+ mGraphPanel.setGraphModelManager(mGraphModelManager);
+ mGraphScrollPane = new JScrollPane(mGraphPanel);
+ mGraphModelManager.setExternalEdgeFactory(eFactory);
+ mGraphModelManager.setExternalVertexFactory(vFactory);
+ mGraphModelManager.setVertexOutlineCreator(vOutlineCreator);
+ mEditorToolBar = new EditorToolBar(edgeCreationMode, otherButtons, graphPanel);
+ mEditorToolBar.setGraphModelManager(mGraphModelManager);
+ mEditorToolBar.setGraphPanel(mGraphPanel);
+ createLayout();
+ // The graph panel observes the graph model
+ mGraphModelManager.addObserver(mGraphPanel);
+ // The multi selection drag controller modifies the graph model
+ // and listens to the graph panel and editor tool bar
+ mMultiSelectionDragController.setGraphModelManager(mGraphModelManager);
+ mGraphPanel.addMouseListener(mMultiSelectionDragController);
+ mGraphPanel.addMouseMotionListener(mMultiSelectionDragController);
+ mGraphPanel.addKeyListener(mMultiSelectionDragController);
+ mEditorToolBar.addEditorModeListener(mMultiSelectionDragController);
+ // The edge construction controller modifies the graph model
+ // and listens to the graph panel and editor tool bar
+ mEdgeConstructionController.setGraphModelManager(mGraphModelManager);
+ mGraphPanel.addMouseListener(mEdgeConstructionController);
+ mGraphPanel.addMouseMotionListener(mEdgeConstructionController);
+ mEdgeConstructionController.setEditorToolBar(mEditorToolBar);
+ // The vertex construction controller modifies the graph model
+ // and listens to the graph panel and editor tool bar
+ mVertexConstructionController.setGraphModelManager(mGraphModelManager);
+ mGraphPanel.addMouseListener(mVertexConstructionController);
+ mVertexConstructionController.setEditorToolBar(mEditorToolBar);
+ // The auto scroll controller listens to and modifies the
+ // graph panel
+ mAutoScrollController.setGraphPanel(mGraphPanel);
+ }
+
+ protected void createLayout()
+ {
+ setLayout(new BorderLayout());
+ add(mEditorToolBar, BorderLayout.NORTH);
+ mGraphPanel.setPreferredSize(new Dimension(mGraphModelManager.getModel().getWidth(), mGraphModelManager.getModel().getHeight()));
+ add(mGraphScrollPane, BorderLayout.CENTER);
+ }
+ public void enterSelectMode()
+ {
+ mEditorToolBar.enterSelectMode();
+ }
+ public void updateEdgeTypes(TypeNameAndConstructionInfo[] typeNameAndConstructionInfo)
+ {
+ mEditorToolBar.updateEdgeTypes(typeNameAndConstructionInfo);
+ }
+ public void updateVertexTypes(TypeNameAndConstructionInfo[] typeNameAndConstructionInfo)
+ {
+ mEditorToolBar.updateVertexTypes(typeNameAndConstructionInfo);
+ }
+ public void setEditable(boolean editable)
+ {
+ mGraphModelManager.setEditable(editable);
+ mEditorToolBar.setGraphEditable(editable);
+ }
+}
diff --git a/source/com/c2kernel/graph/view/EditorToolBar.java b/source/com/c2kernel/graph/view/EditorToolBar.java
new file mode 100755
index 0000000..2730ab7
--- /dev/null
+++ b/source/com/c2kernel/graph/view/EditorToolBar.java
@@ -0,0 +1,336 @@
+package com.c2kernel.graph.view;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.Insets;
+import java.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.ClipboardOwner;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.print.PageFormat;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+import java.util.Vector;
+
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JToggleButton;
+
+import com.c2kernel.graph.controller.DeletionController;
+import com.c2kernel.graph.controller.StartVertexController;
+import com.c2kernel.graph.model.GraphModelManager;
+import com.c2kernel.graph.model.TypeNameAndConstructionInfo;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.Resource;
+/**
+ * Tool bar with mode toggle buttons, start and delete buttons, and the possibility to add other arbitrary buttons at constructions time.
+ */
+public class EditorToolBar extends Box implements Printable
+{
+ protected boolean mEdgeCreationMode = false; // True if edges can be created
+ protected GraphPanel mGraphPanel = null;
+ // There is on mode button listener per mode button.
+ // When a mode button fires anaction performed event
+ // its corresponding listener notifies all of the
+ // editor mode listeners.
+ protected class ModeButtonListener implements ActionListener
+ {
+ protected String mModeId = null;
+ public ModeButtonListener(String modeId)
+ {
+ mModeId = modeId;
+ }
+ public void actionPerformed(ActionEvent ae)
+ {
+ notifyListeners(mModeId);
+ }
+ }
+ // Vertex types and ids
+ protected JComboBox mVertexTypeBox = new JComboBox();
+ // Edge types and ids
+ protected JComboBox mEdgeTypeBox = new JComboBox();
+ // Mode buttons
+ protected ButtonGroup mModeButtonGroup = new ButtonGroup();
+ protected JToggleButton mVertexModeButton = new JToggleButton(Resource.getImageResource("graph/newvertex.png"));
+ protected JToggleButton mSelectModeButton = new JToggleButton(Resource.getImageResource("graph/selection.gif"));
+ protected JToggleButton mEdgeModeButton = new JToggleButton(Resource.getImageResource("graph/edge.png"));
+ // Normal buttons
+ protected JButton[] mOtherButtons = null;
+ protected JButton mStartButton = new JButton(Resource.getImageResource("graph/start.png"));
+ protected JButton mDeleteButton = new JButton(Resource.getImageResource("graph/delete.png"));
+ protected JButton mPrintButton = new JButton(Resource.getImageResource("graph/print.png"));
+ protected JButton mCopyButton = new JButton(Resource.getImageResource("graph/copy.png"));
+ // Controllers
+ protected StartVertexController mStartVertexController = new StartVertexController();
+ protected DeletionController mDeletionController = new DeletionController();
+ // Editor mode listeners
+ protected Vector mListenerVector = new Vector(10, 10);
+ public EditorToolBar(boolean edgeCreationMode, // True if edges can be created
+ JButton[] otherButtons, GraphPanel graphP)
+ {
+ super(BoxLayout.X_AXIS);
+ mGraphPanel = graphP;
+ mEdgeCreationMode = edgeCreationMode;
+ mOtherButtons = otherButtons;
+ prepareModeButtons();
+ mStartVertexController.setStartButton(mStartButton);
+ mDeletionController.setDeleteButton(mDeleteButton);
+ createLayout();
+ createListeners();
+ }
+ protected void prepareModeButtons()
+ {
+ // Set the tool tip texts
+ mVertexModeButton.setToolTipText(Language.translate("Create vertex"));
+ mSelectModeButton.setToolTipText(Language.translate("Multi-select and drag"));
+ mEdgeModeButton.setToolTipText(Language.translate("Create edge"));
+ mStartButton.setToolTipText(Language.translate("Select the start vertex of the graph"));
+ mDeleteButton.setToolTipText(Language.translate("Delete the selection"));
+ mPrintButton.setToolTipText(Language.translate("Print this graph"));
+ mPrintButton.setToolTipText(Language.translate("Copy an image of this graph to the clipboard"));
+ // Set the button margins to 0
+ mVertexModeButton.setMargin(new Insets(0, 0, 0, 0));
+ mSelectModeButton.setMargin(new Insets(0, 0, 0, 0));
+ mEdgeModeButton.setMargin(new Insets(0, 0, 0, 0));
+ // The initial mode is select mode
+ mSelectModeButton.setSelected(true);
+ // Add the mode buttons to the mode button group
+ mModeButtonGroup.add(mVertexModeButton);
+ mModeButtonGroup.add(mSelectModeButton);
+ mModeButtonGroup.add(mEdgeModeButton);
+ // Add the action listeners
+ mVertexModeButton.addActionListener(new ModeButtonListener("Vertex"));
+ mSelectModeButton.addActionListener(new ModeButtonListener("Select"));
+ mEdgeModeButton.addActionListener(new ModeButtonListener("Edge"));
+ }
+ public void enterSelectMode()
+ {
+ mSelectModeButton.setSelected(true);
+ notifyListeners("Select");
+ }
+ public void updateVertexTypes(TypeNameAndConstructionInfo[] typeNameAndConstructionInfo)
+ {
+ int i = 0;
+ mVertexTypeBox.removeAllItems();
+ for (i = 0; i < typeNameAndConstructionInfo.length; i++)
+ {
+ mVertexTypeBox.addItem(typeNameAndConstructionInfo[i]);
+ }
+ }
+ public void updateEdgeTypes(TypeNameAndConstructionInfo[] typeNameAndConstructionInfo)
+ {
+ int i = 0;
+ mEdgeTypeBox.removeAllItems();
+ for (i = 0; i < typeNameAndConstructionInfo.length; i++)
+ {
+ mEdgeTypeBox.addItem(typeNameAndConstructionInfo[i]);
+ }
+ }
+ public TypeNameAndConstructionInfo getSelectedVertexType()
+ {
+ return (TypeNameAndConstructionInfo) mVertexTypeBox.getSelectedItem();
+ }
+ public TypeNameAndConstructionInfo getSelectedEdgeType()
+ {
+ return (TypeNameAndConstructionInfo) mEdgeTypeBox.getSelectedItem();
+ }
+ protected void createLayout()
+ {
+ int i = 0;
+ add(mSelectModeButton);
+ add(mVertexModeButton);
+ add(mVertexTypeBox);
+ add(Box.createHorizontalStrut(10));
+ if (mEdgeCreationMode)
+ {
+ add(mEdgeModeButton);
+ add(mEdgeTypeBox);
+ }
+ add(Box.createGlue());
+ mPrintButton.setEnabled(true);
+ mPrintButton.setMargin(new Insets(0, 0, 0, 0));
+ add(mPrintButton);
+ mCopyButton.setEnabled(true);
+ mCopyButton.setMargin(new Insets(0, 0, 0, 0));
+ add(mCopyButton);
+ mStartButton.setEnabled(false);
+ mStartButton.setMargin(new Insets(0, 0, 0, 0));
+ mDeleteButton.setEnabled(false);
+ mDeleteButton.setMargin(new Insets(0, 0, 0, 0));
+ add(mDeleteButton);
+ add(Box.createRigidArea(new Dimension(20, 0)));
+ add(mStartButton);
+ if (mOtherButtons != null)
+ {
+ for (i = 0; i < mOtherButtons.length; i++)
+ {
+ mOtherButtons[i].setMargin(new Insets(0, 0, 0, 0));
+ add(mOtherButtons[i]);
+ }
+ }
+ }
+ protected void createListeners()
+ {
+ // The vertex mode button should be selected if the
+ // user select a vertex type from the vertex type box
+ mVertexTypeBox.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent ae)
+ {
+ mVertexModeButton.setSelected(true);
+ notifyListeners("Vertex");
+ }
+ });
+ // The edge mode button should be selected if the
+ // user select an edge type from the edge type box
+ mEdgeTypeBox.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent ae)
+ {
+ mEdgeModeButton.setSelected(true);
+ notifyListeners("Edge");
+ }
+ });
+ mPrintButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent ae)
+ {
+ PrinterJob _monJob = PrinterJob.getPrinterJob();
+ if (_monJob.printDialog())
+ _monJob.setPrintable(self());
+ try
+ {
+ _monJob.print();
+ }
+ catch (Exception ex)
+ {
+ }
+ }
+ });
+
+ try {
+ Class.forName("java.awt.datatransfer.DataFlavor").getDeclaredField("imageFlavor");
+ mCopyButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent ae)
+ {
+ try
+ {
+ Image i = createImage(mGraphPanel.getWidth(),mGraphPanel.getHeight());
+ Graphics g = i.getGraphics();
+ mGraphPanel.paintComponent(g);
+ ImageTransferable it = new ImageTransferable(i, mGraphPanel.getWidth(), mGraphPanel.getHeight());
+ Toolkit.getDefaultToolkit().getSystemClipboard().setContents(it, it);
+ }
+ catch (Exception e)
+ {
+ Logger.error(e);
+ }
+ }
+ });
+ } catch (Exception ex) { //image clipboard transfer not supported
+ mCopyButton.setEnabled(false);
+ }
+ }
+
+ protected class ImageTransferable implements Transferable, ClipboardOwner {
+ Image image;
+ int width,height;
+ DataFlavor javaImg;
+ public ImageTransferable(Image image, int width, int height) {
+ this.image = image;
+ this.width = width;
+ this.height = height;
+ try {
+ javaImg = new DataFlavor("image/x-java-image; class=java.awt.Image", "AWT Image");
+ } catch (Exception ex){ }
+ }
+ public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
+ if (!isDataFlavorSupported(flavor) || image == null) {
+ throw new UnsupportedFlavorException(flavor);
+ }
+ return image;
+ }
+
+ public boolean isDataFlavorSupported(DataFlavor flavor) {
+ boolean result = in(flavor, getTransferDataFlavors());
+ return result;
+ }
+
+ public DataFlavor[] getTransferDataFlavors() {
+ return new DataFlavor[] { javaImg };
+ }
+ protected boolean in(DataFlavor flavor, DataFlavor[] flavors) {
+ int f = 0;
+ while ((f < flavors.length) && !flavor.equals(flavors[f])) {
+ f++;
+ }
+ return f < flavors.length;
+ }
+ public void lostOwnership(Clipboard clipboard, Transferable contents) {
+ image = null;
+ }
+ }
+
+ protected void notifyListeners(String newModeId)
+ {
+ int i = 0;
+ EditorModeListener listener = null;
+ for (i = 0; i < mListenerVector.size(); i++)
+ {
+ listener = (EditorModeListener) mListenerVector.elementAt(i);
+ listener.editorModeChanged(newModeId);
+ }
+ }
+ public void setGraphModelManager(GraphModelManager graphModelManager)
+ {
+ mStartVertexController.setGraphModelManager(graphModelManager);
+ mDeletionController.setGraphModelManager(graphModelManager);
+ }
+ public void setGraphPanel(GraphPanel graphPanel)
+ {
+ graphPanel.addKeyListener(mDeletionController);
+ }
+ public void addEditorModeListener(EditorModeListener listener)
+ {
+ mListenerVector.add(listener);
+ }
+ public void removeEditorModeListener(EditorModeListener listener)
+ {
+ mListenerVector.remove(listener);
+ }
+ public void setGraphEditable(boolean editable)
+ {
+ mVertexModeButton.setEnabled(editable);
+ mEdgeModeButton.setEnabled(editable);
+ }
+ public EditorToolBar self()
+ {
+ return this;
+ }
+ public int print(Graphics g, PageFormat pf, int i) throws PrinterException
+ {
+ if (i >= 1)
+ {
+ return Printable.NO_SUCH_PAGE;
+ }
+ Graphics2D g2d = (Graphics2D) g;
+ double scalex = pf.getImageableWidth() / mGraphPanel.getWidth();
+ double scaley = pf.getImageableHeight() / mGraphPanel.getHeight();
+ double scale = Math.min(Math.min(scalex, scaley), 1);
+ g2d.translate(pf.getImageableX(), pf.getImageableY());
+ g2d.scale(scale, scale);
+ mGraphPanel.printComponent(g2d);
+ return Printable.PAGE_EXISTS;
+ }
+}
diff --git a/source/com/c2kernel/graph/view/GraphPanel.java b/source/com/c2kernel/graph/view/GraphPanel.java
new file mode 100755
index 0000000..9db481e
--- /dev/null
+++ b/source/com/c2kernel/graph/view/GraphPanel.java
@@ -0,0 +1,274 @@
+package com.c2kernel.graph.view;
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.Paint;
+import java.awt.Point;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.Observable;
+import java.util.Observer;
+
+import javax.swing.JPanel;
+
+import com.c2kernel.graph.event.EntireModelChangedEvent;
+import com.c2kernel.graph.event.GraphModelResizedEvent;
+import com.c2kernel.graph.model.DirectedEdge;
+import com.c2kernel.graph.model.ElasticBand;
+import com.c2kernel.graph.model.GraphModelManager;
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.graph.model.Selection;
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.utils.Resource;
+public class GraphPanel extends JPanel implements Observer
+{
+ protected final Paint mSelectionPaint = Color.black;
+ protected final Paint mStartPaint = Color.green;
+ protected final Image mResizePadImg = Resource.getImageResource("graph/resizepad.gif").getImage();
+ protected final BasicStroke mDashed =
+ new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, new float[] { 5.0f }, 0.0f);
+ protected GraphModelManager mGraphModelManager = null;
+ protected VertexRenderer mVertexRenderer = null;
+ protected DirectedEdgeRenderer mDirectedEdgeRenderer = null;
+ public GraphPanel(DirectedEdgeRenderer eRenderer, VertexRenderer vRenderer)
+ {
+ mVertexRenderer = vRenderer;
+ mDirectedEdgeRenderer = eRenderer;
+ // Request the keyboard focus if the mouse
+ // is pressed on the graph panel
+ addMouseListener(new MouseAdapter()
+ {
+ public void mousePressed(MouseEvent me)
+ {
+ requestFocus();
+ }
+ });
+ }
+ public void setGraphModelManager(GraphModelManager graphModelManager)
+ {
+ mGraphModelManager = graphModelManager;
+ }
+ public void update(Observable o, Object arg)
+ {
+ if (arg instanceof GraphModelResizedEvent || arg instanceof EntireModelChangedEvent)
+ {
+ setPreferredSize(new Dimension(mGraphModelManager.getModel().getWidth(), mGraphModelManager.getModel().getHeight()));
+ revalidate();
+ }
+ repaint();
+ }
+ public void paintComponent(Graphics g)
+ {
+ Graphics2D g2d = (Graphics2D) g;
+ DirectedEdge[] edges = null;
+ Vertex[] vertices = null;
+ Vertex startVertex = null;
+ Selection selection = null;
+ ElasticBand elasticBand = null;
+ Vertex newEdgeOriginVertex = null;
+ GraphPoint newEdgeOriginPoint = null;
+ Point newEdgeEndPoint = null;
+ GraphPoint vertexCentre = null;
+ int i = 0;
+ super.paintComponent(g);
+ if (mGraphModelManager != null)
+ {
+ // Get the edges and vertices from the model
+ edges = mGraphModelManager.getModel().getEdges();
+ vertices = mGraphModelManager.getModel().getVertices();
+ //graphable = mGraphModelManager.getModel().
+ // Draw the edges
+ for (i = 0; i < edges.length; i++)
+ {
+ mDirectedEdgeRenderer.draw(g2d, edges[i]);
+ }
+ // Draw the vertices
+ for (i = 0; i < vertices.length; i++)
+ {
+ mVertexRenderer.draw(g2d, vertices[i]);
+ }
+ g2d.setPaint(mStartPaint);
+ // Highlight the start vertex if there is one
+ startVertex = mGraphModelManager.getModel().getStartVertex();
+ if (startVertex != null)
+ {
+ drawVertexHighlight(g2d, startVertex, 1);
+ }
+ // Get the present selection
+ selection = mGraphModelManager.getModel().getSelection();
+ g2d.setPaint(mSelectionPaint);
+ // Draw the outline of the selected
+ // vertices if there are any
+ if (selection.mVertices != null)
+ {
+ g2d.setStroke(mDashed);
+ for (i = 0; i < selection.mVertices.length; i++)
+ {
+ if (selection.mVertices[i] != mGraphModelManager.getModel().getContainingVertex())
+ drawVertexHighlight(g2d, selection.mVertices[i], 5);
+ }
+ // Draw the resize pads if there is one and only one vertex selected
+ if (selection.mVertices.length == 1 &&
+ selection.mVertices[0] != mGraphModelManager.getModel().getContainingVertex())
+ {
+ vertexCentre = selection.mVertices[0].getCentrePoint();
+ g2d.drawImage(
+ mResizePadImg,
+ vertexCentre.x + selection.mVertices[0].getWidth() / 2,
+ vertexCentre.y + selection.mVertices[0].getHeight() / 2,
+ this);
+ }
+ }
+ // Draw the outline of the selected
+ // edge if there is one
+ if (selection.mEdge != null)
+ {
+ drawEdgeHighlight(g2d, selection.mEdge);
+ }
+ // Get the elastic band
+ elasticBand = mGraphModelManager.getModel().getElasticBand();
+ // Draw the elastic band if there
+ // is one
+ if (elasticBand != null)
+ {
+ g2d.drawLine(
+ elasticBand.mFixedCorner.x,
+ elasticBand.mFixedCorner.y,
+ elasticBand.mMovingCorner.x,
+ elasticBand.mFixedCorner.y);
+ g2d.drawLine(
+ elasticBand.mMovingCorner.x,
+ elasticBand.mFixedCorner.y,
+ elasticBand.mMovingCorner.x,
+ elasticBand.mMovingCorner.y);
+ g2d.drawLine(
+ elasticBand.mMovingCorner.x,
+ elasticBand.mMovingCorner.y,
+ elasticBand.mFixedCorner.x,
+ elasticBand.mMovingCorner.y);
+ g2d.drawLine(
+ elasticBand.mFixedCorner.x,
+ elasticBand.mMovingCorner.y,
+ elasticBand.mFixedCorner.x,
+ elasticBand.mFixedCorner.y);
+ }
+ // Draw the new edge under construction if there is one
+ newEdgeEndPoint = mGraphModelManager.getModel().getNewEdgeEndPoint();
+ newEdgeOriginVertex = mGraphModelManager.getModel().getNewEdgeOriginVertex();
+ if ((newEdgeEndPoint != null) && (newEdgeOriginVertex != null))
+ {
+ newEdgeOriginPoint = newEdgeOriginVertex.getCentrePoint();
+ g2d.setPaint(Color.black);
+ g2d.drawLine(newEdgeOriginPoint.x, newEdgeOriginPoint.y, newEdgeEndPoint.x, newEdgeEndPoint.y);
+ }
+ }
+ }
+ // Draws the highlight of the specified vertex the specified dist from its outline
+ protected void drawVertexHighlight(Graphics2D g2d, Vertex vertex, int dist)
+ {
+ GraphPoint[] outlinePoints = vertex.getOutlinePoints();
+ GraphPoint centrePoint = vertex.getCentrePoint();
+ int i = 0;
+ /*
+ * float dash1[] ={5.0f}; BasicStroke bs = new BasicStroke(5.0f, BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND,10.0f, dash1,0.0f);
+ */
+ for (i = 0; i < outlinePoints.length - 1; i++)
+ {
+ drawShiftedLine(dist, g2d, centrePoint, outlinePoints[i].x, outlinePoints[i].y, outlinePoints[i + 1].x, outlinePoints[i + 1].y);
+ }
+ drawShiftedLine(
+ dist,
+ g2d,
+ centrePoint,
+ outlinePoints[outlinePoints.length - 1].x,
+ outlinePoints[outlinePoints.length - 1].y,
+ outlinePoints[0].x,
+ outlinePoints[0].y);
+ }
+ // Draws the specifed line the specified distance away from the specified centre point
+ private void drawShiftedLine(int dist, Graphics2D g2d, GraphPoint centrePoint, int x1, int y1, int x2, int y2)
+ {
+ if (x1 > centrePoint.x)
+ x1 += dist;
+ if (x1 < centrePoint.x)
+ x1 -= dist;
+ if (y1 > centrePoint.y)
+ y1 += dist;
+ if (y1 < centrePoint.y)
+ y1 -= dist;
+ if (x2 > centrePoint.x)
+ x2 += dist;
+ if (x2 < centrePoint.x)
+ x2 -= dist;
+ if (y2 > centrePoint.y)
+ y2 += dist;
+ if (y2 < centrePoint.y)
+ y2 -= dist;
+ g2d.drawLine(x1, y1, x2, y2);
+ }
+ // Draws the highlight of the specified edge
+ protected void drawEdgeHighlight(Graphics2D g2d, DirectedEdge edge)
+ {
+ GraphPoint originPoint = edge.getOriginPoint();
+ GraphPoint terminusPoint = edge.getTerminusPoint();
+ int midX = originPoint.x + (terminusPoint.x - originPoint.x) / 2;
+ int midY = originPoint.y + (terminusPoint.y - originPoint.y) / 2;
+ int minX = midX - 10;
+ int minY = midY - 10;
+ int maxX = midX + 10;
+ int maxY = midY + 10;
+ g2d.drawLine(minX, minY, maxX, minY);
+ g2d.drawLine(maxX, minY, maxX, maxY);
+ g2d.drawLine(maxX, maxY, minX, maxY);
+ g2d.drawLine(minX, maxY, minX, minY);
+ }
+ public void printComponent(Graphics g)
+ {
+ super.paintComponent(g);
+ Graphics2D g2d = (Graphics2D) g;
+ DirectedEdge[] edges = null;
+ Vertex[] vertices = null;
+ Vertex startVertex = null;
+ Selection selection = null;
+ ElasticBand elasticBand = null;
+ Vertex newEdgeOriginVertex = null;
+ GraphPoint newEdgeOriginPoint = null;
+ Point newEdgeEndPoint = null;
+ GraphPoint vertexCentre = null;
+ int i = 0;
+ g.setColor(Color.white);
+ g2d.fillRect(0,0,getWidth(),getHeight());
+ if (mGraphModelManager != null)
+ {
+ // Get the edges and vertices from the model
+ edges = mGraphModelManager.getModel().getEdges();
+ vertices = mGraphModelManager.getModel().getVertices();
+ //graphable = mGraphModelManager.getModel().
+ // Draw the edges
+ for (i = 0; i < edges.length; i++)
+ {
+ mDirectedEdgeRenderer.draw(g2d, edges[i]);
+ }
+ // Draw the vertices
+ for (i = 0; i < vertices.length; i++)
+ {
+ mVertexRenderer.draw(g2d, vertices[i]);
+ }
+ g2d.setPaint(mStartPaint);
+ // Highlight the start vertex if there is one
+ startVertex = mGraphModelManager.getModel().getStartVertex();
+ if (startVertex != null)
+ {
+ drawVertexHighlight(g2d, startVertex, 1);
+ }
+ }
+ }
+
+ protected void superPaint(Graphics g)
+ {
+ super.paintComponent(g);
+ }
+}
diff --git a/source/com/c2kernel/graph/view/PropertyTable.java b/source/com/c2kernel/graph/view/PropertyTable.java
new file mode 100755
index 0000000..e067e68
--- /dev/null
+++ b/source/com/c2kernel/graph/view/PropertyTable.java
@@ -0,0 +1,38 @@
+package com.c2kernel.graph.view;
+
+import javax.swing.JTable;
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableCellRenderer;
+
+
+public class PropertyTable extends JTable
+{
+ public PropertyTable(PropertyTableModel tableModel)
+ {
+ super(tableModel);
+ }
+
+
+ public TableCellRenderer getCellRenderer(int row, int column) {
+
+
+ return getDefaultRenderer(getCellClass(row, column));
+
+ }
+
+ public TableCellEditor getCellEditor(int row, int column) {
+
+ return getDefaultEditor(getCellClass(row, column));
+
+ }
+
+ private Class getCellClass(int row, int column) {
+ Class cellClass = String.class;
+
+ try {
+ cellClass = dataModel.getValueAt(row, column).getClass();
+ } catch (NullPointerException ex) { }
+
+ return cellClass;
+ }
+}
diff --git a/source/com/c2kernel/graph/view/PropertyTableModel.java b/source/com/c2kernel/graph/view/PropertyTableModel.java
new file mode 100755
index 0000000..9755cf6
--- /dev/null
+++ b/source/com/c2kernel/graph/view/PropertyTableModel.java
@@ -0,0 +1,125 @@
+package com.c2kernel.graph.view;
+
+import java.util.*;
+
+import javax.swing.JOptionPane;
+import javax.swing.event.TableModelEvent;
+import javax.swing.table.AbstractTableModel;
+
+import com.c2kernel.utils.Language;
+
+/**************************************************************************
+ *
+ * $Revision: 1.4 $
+ * $Date: 2005/08/02 07:50:10 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class PropertyTableModel extends AbstractTableModel {
+
+ private String[] mColumnNames = { Language.translate("Name"), Language.translate("Value") };
+ HashMap sourceMap = new HashMap();
+ ArrayList sortedNameList = new ArrayList();
+ boolean isEditable = false;
+
+ public PropertyTableModel() {
+ super();
+ }
+
+ public int getColumnCount()
+ {
+ return mColumnNames.length;
+ }
+ public String getColumnName(int col)
+ {
+ return mColumnNames[col];
+ }
+ public int getRowCount()
+ {
+ synchronized (sourceMap) {
+ return sourceMap.size();
+ }
+ }
+ public Object getValueAt(int rowIndex, int colIndex)
+ {
+ synchronized (sourceMap) {
+ String rowName = (String)sortedNameList.get(rowIndex);
+ if (colIndex == 0)
+ return rowName;
+ else
+ return sourceMap.get(rowName);
+ }
+ }
+
+ public void setValueAt(Object value, int rowIndex, int colIndex)
+ {
+ synchronized (sourceMap) {
+ if (colIndex == 0) return;
+ String rowName = (String)sortedNameList.get(rowIndex);
+ Class oldElement = sourceMap.get(rowName).getClass();
+ if (oldElement == Float.class && value.getClass() == String.class)
+ try {
+ value = Float.valueOf((String)value);
+ } catch (Exception ex) { }
+ if (value.getClass() != oldElement)
+ JOptionPane.showMessageDialog(null, "This property should contain a "+oldElement.getName()+" not a "+value.getClass().getName(), "Incorrect datatype", JOptionPane.ERROR_MESSAGE);
+ else {
+ sourceMap.put(rowName, value);
+ fireTableCellUpdated(rowIndex, colIndex);
+ }
+ }
+ }
+
+ public void setMap(HashMap props) {
+ synchronized (sourceMap) {
+ sourceMap = props;
+ sortedNameList = new ArrayList(props.size());
+ for (Iterator keys = props.keySet().iterator(); keys.hasNext();)
+ sortedNameList.add(keys.next());
+
+ Collections.sort(sortedNameList, new Comparator() {
+ public int compare(Object o1, Object o2) {
+ return ((String)o1).compareToIgnoreCase((String)o2);
+ }
+ });
+ }
+ fireTableChanged(new TableModelEvent(this));
+ }
+
+ public boolean isCellEditable(int row, int col)
+ {
+ return col==1 && isEditable;
+ }
+
+ /**
+ * @return Returns the isEditable.
+ */
+ public boolean isEditable() {
+ return isEditable;
+ }
+ /**
+ * @param isEditable The isEditable to set.
+ */
+ public void setEditable(boolean isEditable) {
+ this.isEditable = isEditable;
+ }
+
+ /**
+ * @param text
+ * @param object
+ */
+ public void addProperty(String text, Object object) {
+ sourceMap.put(text,object);
+ setMap(sourceMap);
+ }
+
+ /**
+ * @param object
+ */
+ public void delProperty(Object propName) {
+ sourceMap.remove(propName);
+ setMap(sourceMap);
+ }
+}
diff --git a/source/com/c2kernel/graph/view/SelectedVertexPanel.java b/source/com/c2kernel/graph/view/SelectedVertexPanel.java
new file mode 100755
index 0000000..18658dd
--- /dev/null
+++ b/source/com/c2kernel/graph/view/SelectedVertexPanel.java
@@ -0,0 +1,27 @@
+package com.c2kernel.graph.view;
+
+import javax.swing.JPanel;
+
+import com.c2kernel.graph.model.Vertex;
+
+/**************************************************************************
+ *
+ * $Revision: 1.1 $
+ * $Date: 2005/05/12 10:12:52 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+
+
+public abstract class SelectedVertexPanel extends JPanel {
+
+ public SelectedVertexPanel() {
+ super();
+ }
+
+ public abstract void select(Vertex vert);
+
+ public abstract void clear();
+}
diff --git a/source/com/c2kernel/graph/view/VertexPropertyPanel.java b/source/com/c2kernel/graph/view/VertexPropertyPanel.java
new file mode 100755
index 0000000..be08b53
--- /dev/null
+++ b/source/com/c2kernel/graph/view/VertexPropertyPanel.java
@@ -0,0 +1,245 @@
+package com.c2kernel.graph.view;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.lang.reflect.Constructor;
+import java.util.HashMap;
+import java.util.Observable;
+import java.util.Observer;
+
+import javax.swing.*;
+import javax.swing.event.TableModelEvent;
+import javax.swing.event.TableModelListener;
+
+import com.c2kernel.graph.event.EntireModelChangedEvent;
+import com.c2kernel.graph.event.SelectionChangedEvent;
+import com.c2kernel.graph.model.*;
+import com.c2kernel.gui.tabs.EntityTabPane;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+
+/**************************************************************************
+ *
+ * $Revision: 1.4 $
+ * $Date: 2005/09/09 12:19:28 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class VertexPropertyPanel extends JPanel implements Observer, TableModelListener, ActionListener {
+
+ private PropertyTableModel mPropertyModel;
+ private PropertyTable mPropertyTable;
+ private GraphModelManager mGraphModelManager;
+ private boolean isEditable = false;
+ GridBagLayout gridbag = new GridBagLayout();
+ protected JLabel selObjName;
+ protected JLabel selObjClass;
+ JButton addPropButton;
+ JButton delPropButton;
+ Box newPropBox;
+ private JTextField newPropName;
+ private JComboBox newPropType;
+ String[] typeOptions = { "String", "Boolean", "Integer", "Float" };
+ String[] typeInitVal = { "", "false", "0", "0.0"};
+ SelectedVertexPanel mSelPanel;
+
+ public VertexPropertyPanel() {
+ super();
+ setLayout(gridbag);
+ mPropertyModel = new PropertyTableModel();
+ mPropertyModel.addTableModelListener(this);
+ mPropertyTable = new PropertyTable(mPropertyModel);
+ }
+
+ /**
+ *
+ */
+
+ public void update(Observable o, Object arg) {
+ Vertex[] selectedVertices = null;
+ DirectedEdge selectedEdge = null;
+ // If the selection has changed
+ if (arg instanceof SelectionChangedEvent)
+ {
+ SelectionChangedEvent event = (SelectionChangedEvent) arg;
+ selectedVertices = event.mSelection.mVertices;
+ if (selectedVertices != null)
+ {
+ if (selectedVertices.length == 1)
+ {
+ setVertex(selectedVertices[0]);
+ return;
+ }
+ }
+ selectedEdge = event.mSelection.mEdge;
+ if (selectedEdge != null)
+ {
+ setEdge(selectedEdge);
+ return;
+ }
+ }
+ if (arg instanceof SelectionChangedEvent || arg instanceof EntireModelChangedEvent){
+ clear();
+ }
+ }
+
+
+ public void tableChanged(TableModelEvent e) {
+ if (mGraphModelManager!=null)
+ mGraphModelManager.forceNotify();
+
+ }
+
+ public void setVertex(Vertex vert) {
+ if (vert.getName().equals("domain"))
+ selObjName.setText("Domain Workflow");
+ else
+ selObjName.setText(vert.getName());
+ String className = vert.getClass().getName();
+ selObjClass.setText(className.substring(className.lastIndexOf('.')+1));
+ if (mSelPanel != null) mSelPanel.select(vert);
+ if (vert instanceof GraphableVertex) {
+ mPropertyModel.setMap(((GraphableVertex)vert).getProperties());
+ addPropButton.setEnabled(isEditable);
+ delPropButton.setEnabled(isEditable);
+ }
+ }
+
+ public void setEdge(DirectedEdge edge) {
+ selObjName.setText(edge.getName());
+ String className = edge.getClass().getName();
+ selObjClass.setText(className.substring(className.lastIndexOf('.')+1));
+ if (edge instanceof GraphableEdge) {
+ mPropertyModel.setMap(((GraphableEdge)edge).getProperties());
+ addPropButton.setEnabled(isEditable);
+ delPropButton.setEnabled(isEditable);
+ }
+ if (mSelPanel != null) mSelPanel.clear();
+ }
+
+ public void clear() {
+ selObjName.setText("");
+ selObjClass.setText("Nothing Selected");
+ mPropertyModel.setMap(new HashMap());
+ if (mSelPanel != null) mSelPanel.clear();
+ addPropButton.setEnabled(false);
+ delPropButton.setEnabled(false);
+ }
+
+ /**
+ * @param isEditable The isEditable to set.
+ */
+ public void setEditable(boolean editable) {
+ mPropertyModel.setEditable(editable);
+ isEditable = editable;
+ newPropBox.setVisible(editable);
+ }
+
+ public void setGraphModelManager(GraphModelManager manager) {
+ mGraphModelManager = manager;
+ manager.addObserver(this);
+ }
+
+ public void createLayout(SelectedVertexPanel selPanel)
+ {
+ GridBagConstraints c = new GridBagConstraints();
+ c.gridx = 0;
+ c.gridy = 0;
+ c.weightx = 1;
+ c.weighty = 0;
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.ipadx = 5;
+ c.ipady = 5;
+
+ selObjName = new JLabel();
+ selObjName.setFont(EntityTabPane.titleFont);
+ gridbag.setConstraints(selObjName, c);
+ add(selObjName);
+
+ c.gridy++;
+ selObjClass = new JLabel();
+ gridbag.setConstraints(selObjClass, c);
+ add(selObjClass);
+
+ c.gridy++;
+ JLabel title = new JLabel("Properties");
+ title.setFont(EntityTabPane.titleFont);
+ gridbag.setConstraints(title, c);
+ add(title);
+
+ c.gridy++;
+ c.fill = GridBagConstraints.BOTH;
+ c.weighty = 2;
+ JScrollPane scroll = new JScrollPane(mPropertyTable);
+ gridbag.setConstraints(scroll, c);
+ add(scroll);
+
+ newPropBox = Box.createHorizontalBox();
+ newPropBox.add(new JLabel(Language.translate("New :")));
+ newPropBox.add(Box.createHorizontalGlue());
+ newPropName = new JTextField(15);
+ newPropBox.add(newPropName);
+ newPropType = new JComboBox(typeOptions);
+ newPropBox.add(newPropType);
+ newPropBox.add(Box.createHorizontalStrut(1));
+ addPropButton = new JButton("Add");
+ addPropButton.setMargin(new Insets(0, 0, 0, 0));
+ delPropButton = new JButton("Del");
+ delPropButton.setMargin(new Insets(0, 0, 0, 0));
+ addPropButton.addActionListener(this);
+ delPropButton.addActionListener(this);
+ newPropBox.add(addPropButton);
+ newPropBox.add(delPropButton);
+
+ c.gridy++;
+ c.weighty=0;
+ c.fill= GridBagConstraints.HORIZONTAL;
+ gridbag.setConstraints(newPropBox, c);
+ add(newPropBox);
+
+ if (selPanel != null) {
+ c.gridy++;
+ mSelPanel = selPanel;
+ gridbag.setConstraints(mSelPanel, c);
+ add(mSelPanel);
+ }
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ if (e.getSource() == addPropButton) {
+ if (newPropName.getText().length() < 1) {
+ JOptionPane.showMessageDialog(this, "Enter a name for the new property", "Cannot add property", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ if (mPropertyModel.sourceMap.containsKey(newPropName.getText())) {
+ JOptionPane.showMessageDialog(this, "Property '"+newPropName.getText()+"' already exists.", "Cannot add property", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ if (mPropertyTable.getCellEditor() != null)
+ mPropertyTable.getCellEditor().stopCellEditing();
+
+ try {
+ Class newPropClass = Class.forName("java.lang."+typeOptions[newPropType.getSelectedIndex()]);
+ Class[] params = {String.class};
+ Constructor init = newPropClass.getConstructor(params);
+ Object[] initParams = { typeInitVal[newPropType.getSelectedIndex()] };
+ mPropertyModel.addProperty(newPropName.getText(), init.newInstance(initParams));
+ } catch (Exception ex) {
+ Logger.exceptionDialog(ex);
+ }
+ }
+ else if (e.getSource() == delPropButton) {
+ int selrow = mPropertyTable.getSelectedRow();
+ if (selrow == -1) {
+ JOptionPane.showMessageDialog(this, "Select a property to remove", "Cannot delete property", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ mPropertyModel.delProperty(mPropertyModel.sortedNameList.get(selrow));
+ }
+ }
+}
diff --git a/source/com/c2kernel/graph/view/VertexRenderer.java b/source/com/c2kernel/graph/view/VertexRenderer.java
new file mode 100755
index 0000000..1a8d263
--- /dev/null
+++ b/source/com/c2kernel/graph/view/VertexRenderer.java
@@ -0,0 +1,11 @@
+package com.c2kernel.graph.view;
+
+import java.awt.Graphics2D;
+
+import com.c2kernel.graph.model.Vertex;
+
+
+public interface VertexRenderer
+{
+ public void draw(Graphics2D g2d, Vertex vertex);
+}
diff --git a/source/com/c2kernel/gui/Console.java b/source/com/c2kernel/gui/Console.java
new file mode 100755
index 0000000..370413a
--- /dev/null
+++ b/source/com/c2kernel/gui/Console.java
@@ -0,0 +1,269 @@
+package com.c2kernel.gui;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.io.*;
+import java.net.Socket;
+import java.util.Iterator;
+import java.util.Properties;
+
+import javax.swing.*;
+
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.FileStringUtility;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.Resource;
+
+/**************************************************************************
+ *
+ * $Revision: 1.10 $
+ * $Date: 2005/10/05 07:39:37 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class Console extends JFrame {
+ JTextArea output;
+ JScrollPane scroll;
+ JTextField input;
+ JButton sendButton;
+ JButton toFileButton;
+ FileWriter logFile;
+ ConsoleConnection connection;
+ JFileChooser scriptLoader = new JFileChooser();
+ static int bufferSize = Integer.parseInt(Gateway.getProperty("Console.bufferSize", "200"));
+
+ public Console(String host, int port) {
+ super("Cristal Console - "+host);
+ GridBagLayout gridbag = new GridBagLayout();
+ getContentPane().setLayout(gridbag);
+ output = new JTextArea("Type 'help' for help. . .\n");
+ output.setEditable(false);
+ input = new JTextField();
+ setSize(400, 600);
+ sendButton = new JButton("Send");
+ sendButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ submit();
+ }
+ });
+ JButton clearButton = new JButton("Clear");
+ clearButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ synchronized (output) {
+ output.setText("");
+ }
+ }
+ });
+ toFileButton = new JButton("Save");
+ toFileButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ if (logFile == null) {
+ int returnValue = scriptLoader.showSaveDialog(null);
+ switch (returnValue)
+ {
+ case JFileChooser.APPROVE_OPTION :
+ try {
+ logFile = new FileWriter(scriptLoader.getSelectedFile());
+ print ("Starting writing log to "+scriptLoader.getSelectedFile().getAbsolutePath());
+ } catch (Exception ex) {
+ print(ex.getClass().getName()+": "+ex.getMessage());
+ Logger.error(ex);
+ }
+ toFileButton.setText("Stop");
+ case JFileChooser.CANCEL_OPTION :
+ case JFileChooser.ERROR_OPTION :
+ default :
+ }
+ }
+ else {
+ try {
+ logFile.close();
+ } catch (Exception ex) {
+ logFile = null;
+ print(ex.getClass().getName()+": "+ex.getMessage());
+ }
+ logFile = null;
+ toFileButton.setText("Save");
+ }
+ }
+ });
+
+
+ input.addKeyListener(new EnterListener(this));
+
+ scroll = new JScrollPane(output);
+ GridBagConstraints c = new GridBagConstraints();
+ c.gridx=0; c.gridy=0;
+ c.fill=GridBagConstraints.BOTH;
+ c.weightx=1.0;c.weighty=1.0;
+ gridbag.setConstraints(scroll, c);
+ getContentPane().add(scroll);
+
+ Box inputBox = Box.createHorizontalBox();
+ inputBox.add(input);
+ inputBox.add(Box.createHorizontalStrut(5));
+ inputBox.add(sendButton);
+ inputBox.add(clearButton);
+ inputBox.add(toFileButton);
+ c.gridy=1; c.fill=GridBagConstraints.HORIZONTAL;
+ c.weighty=0;
+ gridbag.setConstraints(inputBox, c);
+ getContentPane().add(inputBox);
+
+ try {
+ Properties utilProps = FileStringUtility.loadConfigFile( Resource.getDomainResourceURL("ScriptUtils.conf").toString());
+ Box utilBox = Box.createHorizontalBox();
+ for (Iterator utilIter = utilProps.keySet().iterator(); utilIter.hasNext();) {
+ String name = (String) utilIter.next();
+ String value = utilProps.getProperty(name);
+ JButton newUtil = new JButton(name);
+ newUtil.setActionCommand(value);
+ newUtil.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ processUtil(e.getActionCommand());
+ }
+ });
+ utilBox.add(newUtil);
+ utilBox.add(Box.createHorizontalStrut(5));
+ }
+
+ c.gridy++;
+ gridbag.setConstraints(utilBox, c);
+ getContentPane().add(utilBox);
+ } catch (Exception ex) { // no domain utils
+ }
+
+
+ validate();
+ connection = new ConsoleConnection(host, port, this);
+ new Thread(connection).start();
+ addWindowListener(new java.awt.event.WindowAdapter() {
+ public void windowClosing(java.awt.event.WindowEvent evt) {
+ if (connection!=null) connection.shutdown();
+ dispose();
+ }
+ });
+ }
+
+ public void setVisible(boolean visible) {
+ super.setVisible(visible);
+ if (visible) input.requestFocus();
+ }
+
+ public void processUtil(String command) {
+ int replace;
+ String text = input.getText();
+ while ((replace = command.indexOf("%s")) > -1) {
+ command = command.substring(0, replace)+text+command.substring(replace+2);
+ }
+ connection.sendCommand(command);
+ }
+
+ public void submit() {
+ connection.sendCommand(input.getText());
+ input.setText("");
+ }
+
+ public void print(String line) {
+ synchronized (output) {
+ String currentText = output.getText()+line+"\n";
+ while (output.getLineCount() > bufferSize) {
+ currentText = currentText.substring(currentText.indexOf("\n")+1);
+ output.setText(currentText);
+ }
+ output.setText(currentText);
+ output.setCaretPosition(output.getText().length());
+ if (logFile != null) try {
+ logFile.write(line+"\n");
+ } catch (IOException ex) {
+ logFile = null;
+ print("Error writing to file.");
+ }
+ }
+ }
+
+ public void disable() {
+ synchronized (output) {
+ output.append("Lost connection");
+ }
+ output.setEnabled(false);
+ input.setEnabled(false);
+ sendButton.setEnabled(false);
+ }
+
+ private class EnterListener extends KeyAdapter
+ {
+ Console parent;
+ public EnterListener(Console parent) {
+ this.parent = parent;
+ }
+ public void keyPressed(KeyEvent e) {
+ if (e.getKeyCode()==10) {
+ parent.submit();
+ }
+ }
+ };
+
+ private class ConsoleConnection implements Runnable {
+ String host; int port; Console parent; boolean keepConnected = true;
+ Socket conn; PrintWriter consoleOutput; BufferedReader consoleInput;
+
+
+ public ConsoleConnection(String host, int port, Console parent) {
+ Thread.currentThread().setName("Console Client to "+host+":"+port);
+ this.host = host;
+ this.port = port;
+ this.parent = parent;
+ }
+
+ public void run() {
+ connect();
+ while (keepConnected) {
+ try {
+ String line = consoleInput.readLine();
+ if (line == null) {
+ parent.disable();
+ keepConnected = false;
+ }
+ else
+ parent.print(line);
+ } catch (InterruptedIOException ex) { // timeout - ignore
+ } catch (IOException ex) { // error reading
+ parent.disable();
+ keepConnected = false;
+ }
+ }
+
+ try {
+ conn.close();
+ } catch (IOException ex) { }
+ }
+
+ public void sendCommand(String command) {
+ consoleOutput.println(command);
+ }
+
+ public void shutdown() {
+ keepConnected = false;
+ }
+
+ public void connect() {
+ parent.print("Connecting to "+host+":"+port);
+ try {
+ conn = new Socket(host, port);
+ conn.setKeepAlive(true);
+ conn.setSoTimeout(500);
+ consoleOutput = new PrintWriter(conn.getOutputStream(), true);
+ consoleInput = new BufferedReader(new InputStreamReader(conn.getInputStream()));
+ } catch (Exception ex) {
+
+ }
+ }
+ }
+}
diff --git a/source/com/c2kernel/gui/DomainKeyConsumer.java b/source/com/c2kernel/gui/DomainKeyConsumer.java
new file mode 100755
index 0000000..9eb878c
--- /dev/null
+++ b/source/com/c2kernel/gui/DomainKeyConsumer.java
@@ -0,0 +1,16 @@
+package com.c2kernel.gui;
+
+import com.c2kernel.lookup.DomainPath;
+
+/**
+ * Things that can be told when a barcode etc is entered
+ * @version $Revision: 1.2 $ $Date: 2003/03/13 16:42:38 $
+ * @author $Author: abranson $
+ */
+
+public interface DomainKeyConsumer {
+ public void push(DomainPath key);
+
+ public void push(String name);
+
+}
diff --git a/source/com/c2kernel/gui/DomainKeyListener.java b/source/com/c2kernel/gui/DomainKeyListener.java
new file mode 100755
index 0000000..5c1575b
--- /dev/null
+++ b/source/com/c2kernel/gui/DomainKeyListener.java
@@ -0,0 +1,27 @@
+package com.c2kernel.gui;
+
+import java.io.IOException;
+
+import javax.swing.ImageIcon;
+
+/**
+ * Interface for external key input classes (e.g. barcode scanner)
+ * @version $Revision: 1.5 $ $Date: 2004/10/20 14:10:21 $
+ * @author $Author: abranson $
+ */
+
+public interface DomainKeyListener {
+ public void init();
+
+ public boolean enable() throws IOException;
+
+ public void setConsumer(EntityFinder consumer);
+
+ public void disable();
+
+ // return 25x25 icon for enable/disable button
+ public ImageIcon getIcon();
+
+ // tooltip for the button
+ public String getDescription();
+}
diff --git a/source/com/c2kernel/gui/DynamicTreeBuilder.java b/source/com/c2kernel/gui/DynamicTreeBuilder.java
new file mode 100755
index 0000000..29a62dc
--- /dev/null
+++ b/source/com/c2kernel/gui/DynamicTreeBuilder.java
@@ -0,0 +1,176 @@
+package com.c2kernel.gui;
+
+import javax.swing.ImageIcon;
+import javax.swing.JTree;
+import javax.swing.SwingUtilities;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+
+import com.c2kernel.gui.data.Node;
+import com.c2kernel.gui.data.NodeSubscriber;
+import com.c2kernel.lookup.Path;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.Resource;
+
+/**
+ * Installed as the user object on a single child node of a new node known to be composite.
+ * <p>Shows 'Loading . . .' when the branch is opened, but a TreeExpansionListener attempts to fire this thread off in the first child node.
+ * <br>When started, this thread will retrieve all of the real child nodes and add them to its parent while removing itself (hopefully for garbage collection)
+ *
+ * @version $Revision: 1.24 $ $Date: 2004/12/15 12:12:06 $
+ * @author $Author: abranson $
+ */
+
+public class DynamicTreeBuilder implements NodeSubscriber {
+ private DefaultTreeModel treeModel;
+ private DefaultMutableTreeNode parent;
+ public short state = IDLE;
+ public static final short IDLE = 0;
+ public static final short LOADING = 1;
+ public static final short PARTIAL = 2;
+ public static final short FINISHED = 3;
+ private DefaultMutableTreeNode loading;
+ private static ImageIcon loadIcon = Resource.getImageResource("loading.gif");
+ private static ImageIcon pauseIcon = Resource.getImageResource("reload.gif");
+
+ /**
+ * The newly created DynamicTreeBuilder records its parent node - the one for which it will build child nodes for.
+ * @param nodeClicked The Parent Tree Node that will be populated.
+ * @see NodeItem
+ * @see TreeDisplay*/
+ public DynamicTreeBuilder(DefaultMutableTreeNode parent) {
+ this.parent = parent;
+ loading = new DefaultMutableTreeNode(this);
+ }
+
+ /**
+ * Before the tree builder can execute, it needs to be given references to the tree and NodeFactory needed to create the new nodes.
+ * @param myNodeFactory The NodeFactory that can be queried for new NodeItems.
+ * @param parentTree The JTree in which this node is currently contained.
+ */
+ public void buildInfo(JTree parentTree) {
+ this.treeModel = (DefaultTreeModel)parentTree.getModel();
+ }
+
+ public void start() {
+ // find the clicked tree node
+ Node parentNode = (Node)parent.getUserObject();
+ Logger.msg(2, "DynamicTreeBuilder.start() - Filling in children of '"+parentNode.toString()+"'");
+ if (state == IDLE)
+ parentNode.subscribeNode(this);
+ else
+ parentNode.loadMore();
+ state = LOADING;
+ }
+
+ /**
+ * Used by the JTree to find the text representation of the node.
+ */
+ public String toString() {
+ switch (state) {
+ case IDLE:
+ return Language.translate("Initializing Tree Node Loader");
+ case LOADING:
+ return Language.translate("Loading . . .");
+ case PARTIAL:
+ return Language.translate("Double-click to load more");
+ case FINISHED:
+ return Language.translate("Done");
+ default:
+ return "";
+ }
+
+ }
+
+ public ImageIcon getIcon() {
+ if (state == LOADING)
+ return loadIcon;
+ else
+ return pauseIcon;
+ }
+
+ public DefaultMutableTreeNode getTreeNode() {
+ return loading;
+ }
+
+ public void add(Node newNode) {
+ Logger.msg(2, "DynamicTreeBuilder.add() - Received item for tree. Name: "+newNode);
+
+ // have we inserted the node yet?
+ SwingUtilities.invokeLater(new TreeAddThread(newNode));
+ }
+
+ class TreeAddThread implements Runnable {
+ Node newNode;
+ TreeAddThread(Node newNode) {
+ this.newNode = newNode;
+ }
+ public void run() {
+ boolean inserted = false;
+ DefaultMutableTreeNode newTreeNode = newNode.getTreeNode();
+ // loop though all children unless we have done the insertion
+ for (int i=0; i<parent.getChildCount() && !inserted; i++) {
+ DefaultMutableTreeNode child = (DefaultMutableTreeNode)treeModel.getChild(parent, i);
+ if (child == loading) continue; // skip loading node
+
+ Node childNode = (Node)child.getUserObject();
+ if (childNode.getName().equals(newNode.getName())) {
+ // we already have this one, skip it
+ inserted = true;
+ break;
+ }
+ if (childNode.getName().compareTo(newNode.getName()) >= 0) {
+ // if the next string is 'greater than' ours, insert the node before
+ treeModel.insertNodeInto(newTreeNode, parent, i);
+ inserted = true;
+ break;
+ }
+
+ }
+ // if we haven't inserted yet, it must go at the end.
+
+ if (!inserted)
+ treeModel.insertNodeInto(newTreeNode, parent, parent.getChildCount());
+ }
+
+ }
+
+ class TreeRemoveThread implements Runnable {
+ DefaultMutableTreeNode oldNode;
+ TreeRemoveThread(DefaultMutableTreeNode oldNode) {
+ this.oldNode = oldNode;
+ }
+
+ public void run() {
+ treeModel.removeNodeFromParent(oldNode);
+ }
+ }
+
+ public void end(boolean more) {
+ if (more) {
+ state = PARTIAL;
+ }
+ else {
+ state = FINISHED;
+ synchronized(treeModel) {
+ if (loading.getParent() != null)
+ SwingUtilities.invokeLater(new TreeRemoveThread(loading));
+ }
+ }
+ }
+
+ public void remove(Path path) {
+ synchronized (treeModel) {
+ for (int i=0; i<parent.getChildCount(); i++) {
+ DefaultMutableTreeNode child = (DefaultMutableTreeNode)treeModel.getChild(parent, i);
+ if (!(child.getUserObject() instanceof Node)) continue;
+ Node childNode = (Node)child.getUserObject();
+ if (childNode.getPath().equals(path)) {
+ SwingUtilities.invokeLater(new TreeRemoveThread(child));
+ return;
+ }
+ }
+ }
+ }
+}
diff --git a/source/com/c2kernel/gui/EntityDetails.java b/source/com/c2kernel/gui/EntityDetails.java
new file mode 100755
index 0000000..b6c5245
--- /dev/null
+++ b/source/com/c2kernel/gui/EntityDetails.java
@@ -0,0 +1,223 @@
+package com.c2kernel.gui;
+
+import java.awt.BorderLayout;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+import javax.swing.SwingConstants;
+import javax.swing.event.ChangeListener;
+import com.c2kernel.gui.data.NodeEntity;
+import com.c2kernel.gui.tabs.EntityTabPane;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.Resource;
+
+/**
+ * The tab pane for each viewed item
+ * @version $Revision: 1.38 $ $Date: 2005/06/27 15:16:14 $
+ * @author $Author: abranson $
+ */
+public class EntityDetails extends JPanel implements ChangeListener, Runnable {
+ protected JTabbedPane myTabbedPane = new JTabbedPane(SwingConstants.BOTTOM);
+ protected JPanel itemTitlePanel;
+ private EntityTabManager desktopManager;
+ protected NodeEntity myEntity;
+ protected HashMap childPanes = new HashMap();
+ protected String startTab;
+ protected String startCommand = null;
+ protected boolean initialized = false;
+
+ public EntityDetails(NodeEntity thisItem) {
+ super();
+ startTab = MainFrame.getPref("DefaultStartTab", "Properties");
+ myEntity = thisItem;
+ }
+
+ public void run() {
+ Thread.currentThread().setName("Entity Pane Builder");
+ EntityTabPane componentToAdd = null;
+ setLayout(new BorderLayout());
+ itemTitlePanel = getItemTitlePanel();
+ add(itemTitlePanel, BorderLayout.NORTH);
+ add(myTabbedPane);
+
+ // decide which tabs to create
+ ArrayList requiredTabs = myEntity.getTabs();
+
+ for (Iterator en = requiredTabs.iterator(); en.hasNext();) {
+ String tabName = (String)en.next();
+ if (tabName != null) {
+ //create class instances and initialise
+ Class myClass = null;
+ //look up the required TabbedPane
+ try {
+ myClass = Class.forName(this.getClass().getPackage().getName() + ".tabs." + tabName + "Pane");
+ Logger.msg(2, "ItemDetails.<init> - Creating ItemTabPane instance: " +
+ this.getClass().getPackage().getName() + ".tabs." + tabName + "Pane");
+ componentToAdd = (EntityTabPane)myClass.newInstance();
+ } catch (ClassNotFoundException e) {
+ Logger.msg(2, "ItemDetails.<init> - No specialist tab found for " + tabName + ". Using default.");
+ } catch (InstantiationException e) {
+ Logger.msg(0, "ItemDetails.<init> - Instantiation Error! " + e);
+ } catch (IllegalAccessException e) {
+ Logger.msg(0, "ItemDetails.<init> - Illegal Method Access Error! Class was probably not a ItemTabPane: " + e);
+ }
+ if (componentToAdd == null) componentToAdd = new EntityTabPane(tabName, null);
+ componentToAdd.setParent(this);
+
+ //adds the component to the panel
+ childPanes.put(componentToAdd, new Boolean(false));
+
+ int placement = myTabbedPane.getTabCount();
+ if (tabName.equals("Properties")) // must be first
+ placement = 0;
+ myTabbedPane.insertTab(componentToAdd.getTabName(), null, componentToAdd, null, placement);
+ }
+ }
+ initialized = true;
+ if (!(requiredTabs.contains(startTab))) {
+ startTab = "Properties";
+ startCommand = null;
+ }
+ runCommand(Language.translate(startTab), startCommand);
+ myTabbedPane.setVisible(true);
+ myTabbedPane.addChangeListener(this);
+ validate();
+
+ }
+
+ public void stateChanged(javax.swing.event.ChangeEvent p1) {
+ initialisePane((EntityTabPane)myTabbedPane.getSelectedComponent());
+ }
+
+ public void initialisePane(EntityTabPane pane) {
+ Boolean isInit = (Boolean)childPanes.get(pane);
+ if (isInit.booleanValue() == false) {
+ Logger.msg(4,"Initialising "+pane.getTabName());
+ pane.initForEntity(myEntity);
+ childPanes.put(pane, new Boolean(true));
+ validate();
+ }
+ }
+
+ public EntityTabManager getDesktopManager() {
+ return desktopManager;
+ }
+
+ public void setDesktopManager(EntityTabManager newDesktopManager) {
+ desktopManager = newDesktopManager;
+ }
+
+ public JPanel getItemTitlePanel() {
+ JPanel titlePanel = new JPanel();
+ JComponent current;
+ // Use gridbag layout for title
+ GridBagLayout gridbag = new GridBagLayout();
+ GridBagConstraints c = new GridBagConstraints();
+ titlePanel.setLayout(gridbag);
+ // Place Item Icon
+ c.gridx = 0;
+ c.gridy = 0;
+ c.gridheight = GridBagConstraints.REMAINDER;
+ c.anchor = GridBagConstraints.NORTH;
+ c.ipadx = 5;
+ c.ipady = 5;
+ current = new JLabel(Resource.getImageResource("typeicons/"+myEntity.getIconName()+"_32.png"));
+ gridbag.setConstraints(current, c);
+ titlePanel.add(current);
+ // Place Name/ID Label
+ current = new JLabel(myEntity.getName() + " (" + myEntity.getSysKey() + ")");
+ c.gridx = 1; c.gridy = 0; c.gridheight = 1;
+ c.anchor = GridBagConstraints.NORTH; c.fill = GridBagConstraints.HORIZONTAL;
+ c.weightx = 1.0; c.ipadx = 2; c.ipady = 2;
+ current.setFont(new Font("Helvetica", Font.PLAIN, 18));
+ gridbag.setConstraints(current, c);
+ titlePanel.add(current);
+ // Place Type Label
+ current = new JLabel(myEntity.getType());
+ c.gridx = 1; c.gridy = 2; c.gridheight = 1;
+ c.anchor = GridBagConstraints.CENTER; c.fill = GridBagConstraints.HORIZONTAL;
+ c.weightx = 1.0;
+ current.setFont(new Font("Helvetica", Font.PLAIN, 12));
+ gridbag.setConstraints(current, c);
+ titlePanel.add(current);
+ return titlePanel;
+ }
+
+ public void discardTabs() {
+ myTabbedPane.removeChangeListener(this);
+ myTabbedPane.removeAll();
+ for (Iterator iter = childPanes.keySet().iterator(); iter.hasNext();) {
+ EntityTabPane element = (EntityTabPane)iter.next();
+ element.destroy();
+ iter.remove();
+ }
+ }
+
+ public int getSysKey()
+ {
+ return myEntity.getSysKey();
+ }
+
+ public void closeTab() {
+ desktopManager.remove(myEntity.getSysKey());
+ Logger.msg(5,"Remove master Tab :"+myEntity.getType()+ " SysKey "+myEntity.getSysKey());
+ myEntity.getEntity().dumpSubscriptions(0);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand().equals("close"))
+ closeTab();
+ }
+
+ public void runCommand(String tab, String command) {
+ if (initialized) {
+ int tabIndex = findTab(tab);
+ Logger.msg(3, "Running command "+tab+" "+command+" ("+tabIndex+")");
+ if (tabIndex == -1) {
+ Logger.error("Tab "+tab+" not found for command "+command);
+ return;
+ }
+ EntityTabPane startPane = (EntityTabPane)myTabbedPane.getComponentAt(tabIndex);
+ myTabbedPane.setSelectedIndex(tabIndex);
+ initialisePane(startPane);
+ if (command!= null) startPane.runCommand(command);
+ }
+ else
+ {
+ Logger.msg(3, "Storing command "+tab+" "+command+" until initialised.");
+ startTab = tab;
+ startCommand = command;
+ }
+ }
+
+ protected int findTab(String tabName) {
+ for (int i=0; i< myTabbedPane.getTabCount(); i++) {
+ EntityTabPane thisPane = (EntityTabPane)myTabbedPane.getComponentAt(i);
+ if (thisPane.getTabName().equals(tabName))
+ return i;
+ }
+ return -1;
+ }
+
+
+ public void refresh()
+ {
+ }
+ /**
+ *
+ */
+ protected void finalize() throws Throwable {
+ Logger.msg(7, "EntityDetails "+myEntity.getSysKey()+" reaped");
+ super.finalize();
+ }
+
+} \ No newline at end of file
diff --git a/source/com/c2kernel/gui/EntityFinder.java b/source/com/c2kernel/gui/EntityFinder.java
new file mode 100755
index 0000000..6f23a5d
--- /dev/null
+++ b/source/com/c2kernel/gui/EntityFinder.java
@@ -0,0 +1,205 @@
+package com.c2kernel.gui;
+
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+
+import javax.swing.*;
+
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.lookup.LDAPLookup;
+import com.c2kernel.lookup.Path;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.Resource;
+
+public class EntityFinder extends Box implements Runnable {
+ JTextField inputField;
+ JButton findButton;
+ JButton findNextButton;
+ GridBagLayout gridbag = new GridBagLayout();
+ LDAPLookup lookup = Gateway.getLDAPLookup();
+ DomainKeyConsumer defaultConsumer = null;
+ DomainKeyConsumer currentConsumer = null;
+ Enumeration matches;
+ Path rootNode = MainFrame.userNode.getPath();
+
+ static protected ImageIcon mFindIcon = null;
+ static protected ImageIcon mNextIcon = null;
+ static {
+ try
+ {
+ mNextIcon =Resource.getImageResource("next.png");
+ mFindIcon =Resource.getImageResource("find.png");
+ }
+ catch (Exception e)
+ {
+ Logger.error("Couldn't load images: " + e);
+ }
+ }
+
+ public EntityFinder() {
+ super(BoxLayout.X_AXIS);
+ initPanel();
+ }
+
+ public void pushNewKey(String key) {
+ inputField.setText(key);
+ runSearch();
+ }
+
+ public void setDefaultConsumer(DomainKeyConsumer newConsumer) {
+ defaultConsumer = newConsumer;
+ currentConsumer = newConsumer;
+ }
+
+ public void setConsumer(DomainKeyConsumer newConsumer, String label) {
+ currentConsumer = newConsumer;
+ findButton.setText(label);
+ }
+
+ public void clearConsumer(DomainKeyConsumer oldConsumer) {
+ if (currentConsumer == oldConsumer) {
+ currentConsumer = defaultConsumer;
+ findButton.setText("");
+ }
+ }
+
+ private void initPanel() {
+
+ JLabel search = new JLabel(" "+Language.translate("Search")+":");
+ add(search);
+ add(Box.createHorizontalStrut(7));
+
+ inputField = new JTextField(20);
+ add(inputField);
+ add(Box.createHorizontalStrut(5));
+ inputField.addActionListener( new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ pushNewKey(inputField.getText());
+ }
+ });
+
+ findButton = new JButton(mFindIcon);//(Language.translate("Find"));
+ findButton.setMargin(new Insets(2, 5, 2, 5));
+ findButton.addActionListener( new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ pushNewKey(inputField.getText());
+ }
+ });
+ add(findButton);
+ add(Box.createHorizontalStrut(5));
+
+ findNextButton = new JButton(mNextIcon);//(Language.translate("Next"));
+ findNextButton.setMargin(new Insets(2, 5, 2, 5));
+ findNextButton.addActionListener( new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ MainFrame.status.setText("Navigating to next match");
+ nextMatch();
+ }
+ });
+ findNextButton.setEnabled(false);
+ add(findNextButton);
+ add(Box.createHorizontalStrut(15));
+
+ // create plugins
+ Logger.msg(6, "ItemFinder() - creating plugins");
+ String requiredListeners = Gateway.getProperty("DomainKeyListeners");
+ if (requiredListeners != null) {
+ StringTokenizer tok = new StringTokenizer(requiredListeners, ",");
+ while (tok.hasMoreTokens()) {
+ String listenerName = tok.nextToken();
+ Logger.msg(6, "ItemFinder() - creating a " + listenerName);
+ try {
+ Class listenerClass = Class.forName(listenerName);
+ DomainKeyListener newListener = (DomainKeyListener)listenerClass.newInstance();
+ newListener.init(); newListener.setConsumer(this);
+ JToggleButton listenerButton = new JToggleButton(newListener.getIcon(), false);
+ listenerButton.addItemListener(new ListenerButtonListener(newListener, listenerButton));
+ listenerButton.setMargin(new Insets(0, 2, 0, 2));
+ listenerButton.setToolTipText("Enable "+newListener.getDescription());
+ add(listenerButton);
+ add(Box.createHorizontalStrut(7));
+ } catch (Exception e) {
+ Logger.error("ItemFinder() - could not create a "+listenerName+": "+e);
+ }
+ }
+ add(Box.createHorizontalGlue());
+ }
+ }
+
+ private void runSearch() {
+ Thread searcher = new Thread(this);
+ searcher.start();
+ }
+
+ public void run() {
+ Thread.currentThread().setName("Entity Search");
+ MainFrame.status.setText("Searching. Please Wait");
+ findButton.setEnabled(false); findNextButton.setEnabled(false);
+ String searchTerm = inputField.getText();
+ if (searchTerm.length() == 0) return; // don't allow null searches
+ findNextButton.setEnabled(false);
+ matches = lookup.search(rootNode,inputField.getText());
+ if (!matches.hasMoreElements()) {
+ MainFrame.status.setText("No results");
+ currentConsumer.push(searchTerm); // for subscribers who don't care if it exists
+ findButton.setEnabled(true);
+ return;
+ }
+ MainFrame.status.setText("Selecting first match.");
+ nextMatch();
+
+ }
+
+ void nextMatch() {
+ findButton.setEnabled(false); findNextButton.setEnabled(false);
+ DomainPath nextMatch = (DomainPath)matches.nextElement();
+ try
+ {
+ currentConsumer.push(nextMatch);
+ }
+ catch (NullPointerException e)
+ {
+ //case the item searched is not found !
+ }
+ findButton.setEnabled(true);
+ findNextButton.setToolTipText("Click to show next match");
+ if (matches.hasMoreElements()) findNextButton.setEnabled(true);
+ }
+
+ private class ListenerButtonListener implements ItemListener {
+ private DomainKeyListener listener;
+ private JToggleButton listenerButton;
+
+ public ListenerButtonListener(DomainKeyListener newListener, JToggleButton listenerButton) {
+ this.listener = newListener;
+ this.listenerButton = listenerButton;
+ }
+
+ public void itemStateChanged(ItemEvent e) {
+ if (e.getStateChange() == ItemEvent.SELECTED) {
+ // Switch on
+ try {
+ if (!(listener.enable())) listenerButton.doClick(); // allow plugins to disable themselves
+ } catch (IOException ex) {
+ JOptionPane.showMessageDialog(null, ex.getMessage(), "Error initialising "+listener.getDescription(), JOptionPane.ERROR_MESSAGE);
+ listenerButton.doClick();
+ }
+ listenerButton.setToolTipText("Disable "+listener.getDescription());
+ } else {
+ // Switch off
+ listener.disable();
+ listenerButton.setToolTipText("Enable "+listener.getDescription());
+ }
+ }
+ }
+
+}
diff --git a/source/com/c2kernel/gui/EntityTabManager.java b/source/com/c2kernel/gui/EntityTabManager.java
new file mode 100755
index 0000000..208ae89
--- /dev/null
+++ b/source/com/c2kernel/gui/EntityTabManager.java
@@ -0,0 +1,88 @@
+package com.c2kernel.gui;
+import java.awt.GridLayout;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import javax.swing.BorderFactory;
+import javax.swing.JPanel;
+
+import com.c2kernel.gui.data.NodeEntity;
+import com.c2kernel.gui.tabs.JTabbedPaneWithCloseIcons;
+import com.c2kernel.utils.Logger;
+
+/**
+ * Keeps
+ *
+ * @version $Revision: 1.12 $ $Date: 2005/09/12 14:56:19 $
+ * @author $Author: abranson $
+ */
+
+public class EntityTabManager extends JPanel
+{
+ private MainFrame mMainframe;
+
+ protected HashMap openItems = new HashMap();
+ protected JTabbedPaneWithCloseIcons tabbedPane = new JTabbedPaneWithCloseIcons();
+ //JTabbedPane tabbedPane = new JTabbedPane();
+ MenuBuilder myMenuBuilder;
+
+
+ public EntityTabManager() {
+ super();
+ setLayout(new GridLayout(1,1));
+ setBorder(BorderFactory.createLoweredBevelBorder());
+ //UIDefaults ui = UIManager.getDefaults();
+ //ui.put("TabbedPane.selected",Color.red);
+ add(tabbedPane);
+ }
+
+ public EntityDetails add(NodeEntity thisEntity) {
+
+ EntityDetails requestedDetails;
+ if (!openItems.containsKey(new Integer(thisEntity.getSysKey()))) {
+ Logger.msg(1, "ItemWindowManager.add() - Window for syskey "+thisEntity.getSysKey()+" not found. Opening new one.");
+ requestedDetails = new EntityDetails(thisEntity);
+ Thread itemLoader = new Thread(requestedDetails);
+ itemLoader.start();
+ openItems.put(new Integer(thisEntity.getSysKey()), requestedDetails);
+ requestedDetails.setDesktopManager(this);
+
+ // get currently selected item to set location
+ tabbedPane.addTab(thisEntity.getName(), thisEntity.getIcon(), requestedDetails, Integer.toString(thisEntity.getSysKey()));
+
+
+ }
+ else { //opened window but different nodeitem
+ requestedDetails = (EntityDetails)openItems.get(new Integer(thisEntity.getSysKey()));
+ }
+ tabbedPane.setSelectedComponent(requestedDetails);
+ return requestedDetails;
+ }
+
+ public void setMenuBuilder(MenuBuilder myMenuBuilder) {
+ this.myMenuBuilder = myMenuBuilder;
+ }
+
+ public void remove(int sysKey) {
+ Integer sysKeyObj = new Integer(sysKey);
+ if (!openItems.containsKey(sysKeyObj)) return;
+ EntityDetails tabToClose = (EntityDetails)openItems.get(sysKeyObj);
+ tabbedPane.remove(tabToClose);
+ tabToClose.discardTabs();
+ openItems.remove(sysKeyObj);
+ }
+
+ public void closeAll(boolean keepOpen) {
+ ArrayList toRemove = new ArrayList();
+ for (Iterator iter = openItems.keySet().iterator(); iter.hasNext();) {
+ Integer element = (Integer) iter.next();
+ if (keepOpen && openItems.get(element).equals(tabbedPane.getSelectedComponent())) continue;
+ toRemove.add(element);
+ }
+ for (Iterator iter = toRemove.iterator(); iter.hasNext();) {
+ Integer element = (Integer) iter.next();
+ remove(element.intValue());
+ }
+ }
+}
diff --git a/source/com/c2kernel/gui/LoginBox.java b/source/com/c2kernel/gui/LoginBox.java
new file mode 100755
index 0000000..f813cef
--- /dev/null
+++ b/source/com/c2kernel/gui/LoginBox.java
@@ -0,0 +1,312 @@
+package com.c2kernel.gui;
+
+/**
+ * <p>Title: </p>
+ * <p>Description: </p>
+ * <p>Copyright: Copyright (c) 2003</p>
+ * <p>Company: </p>
+ * @author not attributable
+ * @version 1.0
+ */
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+
+import javax.swing.*;
+import javax.swing.border.EmptyBorder;
+
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.entity.proxy.AgentProxy;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.Resource;
+
+
+//import com.borland.jbcl.layout.*;
+
+/**
+ * <p>Title: </p>
+ * <p>Description: </p>
+ * <p>Copyright: Copyright (c) 2003</p>
+ * <p>Company: </p>
+ * @author not attributable
+ * @version 1.0
+ */
+
+public class LoginBox extends JFrame {
+ private int xMov;
+ private int yMov;
+ public String errorMessage=new String("");
+ private int maxNumberLogon;
+ public boolean action = false;
+ public int loginAttemptNumber= 0;
+ JLabel passwordLabel = new JLabel();
+ JTextField username = new JTextField();
+ JButton OK = new JButton();
+ JLabel errorLabel = new JLabel();
+ JPasswordField password = new JPasswordField();
+ JButton Cancel = new JButton();
+ JLabel userLabel = new JLabel();
+ ImageIcon imageMainHolder = new ImageIcon();
+ JLabel pictureLabel = new JLabel();
+ GridBagLayout gridBagLayout1 = new GridBagLayout();
+ MainFrame mainFrameFather;
+ public static AgentProxy userAgent;
+ private boolean logged;
+ private boolean errorSet;
+
+ public LoginBox(int attempt,String title,String lastUser,String bottomMessage,
+ javax.swing.ImageIcon imageHolder,MainFrame mainFrame) {
+ String iconFile = Gateway.getProperty("AppIcon");
+ if (iconFile != null)
+ this.setIconImage(Resource.getImageResource(iconFile).getImage());
+ this.errorLabel.setText(bottomMessage);
+ if (errorMessage.compareTo("")!=0) this.errorLabel.setText(errorMessage);
+ mainFrameFather=mainFrame;
+ xMov=imageHolder.getIconWidth()+90;
+ yMov=imageHolder.getIconHeight()+40;
+ imageMainHolder=imageHolder;
+ try {
+ jbInit();
+ }
+ catch(Exception e) {
+ e.printStackTrace();
+ }
+ if (attempt==0) maxNumberLogon=5;
+ else maxNumberLogon=attempt;
+ if (title == null)
+ title = "Cristal2";
+ title = Language.translate("Log in to ")+title;
+ setTitle(title);
+ username.setText(lastUser);
+
+ }
+//OK button pressed OR Enter Hit
+ private void loginClicked(){
+ errorSet=false;
+ try {
+ if (this.getUser().length()>0 && this.getPassword().length()>0)
+ userAgent = Gateway.connect(this.getUser(), this.getPassword());
+ logged = (userAgent != null);
+ Logger.msg(7, "AbstractMain::standardSetUp() - Gateway.connect() OK.");
+ }
+ catch (InvalidDataException ex) {
+ String message = ex.getMessage();
+ int i = ex.getMessage().indexOf(' ');
+ if (i > -1 ) message = message.substring(i);
+ //Here us elanguage translate I guess :)
+ //if (message.length()>65 && message.substring(1,5).compareTo("User")==0)
+ // message = (message.substring(1,50)+ "... not found" );
+ this.errorLabel.setText(message);
+ logged= false;
+ errorSet=true;
+ }
+ if (!logged) {
+ Logger.msg("Login attempt "+loginAttemptNumber+" of "+maxNumberLogon+" failed");
+ if (loginAttemptNumber>=maxNumberLogon) Logger.die("Login failure limit reached");
+ if (!errorSet) this.errorLabel.setText(Language.translate("Please enter username & password"));
+// int posx=xMov+120;
+// int posy=yMov;
+// if (posy<135) posy=135;
+// float texstSize = errorLabel.getFont().getSize2D();
+// if (posx-xMov<errorLabel.getText().length()*(texstSize/2))
+// posx=errorLabel.getText().length()*(int)(texstSize/2)+xMov;
+
+
+ // obtain screen dimensions
+// Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
+// this.setBounds(screen.width/2-posx/2, screen.height/2-posy/2,posx,posy);
+ this.validate();
+ }
+
+ else {
+ MainFrame.userAgent = userAgent;
+ this.setVisible(false);
+ mainFrameFather.mainFrameShow();
+ Logger.msg(1, "Login attempt "+loginAttemptNumber+" of "+maxNumberLogon+" succeeded.");
+ }
+ }
+
+
+ private void jbInit() throws Exception {
+
+ //this.getContentPane().setBackground(SystemColor.control);
+ this.setDefaultCloseOperation(EXIT_ON_CLOSE);
+ this.setEnabled(true);
+ this.setLocale(java.util.Locale.getDefault());
+ this.setResizable(false);
+ this.setState(Frame.NORMAL);
+ this.setTitle("");
+ LoginBox_this_keyAdapter submitListener = new LoginBox_this_keyAdapter(this);
+ username.addKeyListener(submitListener);
+ password.addKeyListener(submitListener);
+ this.getContentPane().setLayout(gridBagLayout1);
+
+ passwordLabel.setText(Language.translate("Password")+":");
+
+ OK.setActionCommand("OK");
+ OK.setSelected(true);
+ OK.setText(Language.translate("OK"));
+ OK.addActionListener(new Frame2_OK_actionAdapter(this));
+ OK.setPreferredSize(new Dimension(80,30));
+
+ Cancel.setActionCommand("Cancel");
+ Cancel.setText(Language.translate("Cancel"));
+ Cancel.addActionListener(new Frame2_Cancel_actionAdapter(this));
+ Cancel.setPreferredSize(new Dimension(80,30));
+
+ userLabel.setText(Language.translate("User")+":");
+ pictureLabel= new JLabel(imageMainHolder);
+ pictureLabel.setBorder(new EmptyBorder(0,0,0,5));
+ password.setText("");
+
+ username.setText("");
+
+ GridBagConstraints c = new GridBagConstraints();
+ initBasicConstraints(c,1,1,1,4);
+ c.anchor=GridBagConstraints.CENTER;
+ c.fill = GridBagConstraints.NONE;
+ c.weightx=0;
+ c.weighty=1;
+ getContentPane().add(pictureLabel,c);
+
+ initBasicConstraints(c,2,1,1,1);
+ c.anchor=GridBagConstraints.SOUTHWEST;
+ c.fill = GridBagConstraints.NONE;
+ c.weightx=0;
+ c.weighty=1;
+ getContentPane().add(userLabel,c);
+ initBasicConstraints(c,2,2,1,1);
+ c.anchor=GridBagConstraints.SOUTHWEST;
+ c.fill = GridBagConstraints.NONE;
+ c.weightx=0;
+ c.weighty=1;
+ getContentPane().add(passwordLabel,c);
+
+ initBasicConstraints(c,3,1,1,1);
+ c.anchor=GridBagConstraints.SOUTH;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.weightx=1;
+ c.weighty=1;
+ getContentPane().add(username,c);
+
+ initBasicConstraints(c,3,2,1,1);
+ c.anchor=GridBagConstraints.SOUTH;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.weightx=1;
+ c.weighty=1;
+ getContentPane().add(password,c);
+
+ JPanel buttonPane = new JPanel();
+ buttonPane.setLayout(new BoxLayout(buttonPane,BoxLayout.X_AXIS));
+ buttonPane.add(Box.createGlue());
+ buttonPane.add(OK);
+ buttonPane.add(Box.createRigidArea(new Dimension(5,0)));
+ buttonPane.add(Cancel);
+ buttonPane.add(Box.createGlue());
+ buttonPane.setBorder(new EmptyBorder(5,0,0,0));
+
+ initBasicConstraints(c,2,3,2,1);
+ c.weightx=0;
+ c.weighty=1;
+ c.anchor=GridBagConstraints.SOUTH;
+ c.fill = GridBagConstraints.BOTH;
+ getContentPane().add(buttonPane,c);
+
+ initBasicConstraints(c,2,4,2,1);
+ c.weightx=1;
+ c.weighty=1;
+ c.fill = GridBagConstraints.BOTH;
+ c.anchor= GridBagConstraints.SOUTHEAST;
+ JPanel msgPane = new JPanel();
+ msgPane.setLayout(new BoxLayout(msgPane,BoxLayout.X_AXIS));
+ msgPane.add(Box.createGlue());
+ msgPane.add(errorLabel);
+ msgPane.add(Box.createGlue());
+ getContentPane().add(msgPane,c);
+
+ ((JPanel)getContentPane()).setBorder(new EmptyBorder(0,0,0,5));
+ pack();
+ Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
+ setLocation(screen.width/2-getWidth()/2, screen.height/2-getHeight()/2);
+
+ }
+
+
+
+ protected void initBasicConstraints(GridBagConstraints constraints,int x,int y,int width,int height)
+ {
+ constraints.gridx=x;
+ constraints.gridy=y;
+ constraints.gridwidth=width;
+ constraints.gridheight=height;
+ }
+
+ public String getUser() {
+ return username.getText();
+ }
+
+ public String getPassword() {
+ return String.valueOf(password.getPassword());
+ }
+
+ void Cancel_actionPerformed(ActionEvent e) {
+ Logger.die("User cancelled login.");
+ }
+
+ void OK_actionPerformed(ActionEvent e) {
+ try{
+ this.loginAttemptNumber++;
+ loginClicked();}
+ catch (Exception ex){
+ Logger.error(ex);
+ }
+ }
+
+ void this_keyPressed(KeyEvent e) {
+ if (e.getKeyCode()==10){
+ try{
+ this.loginAttemptNumber++;
+ loginClicked();
+ }
+ catch (Exception ex){
+ Logger.error(ex);
+ }
+ }
+ }
+
+}
+
+class Frame2_Cancel_actionAdapter implements java.awt.event.ActionListener {
+ LoginBox adaptee;
+
+ Frame2_Cancel_actionAdapter(LoginBox adaptee) {
+ this.adaptee = adaptee;
+ }
+ public void actionPerformed(ActionEvent e) {
+ adaptee.Cancel_actionPerformed(e);
+ }
+}
+
+class Frame2_OK_actionAdapter implements java.awt.event.ActionListener {
+ LoginBox adaptee;
+
+ Frame2_OK_actionAdapter(LoginBox adaptee) {
+ this.adaptee = adaptee;
+ }
+ public void actionPerformed(ActionEvent e) {
+ adaptee.OK_actionPerformed(e);
+ }
+}
+
+class LoginBox_this_keyAdapter extends java.awt.event.KeyAdapter {
+ LoginBox adaptee;
+
+ LoginBox_this_keyAdapter(LoginBox adaptee) {
+ this.adaptee = adaptee;
+ }
+ public void keyPressed(KeyEvent e) {
+ adaptee.this_keyPressed(e);
+ }
+} \ No newline at end of file
diff --git a/source/com/c2kernel/gui/Main.java b/source/com/c2kernel/gui/Main.java
new file mode 100755
index 0000000..4c77d63
--- /dev/null
+++ b/source/com/c2kernel/gui/Main.java
@@ -0,0 +1,39 @@
+package com.c2kernel.gui;
+
+
+import com.c2kernel.process.StandardClient;
+import com.c2kernel.utils.Logger;
+
+
+/**
+ *
+ * @version $Revision: 1.15 $ $Date: 2004/10/26 11:33:56 $
+ * @author $Author: abranson $
+ */
+public class Main extends StandardClient
+{
+ static public void main(String[] args)
+ {
+ try
+ {
+ standardSetUp(args);
+ Logger.initConsole("GUI");
+ MainFrame client = new MainFrame();
+ client.showLogin();
+
+ }
+ catch( Exception ex )
+ {
+ Logger.error(ex);
+
+ try
+ {
+ standardTearDown();
+ }
+ catch(Exception ex1)
+ {
+ Logger.error(ex1);
+ }
+ }
+ }
+}
diff --git a/source/com/c2kernel/gui/MainFrame.java b/source/com/c2kernel/gui/MainFrame.java
new file mode 100755
index 0000000..99a1fab
--- /dev/null
+++ b/source/com/c2kernel/gui/MainFrame.java
@@ -0,0 +1,306 @@
+package com.c2kernel.gui;
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Point;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+import javax.swing.*;
+import javax.swing.BorderFactory;
+import javax.swing.ImageIcon;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSplitPane;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+
+import com.c2kernel.entity.proxy.AgentProxy;
+import com.c2kernel.gui.data.Node;
+import com.c2kernel.gui.data.NodeContext;
+import com.c2kernel.gui.tabs.execution.DefaultExecutor;
+import com.c2kernel.gui.tabs.execution.Executor;
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.Resource;
+/**
+ * @version $Revision: 1.83 $ $Date: 2005/09/12 14:56:19 $
+ * @author $Author: abranson $
+ */
+public class MainFrame extends javax.swing.JFrame {
+ public static TreeBrowser treeBrowser;
+ public static EntityTabManager myDesktopManager;
+ public static EntityFinder itemFinder;
+ protected static Node userNode = null;
+ protected MenuBuilder menuBuilder;
+ protected org.omg.CORBA.ORB orb;
+ public static Properties prefs = new Properties();
+ public static JLabel status = new JLabel();
+ public String logoURL;
+ public static AgentProxy userAgent;
+ protected JSplitPane splitPane;
+ public static boolean isAdmin;
+ int splitPanePos;
+ public static final JFileChooser xmlChooser;
+
+ static {
+ xmlChooser = new JFileChooser();
+ xmlChooser.addChoosableFileFilter(
+ new javax.swing.filechooser.FileFilter() {
+ public String getDescription() {
+ return "XML Files";
+ }
+ public boolean accept(File f) {
+ if (f.isDirectory() || (f.isFile() && f.getName().endsWith(".xml"))) {
+ return true;
+ }
+ return false;
+ }
+ });
+ }
+ /** Creates new gui client for Cristal2 */
+
+ public MainFrame() {
+
+ // Load gui preferences
+ try {
+ FileInputStream prefsfile =
+ new FileInputStream("cristal.preferences");
+ prefs.load(prefsfile);
+ prefsfile.close();
+ } catch (IOException e) {
+ Logger.msg(2, "Creating new preference file");
+ }
+
+ // set look & feel from pref
+ try {
+ String lf = getPref("Style", null);
+ if (lf == null)
+ lf = UIManager.getCrossPlatformLookAndFeelClassName();
+ UIManager.setLookAndFeel(lf);
+ SwingUtilities.updateComponentTreeUI(this);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void showLogin() {
+ // Log in
+ logoURL = Gateway.getProperty("Logo");
+ URL pictureUrl;
+ String bottomMessage =
+ Language.translate("Please enter username & password");
+ ImageIcon imageHolder = new ImageIcon("");
+ try {
+ pictureUrl = new URL(logoURL);
+ imageHolder = new ImageIcon(pictureUrl);
+ } catch (java.net.MalformedURLException m) {
+ imageHolder = Resource.getImageResource(logoURL);
+ }
+
+ LoginBox login =
+ new LoginBox(
+ 5,
+ Gateway.getProperty("Name"),
+ getPref("lastUser."+Gateway.getCentreId(), null),
+ bottomMessage,
+ imageHolder, this);
+
+ login.setVisible(true);
+ }
+
+ public void mainFrameShow() {
+ prefs.setProperty("lastUser."+Gateway.getCentreId(), userAgent.getName());
+ isAdmin = userAgent.getPath().hasRole("Admin");
+ GridBagLayout gridbag = new GridBagLayout();
+ getContentPane().setLayout(gridbag);
+
+ this.setTitle(
+ userAgent.getName()+"@"+Gateway.getProperty("Name") + " - " + Language.translate("Cristal 2"));
+
+ String iconFile = Gateway.getProperty("AppIcon");
+ if (iconFile != null)
+ this.setIconImage(Resource.getImageResource(iconFile).getImage());
+
+ //preload loading image
+ Resource.getImageResource("loading.gif");
+ // close listener
+ addWindowListener(new java.awt.event.WindowAdapter() {
+ public void windowClosing(java.awt.event.WindowEvent evt) {
+ exitForm();
+ }
+ });
+ // initialise the desktop manager
+ myDesktopManager = new EntityTabManager();
+
+ //get the menu bar and add it to the frame
+ menuBuilder = new MenuBuilder(this);
+ setJMenuBar(menuBuilder);
+
+ // set the menu builder in the window manager
+ myDesktopManager.setMenuBuilder(menuBuilder);
+
+ userNode = new NodeContext(new DomainPath(""), myDesktopManager);
+ treeBrowser = new TreeBrowser(myDesktopManager, userNode);
+ treeBrowser.setVisible(getPref("ShowTree", "true").equals("true"));
+
+ // add search box
+ itemFinder = new EntityFinder();
+ GridBagConstraints c = new GridBagConstraints();
+ c.gridx = 0;
+ c.gridy = 0;
+ c.weightx = 1.0;
+ c.weighty = 0.0;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ gridbag.setConstraints(itemFinder, c);
+ getContentPane().add(itemFinder);
+ // register the browser as the key consumer
+ itemFinder.setDefaultConsumer(treeBrowser);
+
+ c.gridy++;
+ c.weightx = 1.0;
+ c.weighty = 1.0;
+ c.fill = GridBagConstraints.BOTH;
+ gridbag.setConstraints(getSplitPanel(), c);
+ getContentPane().add(getSplitPanel());
+ // setup status bar
+ status.setText("Cristal 2");
+ status.setFont(
+ new Font("SansSerif", Font.PLAIN, status.getFont().getSize()));
+ JPanel statusPanel = new JPanel();
+ statusPanel.setLayout(new BorderLayout());
+ statusPanel.setBorder(BorderFactory.createLoweredBevelBorder());
+ status.setForeground(Color.black);
+
+ statusPanel.add(status);
+ c.gridy++;
+ c.weighty = 0.0;
+ gridbag.setConstraints(statusPanel, c);
+ getContentPane().add(statusPanel);
+ pack();
+ String paneSize = getPref("WindowSize", null);
+ if (paneSize != null) {
+ StringTokenizer tok = new StringTokenizer(paneSize, ",");
+ Dimension window = new Dimension();
+ window.setSize(
+ Integer.parseInt(tok.nextToken()),
+ Integer.parseInt(tok.nextToken()));
+ this.setSize(window);
+ }
+ String panePos = getPref("WindowPosition", null);
+ if (panePos != null) {
+ StringTokenizer tok = new StringTokenizer(panePos, ",");
+ Point window =
+ new Point(
+ Integer.parseInt(tok.nextToken()),
+ Integer.parseInt(tok.nextToken()));
+ this.setLocation(window);
+ }
+ super.toFront();
+ this.validate();
+ this.setVisible(true);
+ }
+ public static String getPref(String name, String defaultValue) {
+ return prefs.getProperty(name, defaultValue);
+ }
+ public static void setPref(String name, String value) {
+ prefs.setProperty(name, value);
+ }
+ // things to do on exit
+ public void exitForm() {
+ // close connections
+ Gateway.close();
+ // save window sizing
+ setPref(
+ "WindowSize",
+ (int) (this.getSize().getWidth())
+ + ","
+ + (int) (this.getSize().getHeight()));
+ setPref(
+ "WindowPosition",
+ (int) (this.getLocation().getX())
+ + ","
+ + (int) (this.getLocation().getY()));
+ setPref(
+ "Style",
+ UIManager.getLookAndFeel().getClass().getName());
+ setPref(
+ "SplitPanePosition",
+ String.valueOf(splitPane.getDividerLocation()));
+ // save preferences file
+ try {
+ FileOutputStream prefsfile =
+ new FileOutputStream("cristal.preferences", false);
+ prefs.store(prefsfile, "Cristal 2");
+ prefsfile.close();
+ } catch (Exception e) {
+ Logger.warning(
+ "Could not write to preferences file. Preferences have not been updated.");
+ }
+ this.setVisible(false);
+ // allow waiting threads time to quit
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ }
+ System.exit(0);
+ }
+
+ public void toggleTree() {
+ boolean showTree = getPref("ShowTree", "true").equals("false");
+ setPref("ShowTree", String.valueOf(showTree));
+ if (!showTree) splitPanePos = splitPane.getDividerLocation();
+ getSplitPanel().getLeftComponent().setVisible(showTree);
+ if (showTree) getSplitPanel().setDividerLocation(splitPanePos);
+ getSplitPanel().validate();
+ }
+
+ public static JComboBox getExecutionPlugins() {
+ JComboBox plugins = new JComboBox();
+ // create execution selector
+ Executor defaultExecutor = new DefaultExecutor();
+ plugins.addItem(defaultExecutor);
+ plugins.setSelectedIndex(0);
+
+ // load execution plugins
+ String pluginList = Gateway.getProperty("Executors");
+ if (pluginList != null) {
+ StringTokenizer tok = new StringTokenizer(pluginList, ",");
+ while (tok.hasMoreTokens()) {
+ String pluginName = tok.nextToken();
+ try {
+ Class pluginClass = Class.forName(pluginName);
+ Executor domainExecutor = (Executor)pluginClass.newInstance();
+ plugins.addItem(domainExecutor);
+ } catch (Exception ex) {
+ Logger.error("Could not load the executor plugin "+pluginName);
+ }
+ }
+ }
+ return plugins;
+ }
+ protected JSplitPane getSplitPanel()
+ {
+ // create the split pane, and add the Tree to it.
+ if (splitPane == null)
+ {
+ splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, treeBrowser, myDesktopManager);
+ splitPane.setDividerSize(5);
+ splitPanePos = Integer.parseInt(getPref("SplitPanePosition", "200"));
+ getSplitPanel().setDividerLocation(splitPanePos);
+ }
+ return splitPane;
+ }
+
+}
diff --git a/source/com/c2kernel/gui/MenuBuilder.java b/source/com/c2kernel/gui/MenuBuilder.java
new file mode 100755
index 0000000..c385dbe
--- /dev/null
+++ b/source/com/c2kernel/gui/MenuBuilder.java
@@ -0,0 +1,247 @@
+package com.c2kernel.gui;
+import java.awt.Dimension;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemListener;
+import java.util.Enumeration;
+import java.util.HashMap;
+
+import javax.swing.*;
+import javax.swing.event.HyperlinkEvent;
+import javax.swing.event.HyperlinkListener;
+import javax.swing.text.html.HTMLEditorKit;
+
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.lookup.Path;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.property.Property;
+import com.c2kernel.utils.FileStringUtility;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.Resource;
+/**
+ * @version $Revision: 1.47 $ $Date: 2006/03/03 13:52:21 $
+ * @author $Author: abranson $
+ */
+public class MenuBuilder extends JMenuBar implements ActionListener, ItemListener, HyperlinkListener
+{
+
+ protected UIManager.LookAndFeelInfo[] availableViews = UIManager.getInstalledLookAndFeels();
+ protected MainFrame myParentFrame;
+ protected JMenu fileMenu;
+ protected JMenu consoleMenu;
+ protected JMenu styleMenu;
+ protected JMenu prefMenu;
+ protected JMenu helpMenu;
+ protected HashMap availableMenus = new HashMap();
+
+ public MenuBuilder()
+ {}
+
+ /** Creates new DynamicMenuBuilder */
+ public MenuBuilder(MainFrame parentFrame)
+ {
+ myParentFrame = parentFrame;
+ fileMenu = new JMenu(Language.translate("File"));
+ consoleMenu = new JMenu(Language.translate("Console"));
+ styleMenu = new JMenu(Language.translate("Style"));
+ prefMenu = new JMenu("Preferences");
+ helpMenu = new JMenu(Language.translate("Help"));
+ availableMenus.put("file", fileMenu);
+ availableMenus.put("console", consoleMenu);
+ availableMenus.put("preferences", prefMenu);
+ availableMenus.put("style", styleMenu);
+ availableMenus.put("help", helpMenu);
+
+ addMenuItem(Language.translate("Close All"), "file", null, 0);
+ addMenuItem(Language.translate("Close Others"), "file", null, 0);
+ fileMenu.insertSeparator(2);
+ addMenuItem(Language.translate("Exit"), "file", null, 0);
+
+ addMenuItem(Language.translate("Local console"), "console", null, 0);
+ consoleMenu.insertSeparator(5);
+ addServerConsoles();
+
+ ButtonGroup styleButtonGroup = new ButtonGroup();
+ for (int i = 0; i < availableViews.length; i++)
+ addMenuItem(availableViews[i].getName(), "style", styleButtonGroup, 0);
+
+ addMenuItem(Language.translate("Tree Browser"), "preferences", null, MainFrame.getPref("ShowTree", "true").equals("true")?2:1);
+ addMenuItem(Language.translate("Outcome Field Help"), "preferences", null, MainFrame.getPref("ShowHelp", "true").equals("true")?2:1);
+ addMenuItem(Language.translate("Graph Properties"), "preferences", null, MainFrame.getPref("ShowProps", "true").equals("true")?2:1);
+ addMenuItem(Language.translate("About"), "help", null, 0);
+
+ add(fileMenu);
+ add(consoleMenu);
+ add(styleMenu);
+ add(prefMenu);
+ add(helpMenu);
+ }
+ /**
+ *
+ */
+ private void addServerConsoles() {
+ Enumeration servers = Gateway.getLDAPLookup().searchEntities(new DomainPath("/servers"));
+ while(servers.hasMoreElements()) {
+ Path thisServerPath = (Path)servers.nextElement();
+ try {
+ int syskey = thisServerPath.getSysKey();
+ String serverName = ((Property)Gateway.getStorage().get(syskey, ClusterStorage.PROPERTY+"/Name", null)).getValue();
+ String portStr = ((Property)Gateway.getStorage().get(syskey, ClusterStorage.PROPERTY+"/ConsolePort", null)).getValue();
+ addMenuItem(serverName+":"+portStr, "console", null, 0);
+ } catch (Exception ex) {
+ Logger.error("Exception retrieving proxy server connection data for "+thisServerPath);
+ Logger.error(ex);
+ }
+ }
+
+ }
+
+ /**
+ * Adds a menu item to a menu. Adds an action listener to the menu item.
+ */
+ public void addMenuItem(String itemName, String menuName, ButtonGroup bg, int checkBox)
+ {
+ //checks to see if the menu to add the item to exists
+ if (availableMenus.containsKey(menuName))
+ {
+ JMenuItem myItem = new JMenuItem(itemName);
+ if (bg != null)
+ {
+ //if the menu item equals the current style, set it selected
+ myItem = new JRadioButtonMenuItem(itemName, UIManager.getLookAndFeel().getName().equals(itemName));
+ bg.add(myItem);
+ }
+ if (checkBox != 0)
+ {
+ myItem = new JCheckBoxMenuItem(itemName, checkBox == 2);
+ }
+ myItem.addActionListener(this);
+ JMenu myMenu = (JMenu) availableMenus.get(menuName);
+ myMenu.add(myItem);
+ }
+ }
+ //checks to see if the event dispatched is one of the
+ //styles that belong to the UIManager
+ public int isStyleChange(String style)
+ {
+ for (int i = 0; i < availableViews.length; i++)
+ {
+ if (style.equals(availableViews[i].getName()))
+ return i;
+ }
+ return -1;
+ }
+ //listens for events performed on the menu items
+ public void actionPerformed(java.awt.event.ActionEvent e)
+ {
+ String s = e.getActionCommand();
+ int i = isStyleChange(s);
+ if (s.equals("Close All") || s.equals("Close Others")) {
+ MainFrame.myDesktopManager.closeAll(s.equals("Close Others"));
+ }
+ else if (s.equals(Language.translate("Exit")))
+ myParentFrame.exitForm();
+ else if (s.equals(Language.translate("About")))
+ showAboutWindow();
+ else if (i >= 0)
+ {
+ try
+ {
+ UIManager.setLookAndFeel(availableViews[i].getClassName());
+ SwingUtilities.updateComponentTreeUI(myParentFrame);
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+ else if (s.equals(Language.translate("Tree Browser")))
+ {
+ myParentFrame.toggleTree();
+ }
+ else if (s.indexOf(":")>0) { // server console
+ try
+ {
+ String[] serverDetails = s.split(":");
+ new Console(serverDetails[0], Integer.parseInt(serverDetails[1])).setVisible(true);
+ }
+ catch (Exception ex)
+ {
+ Logger.error(ex);
+ }
+ }
+ else if (s.equals(Language.translate("Local console"))) {
+ try
+ {
+ new Console("localhost", Logger.getConsolePort()).setVisible(true);
+ }
+ catch (Exception ex)
+ {
+ Logger.error(ex);
+ }
+ }
+ else
+ Logger.msg(1, "MenuBuilder.actionPerformed() - No action associated with the event received");
+ }
+ //constructs an about dialog
+ public void showAboutWindow()
+ {
+ JOptionPane myPane = new JOptionPane();
+ Box about = Box.createVerticalBox();
+
+ String aboutInfo;
+ try
+ {
+ aboutInfo = FileStringUtility.file2String(Gateway.getProperty("about"));
+ }
+ catch (Exception e)
+ {
+ aboutInfo = Language.translate("Cristal 2 Itembrowser");
+ }
+ JLabel title = new JLabel(aboutInfo);
+ about.add(title);
+
+ about.add(new JLabel("Domain version: "+Resource.getDomainVersion()));
+ about.add(new JLabel("Kernel version: "+Resource.getKernelVersion()));
+ // get license info
+ StringBuffer lictxt = new StringBuffer();
+ String domlictxt = Resource.getTextResource("license.html");
+ if (domlictxt != null)
+ lictxt.append(domlictxt);
+ lictxt.append(Resource.getTextResource("textFiles/license.html"));
+
+ JEditorPane license = new JEditorPane();
+ license.setEditable(false);
+ license.setEditorKit(new HTMLEditorKit());
+ license.setContentType("text/html");
+ license.addHyperlinkListener(this);
+ license.setText(lictxt.toString());
+ JScrollPane scroll = new JScrollPane(license);
+ scroll.setPreferredSize(new Dimension(300,200));
+ license.setCaretPosition(0);
+
+ about.add(scroll);
+ myPane.setMessage(about);
+ myPane.setMessageType(JOptionPane.INFORMATION_MESSAGE);
+ JDialog dialog = myPane.createDialog(null, Language.translate("About"));
+ dialog.setResizable(false);
+ Icon icon = Resource.getImageResource(Gateway.getProperty("banner"));
+ myPane.setIcon(icon);
+ dialog.pack();
+ dialog.setVisible(true);
+ }
+
+ public void hyperlinkUpdate(HyperlinkEvent e) {
+ try {
+ if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED)
+ Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler "+e.getURL().toString());
+ } catch (Exception ex) {
+ Logger.exceptionDialog(ex);
+ }
+ }
+
+ public void itemStateChanged(java.awt.event.ItemEvent e)
+ {
+ }
+}
diff --git a/source/com/c2kernel/gui/TreeBrowser.java b/source/com/c2kernel/gui/TreeBrowser.java
new file mode 100755
index 0000000..ccee681
--- /dev/null
+++ b/source/com/c2kernel/gui/TreeBrowser.java
@@ -0,0 +1,197 @@
+package com.c2kernel.gui;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+import javax.swing.*;
+import javax.swing.event.TreeExpansionEvent;
+import javax.swing.event.TreeExpansionListener;
+import javax.swing.tree.*;
+
+import com.c2kernel.gui.data.Node;
+import com.c2kernel.gui.data.NodeEntity;
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.utils.Logger;
+
+/**
+ * Container for the tree browser
+ * @version $Revision: 1.31 $ $Date: 2006/01/17 07:49:44 $
+ * @author $Author: abranson $
+ */
+
+ // must put in top level list of loaded items, so we don't have duplicates
+public class TreeBrowser extends JPanel implements DomainKeyConsumer
+{
+ private EntityTabManager desktop;
+ protected JTree tree;
+ private Node userRoot;
+
+ public TreeBrowser(EntityTabManager target, Node userRoot) {
+ setLayout(new java.awt.BorderLayout());
+ //record the desktop and node factory for our item frames
+ this.desktop = target;
+ this.userRoot = userRoot;
+ this.setPreferredSize(new Dimension(300, 500));
+ tree = new JTree(new DefaultTreeModel(userRoot.getTreeNode()));
+ tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+ tree.setToggleClickCount(3); // need three clicks to expand a branch
+ tree.addTreeExpansionListener(
+ new TreeExpansionListener() {
+ public void treeCollapsed(TreeExpansionEvent e) {
+ //REVISIT: possible reaping here if things are getting heavy
+ }
+ public void treeExpanded(TreeExpansionEvent e) {
+ TreePath p = e.getPath();
+ // find the clicked tree node
+ DefaultMutableTreeNode nodeClicked = (DefaultMutableTreeNode)p.getLastPathComponent();
+ // run the tree builder if it is there.
+ DefaultMutableTreeNode loadNode = (DefaultMutableTreeNode)nodeClicked.getFirstChild();
+ if (loadNode.getUserObject() instanceof DynamicTreeBuilder) {
+ DynamicTreeBuilder loading = (DynamicTreeBuilder)loadNode.getUserObject();
+ if (loading.state == DynamicTreeBuilder.IDLE) {
+ loading.buildInfo(tree);
+ loading.start();
+ }
+ }
+ }
+ }
+ );
+
+ //Enable tool tips.
+ ToolTipManager.sharedInstance().registerComponent(tree);
+ tree.setCellRenderer(new ItemRenderer());
+ tree.addMouseListener(new TreeMouseListener());
+ JScrollPane myScrollPane = new JScrollPane(tree);
+ this.add(myScrollPane);
+ DefaultMutableTreeNode loadNode = (DefaultMutableTreeNode)userRoot.getTreeNode().getFirstChild();
+ DynamicTreeBuilder loading = (DynamicTreeBuilder)loadNode.getUserObject();
+ loading.buildInfo(tree);
+ loading.start();
+ }
+
+ public void push(DomainPath target) {
+ Logger.debug("Opening tree node "+target);
+ String[] components = target.getPath();
+ Node currentNode = userRoot;
+ Object[] treePath = new Object[components.length+1];
+ treePath[0] = currentNode.getTreeNode();
+ for (int i=0; i<components.length; i++) {
+ // create sub-path
+ String[] newPath = new String[i+1];
+ for (int j=0; j<newPath.length; j++)
+ newPath[j] = components[j];
+ DomainPath nextNodePath = new DomainPath(newPath);
+ Node nextNode = currentNode.getChildNode(nextNodePath);
+ if (nextNode == null) {
+ Logger.msg(6, "TreeBrowser.push() - creating "+nextNodePath);
+ nextNode = currentNode.newNode(nextNodePath);
+ currentNode.add(nextNode);
+ DynamicTreeBuilder builder = currentNode.getTreeBuilder();
+ builder.buildInfo(tree);
+ builder.add(nextNode);
+ }
+ treePath[i+1] = nextNode.getTreeNode();
+ currentNode = nextNode;
+ }
+ // select it
+ TreePath targetNode = new TreePath(treePath);
+ if (Logger.doLog(5)) dumpPath(targetNode, 5);
+
+ tree.clearSelection();
+ tree.addSelectionPath(targetNode);
+ tree.makeVisible(targetNode);
+ // open it
+ if (currentNode instanceof NodeEntity) {
+ MainFrame.status.setText("Opening "+currentNode.getName());
+ desktop.add((NodeEntity)currentNode);
+ MainFrame.status.setText("Done");
+ }
+ }
+
+ public void push(String name) {
+ // only interested in real paths
+ JOptionPane.showMessageDialog(null, "'"+name+"' was not found.",
+ "No results", JOptionPane.INFORMATION_MESSAGE);
+
+ }
+
+ private void dumpPath(TreePath selPath, int logLevel) {
+ if (selPath == null) { Logger.msg(logLevel, "TreeBrowser.dumpPath() - selPath null"); return; }
+ for (int i =0; i<selPath.getPath().length; i++)
+ Logger.msg(logLevel, "TreeBrowser.dumpPath() - selPath "+i+" = "+selPath.getPath()[i]);
+ }
+
+ private class ItemRenderer extends DefaultTreeCellRenderer {
+ public ItemRenderer() {
+ }
+
+ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf,
+ int row, boolean hasFocus) {
+ super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
+ Object thisLeaf = ((DefaultMutableTreeNode)value).getUserObject();
+ if (thisLeaf instanceof Node) {
+ Node thisNode = (Node)thisLeaf;
+ if (thisNode.getIcon() !=null) setIcon(thisNode.getIcon());
+ setToolTipText(thisNode.getType());
+ }
+ else if (thisLeaf instanceof DynamicTreeBuilder) {
+ DynamicTreeBuilder thisLoader = (DynamicTreeBuilder)thisLeaf;
+ ImageIcon loadGif = thisLoader.getIcon();
+ setIcon(loadGif);
+ loadGif.setImageObserver(tree);
+ setToolTipText("Tree Content Loader");
+ }
+ return this;
+ }
+ }
+
+ private class TreeMouseListener extends MouseAdapter {
+ public void mousePressed(MouseEvent e) {
+ if (e.isPopupTrigger())
+ showPopup(e);
+ else {
+ Object source = getNodeAt(e);
+ if (source == null) return;
+ if (e.getClickCount() == 2) {
+ if (source instanceof NodeEntity) {
+ NodeEntity thisNode = (NodeEntity)source;
+ desktop.add(thisNode);
+ MainFrame.status.setText("Opened "+thisNode.getName());
+ }
+ if (source instanceof DynamicTreeBuilder) {
+ DynamicTreeBuilder thisLoader = (DynamicTreeBuilder)source;
+ if (thisLoader.state == DynamicTreeBuilder.PARTIAL)
+ thisLoader.start();
+ }
+ }
+ }
+ }
+ public void mouseReleased(MouseEvent e) {
+ if (e.isPopupTrigger()) {
+ showPopup(e);
+ }
+ }
+ private void showPopup(MouseEvent e) {
+ Object source = getNodeAt(e);
+ if (source == null) return;
+ if (source instanceof Node) {
+ Node thisNode = (Node)source;
+ thisNode.getPopupMenu().show(e.getComponent(), e.getX(), e.getY());
+ }
+ }
+ private Object getNodeAt(MouseEvent e) {
+ Object source = null;
+ TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
+ if (selPath != null)
+ try {
+ DefaultMutableTreeNode nodeClicked = (DefaultMutableTreeNode)selPath.getLastPathComponent();
+ source = nodeClicked.getUserObject(); // fetch its nodeItem
+ }
+ catch (Exception ex) { } // Not a node that was clicked on
+
+ return source;
+ }
+ }
+}
diff --git a/source/com/c2kernel/gui/data/Node.java b/source/com/c2kernel/gui/data/Node.java
new file mode 100755
index 0000000..b82ee92
--- /dev/null
+++ b/source/com/c2kernel/gui/data/Node.java
@@ -0,0 +1,234 @@
+package com.c2kernel.gui.data;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+import javax.swing.tree.DefaultMutableTreeNode;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.gui.DynamicTreeBuilder;
+import com.c2kernel.gui.EntityTabManager;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.lookup.Path;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.Resource;
+
+public abstract class Node implements Runnable {
+
+ protected Path binding;
+ protected DefaultMutableTreeNode treeNode;
+ protected String name; // domain key
+ protected int sysKey; // target item
+ // attributes
+ protected String type = "";
+ protected Icon icon;
+ protected boolean isExpandable = false;
+ protected HashMap childNodes = new HashMap();
+ protected ArrayList subscribers = new ArrayList();
+ protected DynamicTreeBuilder loader = null;
+ private boolean loaded = false;
+ private String iconName;
+ protected EntityTabManager desktop;
+ static ImageIcon folder = Resource.getImageResource("folder.png");
+ static ImageIcon emptyLeaf = Resource.getImageResource("leaf.png");
+
+ public Node() {
+ }
+
+ protected void createTreeNode() {
+ this.treeNode = new DefaultMutableTreeNode(this);
+ }
+
+ public Node(Path path, EntityTabManager desktop) {
+ this.binding = path;
+ this.desktop = desktop;
+ this.sysKey = path.getSysKey();
+ // get the name of this node (last path element)
+ String[] pathComponents = path.getPath();
+ if (pathComponents.length > 0)
+ this.name = pathComponents[pathComponents.length-1];
+ else
+ this.name = Gateway.getProperty("Name");
+ }
+
+ public EntityTabManager getDesktop() {
+ return desktop;
+ }
+
+ public Node newNode(Path path)
+ {
+ try {
+ if (path.getEntity() instanceof AgentPath)
+ return new NodeAgent(path, desktop);
+ else
+ return new NodeItem(path, desktop);
+ } catch (ObjectNotFoundException ex) {
+ return new NodeContext(path, desktop);
+ }
+
+ }
+
+ /** Inserts a tree builder as the first child of the node, so it can be opened in the tree
+ */
+ public void makeExpandable() {
+ if (isExpandable) return;
+ loader = new DynamicTreeBuilder(this.treeNode);
+ this.treeNode.insert(loader.getTreeNode(),0);
+ isExpandable = true;
+ }
+
+
+ public DefaultMutableTreeNode getTreeNode() {
+ return treeNode;
+ }
+
+ public void setTreeNode(DefaultMutableTreeNode treeNode) {
+ this.treeNode = treeNode;
+ treeNode.setUserObject(this);
+ }
+
+ /** Subscription for loading node children.
+ * Note this is separate from the itemproxy subscription as it included query of the naming service
+ * and eventually should not require access to the item at all for higher performance */
+ public void subscribeNode(NodeSubscriber target) {
+ subscribers.add(target);
+ if (loaded == false) {
+ loaded = true;
+ loadMore();
+ }
+ else {
+ synchronized (childNodes) {
+ Node newNode;
+ for (Iterator nodes = childNodes.values().iterator(); nodes.hasNext();) {
+ newNode = (Node)nodes.next();
+ Logger.msg("subscribeNode target.add("+newNode.name+")");
+ target.add(newNode);
+ }
+ }
+ }
+ }
+
+ public void loadMore() {
+ Thread loading = new Thread(this);
+ loading.start();
+ }
+
+ public void unsubscribeNode(NodeSubscriber target) {
+ subscribers.remove(target);
+ }
+
+ public void add(Node newNode) {
+ synchronized(childNodes) {
+ childNodes.put(newNode.getPath(), newNode);
+ for (Iterator e = subscribers.iterator(); e.hasNext();) {
+ NodeSubscriber thisSub = (NodeSubscriber)e.next();
+
+ thisSub.add(newNode);
+ }
+ }
+ }
+
+ public void remove(Path oldPath) {
+ synchronized(childNodes) {
+ childNodes.remove(oldPath);
+ for (Iterator e = subscribers.iterator(); e.hasNext();) {
+ NodeSubscriber thisSub = (NodeSubscriber)e.next();
+ thisSub.remove(oldPath);
+ }
+ }
+ }
+
+ public void removeAllChildren() {
+ synchronized(childNodes) {
+ Path thisPath;
+ while (childNodes.keySet().iterator().hasNext()) {
+ remove((Path)childNodes.keySet().iterator().next());
+ }
+ }
+ }
+
+ public Node getChildNode(Path itsPath) {
+ for (Iterator i = childNodes.keySet().iterator(); i.hasNext();) {
+ Object next = i.next();
+ if ( next.equals(itsPath) ) return (Node)childNodes.get(next);
+ }
+ return null;
+ }
+
+ // end of current batch
+ public void end(boolean more) {
+ for (Iterator e = subscribers.iterator(); e.hasNext();) {
+ NodeSubscriber thisSub = (NodeSubscriber)e.next();
+ thisSub.end(more);
+ }
+ }
+
+
+ public void run() {
+ Thread.currentThread().setName("Node Loader: "+name);
+ loadChildren();
+ }
+
+ public abstract void loadChildren();
+
+ public void refresh() {
+ removeAllChildren();
+ loadChildren();
+ }
+
+ // Getters and Setters
+
+ public int getSysKey() { return sysKey; }
+// public void setSysKey( int sysKey ) { this.sysKey = sysKey; }
+
+ public String getName() { return name; }
+// public void setName( String name ) { this.name = name; }
+
+ public String getType() { return type; }
+// public void setType( String type ) { this.type = type; }
+
+ public Path getPath() { return binding; }
+
+ public DynamicTreeBuilder getTreeBuilder() { return loader; }
+
+ public String toString() {
+ if (this.name.length() > 0) {
+ return this.name;
+ }
+ else { return "Cristal"; }
+ }
+
+ public Icon getIcon() {
+ if (icon != null) return icon;
+ return(isExpandable?folder:emptyLeaf);
+ }
+
+ public String getIconName() {
+ return iconName;
+ }
+
+ public void setIcon(String icon) {
+ iconName = icon;
+ this.icon = Resource.getImageResource("typeicons/"+icon+"_16.png");
+ }
+
+ public JPopupMenu getPopupMenu() {
+ JPopupMenu popup = new JPopupMenu();
+ JMenuItem menuItem = new JMenuItem(Language.translate("Refresh"));
+ menuItem.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ if (isExpandable) refresh();
+ }
+ });
+ popup.add(menuItem);
+ return popup;
+ }
+}
diff --git a/source/com/c2kernel/gui/data/NodeAgent.java b/source/com/c2kernel/gui/data/NodeAgent.java
new file mode 100755
index 0000000..9ef738a
--- /dev/null
+++ b/source/com/c2kernel/gui/data/NodeAgent.java
@@ -0,0 +1,31 @@
+
+package com.c2kernel.gui.data;
+
+
+import java.util.ArrayList;
+
+import com.c2kernel.gui.EntityTabManager;
+import com.c2kernel.lookup.Path;
+
+/**
+ * Structure for Item presence on the tree and ItemDetails boxes. Created by NodeFactory.
+ * @author $Author: abranson $
+ * @version $Version$
+ */
+public class NodeAgent extends NodeEntity {
+
+ public NodeAgent(Path path, EntityTabManager desktop) {
+ super(path, desktop);
+ }
+
+ public void loadChildren() {
+ }
+
+ public ArrayList getTabs() {
+
+ ArrayList requiredTabs = super.getTabs();
+ requiredTabs.add("AgentProperties");
+ requiredTabs.add("JobList");
+ return requiredTabs;
+ }
+}
diff --git a/source/com/c2kernel/gui/data/NodeCollection.java b/source/com/c2kernel/gui/data/NodeCollection.java
new file mode 100755
index 0000000..3b02098
--- /dev/null
+++ b/source/com/c2kernel/gui/data/NodeCollection.java
@@ -0,0 +1,66 @@
+package com.c2kernel.gui.data;
+
+import java.util.ArrayList;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+
+import com.c2kernel.collection.CollectionMember;
+import com.c2kernel.collection.Parent2ChildCollection;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.gui.EntityTabManager;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.lookup.InvalidEntityPathException;
+import com.c2kernel.utils.Logger;
+
+public class NodeCollection extends Node {
+
+ ItemProxy parent;
+ Parent2ChildCollection thisCollection;
+ String path;
+
+ public NodeCollection(ItemProxy parent, String name, EntityTabManager desktop) {
+ this.desktop = desktop;
+ this.parent = parent;
+ this.name = name;
+ this.path = parent.getSystemKey()+"/Collection/"+name;
+ createTreeNode();
+ this.makeExpandable();
+ }
+
+ public void loadChildren() {
+ Logger.msg(8, "NodeCollection::loadChildren()");
+ try {
+ thisCollection = (Parent2ChildCollection)parent.getObject("Collection/"+name);
+ } catch (ObjectNotFoundException ex) {
+ end(false);
+ return;
+ }
+
+ this.type = thisCollection.getClass().getName();
+ int lastDot = this.type.lastIndexOf('.');
+ if (lastDot > -1) this.type = this.type.substring(lastDot+1);
+ ArrayList collectionMembers = thisCollection.getMembers().list;
+ for (int i=0; i<collectionMembers.size(); i++)
+ {
+ CollectionMember aMember = (CollectionMember)collectionMembers.get(i);
+ if (aMember!=null)
+ try
+ {
+ EntityPath entityPath = new EntityPath(aMember.getEntityKey());
+ add(new NodeItem(entityPath, desktop));
+ }
+ catch (InvalidEntityPathException ex)
+ {
+ Logger.error("InvalidEntityPathException::NodeCollection::loadChildren() " + ex.toString());
+ }
+ }
+
+ end(false);
+
+ }
+
+ public DefaultMutableTreeNode getTreeNode() {
+ return treeNode;
+ }
+}
diff --git a/source/com/c2kernel/gui/data/NodeContext.java b/source/com/c2kernel/gui/data/NodeContext.java
new file mode 100755
index 0000000..6e2bc75
--- /dev/null
+++ b/source/com/c2kernel/gui/data/NodeContext.java
@@ -0,0 +1,61 @@
+package com.c2kernel.gui.data;
+
+import java.util.Enumeration;
+
+import com.c2kernel.entity.proxy.DomainPathSubscriber;
+import com.c2kernel.gui.EntityTabManager;
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.lookup.Path;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Logger;
+
+
+public class NodeContext extends Node implements DomainPathSubscriber {
+ Enumeration children;
+
+ public NodeContext(Path path, EntityTabManager desktop) {
+ super(path, desktop);
+ this.sysKey=Path.INVALID;
+ createTreeNode();
+ this.makeExpandable();
+ this.type = "Cristal Context";
+ }
+
+
+ public void loadChildren() {
+ if (children == null) {
+ Gateway.getProxyManager().subscribeTree(this, (DomainPath)binding);
+ children = binding.getChildren();
+ }
+
+ int batch = 75;
+ while (children.hasMoreElements() && batch > 0) {
+ Path newPath = (Path)children.nextElement();
+ if (newPath == null) break;
+ Logger.msg(2, "Subscription.run() - new node: " + newPath );
+ add( newNode(newPath));
+ batch--;
+ }
+ end(children.hasMoreElements());
+ }
+
+ public void pathAdded(DomainPath path) {
+ add(newNode(path));
+ }
+
+ public void refresh() {
+ children = null;
+ super.refresh();
+ }
+ public void pathRemoved(DomainPath path) {
+ remove(path);
+ }
+
+}
+
+
+
+
+
+
+
diff --git a/source/com/c2kernel/gui/data/NodeEntity.java b/source/com/c2kernel/gui/data/NodeEntity.java
new file mode 100755
index 0000000..adff241
--- /dev/null
+++ b/source/com/c2kernel/gui/data/NodeEntity.java
@@ -0,0 +1,80 @@
+package com.c2kernel.gui.data;
+
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+
+import com.c2kernel.entity.proxy.EntityProxy;
+import com.c2kernel.gui.EntityTabManager;
+import com.c2kernel.lookup.Path;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+
+/**
+ * Structure for Item presence on the tree and ItemDetails boxes. Created by NodeFactory.
+ * @author $Author: abranson $
+ * @version $Version$
+ */
+public abstract class NodeEntity extends Node {
+
+ protected EntityProxy myEntity = null;
+
+ public NodeEntity(Path path, EntityTabManager desktop) {
+ super(path, desktop);
+ Logger.msg(2,"NodeEntity.<init> - Creating item for '"+path.toString()+"'.");
+
+ try {
+ // if an item - resolve the item and get its properties
+ myEntity = Gateway.getProxyManager().getProxy(path);
+ this.sysKey = path.getSysKey();
+ Logger.msg(2,"NodeEntity.<init> - System key is "+this.sysKey);
+
+ // Name should be the alias if present
+ String alias = myEntity.getName();
+ if (alias != null) this.name = alias;
+
+ this.type = myEntity.getProperty("Type");
+ String iconString = this.type;
+ if (type.equals("ActivityDesc")) iconString = myEntity.getProperty("Complexity")+iconString;
+ iconString = iconString.toLowerCase();
+ this.setIcon(iconString);
+ createTreeNode();
+ } catch (Exception e) {
+ Logger.msg(2, "NodeEntity.<init> - "+sysKey+" failed to resolve:");
+ Logger.error(e);
+ }
+ }
+
+ public EntityProxy getEntity() {
+ return myEntity;
+ }
+ /**
+ *
+ */
+ public JPopupMenu getPopupMenu() {
+ JPopupMenu popup = super.getPopupMenu();
+ JMenuItem openItem = new JMenuItem(Language.translate("Open"));
+ openItem.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ openItem();
+ }
+ });
+ popup.addSeparator();
+ popup.add(openItem);
+ return popup;
+ }
+
+ public void openItem() {
+ desktop.add(this);
+ }
+
+ public ArrayList getTabs() {
+ ArrayList requiredTabs = new ArrayList();
+ return requiredTabs;
+ }
+}
diff --git a/source/com/c2kernel/gui/data/NodeItem.java b/source/com/c2kernel/gui/data/NodeItem.java
new file mode 100755
index 0000000..410f13a
--- /dev/null
+++ b/source/com/c2kernel/gui/data/NodeItem.java
@@ -0,0 +1,110 @@
+package com.c2kernel.gui.data;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+
+import com.c2kernel.entity.agent.Job;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.gui.EntityDetails;
+import com.c2kernel.gui.EntityTabManager;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.lookup.Path;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.utils.Logger;
+
+/**
+ * Structure for Item presence on the tree and ItemDetails boxes. Created by NodeFactory.
+ * @author $Author: abranson $
+ * @version $Version$
+ */
+public class NodeItem extends NodeEntity {
+
+ public NodeItem(Path path, EntityTabManager desktop) {
+ super(path, desktop);
+ try {
+ makeExpandable();
+ } catch (Exception e) {
+ Logger.error(e);
+ }
+ }
+
+ public void loadChildren() {
+ try {
+ String collections = myEntity.queryData("Collection/all");
+ StringTokenizer tok = new StringTokenizer(collections, ",");
+ while (tok.hasMoreTokens()) {
+ NodeCollection newCollection = new NodeCollection((ItemProxy)myEntity, tok.nextToken(), desktop);
+ add(newCollection);
+ }
+ end(false);
+ } catch (Exception e) {
+ Logger.error(e);
+ }
+ }
+
+ public JPopupMenu getPopupMenu() {
+ JPopupMenu popup = super.getPopupMenu();
+ popup.addSeparator();
+ try {
+ ArrayList jobList = ((ItemProxy)myEntity).getJobList(MainFrame.userAgent);
+ ArrayList already = new ArrayList();
+ if (jobList.size() > 0) {
+ for (Iterator e = jobList.iterator(); e.hasNext();) {
+ Job thisJob = (Job)e.next();
+ String stepName = thisJob.getStepName();
+ if (already.contains(stepName))
+ continue;
+ already.add(stepName);
+ JMenuItem menuItem = new JMenuItem(stepName);
+ menuItem.setActionCommand(stepName);
+ menuItem.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ execute(e.getActionCommand());
+ }
+ });
+ popup.add(menuItem);
+
+ }
+ }
+ else {
+ JMenuItem noAct = new JMenuItem("No activities");
+ noAct.setEnabled(false);
+ popup.add(noAct);
+ }
+ } catch (Exception ex) {
+ JMenuItem error = new JMenuItem("Error querying jobs");
+ error.setEnabled(false);
+ popup.add(error);
+ }
+
+ return popup;
+ }
+
+ public void execute(String stepName) {
+ EntityDetails thisDetail = desktop.add(this);
+ thisDetail.runCommand("Execution", stepName);
+ }
+
+ public ArrayList getTabs() {
+
+ ArrayList requiredTabs = super.getTabs();
+ requiredTabs.add("Properties");
+ try {
+ String collNames = myEntity.queryData(ClusterStorage.COLLECTION+"/all");
+ if (collNames.length() > 0)
+ requiredTabs.add("Collection");
+ } catch (Exception e) { }
+ requiredTabs.add("Execution");
+ requiredTabs.add("History");
+ requiredTabs.add("Viewpoint");
+ requiredTabs.add("Workflow");
+ return requiredTabs;
+
+ }
+}
diff --git a/source/com/c2kernel/gui/data/NodeSubscriber.java b/source/com/c2kernel/gui/data/NodeSubscriber.java
new file mode 100755
index 0000000..ae2ab44
--- /dev/null
+++ b/source/com/c2kernel/gui/data/NodeSubscriber.java
@@ -0,0 +1,13 @@
+package com.c2kernel.gui.data;
+
+import com.c2kernel.lookup.Path;
+
+
+public interface NodeSubscriber {
+
+ public void add(Node newNode);
+
+ public void remove(Path path);
+
+ public void end(boolean more);
+}
diff --git a/source/com/c2kernel/gui/tabs/AgentPropertiesPane.java b/source/com/c2kernel/gui/tabs/AgentPropertiesPane.java
new file mode 100755
index 0000000..b859c44
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/AgentPropertiesPane.java
@@ -0,0 +1,50 @@
+package com.c2kernel.gui.tabs;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.JTextField;
+
+/**************************************************************************
+ *
+ * $Revision: 1.2 $
+ * $Date: 2005/07/05 11:34:17 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+
+public class AgentPropertiesPane extends EntityTabPane {
+
+ JTable roleTable;
+ JTextField newPassword;
+ JTextField newPasswordConfirm;
+ JButton changePassword;
+
+ public AgentPropertiesPane() {
+ super("Properties", "Agent Details");
+ initPanel();
+ getGridBagConstraints();
+ c.gridy++;
+ JLabel roleHeader = new JLabel("Roles held");
+ roleHeader.setFont(titleFont);
+ roleHeader.setForeground(headingColor);
+ gridbag.setConstraints(roleHeader, c);
+ add(roleHeader);
+ roleTable = new JTable(1,1);
+ JScrollPane roleScroll = new JScrollPane(roleTable);
+ c.gridy++;
+ gridbag.setConstraints(roleScroll, c);
+ add(roleScroll);
+
+ JLabel passHeader = new JLabel("Change password");
+
+ }
+
+ public void run() {
+
+ }
+
+}
diff --git a/source/com/c2kernel/gui/tabs/CloseTabIcon.java b/source/com/c2kernel/gui/tabs/CloseTabIcon.java
new file mode 100755
index 0000000..ca2bf0b
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/CloseTabIcon.java
@@ -0,0 +1,67 @@
+package com.c2kernel.gui.tabs;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+
+import javax.swing.Icon;
+
+/**
+ * @author Developpement
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+/** * The class which generates the 'X' icon for the tabs. The constructor * accepts an icon which is extra to the 'X' icon, so you can have tabs * like in JBuilder. This value is null if no extra icon is required. */
+class CloseTabIcon implements Icon
+{
+ private int x_pos;
+ private int y_pos;
+ private int width;
+ private int height;
+ private Icon fileIcon;
+ public CloseTabIcon(Icon fileIcon)
+ {
+ this.fileIcon = fileIcon;
+ width = 16;
+ height = 16;
+ }
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ this.x_pos = x;
+ this.y_pos = y;
+ Color col = g.getColor();
+ g.setColor(Color.black);
+ int y_p = y + 2;
+ g.drawLine(x + 1, y_p, x + 12, y_p);
+ g.drawLine(x + 1, y_p + 13, x + 12, y_p + 13);
+ g.drawLine(x, y_p + 1, x, y_p + 12);
+ g.drawLine(x + 13, y_p + 1, x + 13, y_p + 12);
+ g.drawLine(x + 3, y_p + 3, x + 10, y_p + 10);
+ g.drawLine(x + 3, y_p + 4, x + 9, y_p + 10);
+ g.drawLine(x + 4, y_p + 3, x + 10, y_p + 9);
+ g.drawLine(x + 10, y_p + 3, x + 3, y_p + 10);
+ g.drawLine(x + 10, y_p + 4, x + 4, y_p + 10);
+ g.drawLine(x + 9, y_p + 3, x + 3, y_p + 9);
+ g.setColor(col);
+ if (fileIcon != null)
+ {
+ fileIcon.paintIcon(c, g, x + width, y_p);
+ }
+ }
+ public int getIconWidth()
+ {
+ return width + (fileIcon != null ? fileIcon.getIconWidth() : 0);
+ }
+ public int getIconHeight()
+ {
+ return height;
+ }
+ public Rectangle getBounds()
+ {
+ return new Rectangle(x_pos, y_pos, width, height);
+ }
+} \ No newline at end of file
diff --git a/source/com/c2kernel/gui/tabs/CollectionPane.java b/source/com/c2kernel/gui/tabs/CollectionPane.java
new file mode 100755
index 0000000..92492fc
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/CollectionPane.java
@@ -0,0 +1,100 @@
+package com.c2kernel.gui.tabs;
+import java.awt.GridBagConstraints;
+
+import javax.swing.JTabbedPane;
+
+import com.c2kernel.collection.Aggregation;
+import com.c2kernel.collection.Collection;
+import com.c2kernel.collection.Dependency;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.entity.proxy.EntityProxyObserver;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.gui.tabs.collection.AggregationView;
+import com.c2kernel.gui.tabs.collection.CollectionView;
+import com.c2kernel.gui.tabs.collection.DependencyView;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Logger;
+/**
+ * @version $Revision: 1.36 $ $Date: 2005/10/06 06:51:15 $
+ * @author $Author: abranson $
+ */
+public class CollectionPane extends EntityTabPane implements EntityProxyObserver
+{
+ JTabbedPane collTabs;
+
+ public CollectionPane()
+ {
+ super("Collection", "Item Collection");
+ createLayout();
+ }
+
+ public void add(C2KLocalObject contents)
+ {
+ Logger.msg(5, "Got "+contents.getName()+": "+contents.getClass().getName());
+ if (!(contents instanceof Collection))
+ {
+ // ignore member control objects
+ return;
+ }
+ Logger.msg(7, "Looking for existing "+contents.getName());
+ CollectionView thisCollView = findTabForCollName(contents.getName());
+ if (thisCollView == null){
+ if (contents instanceof Aggregation)
+ thisCollView = new AggregationView();
+ else if (contents instanceof Dependency)
+ thisCollView = new DependencyView();
+ else {
+ Logger.error("Collection type "+contents.getClass().getName()+" not known");
+ return;
+ }
+ Logger.msg(3, "Adding new "+thisCollView.getClass().getName());
+ thisCollView.setItem((ItemProxy)sourceEntity.getEntity());
+ collTabs.add(contents.getName(), thisCollView);
+ }
+ thisCollView.setCollection((Collection)contents);
+ }
+
+ public void remove(String id)
+ {
+
+ }
+
+ private CollectionView findTabForCollName(String collName) {
+ CollectionView thisCollView = null;
+ for (int i = 0; i < collTabs.getTabCount(); i++) {
+ String tabName = collTabs.getTitleAt(i);
+ if (tabName.equals(collName)) {
+ thisCollView = (CollectionView)collTabs.getComponentAt(i);
+ }
+ }
+ return thisCollView;
+ }
+
+ protected void createLayout()
+ {
+ initPanel();
+ // Add the collection tab pane
+ getGridBagConstraints();
+ c.gridx = 0;
+ c.gridy = 1;
+ c.fill = GridBagConstraints.BOTH;
+ c.weighty = 2.0;
+ collTabs = new JTabbedPane();
+ gridbag.setConstraints(collTabs, c);
+ add(collTabs);
+ }
+
+ public void run()
+ {
+ Thread.currentThread().setName("Collection Loader");
+ sourceEntity.getEntity().subscribe(this, ClusterStorage.COLLECTION, true);
+ }
+
+ public void reload()
+ {
+ Gateway.getStorage().clearCache(sourceEntity.getSysKey(), ClusterStorage.COLLECTION);
+ collTabs.removeAll();
+ initForEntity(sourceEntity);
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/DomainPathAdmin.java b/source/com/c2kernel/gui/tabs/DomainPathAdmin.java
new file mode 100755
index 0000000..35104d7
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/DomainPathAdmin.java
@@ -0,0 +1,161 @@
+package com.c2kernel.gui.tabs;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+import javax.swing.*;
+import javax.swing.table.AbstractTableModel;
+
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Logger;
+
+/**************************************************************************
+ *
+ * $Revision: 1.3 $
+ * $Date: 2004/10/21 08:02:21 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class DomainPathAdmin extends Box implements ActionListener {
+
+ ItemProxy entity;
+ JTable table;
+ DomainPathTableModel model;
+ JButton addButton;
+ JButton removeButton;
+
+ public DomainPathAdmin() {
+ super(BoxLayout.Y_AXIS);
+
+ model = new DomainPathTableModel(this);
+ table = new JTable(model);
+ add(new JScrollPane(table));
+
+ add(Box.createVerticalGlue());
+ Box buttonBox = Box.createHorizontalBox();
+ addButton = new JButton("Add");
+ buttonBox.add(addButton);
+ buttonBox.add(Box.createHorizontalGlue());
+ removeButton = new JButton("Remove");
+ buttonBox.add(removeButton);
+ buttonBox.add(Box.createHorizontalGlue());
+ add(buttonBox);
+
+ addButton.setActionCommand("add");
+ addButton.addActionListener(this);
+ removeButton.setActionCommand("remove");
+ removeButton.addActionListener(this);
+ }
+
+ public void setEntity(ItemProxy entity) {
+ this.entity = entity;
+ model.loadPaths();
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand().equals("add")) {
+ String newPath = JOptionPane.showInputDialog(this, "Enter new path,", "Add Domain Path", JOptionPane.PLAIN_MESSAGE);
+ addDomainPath(new DomainPath(newPath));
+ model.loadPaths();
+ }
+ else if (e.getActionCommand().equals("remove")) {
+ if (table.getSelectedRow() > -1) {
+ DomainPath oldPath = model.getPath(table.getSelectedRow());
+ removeDomainPath(oldPath);
+ model.loadPaths();
+ }
+ }
+ }
+
+ public boolean removeDomainPath(DomainPath oldPath) {
+ return alterDomainPath(oldPath, "Remove");
+ }
+
+ public boolean addDomainPath(DomainPath newPath) {
+ return alterDomainPath(newPath, "Add");
+ }
+
+ public boolean alterDomainPath(DomainPath path, String action) {
+
+ if (JOptionPane.showConfirmDialog(this,
+ action+" "+path+"?",
+ action+" Domain Path",
+ JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION)
+ return false;
+
+ String[] params = new String[1];
+ params[0] = path.toString();
+ try {
+ MainFrame.userAgent.execute(entity, action+"DomainPath", params);
+ } catch (Exception e) {
+ Logger.exceptionDialog(e);
+ return false;
+ }
+ return true;
+ }
+
+ private class DomainPathTableModel extends AbstractTableModel {
+ ArrayList domPaths;
+ DomainPathAdmin parent;
+ public DomainPathTableModel(DomainPathAdmin parent) {
+ this.parent = parent;
+ domPaths = new ArrayList();
+ }
+
+ public void loadPaths() {
+ domPaths.clear();
+ for (Enumeration currentPaths = Gateway.getLDAPLookup().search(new DomainPath(), entity.getName()); currentPaths.hasMoreElements();) {
+ DomainPath thisPath = (DomainPath)currentPaths.nextElement();
+ if (thisPath.getSysKey() == entity.getSystemKey())
+ domPaths.add(thisPath);
+ }
+ fireTableDataChanged();
+ }
+
+ public DomainPath getPath(int rowIndex) {
+ return (DomainPath)domPaths.get(rowIndex);
+ }
+ public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+ DomainPath oldPath = (DomainPath)domPaths.get(rowIndex);
+ DomainPath newPath = new DomainPath((String)aValue);
+ boolean success = parent.addDomainPath(newPath);
+ if (success)
+ success = parent.removeDomainPath(oldPath);
+ if (success) {
+ oldPath.setPath(newPath);
+ fireTableDataChanged();
+ }
+ }
+
+ public Class getColumnClass(int columnIndex) {
+ return String.class;
+ }
+
+ public int getColumnCount() {
+ return 1;
+ }
+
+ public String getColumnName(int column) {
+ return "Path";
+ }
+
+ public int getRowCount() {
+ return domPaths.size();
+ }
+
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ return domPaths.get(rowIndex).toString();
+ }
+
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ return true;
+ }
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/EntityTabPane.java b/source/com/c2kernel/gui/tabs/EntityTabPane.java
new file mode 100755
index 0000000..f6fae14
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/EntityTabPane.java
@@ -0,0 +1,182 @@
+/*
+ * TabbedPane.java
+ *
+ * Created on March 22, 2001, 11:39 AM
+ */
+package com.c2kernel.gui.tabs;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+
+import javax.swing.*;
+
+import com.c2kernel.entity.proxy.EntityProxyObserver;
+import com.c2kernel.gui.EntityDetails;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.gui.data.NodeEntity;
+import com.c2kernel.gui.tabs.outcome.OutcomeHandler;
+import com.c2kernel.gui.tabs.outcome.form.OutcomePanel;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.Resource;
+/**
+ * Generic item details tabbed pane.
+ *
+ * @version $Revision: 1.31 $ $Date: 2005/06/08 16:47:44 $
+ * @author $Author: abranson $
+ */
+public class EntityTabPane extends JPanel implements Runnable {
+
+ protected NodeEntity sourceEntity;
+ protected String titleText = null;
+ protected ImageIcon titleIcon = null;
+ private String tabName;
+ protected GridBagLayout gridbag = new GridBagLayout();
+ protected GridBagConstraints c = null;
+ public static Font titleFont = null;
+ public static Color headingColor = new Color(0, 0, 185);
+ protected EntityDetails parent;
+ protected static ImageIcon mReloadIcon = null;
+ protected Box titleBox;
+ static {
+ try {
+ mReloadIcon = Resource.getImageResource("reload.gif");
+ } catch (Exception e) {
+ Logger.warning("Couldn't load images: " + e);
+ }
+ }
+
+ public void focusLost(FocusEvent e)
+ {
+ }
+
+ public EntityTabPane(String tabName, String titleText) {
+ this.tabName = Language.translate(tabName);
+ this.titleText =
+ titleText == null ? null : Language.translate(titleText);
+ if (titleFont == null)
+ titleFont =
+ new Font("SansSerif", Font.BOLD, this.getFont().getSize() + 5);
+ Logger.msg(2, "ItemTabPane.<init> - viewing " + tabName);
+ setLayout(gridbag);
+ }
+ public void setParent(EntityDetails parent) {
+ this.parent = parent;
+ }
+ public String getTabName() {
+ return tabName;
+ }
+ protected GridBagConstraints getGridBagConstraints() {
+ if (c == null)
+ c = new GridBagConstraints();
+ return c;
+ }
+ protected void initPanel() {
+ getGridBagConstraints().gridx = 0;
+ getGridBagConstraints().gridy = 0;
+ getGridBagConstraints().anchor = GridBagConstraints.NORTHWEST;
+ getGridBagConstraints().fill = GridBagConstraints.HORIZONTAL;
+ getGridBagConstraints().ipadx = 5;
+ getGridBagConstraints().weightx = 1.0;
+ getGridBagConstraints().ipady = 5;
+ // Help panel
+ if (titleText == null)
+ titleText = tabName;
+ if (titleIcon == null)
+ titleIcon = Resource.getImageResource("info.png");
+ JLabel title = new JLabel(titleText, titleIcon, SwingConstants.LEFT);
+ title.setFont(titleFont);
+ title.setForeground(headingColor);
+ JButton refreshButton = new JButton(mReloadIcon);
+ refreshButton.setToolTipText(Language.translate("Refresh"));
+ refreshButton.setMargin(new Insets(0, 0, 0, 0));
+ refreshButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ setCursor(new Cursor(Cursor.WAIT_CURSOR));
+ reload();
+ setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
+ }
+ });
+ String defaultStartTab = MainFrame.getPref("DefaultStartTab", "Properties");
+ JToggleButton defaultStart =
+ new JToggleButton(Resource.getImageResource("graph/start.png"));
+ defaultStart.setMargin(new Insets(0, 0, 0, 0));
+ defaultStart.setToolTipText(
+ Language.translate("Select this tab to be the default one opened when you double click an item"));
+ defaultStart.setSelected(tabName.equals(defaultStartTab));
+ defaultStart.setActionCommand(tabName);
+ defaultStart.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ if (((JToggleButton)e.getSource()).isSelected())
+ MainFrame.setPref("DefaultStartTab", e.getActionCommand());
+ }
+ });
+ titleBox = Box.createHorizontalBox();
+ titleBox.add(title);
+ titleBox.add(Box.createHorizontalGlue());
+ titleBox.add(defaultStart);
+ titleBox.add(refreshButton);
+ gridbag.setConstraints(titleBox, c);
+ this.add(titleBox);
+ }
+ public void initForEntity(NodeEntity sourceEntity) {
+ this.sourceEntity = sourceEntity;
+ Thread loader = new Thread(this);
+ loader.start();
+ }
+ public void run() {
+ Thread.currentThread().setName("Default Entity Pane Builder");
+ getGridBagConstraints();
+ c.gridx = 0;
+ c.gridy = 1;
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.ipadx = 5;
+ c.weightx = 1.0;
+ c.weighty = 1.0;
+ c.ipady = 5;
+ JLabel error = new JLabel("In Development");
+ gridbag.setConstraints(error, c);
+ this.add(error);
+ }
+ public void reload() {
+ }
+ public void runCommand(String command) {
+ }
+
+ public void destroy() {
+ if (sourceEntity != null && this instanceof EntityProxyObserver) {
+ sourceEntity.getEntity().unsubscribe((EntityProxyObserver)this);
+ }
+ parent = null;
+ }
+
+ protected void finalize() throws Throwable {
+ Logger.msg(7, "Reaping "+getClass().getName());
+ }
+
+ static public OutcomeHandler getOutcomeHandler(String schema, int version) {
+ String ohClassName = Gateway.getProperty("OutcomeHandler."+schema+"."+version);
+ try {
+ if (ohClassName != null && ohClassName.length() > 0) {
+ Class ohClass = Class.forName(ohClassName);
+ return (OutcomeHandler) ohClass.newInstance();
+ }
+ } catch (Exception ex) {
+ Logger.error("Error creating handler "+ohClassName+". using default outcome editor");
+ }
+ ohClassName = Gateway.getProperty("OutcomeHandler.*");
+ try {
+ if (ohClassName != null && ohClassName.length() > 0) {
+ Class ohClass = Class.forName(ohClassName);
+ return (OutcomeHandler) ohClass.newInstance();
+ }
+ } catch (Exception ex) {
+ Logger.error("Error creating handler "+ohClassName+". using default outcome editor");
+ Logger.error(ex);
+ }
+ return new OutcomePanel();
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/ExecutionPane.java b/source/com/c2kernel/gui/tabs/ExecutionPane.java
new file mode 100755
index 0000000..de07319
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/ExecutionPane.java
@@ -0,0 +1,198 @@
+package com.c2kernel.gui.tabs;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridLayout;
+import java.awt.Insets;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.util.ArrayList;
+import java.util.Iterator;
+import javax.swing.Box;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.entity.agent.Job;
+import com.c2kernel.entity.proxy.EntityProxyObserver;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.gui.tabs.execution.ActivityItem;
+import com.c2kernel.gui.tabs.execution.ActivityViewer;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+
+public class ExecutionPane extends EntityTabPane implements EntityProxyObserver {
+
+ ArrayList jobList = null;
+ Object jobLock = new Object();
+ String[] emptyAct = { "--" };
+ JLabel noActs = new JLabel(Language.translate("There are currently no activities that you can execute in this item."));
+ JPanel view = new JPanel(new GridLayout(1, 1));
+ ActivityViewer currentActView;
+ JComboBox activitySelector = new JComboBox(emptyAct);
+ Box activityBox = Box.createHorizontalBox();
+ String selAct = null;
+ ArrayList activities;
+ String autoRun = null;
+ boolean init = false;
+ boolean formIsActive = false;
+ public ExecutionPane() {
+ super("Execution", "Activity Execution");
+ super.initPanel();
+ // add view panel
+ c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = 1; c.weightx = 1.0; c.weighty = 2.0;
+ c.insets = new Insets(5, 5, 5, 5);
+ c.anchor = GridBagConstraints.CENTER;
+ c.fill = GridBagConstraints.BOTH;
+ gridbag.setConstraints(view, c);
+
+ add(view);
+ // create activity selection box
+ activityBox.add(new JLabel(Language.translate("Select Activity") + ": "));
+ activityBox.add(Box.createHorizontalStrut(5));
+ activitySelector.setEditable(false);
+ activityBox.add(activitySelector);
+ activitySelector.addItemListener(new ItemListener() {
+ public void itemStateChanged(ItemEvent selection) {
+ if (selection.getStateChange() == ItemEvent.SELECTED) {
+ selectActivity(selection.getItem());
+ }
+ }
+ });
+ }
+ public void run() {
+ Thread.currentThread().setName("Execution Pane Builder");
+ sourceEntity.getEntity().subscribe(this, ClusterStorage.LIFECYCLE, false);
+ loadJobList();
+ init = true;
+ if (autoRun != null) {
+ runCommand(autoRun);
+ autoRun = null;
+ }
+ }
+ private void loadJobList() {
+ synchronized (jobLock) {
+ activitySelector.removeAllItems();
+ view.removeAll();
+ activities = new ArrayList();
+ try {
+ jobList = ((ItemProxy)sourceEntity.getEntity()).getJobList(MainFrame.userAgent);
+ activitySelector.addItem("--");
+ for (Iterator e = jobList.iterator(); e.hasNext();) {
+ Job thisJob = (Job)e.next();
+ Logger.msg(7, "ExecutionPane - loadJobList " + thisJob.isOutcomeUsed() + "|" + thisJob.getSchemaType() + "|" + thisJob.getSchemaVersion() + "|");
+ ActivityItem newAct = new ActivityItem(thisJob);
+ if (activities.contains(newAct)) {
+ int actIndex = activities.indexOf(newAct);
+ ((ActivityItem)activities.get(actIndex)).addJob(thisJob);
+ } else {
+ Logger.msg(2, "ExecutionPane - Adding activity " + thisJob.getStepPath());
+ addActivity(newAct);
+ }
+ }
+ } catch (Exception e) {
+ activitySelector.addItem("Error fetching JobList");
+ Logger.debug("Error fetching joblist");
+ Logger.error(e);
+ }
+
+ switch (activities.size()) {
+ case 0 :
+ view.add(noActs);
+ break;
+ case 1 :
+ currentActView = new ActivityViewer((ActivityItem)activities.get(0), (ItemProxy)sourceEntity.getEntity(), this);
+ c.fill = GridBagConstraints.BOTH;
+ gridbag.setConstraints(view, c);
+ view.add(currentActView);
+ currentActView.init();
+ break;
+ default :
+ c.fill = GridBagConstraints.HORIZONTAL;
+ gridbag.setConstraints(view, c);
+ view.add(activityBox);
+ }
+ }
+ revalidate();
+ updateUI();
+ }
+ public void reload() {
+ loadJobList();
+ }
+ private void addActivity(ActivityItem newAct) {
+ if (activities.contains(newAct)) {
+ Logger.msg(6, "ExecutionPane.addActivity(): Already in " + newAct.getStepPath());
+ int actIndex = activities.indexOf(newAct);
+ activitySelector.removeItemAt(actIndex);
+ activitySelector.insertItemAt(newAct, actIndex);
+ activities.set(actIndex, newAct);
+ } else {
+ Logger.msg(6, "ExecutionPane.addActivity(): New " + newAct.getStepPath());
+ activities.add(newAct);
+ activitySelector.addItem(newAct);
+ }
+ }
+ private void selectActivity(Object selObj) {
+ if (!(selObj instanceof ActivityItem))
+ return;
+ view.removeAll();
+ c.fill = GridBagConstraints.BOTH;
+ gridbag.setConstraints(view, c);
+ currentActView = new ActivityViewer((ActivityItem)selObj, (ItemProxy)sourceEntity.getEntity(), this);
+ view.add(currentActView);
+ revalidate();
+ updateUI();
+ currentActView.init();
+ }
+ public void runCommand(String command) {
+ if (init) {
+ for (Iterator iter = activities.iterator(); iter.hasNext();) {
+ ActivityItem act = (ActivityItem)iter.next();
+ if (act.name.equals(command)) {
+ selectActivity(act);
+ }
+ }
+ } else
+ autoRun = command;
+ }
+ /**
+ * when the workflow changes, reload this pane.
+ */
+ public void add(C2KLocalObject contents) {
+ if (!formIsActive)
+ reload();
+ else { // look to see if this form is now invalid
+ // get the new joblist
+ try {
+ jobList = ((ItemProxy)sourceEntity.getEntity()).getJobList(MainFrame.userAgent);
+ } catch (Exception ex) {
+ return;
+ }
+ // compare to currently editing jobs
+ ArrayList currentActJobs = currentActView.getActivity().getJobs();
+ boolean allValid = true;
+ for (Iterator iter = currentActJobs.iterator(); iter.hasNext() && allValid;) {
+ Job thisJob = (Job)iter.next();
+ boolean stillValid = false;
+ for (Iterator iter2 = jobList.iterator(); iter2.hasNext();) {
+ Job newJob = (Job)iter2.next();
+ if (thisJob.equals(newJob)) {
+ stillValid = true;
+ break;
+ }
+ }
+ allValid &= stillValid;
+ }
+ if (!allValid) { // not all transitions are now valid
+ reload(); // refresh the execution pane
+ }
+ }
+ }
+ /**
+ * Not pertinent for this one
+ */
+ public void remove(String id) {
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/HistoryPane.java b/source/com/c2kernel/gui/tabs/HistoryPane.java
new file mode 100755
index 0000000..091ef5e
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/HistoryPane.java
@@ -0,0 +1,253 @@
+/*
+ * StatusPane.java
+ *
+ * Created on March 20, 2001, 3:30 PM
+ */
+
+package com.c2kernel.gui.tabs;
+
+/**
+ * @author abranson
+ * @version
+ */
+import java.awt.GridBagConstraints;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.table.AbstractTableModel;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.entity.proxy.EntityProxyObserver;
+import com.c2kernel.events.Event;
+import com.c2kernel.events.History;
+import com.c2kernel.lifecycle.instance.stateMachine.Transitions;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+
+/**
+ * Pane to display all work orders that this agent can execute, and activate
+ * them on request from the user. Subscribes to NodeItem for WorkOrder objects.
+ * @version $Revision: 1.22 $ $Date: 2005/04/26 06:48:13 $
+ * @author $Author: abranson $
+ */
+public class HistoryPane extends EntityTabPane implements ActionListener, EntityProxyObserver {
+
+ History history;
+ HistoryTableModel model;
+ JTable eventTable;
+ JButton startButton = new JButton("<<");
+ JButton prevButton = new JButton("<");
+ JButton nextButton = new JButton(">");
+ JButton endButton = new JButton(">>");
+ public static final int SIZE = 30;
+ int currentSize = SIZE;
+
+ public HistoryPane() {
+ super("History", "Event History");
+ initPanel();
+
+ // add buttons
+ Box navBox = Box.createHorizontalBox();
+ navBox.add(startButton); navBox.add(prevButton);
+ navBox.add(nextButton); navBox.add(endButton);
+
+ // setup buttons
+ //startButton.setEnabled(false); nextButton.setEnabled(false);
+ //prevButton.setEnabled(false); endButton.setEnabled(false);
+ startButton.setActionCommand("start");
+ startButton.addActionListener(this);
+ prevButton.setActionCommand("prev");
+ prevButton.addActionListener(this);
+ nextButton.setActionCommand("next");
+ nextButton.addActionListener(this);
+ endButton.setActionCommand("end");
+ endButton.addActionListener(this);
+ getGridBagConstraints();
+ c.gridx = 0; c.gridy = 1;
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.fill=GridBagConstraints.NONE;
+ c.weightx=0; c.weighty=0;
+ gridbag.setConstraints(navBox, c);
+ add(navBox);
+
+
+ // Create table
+ eventTable = new JTable();
+ JScrollPane eventScroll= new JScrollPane(eventTable);
+ c.weightx = 1.0; c.weighty = 1.0;
+ c.fill = GridBagConstraints.BOTH; c.gridy++;
+ gridbag.setConstraints(eventScroll, c);
+ add(eventScroll);
+
+ }
+
+ public void reload() {
+ history.clear();
+ jumpToEnd();
+ }
+
+ public void run() {
+ Thread.currentThread().setName("History Pane Builder");
+ try {
+ history = (History)sourceEntity.getEntity().getObject(ClusterStorage.HISTORY);
+ sourceEntity.getEntity().subscribe(this, ClusterStorage.HISTORY, false);
+ } catch (ObjectNotFoundException e) {
+ Logger.error(e);
+ }
+ model = new HistoryTableModel();
+ eventTable.setModel(model);
+ jumpToEnd();
+ }
+
+ public void jumpToEnd() {
+ int lastEvent = history.getLastId();
+ int firstEvent = 0; currentSize = SIZE;
+ if (lastEvent > currentSize) firstEvent = lastEvent - currentSize + 1;
+ if (lastEvent < currentSize) currentSize = lastEvent + 1;
+ Logger.msg(5, "HistoryPane.run() - init table start "+firstEvent+" for "+currentSize);
+ model.setView(firstEvent, currentSize);
+ }
+
+ public void add(C2KLocalObject contents) {
+ jumpToEnd();
+ }
+
+ public void remove(String id) {
+ // don't have to deal with this normally
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand().equals("end")) {
+ jumpToEnd();
+ return;
+ }
+
+ int lastEvent = history.getLastId();
+ int startEvent = model.getStartId();
+ if (e.getActionCommand().equals("start")) {
+ currentSize = SIZE;
+ startEvent = 0;
+ }
+
+ else if (e.getActionCommand().equals("prev")) {
+ currentSize = SIZE;
+ startEvent-=currentSize;
+ if (startEvent<0) startEvent = 0;
+ }
+ else if (e.getActionCommand().equals("next")) {
+ currentSize = SIZE;
+ startEvent+=currentSize;
+ if (startEvent > lastEvent)
+ startEvent = lastEvent - currentSize +1;
+ }
+ else { // unknown action
+ return;
+ }
+
+ model.setView(startEvent, currentSize);
+ }
+
+ private class HistoryTableModel extends AbstractTableModel {
+ Event[] event;
+ Integer[] ids;
+ int loaded = 0;
+ int startId = 0;
+
+ public HistoryTableModel() {
+ event = new Event[0];
+ ids = new Integer[0];
+ }
+
+ public int getStartId() {
+ return startId;
+ }
+
+ public void setView(int startId, int size) {
+ event = new Event[size];
+ ids = new Integer[size];
+ this.startId = startId;
+ for (int i=0; i<size; i++) {
+ event[i] = history.getEvent(startId+i);
+ ids[i] = new Integer(startId+i);
+ loaded = i+1;
+ }
+ fireTableStructureChanged();
+ }
+ /**
+ * @see javax.swing.table.TableModel#getColumnClass(int)
+ */
+ public Class getColumnClass(int columnIndex) {
+ switch(columnIndex) {
+ case 0:
+ return Integer.class;
+ default:
+ return String.class;
+ }
+ }
+
+ /**
+ * @see javax.swing.table.TableModel#getColumnCount()
+ */
+ public int getColumnCount() {
+ return 6;
+ }
+
+ /**
+ * @see javax.swing.table.TableModel#getColumnName(int)
+ */
+ public String getColumnName(int columnIndex) {
+ switch(columnIndex) {
+ case 0: return Language.translate("ID");
+ case 1: return Language.translate("Activity");
+ case 2: return Language.translate("Transition");
+ case 3: return Language.translate("Date");
+ case 4: return Language.translate("Agent Name");
+ case 5: return Language.translate("Agent Role");
+ default: return "";
+ }
+ }
+
+ /**
+ * @see javax.swing.table.TableModel#getRowCount()
+ */
+ public int getRowCount() {
+ return loaded;
+ }
+
+ /**
+ * @see javax.swing.table.TableModel#getValueAt(int, int)
+ */
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ if (event.length <= rowIndex || event[rowIndex] == null)
+ return "";
+ try {
+ switch (columnIndex) {
+ case 0: return ids[rowIndex];
+ case 1: return event[rowIndex].getStepName();
+ case 2: return Transitions.getTransitionName(event[rowIndex].getTransition());
+ case 3: return event[rowIndex].getTimeString();
+ case 4: return event[rowIndex].getAgentName();
+ case 5: return event[rowIndex].getAgentRole();
+ default: return "";
+ }
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * @see javax.swing.table.TableModel#isCellEditable(int, int)
+ */
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ return false;
+ }
+
+ }
+
+}
diff --git a/source/com/c2kernel/gui/tabs/JTabbedPaneWithCloseIcons.java b/source/com/c2kernel/gui/tabs/JTabbedPaneWithCloseIcons.java
new file mode 100755
index 0000000..338e0c3
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/JTabbedPaneWithCloseIcons.java
@@ -0,0 +1,88 @@
+package com.c2kernel.gui.tabs;
+import java.awt.Component;
+import java.awt.Rectangle;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+
+import javax.swing.Icon;
+import javax.swing.JTabbedPane;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import com.c2kernel.gui.EntityDetails;
+
+/**
+ * @author Developpement
+ *
+ * Allows a close icone in JTabbePane
+ */
+public class JTabbedPaneWithCloseIcons extends JTabbedPane implements MouseListener, ChangeListener
+{
+ /**
+ *
+ */
+ public JTabbedPaneWithCloseIcons()
+ {
+ super();
+ addMouseListener(this);
+ addChangeListener(this);
+ }
+ /**
+ * @see javax.swing.JTabbedPane#addTab(String, Icon, Component, String)
+ */
+ public void addTab(String title, Icon arg2, Component component, String arg3)
+ {
+ super.addTab(title, new CloseTabIcon(arg2), component, arg3);
+ }
+ /**
+ * @see java.awt.event.MouseListener#mouseClicked(MouseEvent)
+ */
+ public void mouseClicked(MouseEvent e)
+ {
+ int tabNumber = getUI().tabForCoordinate(this, e.getX(), e.getY());
+ Component cp = null;
+ if (tabNumber < 0)
+ return;
+ Rectangle rect = ((CloseTabIcon) getIconAt(tabNumber)).getBounds();
+ if (rect.contains(e.getX(), e.getY())||(e.getModifiers()& MouseEvent.CTRL_MASK) != 0)
+ { //the tab is being closed
+ cp = this.getComponent(tabNumber);
+ //if (getComponentCount() != 1)
+ if (cp instanceof EntityDetails)
+ {
+ ((EntityDetails) cp).closeTab();
+ remove(cp);
+ }
+ }
+ stateChanged(new ChangeEvent(this));
+ }
+ /**
+ * @see java.awt.event.MouseListener#mouseEntered(MouseEvent)
+ */
+ public void mouseEntered(MouseEvent e)
+ {
+ }
+ /**
+ * @see java.awt.event.MouseListener#mouseExited(MouseEvent)
+ */
+ public void mouseExited(MouseEvent e)
+ {
+ }
+ /**
+ * @see java.awt.event.MouseListener#mousePressed(MouseEvent)
+ */
+ public void mousePressed(MouseEvent e)
+ {
+ }
+ /**
+ * @see java.awt.event.MouseListener#mouseReleased(MouseEvent)
+ */
+ public void mouseReleased(MouseEvent e)
+ {
+ }
+ public void stateChanged(ChangeEvent e)
+ {
+ if (getSelectedComponent()!= null)
+ ((EntityDetails) getSelectedComponent()).refresh();
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/JobListPane.java b/source/com/c2kernel/gui/tabs/JobListPane.java
new file mode 100755
index 0000000..ea14222
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/JobListPane.java
@@ -0,0 +1,295 @@
+/*
+ * StatusPane.java
+ *
+ * Created on March 20, 2001, 3:30 PM
+ */
+
+package com.c2kernel.gui.tabs;
+
+/**
+ * @author abranson
+ * @version
+ */
+import java.awt.GridBagConstraints;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.Iterator;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JOptionPane;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.table.AbstractTableModel;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.entity.agent.Job;
+import com.c2kernel.entity.agent.JobList;
+import com.c2kernel.entity.proxy.EntityProxyObserver;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.lifecycle.instance.stateMachine.Transitions;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.property.Property;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+
+/**
+ * Pane to display all work orders that this agent can execute, and activate
+ * them on request from the user. Subscribes to NodeItem for WorkOrder objects.
+ * @version $Revision: 1.4 $ $Date: 2004/10/21 08:02:21 $
+ * @author $Author: abranson $
+ */
+public class JobListPane extends EntityTabPane implements ActionListener, EntityProxyObserver {
+
+ JobList joblist;
+ JoblistTableModel model;
+ JTable eventTable;
+ JButton startButton = new JButton("<<");
+ JButton prevButton = new JButton("<");
+ JButton nextButton = new JButton(">");
+ JButton endButton = new JButton(">>");
+ public static final int SIZE = 30;
+ int currentSize = SIZE;
+
+ public JobListPane() {
+ super("Job List", "Agent Job List");
+ initPanel();
+
+ // add buttons
+ Box navBox = Box.createHorizontalBox();
+ navBox.add(startButton); navBox.add(prevButton);
+ navBox.add(nextButton); navBox.add(endButton);
+
+ // setup buttons
+ //startButton.setEnabled(false); nextButton.setEnabled(false);
+ //prevButton.setEnabled(false); endButton.setEnabled(false);
+ startButton.setActionCommand("start");
+ startButton.addActionListener(this);
+ prevButton.setActionCommand("prev");
+ prevButton.addActionListener(this);
+ nextButton.setActionCommand("next");
+ nextButton.addActionListener(this);
+ endButton.setActionCommand("end");
+ endButton.addActionListener(this);
+ getGridBagConstraints();
+ c.gridx = 0; c.gridy = 1;
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.fill=GridBagConstraints.NONE;
+ c.weightx=0; c.weighty=0;
+ gridbag.setConstraints(navBox, c);
+ add(navBox);
+
+
+ // Create table
+ eventTable = new JTable();
+ JScrollPane eventScroll= new JScrollPane(eventTable);
+ c.weightx = 1.0; c.weighty = 1.0;
+ c.fill = GridBagConstraints.BOTH; c.gridy++;
+ gridbag.setConstraints(eventScroll, c);
+ add(eventScroll);
+
+ // detect double clicked jobs
+ eventTable.addMouseListener(new JobListMouseListener());
+ }
+
+ public void reload() {
+ joblist.clear();
+ jumpToEnd();
+ }
+
+ public void run() {
+ Thread.currentThread().setName("Joblist Pane Builder");
+ try {
+ joblist = (JobList)sourceEntity.getEntity().getObject(ClusterStorage.JOB);
+ sourceEntity.getEntity().subscribe(this, ClusterStorage.JOB, false);
+ } catch (ObjectNotFoundException e) {
+ Logger.error(e);
+ }
+ model = new JoblistTableModel(joblist);
+ eventTable.setModel(model);
+ jumpToEnd();
+ }
+
+
+ public void jumpToEnd() {
+ int lastEvent = joblist.getLastId();
+ int firstEvent = 0; currentSize = SIZE;
+ if (lastEvent > currentSize) firstEvent = lastEvent - currentSize + 1;
+ if (lastEvent < currentSize) currentSize = lastEvent + 1;
+ Logger.msg(5, "JobListPane.run() - init table start "+firstEvent+" for "+currentSize);
+ model.setView(firstEvent, currentSize);
+ }
+
+ public void add(C2KLocalObject contents) {
+ reload();
+ }
+
+ public void remove(String id) {
+ reload();
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand().equals("end")) {
+ jumpToEnd();
+ return;
+ }
+
+ int lastEvent = joblist.getLastId();
+ int startEvent = model.getStartId();
+ if (e.getActionCommand().equals("start")) {
+ currentSize = SIZE;
+ startEvent = 0;
+ }
+
+ else if (e.getActionCommand().equals("prev")) {
+ currentSize = SIZE;
+ startEvent-=currentSize;
+ if (startEvent<0) startEvent = 0;
+ }
+ else if (e.getActionCommand().equals("next")) {
+ currentSize = SIZE;
+ startEvent+=currentSize;
+ if (startEvent > lastEvent)
+ startEvent = lastEvent - currentSize +1;
+ }
+ else { // unknown action
+ return;
+ }
+
+ model.setView(startEvent, currentSize);
+ }
+
+ private class JoblistTableModel extends AbstractTableModel {
+ Job[] job;
+ Integer[] ids;
+ String[] itemNames;
+ int loaded = 0;
+ int startId = 0;
+
+ public JoblistTableModel(JobList joblist) {
+ job = new Job[0];
+ ids = new Integer[0];
+ }
+
+ public int getStartId() {
+ return startId;
+ }
+
+ public void setView(int startId, int size) {
+ job = new Job[size];
+ ids = new Integer[size];
+ itemNames = new String[size];
+ this.startId = startId;
+ int count = 0;
+ for (Iterator i = joblist.keySet().iterator(); i.hasNext();) {
+ Integer thisJobId = new Integer((String)i.next());
+ if (count >= startId) {
+ int idx = count-startId;
+ ids[idx] = thisJobId;
+ Job thisJob = joblist.getJob(thisJobId.intValue());
+ job[idx] = joblist.getJob(thisJobId.intValue());
+ itemNames[idx] = "Item Not Found";
+ try {
+ itemNames[idx] = ((Property)Gateway.getStorage().get(job[count-startId].getItemSysKey(), ClusterStorage.PROPERTY+"/Name", null)).getValue();
+ } catch (Exception ex) {
+ Logger.error(ex);
+ }
+
+ }
+ count++;
+ loaded = count-startId;
+ if (count > (startId + size)) break;
+ }
+ fireTableStructureChanged();
+ }
+ /**
+ * @see javax.swing.table.TableModel#getColumnClass(int)
+ */
+ public Class getColumnClass(int columnIndex) {
+ switch(columnIndex) {
+ case 0:
+ return Integer.class;
+ default:
+ return String.class;
+ }
+ }
+
+ /**
+ * @see javax.swing.table.TableModel#getColumnCount()
+ */
+ public int getColumnCount() {
+ return 4;
+ }
+
+ /**
+ * @see javax.swing.table.TableModel#getColumnName(int)
+ */
+ public String getColumnName(int columnIndex) {
+ switch(columnIndex) {
+ case 0: return Language.translate("ID");
+ case 1: return Language.translate("Subject");
+ case 2: return Language.translate("Activity");
+ case 3: return Language.translate("Transition");
+ default: return "";
+ }
+ }
+
+ /**
+ * @see javax.swing.table.TableModel#getRowCount()
+ */
+ public int getRowCount() {
+ return loaded;
+ }
+
+ /**
+ * @see javax.swing.table.TableModel#getValueAt(int, int)
+ */
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ if (job.length <= rowIndex || job[rowIndex] == null)
+ return "";
+ try {
+ switch (columnIndex) {
+ case 0: return ids[rowIndex];
+ case 1: return itemNames[rowIndex];
+ case 2: return job[rowIndex].getStepName();
+ case 3: return Transitions.getTransitionName(job[rowIndex].getPossibleTransition());
+ default: return "";
+ }
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * @see javax.swing.table.TableModel#isCellEditable(int, int)
+ */
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ return false;
+ }
+
+ public Job getJobAtRow(int rowIndex) {
+ return job[rowIndex];
+ }
+
+ }
+
+ private class JobListMouseListener extends MouseAdapter {
+
+ public void mouseClicked(MouseEvent e) {
+ super.mouseClicked(e);
+ if (e.getClickCount() == 2) {
+ Job selectedJob = model.getJobAtRow(eventTable.getSelectedRow());
+ try {
+ MainFrame.itemFinder.pushNewKey(selectedJob.getItemProxy().getName());
+ } catch (Exception ex) {
+ Logger.error(ex);
+ JOptionPane.showMessageDialog(null, "No Item Found", "Job references an unknown item", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/PropertiesPane.java b/source/com/c2kernel/gui/tabs/PropertiesPane.java
new file mode 100755
index 0000000..5666ae9
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/PropertiesPane.java
@@ -0,0 +1,185 @@
+/*
+ * StatusPane.java
+ *
+ * Created on March 20, 2001, 3:30 PM
+ */
+
+package com.c2kernel.gui.tabs;
+
+/**
+ * @author abranson
+ * @version
+ */
+import java.awt.GridBagConstraints;
+import java.awt.GridLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.HashMap;
+
+import javax.swing.*;
+
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.entity.proxy.EntityProxyObserver;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.gui.data.NodeAgent;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.property.Property;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+
+/**
+ * Pane to display all work orders that this agent can execute, and activate
+ * them on request from the user. Subscribes to NodeItem for Property objects.
+ * @version $Revision: 1.44 $ $Date: 2005/08/31 07:21:20 $
+ * @author $Author: abranson $
+ */
+public class PropertiesPane extends EntityTabPane implements EntityProxyObserver, ActionListener {
+
+ Box propertyBox;
+ boolean subbed = false;
+ HashMap loadedProps = new HashMap();
+ JLabel domTitle;
+ DomainPathAdmin domAdmin;
+
+ public PropertiesPane() {
+ super("Properties", "Properties");
+ initPanel();
+
+ // Create box container for properties
+ getGridBagConstraints();
+ c.gridx = 0; c.gridy = 1;
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.fill = GridBagConstraints.NONE;
+ c.weightx = 1.0; c.weighty = 2.0;
+ propertyBox = Box.createVerticalBox();
+ gridbag.setConstraints(propertyBox, c);
+ add(propertyBox);
+ if (MainFrame.isAdmin) { // edit dompath
+ c.gridy++;
+ c.fill = GridBagConstraints.NONE;
+ c.weighty=0.0;
+ domTitle = new JLabel("Domain Paths", titleIcon, SwingConstants.LEFT);
+ domTitle.setFont(titleFont);
+ domTitle.setForeground(headingColor);
+ gridbag.setConstraints(domTitle, c);
+ add(domTitle);
+
+ c.gridy++;
+ c.fill = GridBagConstraints.BOTH;
+ c.weighty=1.0;
+ domAdmin = new DomainPathAdmin();
+ gridbag.setConstraints(domAdmin, c);
+ add(domAdmin);
+
+
+ if ("true".equals(Gateway.getProperty("EnableItemErase"))) {
+ c.gridy++;
+ c.fill = GridBagConstraints.NONE;
+ JButton eraseButton = new JButton(Language.translate("Erase!"));
+ eraseButton.addActionListener(this);
+ eraseButton.setActionCommand("Erase Item");
+ gridbag.setConstraints(eraseButton, c);
+ add(eraseButton);
+ }
+ }
+ }
+
+ public void reload() {
+ Gateway.getStorage().clearCache(sourceEntity.getSysKey(), ClusterStorage.PROPERTY);
+ loadedProps = new HashMap();
+ initForEntity(sourceEntity);
+ }
+
+ public void run() {
+ Thread.currentThread().setName("Property Pane Builder");
+ if (sourceEntity instanceof NodeAgent) {
+ remove(domAdmin);
+ remove(domTitle);
+ }
+ else if (domAdmin != null)
+ domAdmin.setEntity((ItemProxy)sourceEntity.getEntity());
+ propertyBox.removeAll();
+ propertyBox.add(Box.createGlue());
+ revalidate();
+ sourceEntity.getEntity().subscribe(this, ClusterStorage.PROPERTY, true);
+
+ }
+ /**
+ *
+ */
+ public void add(C2KLocalObject contents) {
+ if (!(contents instanceof Property)) return;
+ Property newProp = (Property) contents;
+ JLabel propLabel = (JLabel)loadedProps.get(newProp.getName());
+ if (propLabel == null) { // new prop
+ JPanel summaryPanel = new JPanel(new GridLayout(0,2));
+ summaryPanel.add(new JLabel(Language.translate(newProp.getName()) + ":"));
+ Box valueBox = Box.createHorizontalBox();
+ propLabel = new JLabel(newProp.getValue());
+ loadedProps.put(newProp.getName(), propLabel);
+ valueBox.add(propLabel);
+ if (MainFrame.isAdmin) {
+ JButton editButton = new JButton("...");
+ editButton.setMargin(new Insets(0,0,0,0));
+ editButton.setActionCommand(newProp.getName());
+ editButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e){
+ String oldVal = ((JLabel)loadedProps.get(e.getActionCommand())).getText();
+ String newVal = (String)JOptionPane.showInputDialog(null, "Enter new value for "+e.getActionCommand(), "Edit Property",
+ JOptionPane.QUESTION_MESSAGE, null, null, oldVal);
+ if (newVal!=null && !(newVal.equals(oldVal))) {
+ try {
+ ((ItemProxy)sourceEntity.getEntity()).setProperty(MainFrame.userAgent, e.getActionCommand(), newVal);
+ } catch (Exception ex) {
+ Logger.exceptionDialog(ex);
+ }
+ }
+ }
+ });
+ valueBox.add(Box.createVerticalStrut(7));
+ valueBox.add(editButton);
+
+ }
+ summaryPanel.add(valueBox);
+ propertyBox.add(Box.createVerticalStrut(7));
+ propertyBox.add(summaryPanel);
+ }
+ propLabel.setText(newProp.getValue());
+ revalidate();
+ }
+
+ public void remove(String id) {
+ String propName = id.substring(id.lastIndexOf("/")+1);
+ JLabel propbox = (JLabel)loadedProps.get(propName);
+ if (propbox!= null) propbox.setText("DELETED");
+ revalidate();
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ String[] params;
+ String predefStep;
+
+ if (JOptionPane.showConfirmDialog(this,
+ "Are you sure?",
+ e.getActionCommand(),
+ JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION)
+ return;
+
+ if (e.getActionCommand().equals("Erase Item")) {
+ params = new String[0];
+ predefStep = "Erase";
+ }
+ else
+ return;
+
+ try {
+ MainFrame.userAgent.execute((ItemProxy)sourceEntity.getEntity(), predefStep, params);
+ } catch (Exception ex) {
+ Logger.exceptionDialog(ex);
+ }
+ }
+
+}
diff --git a/source/com/c2kernel/gui/tabs/ViewpointPane.java b/source/com/c2kernel/gui/tabs/ViewpointPane.java
new file mode 100755
index 0000000..7bb6176
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/ViewpointPane.java
@@ -0,0 +1,501 @@
+
+package com.c2kernel.gui.tabs;
+import java.awt.GridBagConstraints;
+import java.awt.GridLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.SwingConstants;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.entity.proxy.EntityProxyObserver;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.events.Event;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+import com.c2kernel.gui.tabs.outcome.OutcomeHandler;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.persistency.outcome.Outcome;
+import com.c2kernel.persistency.outcome.Viewpoint;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.LocalObjectLoader;
+import com.c2kernel.utils.Logger;
+
+public class ViewpointPane extends EntityTabPane implements ItemListener, ActionListener, EntityProxyObserver {
+
+ JComboBox schemas;
+ JComboBox views;
+ JComboBox events;
+ JLabel eventDetails;
+ JButton exportButton;
+ JButton viewButton;
+
+ ArrayList schemaList;
+ ArrayList viewpointList;
+ ArrayList eventList;
+ String currentSchema = null;
+ Outcome currentOutcome = null;
+ OutcomeHandler thisOutcome;
+ boolean suspendSelection = false;
+
+ JPanel dataView = new JPanel(new GridLayout(1,1));
+
+ public ViewpointPane() {
+
+ super("Data Viewer", "Outcome Browser");
+ initialize();
+ }
+
+ public void initialize() {
+ initPanel();
+
+ getGridBagConstraints();
+
+ c.gridx = 0; c.gridy = 1;
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.ipadx = 5; c.weightx = 1.0;
+ c.ipady = 5;
+
+ // Set up view box
+
+ Box viewBox = Box.createHorizontalBox();
+
+ JLabel label = new JLabel(Language.translate("Outcome Type")+":", SwingConstants.LEFT);
+ viewBox.add(label);
+ viewBox.add(Box.createHorizontalStrut(7));
+
+ schemas = new JComboBox();
+ viewBox.add(schemas);
+ viewBox.add(Box.createHorizontalGlue());
+ schemas.addItemListener(this);
+
+ label = new JLabel(Language.translate("View")+":", SwingConstants.LEFT);
+ viewBox.add(label);
+ viewBox.add(Box.createHorizontalStrut(7));
+
+ views = new JComboBox();
+ viewBox.add(views);
+ viewBox.add(Box.createHorizontalGlue());
+ views.addItemListener(this);
+
+ gridbag.setConstraints(viewBox, c);
+ this.add(viewBox);
+
+ // Set up event details box
+ c.gridy++;
+ Box eventBox = Box.createHorizontalBox();
+
+ label = new JLabel(Language.translate("Event")+":", SwingConstants.LEFT);
+ eventBox.add(label);
+ eventBox.add(Box.createHorizontalStrut(7));
+
+ events = new JComboBox();
+ eventBox.add(events);
+ eventBox.add(Box.createHorizontalStrut(7));
+ events.addItemListener(this);
+
+ eventDetails = new JLabel();
+ eventBox.add(eventDetails);
+ eventBox.add(Box.createHorizontalGlue());
+
+ if (MainFrame.isAdmin) {
+ viewButton = new JButton(Language.translate("Write View"));
+ viewButton.setMargin(new Insets(0, 0, 0, 0));
+ viewButton.setActionCommand("setview");
+ eventBox.add(viewButton);
+ eventBox.add(Box.createHorizontalStrut(14));
+ viewButton.addActionListener(this);
+ }
+
+ exportButton = new JButton(Language.translate("Export"));
+ exportButton.setMargin(new Insets(0, 0, 0, 0));
+ exportButton.setActionCommand("export");
+ exportButton.addActionListener(this);
+ eventBox.add(exportButton);
+
+ gridbag.setConstraints(eventBox, c);
+ this.add(eventBox);
+
+ // data pane
+ c.gridx = 0; c.gridy = 3;
+ c.anchor = GridBagConstraints.NORTHWEST; c.fill = GridBagConstraints.BOTH;
+ c.weighty = 1.0; c.weightx = 1.0;
+ gridbag.setConstraints(dataView, c);
+ this.add(dataView);
+ }
+
+ public void reload() {
+ // reset boxes
+ schemas.removeAllItems();
+ views.removeAllItems();
+ events.removeAllItems();
+ eventDetails.setText("");
+
+ clearView();
+
+ // reload
+ initForEntity(sourceEntity);
+ }
+
+ public void run() {
+ Thread.currentThread().setName("Viewpoint Pane Builder");
+ //Local object subscriptions
+ sourceEntity.getEntity().subscribe(this, ClusterStorage.VIEWPOINT, false);
+ sourceEntity.getEntity().subscribe(this, ClusterStorage.OUTCOME, false);
+ clearView();
+ schemas.addItem("--");
+ currentSchema = null;
+ schemaList = new ArrayList();
+ try {
+ String outcomeTypes = sourceEntity.getEntity().queryData(ClusterStorage.VIEWPOINT+"/all");
+ StringTokenizer tok = new StringTokenizer(outcomeTypes, ",");
+ for (int i = 0; tok.countTokens() > 0; i++) {
+ String thisType = tok.nextToken();
+ schemas.addItem(thisType);
+ schemaList.add(thisType);
+ }
+ } catch (Exception e) {
+ Logger.msg(2, "No viewpoints found");
+ }
+ }
+
+ public void itemStateChanged(ItemEvent e) {
+
+ Object selectedItem = e.getItem();
+ if (e.getStateChange() == ItemEvent.DESELECTED) return;
+ if (suspendSelection) return;
+ if (e.getItem().equals("--")) return;
+
+ if (e.getItemSelectable() == schemas)
+ switchSchema((String)selectedItem);
+ else if (e.getItemSelectable() == views)
+ switchView((Viewpoint)selectedItem);
+ else if (e.getItemSelectable() == events)
+ showEvent((EventItem)selectedItem);
+ }
+
+ public void switchSchema(String schemaName) {
+ clearView();
+ suspendSelection = true;
+ views.removeAllItems();
+ events.removeAllItems();
+ viewpointList = new ArrayList();
+ eventList = new ArrayList();
+
+ currentSchema = schemaName;
+
+ try {
+ // populate views
+ String viewNames = sourceEntity.getEntity().queryData(ClusterStorage.VIEWPOINT+"/"+schemaName+"/all");
+ StringTokenizer tok = new StringTokenizer(viewNames, ",");
+ Viewpoint lastView = null;
+ while(tok.hasMoreTokens()) {
+ String viewName = tok.nextToken();
+ Viewpoint thisView = (Viewpoint)sourceEntity.getEntity().getObject(ClusterStorage.VIEWPOINT+"/"+schemaName+"/"+viewName);
+ views.addItem(thisView);
+ if (lastView == null) lastView = thisView;
+ if (thisView.getName().equals("last")) //select
+ lastView = thisView;
+ viewpointList.add(thisView);
+ }
+
+ String ocVersions = sourceEntity.getEntity().queryData(ClusterStorage.OUTCOME+"/"+schemaName+"/all");
+ tok = new StringTokenizer(ocVersions, ",");
+ while(tok.hasMoreTokens()) {
+ int schemaVersion = Integer.parseInt(tok.nextToken());
+ String ocEvents = sourceEntity.getEntity().queryData(ClusterStorage.OUTCOME+"/"+schemaName+"/"+schemaVersion+"/all");
+ StringTokenizer tok2 = new StringTokenizer(ocEvents, ",");
+ while(tok2.hasMoreTokens()) {
+ int eventId = Integer.parseInt(tok2.nextToken());
+ EventItem newEvent = new EventItem(eventId, schemaVersion);
+ for (Iterator iter = viewpointList.iterator(); iter.hasNext();) {
+ Viewpoint thisView = (Viewpoint)iter.next();
+ if (thisView.getEventId() == eventId)
+ newEvent.addView(thisView.getName());
+ }
+ eventList.add(newEvent);
+ }
+ Collections.sort(eventList);
+ for (Iterator iter = eventList.iterator(); iter.hasNext();)
+ events.addItem(iter.next());
+ }
+
+ if (lastView != null) {
+ suspendSelection = false;
+ views.setSelectedItem(lastView);
+ switchView(lastView);
+ }
+
+ } catch (Exception e) {
+ Logger.error(e);
+ JOptionPane.showMessageDialog(this,
+ "The data structures of this item are incorrect.\nPlease contact your administrator.",
+ "Viewpoint Error" , JOptionPane.ERROR_MESSAGE);
+ }
+ suspendSelection = false;
+ }
+
+ public void switchView(Viewpoint newView) {
+ for (Iterator iter = eventList.iterator(); iter.hasNext();) {
+ EventItem thisEvent = (EventItem)iter.next();
+ if (thisEvent.eventId == newView.getEventId()) {
+ suspendSelection = true;
+ events.setSelectedItem(thisEvent);
+ showEvent(thisEvent);
+ suspendSelection = false;
+ break;
+ }
+ }
+ }
+
+ public void showEvent(EventItem thisEvent) {
+ eventDetails.setText(thisEvent.getEventDesc());
+ try {
+ setView((Outcome)sourceEntity.getEntity().getObject(
+ ClusterStorage.OUTCOME+"/"+currentSchema+"/"+thisEvent.schemaVersion+"/"+thisEvent.eventId));
+ } catch (Exception ex) {
+ Logger.error(ex);
+ JOptionPane.showMessageDialog(this,
+ "Could not retrieve requested outcome.\nPlease contact your administrator.",
+ "Viewpoint Error" , JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+ public void setView(Outcome data) throws OutcomeException {
+ Logger.msg(6, "ViewpointPane: got outcome type: "+data.getSchemaType()+" version: "+data.getSchemaVersion());
+ String schema;
+ currentOutcome = data;
+ dataView.removeAll();
+ String error = null;
+ try {
+ schema = LocalObjectLoader.getSchema(data.getSchemaType(), data.getSchemaVersion()).schema;
+ thisOutcome = EntityTabPane.getOutcomeHandler(data.getSchemaType(), data.getSchemaVersion());
+ thisOutcome.setDescription(schema);
+ thisOutcome.setOutcome(data.getData());
+ thisOutcome.setReadOnly(true);
+ Thread builder = new Thread(thisOutcome);
+ builder.start();
+ dataView.add(thisOutcome.getPanel());
+ exportButton.setEnabled(true);
+ if (viewButton!=null) viewButton.setEnabled(true);
+ return;
+ } catch (ObjectNotFoundException ex) {
+ error = "Schema not found";
+ } catch (OutcomeException ex) {
+ error = "Outcome was not valid. See log for details: "+ex.getMessage();
+ Logger.error(ex);
+ }
+
+ dataView.add(new JLabel(error));
+ }
+
+ public void clearView() {
+ dataView.removeAll();
+ exportButton.setEnabled(false);
+ if (viewButton!=null) viewButton.setEnabled(false);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand().equals("export") && currentOutcome != null)
+ saveOutcomeToFile();
+ if (e.getActionCommand().equals("setview") && currentOutcome != null)
+ overrideView();
+ }
+
+ private void saveOutcomeToFile() {
+
+ MainFrame.xmlChooser.setSelectedFile(new File(currentOutcome.getSchemaType()+".xml"));
+ int returnVal = MainFrame.xmlChooser.showSaveDialog(this);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ File targetFile = MainFrame.xmlChooser.getSelectedFile();
+ if (!(targetFile.getAbsolutePath().endsWith(".xml")))
+ targetFile = new File(targetFile.getAbsolutePath()+".xml");
+
+ Logger.msg(2, "ViewpointPane.actionPerformed() - Exporting outcome to file " + targetFile.getName());
+ try {
+ thisOutcome.export(targetFile);
+ }
+ catch (Exception ex) {
+ Logger.error(ex);
+ Logger.exceptionDialog(ex);
+ }
+ }
+
+ }
+
+ private void overrideView() {
+
+ Viewpoint oldView = (Viewpoint)views.getSelectedItem();
+ EventItem newEvent = (EventItem)events.getSelectedItem();
+
+ if (oldView.getEventId() == newEvent.eventId) {
+ JOptionPane.showMessageDialog(this,
+ "View '"+oldView.getName()+"' is already set to event "+newEvent.eventId,
+ "Viewpoint Already Set" , JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ if (JOptionPane.showConfirmDialog(this,
+ "Are you sure you want to set the '"+oldView.getName()+
+ "' view to event " + newEvent.eventId+ "?",
+ "Overwrite view",
+ JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION)
+ return;
+
+ oldView.setEventId(newEvent.eventId);
+ try {
+ String[] predefParams = new String[1];
+ predefParams[0] = CastorXMLUtility.marshall(oldView);
+ MainFrame.userAgent.execute((ItemProxy)sourceEntity.getEntity(), "AddC2KObject", predefParams);
+ } catch (Exception e) {
+ Logger.error(e);
+ Logger.exceptionDialog(e);
+ }
+ }
+
+ public void add(C2KLocalObject contents) {
+ if (contents instanceof Viewpoint)
+ addViewpoint((Viewpoint)contents);
+ else if (contents instanceof Outcome)
+ addOutcome((Outcome)contents);
+
+ }
+
+ public void addViewpoint(Viewpoint newView) {
+ String schemaName = newView.getSchemaName();
+ Logger.msg(3, "Viewpoint "+newView.getName()+" now points to "+newView.getEventId());
+ if (!(schemaList.contains(schemaName))) {
+ schemaList.add(schemaName);
+ schemas.addItem(schemaName);
+ return;
+ }
+
+
+ if (!(schemaName.equals(schemas.getSelectedItem())))
+ return;
+
+ for (Iterator iter = eventList.iterator(); iter.hasNext();) {
+ EventItem thisEvent = (EventItem)iter.next();
+ if (thisEvent.eventId == newView.getEventId())
+ thisEvent.addView(newView.getName());
+ else
+ thisEvent.removeView(newView.getName());
+ }
+
+ boolean isSelected = false;
+ for (Iterator iter = viewpointList.iterator(); iter.hasNext();) {
+ Viewpoint thisView = (Viewpoint)iter.next();
+ if (thisView.getName().equals(newView.getName())) {
+ isSelected = thisView.equals(views.getSelectedItem());
+ views.removeItem(thisView);
+ viewpointList.remove(thisView);
+ break;
+ }
+ }
+
+ views.addItem(newView);
+ viewpointList.add(newView);
+ if (isSelected) {
+ views.setSelectedItem(newView);
+ }
+
+ }
+
+ public void addOutcome(Outcome contents) {
+ if (!(contents.getSchemaType().equals(currentSchema))) // not interested
+ return;
+ Logger.msg(3, "Adding event "+contents.getID());
+ EventItem newEvent = new EventItem(contents.getID(), contents.getSchemaVersion());
+ eventList.add(newEvent);
+ events.addItem(newEvent);
+ }
+
+ public void remove(String id) {
+ // we don't really remove viewpoints
+ }
+
+ class EventItem implements Comparable {
+ public int eventId;
+ public int schemaVersion;
+ public ArrayList viewNames = new ArrayList();
+ public String viewList = "";
+
+ public EventItem(int eventId, int schemaVersion) {
+ this.eventId = eventId;
+ this.schemaVersion = schemaVersion;
+ }
+
+ public void addView(String viewName) {
+ if (!(viewNames.contains(viewName))) {
+ viewNames.add(viewName);
+ buildViewLabel();
+ }
+ }
+
+ public void removeView(String viewName) {
+ viewNames.remove(viewName);
+ buildViewLabel();
+ }
+
+ private void buildViewLabel() {
+ if (viewNames.size() == 0) {
+ viewList = "";
+ return;
+ }
+
+ StringBuffer newLabel = new StringBuffer(" (");
+ for (Iterator iter = viewNames.iterator(); iter.hasNext();) {
+ String viewName = (String)iter.next();
+ newLabel.append(viewName);
+ if (iter.hasNext())
+ newLabel.append(", ");
+ }
+
+ viewList = newLabel.append(")").toString();
+ }
+
+ public String toString() {
+ return eventId+viewList;
+
+ }
+
+ public String getEventDesc() {
+ try {
+ Event myEvent = (Event)sourceEntity.getEntity().getObject(ClusterStorage.HISTORY+"/"+eventId);
+ return (Language.translate("Recorded on")+" "+myEvent.getTimeString()+" "+
+ Language.translate("by")+" "+myEvent.getAgentName()+" "+
+ Language.translate("using schema v")+schemaVersion);
+ } catch (Exception ex) {
+ Logger.error(ex);
+ return ("Error retrieving event details");
+ }
+ }
+
+ public int compareTo(Object o) {
+ if (o instanceof EventItem) {
+ EventItem other = (EventItem)o;
+ if (other.eventId < eventId) return 1;
+ if (other.eventId > eventId) return -1;
+ }
+ return 0;
+ }
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/WorkflowPane.java b/source/com/c2kernel/gui/tabs/WorkflowPane.java
new file mode 100755
index 0000000..7b664ba
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/WorkflowPane.java
@@ -0,0 +1,273 @@
+package com.c2kernel.gui.tabs;
+import java.awt.Cursor;
+import java.awt.GridBagConstraints;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+
+import javax.swing.JButton;
+import javax.swing.JFileChooser;
+import javax.swing.JSplitPane;
+
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.entity.proxy.EntityProxyObserver;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.graph.layout.DefaultGraphLayoutGenerator;
+import com.c2kernel.graph.model.EdgeFactory;
+import com.c2kernel.graph.model.Selection;
+import com.c2kernel.graph.model.VertexFactory;
+import com.c2kernel.graph.view.EditorPanel;
+import com.c2kernel.graph.view.VertexPropertyPanel;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.lifecycle.instance.CompositeActivity;
+import com.c2kernel.lifecycle.instance.Workflow;
+import com.c2kernel.lifecycle.instance.gui.model.WfEdgeFactory;
+import com.c2kernel.lifecycle.instance.gui.model.WfGraphPanel;
+import com.c2kernel.lifecycle.instance.gui.model.WfVertexFactory;
+import com.c2kernel.lifecycle.instance.gui.model.WfVertexOutlineCreator;
+import com.c2kernel.lifecycle.instance.gui.view.TransitionPanel;
+import com.c2kernel.lifecycle.instance.gui.view.WfDirectedEdgeRenderer;
+import com.c2kernel.lifecycle.instance.gui.view.WfVertexRenderer;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.*;
+public class WorkflowPane extends EntityTabPane implements EntityProxyObserver
+{
+ // Only for the purpose of loading and saving
+ protected Workflow mWorkflow = null;
+ boolean init = false;
+ TransitionPanel transPanel;
+ protected JButton mLoadButton = new JButton(Resource.getImageResource("graph/load.png"));
+ protected JButton mSaveButton = new JButton(Resource.getImageResource("graph/save.png"));
+ protected JButton mLayoutButton = new JButton(Resource.getImageResource("graph/autolayout.png"));
+ protected JButton mZoomOutButton = new JButton(Resource.getImageResource("graph/zoomout.png"));
+ protected JButton[] mOtherToolBarButtons;
+ // Workflow factories
+ protected EdgeFactory mWfEdgeFactory;
+ protected VertexFactory mWfVertexFactory;
+ // Graph editor panel
+ protected EditorPanel mEditorPanel;
+ // Objects to view/modify the properties of the selected activity
+ protected VertexPropertyPanel mPropertyPanel;
+ protected JSplitPane mSplitPane;
+
+ // Graph editor panel
+ // Objects to view/modify the properties of the selected activity
+ public WorkflowPane()
+ {
+ super("Workflow", "Workflow Viewer");
+ // Workflow factories
+ mWfEdgeFactory = new WfEdgeFactory();
+ mWfVertexFactory = new WfVertexFactory();
+ mZoomOutButton.setToolTipText(Language.translate("Zoom Out"));
+ mLayoutButton.setToolTipText(Language.translate("Auto Layout"));
+ mLoadButton.setToolTipText(Language.translate("Load"));
+ mSaveButton.setToolTipText(Language.translate("Save"));
+ mOtherToolBarButtons = new JButton[] { mZoomOutButton, mLayoutButton, mLoadButton, mSaveButton };
+
+ }
+
+ protected void createListeners()
+ {
+ /**
+ *
+ */
+ mLoadButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent ae)
+ {
+ loadWorkflow();
+ }
+ });
+ /**
+ *
+ */
+ mSaveButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent ae)
+ {
+ setCursor(new Cursor(Cursor.WAIT_CURSOR));
+ saveWorkflow();
+ setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
+ }
+ });
+ /**
+ *
+ */
+ mLayoutButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent ae)
+ {
+ DefaultGraphLayoutGenerator.layoutGraph(mEditorPanel.mGraphModelManager.getModel());
+ }
+ });
+ /**
+ *
+ */
+ mZoomOutButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent ae)
+ {
+ mEditorPanel.mGraphModelManager.zoomOut();
+ }
+ });
+ }
+ /**
+ * Return a single ref on mEditorPanel
+ *
+ * @return EditorPanel
+ */
+ public EditorPanel getEditorPanel()
+ {
+ if (mEditorPanel == null)
+ mEditorPanel =
+ new EditorPanel(
+ mWfEdgeFactory,
+ mWfVertexFactory,
+ new WfVertexOutlineCreator(),
+ true,
+ mOtherToolBarButtons,
+ new WfGraphPanel(new WfDirectedEdgeRenderer(), new WfVertexRenderer()));
+ return mEditorPanel;
+ }
+ public JSplitPane getJSplitPane()
+ {
+ if (mSplitPane == null)
+ {
+ mSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, getEditorPanel(), getPropertyPanel());
+ mSplitPane.setDividerSize(5);
+ mSplitPane.setDividerLocation(800);
+ }
+ return mSplitPane;
+ }
+ public void add(C2KLocalObject contents)
+ {
+ if (contents instanceof Workflow)
+ {
+ mWorkflow = (Workflow) contents;
+ addActivity((CompositeActivity) mWorkflow.search("workflow/domain"));
+ }
+ else if (contents instanceof CompositeActivity)
+ addActivity((CompositeActivity) contents);
+ }
+ public void remove(String id)
+ {
+ }
+ protected void addActivity(CompositeActivity cAct)
+ {
+ // Resolve any undefined references in the workflow
+ mEditorPanel.mGraphModelManager.replace(cAct.getChildrenGraphModel());
+ // Give the editor panel the edge and vertex types
+ mEditorPanel.updateVertexTypes(cAct.getWf().getVertexTypeNameAndConstructionInfo());
+ mEditorPanel.updateEdgeTypes(cAct.getWf().getEdgeTypeNameAndConstructionInfo());
+ mEditorPanel.enterSelectMode();
+ mWfVertexFactory.setCreationContext(cAct);
+ }
+ public void run()
+ {
+ Thread.currentThread().setName("Workflow Pane Builder");
+ if (!init)
+ {
+ getEditorPanel();
+ createLayout();
+ createListeners();
+ mPropertyPanel.setGraphModelManager(mEditorPanel.mGraphModelManager);
+ mEditorPanel.setEditable(MainFrame.isAdmin);
+ init = true;
+ }
+ sourceEntity.getEntity().subscribe(this, ClusterStorage.LIFECYCLE, true);
+ transPanel.setItem((ItemProxy) sourceEntity.getEntity());
+ }
+ public void reload()
+ {
+ Gateway.getStorage().clearCache(sourceEntity.getSysKey(), ClusterStorage.LIFECYCLE);
+ initForEntity(sourceEntity);
+ }
+ protected void createLayout()
+ {
+ initPanel();
+ // Add the editor pane
+ getGridBagConstraints().gridx = 0;
+ getGridBagConstraints().gridy = 1;
+ getGridBagConstraints().fill = GridBagConstraints.BOTH;
+ getGridBagConstraints().weighty = 2.0;
+ gridbag.setConstraints(getJSplitPane(), getGridBagConstraints());
+ add(getJSplitPane());
+ validate();
+ }
+ protected void loadWorkflow()
+ {
+ File selectedFile = null;
+ int returnValue = MainFrame.xmlChooser.showOpenDialog(null);
+ switch (returnValue)
+ {
+ case JFileChooser.APPROVE_OPTION :
+ selectedFile = MainFrame.xmlChooser.getSelectedFile();
+ try
+ {
+ String newWf = FileStringUtility.file2String(selectedFile);
+ add((Workflow) CastorXMLUtility.unmarshall(newWf));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ case JFileChooser.CANCEL_OPTION :
+ case JFileChooser.ERROR_OPTION :
+ default :
+ }
+ }
+ protected String marshall() throws Exception
+ {
+ return com.c2kernel.utils.CastorXMLUtility.marshall(mWorkflow.getWf());
+ }
+ protected void saveWorkflow()
+ {
+ try
+ {
+ CompositeActivity cact = (CompositeActivity)mWorkflow.getWf().search("workflow/domain");
+ MainFrame.userAgent.execute(
+ (ItemProxy)sourceEntity.getEntity(),
+ "ReplaceDomainWorkflow",
+ new String[] { com.c2kernel.utils.CastorXMLUtility.marshall(cact)});
+ cact.getChildrenGraphModel().setSelection(new Selection(null,null,0,0,0,0));
+ }
+ catch (Exception e)
+ {
+ Logger.error(e);
+ }
+ }
+
+ public VertexPropertyPanel getPropertyPanel()
+ {
+ if (mPropertyPanel == null) {
+ setNewPropertyPanel();
+ transPanel = new TransitionPanel();
+ mPropertyPanel.createLayout(transPanel);
+ mPropertyPanel.setGraphModelManager(mEditorPanel.mGraphModelManager);
+ mPropertyPanel.setEditable(MainFrame.isAdmin);
+ }
+ return mPropertyPanel;
+ }
+
+ public void setNewPropertyPanel()
+ {
+ String wfPanelClass = Gateway.getProperty("WfPropertyPanel");
+ if (wfPanelClass != null)
+ {
+ try
+ {
+ Class panelClass = Class.forName(wfPanelClass);
+ mPropertyPanel = (VertexPropertyPanel) panelClass.newInstance();
+ return;
+ }
+ catch (Exception ex)
+ {
+ Logger.error("Could not load wf props panel:" + wfPanelClass);
+ Logger.error(ex);
+ }
+ }
+ mPropertyPanel = new VertexPropertyPanel();
+ }
+
+}
diff --git a/source/com/c2kernel/gui/tabs/collection/AggregationView.java b/source/com/c2kernel/gui/tabs/collection/AggregationView.java
new file mode 100755
index 0000000..8a97c6c
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/collection/AggregationView.java
@@ -0,0 +1,86 @@
+package com.c2kernel.gui.tabs.collection;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+import javax.swing.JSplitPane;
+
+import com.c2kernel.collection.Aggregation;
+import com.c2kernel.collection.Collection;
+import com.c2kernel.collection.gui.model.AggregationVertexFactory;
+import com.c2kernel.collection.gui.model.AggregationVertexOutlineCreator;
+import com.c2kernel.collection.gui.view.AggregationMemberRenderer;
+import com.c2kernel.collection.gui.view.PropertyPanel;
+import com.c2kernel.collection.gui.view.SelectedMemberPanel;
+import com.c2kernel.graph.view.EditorPanel;
+import com.c2kernel.graph.view.GraphPanel;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Resource;
+/**
+ * @version $Revision: 1.5 $ $Date: 2006/09/15 15:02:24 $
+ * @author $Author: abranson $
+ */
+public class AggregationView extends CollectionView
+{
+ protected JButton mSaveButton = new JButton(Resource.getImageResource("graph/save.png"));
+ protected JButton mHistoryButton = new JButton(Resource.getImageResource("graph/history.png"));
+ protected JButton[] mOtherToolBarButtons = { mSaveButton, mHistoryButton };
+ // Graph editor panel
+ protected EditorPanel mEditorPanel;
+ // Objects to view/modify the properties of the selected activity
+ protected PropertyPanel mPropertyPanel;
+ protected JSplitPane mSplitPane;
+ private AggregationVertexFactory mAggregationVertexFactory = new AggregationVertexFactory();
+ private AggregationMemberRenderer mAggregationMemberRenderer = new AggregationMemberRenderer();
+ public AggregationView()
+ {
+ super();
+ setLayout(new GridLayout(1,1));
+ mPropertyPanel = new PropertyPanel();
+ mEditorPanel = new EditorPanel(null, mAggregationVertexFactory, new AggregationVertexOutlineCreator(), false, mOtherToolBarButtons, new GraphPanel(null, mAggregationMemberRenderer));
+ createLayout();
+ createListeners();
+ mPropertyPanel.setGraphModelManager(mEditorPanel.mGraphModelManager);
+ mPropertyPanel.createLayout(new SelectedMemberPanel());
+ mEditorPanel.setEditable(MainFrame.isAdmin);
+ }
+
+ public void setCollection(Collection contents)
+ {
+ thisColl = contents;
+ Aggregation agg = (Aggregation)thisColl;
+ mPropertyPanel.setCollection(agg);
+ mAggregationMemberRenderer.setAggregation(agg);
+ mEditorPanel.mGraphModelManager.setModel(agg.getLayout());
+ mEditorPanel.updateVertexTypes(agg.getVertexTypeNameAndConstructionInfo());
+ mEditorPanel.enterSelectMode();
+ mAggregationVertexFactory.setCreationContext(agg);
+ }
+ public void createLayout()
+ {
+ mSaveButton.setToolTipText(Language.translate("Save Layout Changes"));
+ mSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, mEditorPanel, mPropertyPanel);
+ mSplitPane.setDividerSize(5);
+ add(mSplitPane);
+ }
+
+ protected void createListeners()
+ {
+ mSaveButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent ae)
+ {
+ saveCollection();
+ }
+ });
+ mHistoryButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent ae)
+ {
+ new CollectionHistoryWindow(item, thisColl);
+ }
+ });
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/collection/CollectionHistoryWindow.java b/source/com/c2kernel/gui/tabs/collection/CollectionHistoryWindow.java
new file mode 100755
index 0000000..ef20a1a
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/collection/CollectionHistoryWindow.java
@@ -0,0 +1,184 @@
+package com.c2kernel.gui.tabs.collection;
+
+import java.awt.HeadlessException;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+
+import javax.swing.JFrame;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.table.AbstractTableModel;
+
+import com.c2kernel.collection.Collection;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.entity.proxy.EntityProxy;
+import com.c2kernel.entity.proxy.EntityProxyObserver;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.events.Event;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.lifecycle.instance.predefined.PredefinedStep;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.lookup.InvalidEntityPathException;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.persistency.outcome.Outcome;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+
+public class CollectionHistoryWindow extends JFrame {
+
+ JTable historyTable;
+ HistoryTableModel historyModel;
+
+ public CollectionHistoryWindow(ItemProxy item, Collection coll) throws HeadlessException {
+ super("Collection History");
+ historyModel = new HistoryTableModel(item, coll);
+ historyTable = new JTable(historyModel);
+ this.getContentPane().add(new JScrollPane(historyTable));
+ historyTable.addMouseListener(new HistoryTableListener(item));
+ this.pack();
+ super.toFront();
+ this.validate();
+ this.show();
+ }
+
+ private class HistoryTableModel extends AbstractTableModel implements EntityProxyObserver {
+
+ ItemProxy item;
+ ArrayList collEvents, collEventData;
+ Collection coll;
+ public HistoryTableModel(ItemProxy item, Collection coll) {
+ this.item = item;
+ this.coll = coll;
+ collEvents = new ArrayList();
+ collEventData = new ArrayList();
+ item.subscribe(this, ClusterStorage.HISTORY, true);
+ }
+ public int getColumnCount() {
+ // TODO Auto-generated method stub
+ return 4;
+ }
+
+ public String getColumnName(int columnIndex) {
+ switch(columnIndex) {
+ case 0: return Language.translate("Date");
+ case 1: return Language.translate("Operation");
+ case 2: return Language.translate("Slot");
+ case 3: return Language.translate("Child");
+ default: return "";
+ }
+ }
+ public int getRowCount() {
+ // TODO Auto-generated method stub
+ return collEvents.size();
+ }
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ Event ev = (Event)collEvents.get(rowIndex);
+ switch (columnIndex) {
+ case 0:
+ return ev.getTimeString();
+ case 1:
+ if (ev.getStepName().equals("AssignItemToSlot"))
+ return "Item Assigned";
+ else
+ return "Collection replaced";
+ case 2:
+ if (ev.getStepName().equals("AssignItemToSlot"))
+ return ((String[])collEventData.get(rowIndex))[1];
+ return "";
+ case 3:
+ if (ev.getStepName().equals("AddC2KObject"))
+ return "Click to view";
+ String name;
+ try {
+ EntityProxy childItem = Gateway.getProxyManager().getProxy(new EntityPath(Integer.parseInt(((String[])collEventData.get(rowIndex))[2])));
+ name = childItem.getName();
+ } catch (NumberFormatException e) {
+ name = "Invalid entity key: "+((String[])collEventData.get(rowIndex))[2];
+ } catch (ObjectNotFoundException e) {
+ name = "Item deleted: "+((String[])collEventData.get(rowIndex))[2];
+ } catch (InvalidEntityPathException e) {
+ name = "Invalid entity key: "+((String[])collEventData.get(rowIndex))[2];
+ }
+ return name;
+ default:
+ return "";
+ }
+ }
+ public Object getEventData(int row) {
+ return collEventData.get(row);
+ }
+ public void add(C2KLocalObject contents) {
+ if (!(contents instanceof Event)) return;
+ Event thisEv = (Event)contents;
+ if (thisEv.getStepName().equals("AssignItemToSlot") || thisEv.getStepName().equals("AddC2KObject")) {
+ String[] params;
+ try {
+ Outcome oc = (Outcome)item.getObject(ClusterStorage.OUTCOME+"/PredefinedStepOutcome/0/"+thisEv.getID());
+ params = PredefinedStep.getDataList(oc.getData());
+ } catch (ObjectNotFoundException ex) { return; }
+ if (thisEv.getStepName().equals("AssignItemToSlot")) {
+ if (params[0].equals(coll.getName()))
+ collEventData.add(params);
+ else return;
+ }
+ else {
+ Object obj;
+ try {
+ obj = CastorXMLUtility.unmarshall(params[0]);
+ } catch (Exception e) {
+ Logger.error(e);
+ return;
+ }
+ if (obj instanceof Collection)
+ collEventData.add(obj);
+ else return;
+
+ }
+ }
+ else return;
+ collEvents.add(thisEv);
+ fireTableRowsInserted(collEvents.size()-1, collEvents.size()-1);
+ }
+ public void remove(String id) { }
+ }
+
+ private class HistoryTableListener extends MouseAdapter {
+
+ ItemProxy item;
+ public HistoryTableListener(ItemProxy item) {
+ this.item = item;
+ }
+
+ public void mouseClicked(MouseEvent e) {
+ if (e.getClickCount()==2) {
+ int row = historyTable.getSelectedRow();
+ Object data = historyModel.getEventData(row);
+ if (data instanceof Collection) {
+ showColl((Collection)data);
+ }
+ else {
+ String[] params = (String[])data;
+ try {
+ EntityProxy childItem = Gateway.getProxyManager().getProxy(new EntityPath(Integer.parseInt(params[2])));
+ MainFrame.itemFinder.pushNewKey(childItem.getName());
+ } catch (Exception ex) { }
+ }
+ }
+ }
+ public void showColl(Collection coll) {
+ JFrame newFrame = new JFrame();
+ AggregationView newView = new AggregationView();
+ newView.setCollection(coll);
+ newView.setItem(item);
+ newFrame.getContentPane().add(newView);
+ newFrame.pack();
+ newFrame.toFront();
+ newFrame.validate();
+ newFrame.show();
+ }
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/collection/CollectionView.java b/source/com/c2kernel/gui/tabs/collection/CollectionView.java
new file mode 100755
index 0000000..62a598c
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/collection/CollectionView.java
@@ -0,0 +1,48 @@
+package com.c2kernel.gui.tabs.collection;
+
+import javax.swing.JPanel;
+
+import com.c2kernel.collection.Collection;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.utils.Logger;
+
+/**************************************************************************
+ *
+ * $Revision: 1.1 $
+ * $Date: 2004/08/10 07:56:08 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+
+public abstract class CollectionView extends JPanel {
+
+ protected Collection thisColl;
+ protected ItemProxy item;
+
+ public CollectionView() {
+ super();
+ }
+
+ public void setItem(ItemProxy entity) {
+ this.item = entity;
+ }
+
+ public abstract void setCollection(Collection coll);
+
+ protected void saveCollection()
+ {
+ try
+ {
+ String[] params = new String[1];
+ params[0] = com.c2kernel.utils.CastorXMLUtility.marshall(thisColl);
+ MainFrame.userAgent.execute(item, "AddC2KObject", params);
+ }
+ catch (Exception e)
+ {
+ Logger.error(e);
+ }
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/collection/DependencyView.java b/source/com/c2kernel/gui/tabs/collection/DependencyView.java
new file mode 100755
index 0000000..4465d6a
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/collection/DependencyView.java
@@ -0,0 +1,33 @@
+package com.c2kernel.gui.tabs.collection;
+import java.awt.GridLayout;
+
+import javax.swing.JLabel;
+
+import com.c2kernel.collection.Collection;
+/**
+ * @version $Revision: 1.2 $ $Date: 2005/06/02 12:17:22 $
+ * @author $Author: abranson $
+ */
+public class DependencyView extends CollectionView
+{
+ // Objects to view/modify the properties of the selected activity
+
+ public DependencyView()
+ {
+ super();
+ setLayout(new GridLayout(1,1));
+ createLayout();
+ }
+
+ public void setCollection(Collection contents)
+ {
+ thisColl = contents;
+ }
+ public void createLayout()
+ {
+ // TODO: design a nice dependency view, with property viewing and modification
+ add(new JLabel("Dependency view not yet implemented. Please browse the tree instead."));
+ }
+
+
+}
diff --git a/source/com/c2kernel/gui/tabs/execution/ActivityItem.java b/source/com/c2kernel/gui/tabs/execution/ActivityItem.java
new file mode 100755
index 0000000..1a73dc2
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/execution/ActivityItem.java
@@ -0,0 +1,46 @@
+package com.c2kernel.gui.tabs.execution;
+import java.util.ArrayList;
+
+import com.c2kernel.entity.agent.Job;
+import com.c2kernel.lifecycle.instance.stateMachine.States;
+
+public class ActivityItem {
+ public String stepPath;
+ public int state;
+ public String name;
+ ArrayList jobs = new ArrayList();
+
+ public ActivityItem(Job thisJob) {
+ stepPath = thisJob.getStepPath();
+ state = thisJob.getCurrentState();
+ name = thisJob.getStepName();
+ jobs.add(thisJob);
+ }
+
+ public void addJob(Job newJob) {
+ jobs.add(newJob);
+ }
+
+ public ArrayList getJobs() {
+ return jobs;
+ }
+
+ public String getStepPath() {
+ return stepPath;
+ }
+
+ public String toString() {
+ return name+" ("+States.getStateName(state)+")";
+ }
+
+ public boolean equals(Object other) {
+ if (other instanceof ActivityItem)
+ return hashCode() == ((ActivityItem)other).hashCode();
+ return false;
+ }
+
+ public int hashCode() {
+ return stepPath.hashCode();
+ }
+
+}
diff --git a/source/com/c2kernel/gui/tabs/execution/ActivityViewer.java b/source/com/c2kernel/gui/tabs/execution/ActivityViewer.java
new file mode 100755
index 0000000..4250a37
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/execution/ActivityViewer.java
@@ -0,0 +1,292 @@
+package com.c2kernel.gui.tabs.execution;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.GridLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.agent.Job;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.gui.tabs.EntityTabPane;
+import com.c2kernel.gui.tabs.ExecutionPane;
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+import com.c2kernel.gui.tabs.outcome.OutcomeHandler;
+import com.c2kernel.utils.FileStringUtility;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.LocalObjectLoader;
+import com.c2kernel.utils.Logger;
+
+public class ActivityViewer extends JPanel implements Runnable {
+
+ ItemProxy item;
+ Box outcomeButtons = Box.createHorizontalBox();
+ OutcomeHandler outcomePanel;
+ JPanel outcomeView = new JPanel(new GridLayout(1,1));
+ ActivityItem thisAct;
+ ArrayList requestButtons = new ArrayList();
+ JLabel noOutcome = new JLabel(Language.translate("No outcome data is required for this activity"));
+ ExecutionPane parent;
+ JLabel status;
+ JComboBox executors;
+ JButton saveButton = new JButton("Save");
+ JButton loadButton = new JButton("Load");
+ GridBagLayout gridbag = new GridBagLayout();
+ Job executingJob = null;
+ static JFileChooser chooser = new JFileChooser();
+ static {
+ chooser.addChoosableFileFilter(
+ new javax.swing.filechooser.FileFilter() {
+ public String getDescription() {
+ return "XML Files";
+ }
+ public boolean accept(File f) {
+ if (f.isDirectory() || (f.isFile() && f.getName().endsWith(".xml"))) {
+ return true;
+ }
+ return false;
+ }
+ });
+ }
+
+ public ActivityViewer (ActivityItem newAct, ItemProxy item, ExecutionPane parent){
+ thisAct = newAct;
+ this.item = item;
+ this.parent = parent;
+ setLayout(gridbag);
+
+ GridBagConstraints c = new GridBagConstraints();
+ c.gridx=0; c.gridy=1; c.weightx=1.0; c.weighty=0.0;
+ c.insets = new Insets(5,5,5,5);
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.fill = GridBagConstraints.HORIZONTAL;
+
+// activity title
+ JLabel actTitle = new JLabel(Language.translate("Activity")+": "+newAct.name);
+ actTitle.setFont(EntityTabPane.titleFont);
+ gridbag.setConstraints(actTitle, c);
+ add(actTitle);
+
+ Job firstJob = (Job)(thisAct.getJobs().get(0));
+// desc
+ String desc = firstJob.getDescription();
+ if (desc != null && desc.length() > 0) {
+ Box descBox = Box.createHorizontalBox();
+
+ String chopDesc = null;
+ if(desc.length() >= 40) chopDesc = desc.substring(0,40);
+ else chopDesc = desc;
+
+ descBox.add(new JLabel("Description: "+chopDesc));
+ if (desc.length()>chopDesc.length()) {
+ descBox.add(new JLabel(" ..."));
+ descBox.add(Box.createHorizontalStrut(7));
+ JButton descButton = new JButton("View");
+ descButton.setMargin(new Insets(0,0,0,0));
+ descButton.setActionCommand(desc);
+ descButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ JTextArea descArea = new JTextArea(e.getActionCommand());
+ descArea.setLineWrap(true);
+ descArea.setWrapStyleWord(true);
+ JScrollPane descScroll = new JScrollPane(descArea);
+ descScroll.setPreferredSize(new Dimension(400,150));
+ JOptionPane.showMessageDialog(null, descScroll, "Activity Description", JOptionPane.PLAIN_MESSAGE);
+ }
+ });
+ descBox.add(descButton);
+ }
+
+ c.gridy++;
+ gridbag.setConstraints(descBox, c);
+ add(descBox);
+ }
+
+
+// agentid
+ String roleName = firstJob.getAgentRole();
+ if (roleName!= null && roleName.length()>0) {
+ c.gridy++;
+ JLabel role = new JLabel(Language.translate("Agent Role")+": "+roleName);
+ gridbag.setConstraints(role, c);
+ add(role);
+ }
+
+ c.gridy++;
+ c.anchor = GridBagConstraints.EAST;
+ gridbag.setConstraints(outcomeButtons, c);
+ add(outcomeButtons);
+
+ executors = MainFrame.getExecutionPlugins();
+ if (executors.getItemCount() > 1) {
+ c.gridx++;
+ gridbag.setConstraints(executors, c);
+ add(executors);
+ c.gridx--;
+ }
+
+ c.gridy++;
+
+ status = new JLabel(Language.translate("Waiting for request"));
+ status.setFont(EntityTabPane.titleFont);
+ gridbag.setConstraints(status, c);
+ add(status);
+
+ c.gridx++;
+ Box fileBox = Box.createHorizontalBox();
+ fileBox.add(saveButton); fileBox.add(Box.createHorizontalGlue()); fileBox.add(loadButton);
+ gridbag.setConstraints(fileBox, c);
+ add(fileBox);
+ saveButton.setEnabled(false);
+ loadButton.setEnabled(false);
+ c.gridx--;
+ c.gridwidth = 2;
+ boolean outcomeEmpty = true;
+ for (Iterator e = thisAct.getJobs().iterator(); e.hasNext();) {
+ Job thisJob = (Job)e.next();
+ RequestButton newButton = new RequestButton(thisJob, this);
+ requestButtons.add(newButton);
+ outcomeButtons.add(newButton);
+ outcomeButtons.add(Box.createHorizontalStrut(5));
+
+ if (thisJob.isOutcomeUsed()) {
+ String schema;
+ if (outcomeEmpty) {
+ try {
+ schema = LocalObjectLoader.getSchema(thisJob.getSchemaType(), thisJob.getSchemaVersion()).schema;
+ outcomePanel = EntityTabPane.getOutcomeHandler(thisJob.getSchemaType(), thisJob.getSchemaVersion());
+ outcomePanel.setReadOnly(false);
+ outcomePanel.setDescription(schema);
+ String outcomeString = thisJob.getOutcomeString();
+ if ( outcomeString!= null && outcomeString.length() > 0)
+ outcomePanel.setOutcome(outcomeString);
+ outcomeView = outcomePanel.getPanel();
+ } catch (ObjectNotFoundException ex) {
+ outcomeView.add(new JLabel(Language.translate("Schema not found:")+" "+thisJob.getSchemaType()+" v"+thisJob.getSchemaVersion()));
+ outcomePanel = null;
+ } catch (Exception ex) {
+ outcomeView.add(new JLabel(Language.translate("ERROR loading outcome editor: ")
+ +ex.getClass().getName()+" ("+ex.getMessage()+")"));
+ Logger.error(ex);
+ outcomePanel = null;
+ }
+ }
+ outcomeEmpty = false;
+ if (outcomePanel == null) newButton.setEnabled(false);
+ else {
+ saveButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ String output;
+ try {
+ output = outcomePanel.getOutcome();
+ int returnVal = chooser.showSaveDialog(null);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ File targetFile = chooser.getSelectedFile();
+ if (!(targetFile.getAbsolutePath().endsWith(".xml")))
+ targetFile = new File(targetFile.getAbsolutePath()+".xml");
+
+ Logger.msg(2, "ExecutionPane - Exporting outcome to file " + targetFile.getName());
+ FileStringUtility.string2File(targetFile, output);
+ }
+ } catch (Exception ex) {
+ Logger.error(ex);
+ Logger.exceptionDialog(ex);
+ }
+ }
+ });
+ saveButton.setEnabled(true);
+
+ loadButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ try {
+ int returnVal = chooser.showOpenDialog(null);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ File targetFile = chooser.getSelectedFile();
+
+ Logger.msg(2, "ViewpointPane.actionPerformed() - Reading outcome from file " + targetFile.getName());
+ String outcome = FileStringUtility.file2String(targetFile);
+ outcomePanel.setOutcome(outcome);
+ new Thread(outcomePanel).start();
+ }
+ } catch (Exception ex) {
+ Logger.error(ex);
+ Logger.exceptionDialog(ex);
+ }
+ }
+ });
+ loadButton.setEnabled(true);
+ }
+ }
+ }
+ if (outcomeEmpty)
+ outcomeView.add(noOutcome);
+ c.gridy++; c.weighty=1.0;
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.fill = GridBagConstraints.BOTH;
+ gridbag.setConstraints(outcomeView, c);
+ add(outcomeView);
+
+ }
+
+ public void init() {
+ if (outcomePanel != null)
+ new Thread(outcomePanel).start();
+ }
+
+ public void execute(Job thisJob) {
+ try{
+ if (thisJob.isOutcomeUsed() && thisJob.getSchemaType().length() > 0)
+ thisJob.setOutcome(outcomePanel.getOutcome());
+ executingJob = thisJob;
+ new Thread(this).start();
+ } catch (OutcomeException ex) {
+ Logger.exceptionDialog(ex);
+ }
+
+ }
+
+ /**
+ * Submits the job to the database
+ */
+ public void run() {
+ Thread.currentThread().setName("Activity Execution");
+ enableAllButtons(false);
+ try {
+ Executor selectedExecutor = (Executor)executors.getSelectedItem();
+ selectedExecutor.execute(executingJob, status);
+ } catch (Exception e) {
+ Logger.error(e);
+ status.setText(Language.translate("Error during execution"));
+ Logger.exceptionDialog(e);
+ }
+ enableAllButtons(true);
+ }
+
+ private void enableAllButtons(boolean enabled) {
+
+ for (Iterator iter = requestButtons.iterator(); iter.hasNext();) {
+ RequestButton thisButton = (RequestButton)iter.next();
+ thisButton.setEnabled(enabled);
+ }
+ }
+
+ public ActivityItem getActivity() {
+ return thisAct;
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/execution/DefaultExecutor.java b/source/com/c2kernel/gui/tabs/execution/DefaultExecutor.java
new file mode 100755
index 0000000..ea05568
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/execution/DefaultExecutor.java
@@ -0,0 +1,33 @@
+package com.c2kernel.gui.tabs.execution;
+
+import javax.swing.JLabel;
+
+import com.c2kernel.entity.agent.Job;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.utils.Language;
+
+/**************************************************************************
+ *
+ * $Revision: 1.2 $
+ * $Date: 2003/11/04 14:31:30 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class DefaultExecutor implements Executor {
+
+ public DefaultExecutor() {
+ super();
+ }
+
+ public void execute(Job job, JLabel status) throws Exception {
+ status.setText(Language.translate("Requesting, please wait."));
+ MainFrame.userAgent.execute(job);
+ status.setText(Language.translate("Execution complete. Waiting for joblist update."));
+ }
+
+ public String toString() {
+ return "Normal";
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/execution/Executor.java b/source/com/c2kernel/gui/tabs/execution/Executor.java
new file mode 100755
index 0000000..dd185b4
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/execution/Executor.java
@@ -0,0 +1,21 @@
+package com.c2kernel.gui.tabs.execution;
+
+import javax.swing.JLabel;
+
+import com.c2kernel.entity.agent.Job;
+
+/**************************************************************************
+ *
+ * $Revision: 1.1 $
+ * $Date: 2003/09/25 10:28:02 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public interface Executor {
+
+ public String toString();
+
+ public void execute(Job job, JLabel status) throws Exception;
+}
diff --git a/source/com/c2kernel/gui/tabs/execution/RequestButton.java b/source/com/c2kernel/gui/tabs/execution/RequestButton.java
new file mode 100755
index 0000000..0e11a7f
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/execution/RequestButton.java
@@ -0,0 +1,33 @@
+package com.c2kernel.gui.tabs.execution;
+import java.awt.Color;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+
+import com.c2kernel.entity.agent.Job;
+import com.c2kernel.lifecycle.instance.stateMachine.Transitions;
+/**
+ * Each job gets a RequestButton
+ */
+
+ public class RequestButton extends JButton implements ActionListener {
+
+ Job myJob;
+ ActivityViewer parent;
+
+ public RequestButton(Job myJob, ActivityViewer parent) {
+ super();
+ this.myJob = myJob;
+ this.parent = parent;
+ String label = Transitions.getTransitionName(myJob.getPossibleTransition());
+ label = Character.toUpperCase(label.charAt(0))+label.substring(1);
+ if (myJob.isOutcomeUsed()) setBackground(Color.white);
+ super.setText(label);
+ addActionListener(this);
+ }
+
+ public void actionPerformed(ActionEvent event) {
+ parent.execute(myJob);
+ }
+ }
diff --git a/source/com/c2kernel/gui/tabs/outcome/BasicOutcomeEditor.java b/source/com/c2kernel/gui/tabs/outcome/BasicOutcomeEditor.java
new file mode 100755
index 0000000..451b393
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/BasicOutcomeEditor.java
@@ -0,0 +1,100 @@
+package com.c2kernel.gui.tabs.outcome;
+
+import java.awt.Font;
+import java.awt.GridLayout;
+import java.io.File;
+
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.text.PlainDocument;
+
+import com.c2kernel.utils.FileStringUtility;
+
+/**************************************************************************
+ *
+ * $Revision: 1.4 $
+ * $Date: 2005/09/07 13:46:31 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+
+
+public class BasicOutcomeEditor extends JPanel implements OutcomeHandler {
+
+ PlainDocument doc;
+ JTextArea textarea;
+ boolean unsaved;
+
+ public BasicOutcomeEditor() {
+ super();
+ this.setLayout(new GridLayout(1,1));
+ doc = new PlainDocument();
+ textarea = new JTextArea(doc);
+ textarea.setTabSize(2);
+ textarea.setFont(Font.decode("monospaced"));
+ add(new JScrollPane(textarea));
+ doc.addDocumentListener(new DocumentListener() {
+ public void changedUpdate(DocumentEvent e) { unsaved = true; }
+ public void insertUpdate(DocumentEvent e) { unsaved = true; }
+ public void removeUpdate(DocumentEvent e) { unsaved = true; }
+
+ });
+ }
+
+ public void setOutcome(String outcome) throws InvalidOutcomeException {
+ try {
+ doc.insertString(0, outcome, null);
+ unsaved = false;
+ } catch (Exception ex) {
+ throw new InvalidOutcomeException(ex.getMessage());
+ }
+ }
+
+ public void setDescription(String description) throws InvalidSchemaException { }
+
+ public void setReadOnly(boolean readOnly) {
+ textarea.setEditable(!readOnly);
+ }
+
+
+ public JPanel getPanel() throws OutcomeNotInitialisedException {
+ return this;
+ }
+
+ /**
+ *
+ */
+
+ public String getOutcome() throws OutcomeException {
+ try {
+ return doc.getText(0, doc.getLength());
+ } catch (Exception ex) {
+ throw new OutcomeException(ex.getMessage());
+ }
+ }
+
+ /**
+ *
+ */
+
+ public void run() {
+ }
+
+
+ public boolean isUnsaved() {
+ return unsaved;
+ }
+
+ public void saved() {
+ unsaved = false;
+ }
+
+ public void export(File targetFile) throws Exception {
+ FileStringUtility.string2File(targetFile, getOutcome());
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/InvalidOutcomeException.java b/source/com/c2kernel/gui/tabs/outcome/InvalidOutcomeException.java
new file mode 100755
index 0000000..bab9050
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/InvalidOutcomeException.java
@@ -0,0 +1,11 @@
+package com.c2kernel.gui.tabs.outcome;
+
+public class InvalidOutcomeException extends OutcomeException {
+
+ public InvalidOutcomeException() {
+ super();
+ }
+ public InvalidOutcomeException(String ex) {
+ super(ex);
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/InvalidSchemaException.java b/source/com/c2kernel/gui/tabs/outcome/InvalidSchemaException.java
new file mode 100755
index 0000000..5edbcbf
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/InvalidSchemaException.java
@@ -0,0 +1,11 @@
+package com.c2kernel.gui.tabs.outcome;
+
+public class InvalidSchemaException extends OutcomeException {
+
+ public InvalidSchemaException() {
+ super();
+ }
+ public InvalidSchemaException(String ex) {
+ super(ex);
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/OutcomeException.java b/source/com/c2kernel/gui/tabs/outcome/OutcomeException.java
new file mode 100755
index 0000000..fd608d0
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/OutcomeException.java
@@ -0,0 +1,11 @@
+package com.c2kernel.gui.tabs.outcome;
+
+public class OutcomeException extends Exception {
+
+ public OutcomeException() {
+ super();
+ }
+ public OutcomeException(String ex) {
+ super(ex);
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/OutcomeHandler.java b/source/com/c2kernel/gui/tabs/outcome/OutcomeHandler.java
new file mode 100755
index 0000000..0d6dc74
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/OutcomeHandler.java
@@ -0,0 +1,16 @@
+package com.c2kernel.gui.tabs.outcome;
+import java.io.File;
+
+import javax.swing.JPanel;
+
+public interface OutcomeHandler extends Runnable {
+
+ public void setOutcome(String outcome) throws InvalidOutcomeException;
+ public void setDescription(String description) throws InvalidSchemaException;
+ public void setReadOnly(boolean readOnly);
+ public JPanel getPanel() throws OutcomeNotInitialisedException;
+ public boolean isUnsaved();
+ public void saved();
+ public String getOutcome() throws OutcomeException;
+ public void export(File targetFile) throws Exception;
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/OutcomeNotInitialisedException.java b/source/com/c2kernel/gui/tabs/outcome/OutcomeNotInitialisedException.java
new file mode 100755
index 0000000..7b54f33
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/OutcomeNotInitialisedException.java
@@ -0,0 +1,11 @@
+package com.c2kernel.gui.tabs.outcome;
+
+public class OutcomeNotInitialisedException extends OutcomeException {
+
+ public OutcomeNotInitialisedException() {
+ super();
+ }
+ public OutcomeNotInitialisedException(String ex) {
+ super(ex);
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/form/AttributeList.java b/source/com/c2kernel/gui/tabs/outcome/form/AttributeList.java
new file mode 100755
index 0000000..08c5ea1
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/form/AttributeList.java
@@ -0,0 +1,158 @@
+package com.c2kernel.gui.tabs.outcome.form;
+
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SwingConstants;
+
+import org.exolab.castor.xml.schema.AttributeDecl;
+import org.exolab.castor.xml.schema.ComplexType;
+import org.exolab.castor.xml.schema.ElementDecl;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+
+import com.c2kernel.gui.tabs.outcome.form.field.StringEditField;
+import com.c2kernel.utils.Logger;
+
+public class AttributeList extends JPanel {
+
+ ArrayList attrSet = new ArrayList();
+ ElementDecl model;
+ Element myElement;
+ boolean readOnly;
+ static Font labelFont;
+
+ public AttributeList(ElementDecl model, boolean readOnly, HelpPane helpPane) {
+ super();
+ AttributeDecl thisDecl;
+ this.model = model;
+ this.readOnly = readOnly;
+
+ // set up panel
+ GridBagLayout gridbag = new java.awt.GridBagLayout();
+ setLayout(gridbag);
+ if (labelFont == null)
+ labelFont = this.getFont().deriveFont((float)(this.getFont().getSize()-3.0));
+ // retrieve attributes
+ if (!model.getType().isComplexType()) {
+ // simple types have no attributes
+ return;
+ }
+
+ ComplexType content = (ComplexType)model.getType();
+
+ // place on panel
+
+ GridBagConstraints c = new GridBagConstraints();
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.weightx = 1.0; c.weighty = 1.0; c.gridx = 0;
+ c.ipadx = 5; c.ipady = 0;
+
+ for (Enumeration fields = content.getAttributeDecls(); fields.hasMoreElements();) {
+ c.gridy = 0;
+ thisDecl = (AttributeDecl)fields.nextElement();
+ Logger.msg(8, "Includes Attribute "+thisDecl.getName());
+
+ // Add Label
+ JLabel heading = new JLabel(thisDecl.getName());
+ heading.setFont(labelFont);
+ heading.setVerticalAlignment(SwingConstants.BOTTOM);
+ gridbag.setConstraints(heading, c);
+ this.add(heading);
+
+ // read help
+ String helpText;
+ String doc = OutcomeStructure.extractHelp(thisDecl);
+ if (doc.length() > 0)
+ helpText = doc.toString();
+ else
+ helpText = "<i>No help is available for this attribute</i>";
+
+
+ c.gridy++;
+
+ // Add entry
+ try {
+ StringEditField entry = StringEditField.getEditField(thisDecl);
+ entry.setHelp(helpPane, helpText);
+ attrSet.add(entry);
+ if (readOnly) entry.setEditable(false);
+ gridbag.setConstraints(entry.getControl(), c);
+ this.add(entry.getControl());
+ } catch (StructuralException e) {
+ JLabel entry = new JLabel("Error");
+ entry.setToolTipText(e.getMessage());
+ gridbag.setConstraints(entry, c);
+ this.add(entry);
+ }
+
+
+ c.gridx++;
+ }
+ }
+
+ public void setInstance(Element data) throws StructuralException {
+ this.myElement = data;
+ for (Iterator e = attrSet.iterator(); e.hasNext();) {
+ StringEditField thisField = (StringEditField)e.next();
+ Logger.msg(8, "Populating Attribute "+thisField.getName());
+ Attr thisAttr = myElement.getAttributeNode(thisField.getName());
+ if (thisAttr == null)
+ thisAttr = newAttribute(myElement, (AttributeDecl)thisField.getModel());
+ thisField.setData(thisAttr);
+ }
+ }
+
+ public Attr newAttribute(Element parent, AttributeDecl attr) {
+
+ parent.setAttribute(attr.getName(), attr.getFixedValue()!=null?attr.getFixedValue():attr.getDefaultValue());
+ return parent.getAttributeNode(attr.getName());
+ }
+
+ public String validateAttributes() {
+ if (model.getType().isComplexType()) {
+ ComplexType content = (ComplexType)model.getType();
+ for (Enumeration fields = content.getAttributeDecls(); fields.hasMoreElements();) {
+ AttributeDecl thisDecl = (AttributeDecl)fields.nextElement();
+ String attrVal = myElement.getAttribute(thisDecl.getName());
+ if (attrVal.length() == 0 && thisDecl.isOptional()) {
+ myElement.removeAttribute(thisDecl.getName());
+ }
+ }
+ }
+ return null;
+ }
+
+ public void initNew(Element parent) {
+ AttributeDecl thisDecl;
+ StringEditField thisField;
+ Attr thisAttr;
+ this.myElement = parent;
+
+ if (model.getType().isSimpleType()) return; // no attributes in simple types
+
+ ComplexType content = (ComplexType)model.getType();
+
+ for (Iterator e = attrSet.iterator(); e.hasNext();) {
+ thisField = (StringEditField)e.next();
+
+ thisDecl = content.getAttributeDecl(thisField.getName());
+ thisAttr = newAttribute(myElement, thisDecl);
+ // add into parent - fill in field
+ try {
+ thisField.setData(thisAttr);
+ } catch (Exception ex) { } // impossible name mismatch
+ }
+ }
+ public void grabFocus() {
+ if (attrSet.size() > 0)
+ ((StringEditField)attrSet.get(0)).grabFocus();
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/form/CardinalException.java b/source/com/c2kernel/gui/tabs/outcome/form/CardinalException.java
new file mode 100755
index 0000000..bb6d039
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/form/CardinalException.java
@@ -0,0 +1,14 @@
+package com.c2kernel.gui.tabs.outcome.form;
+
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+
+public class CardinalException extends OutcomeException {
+
+ public CardinalException() {
+ super();
+ }
+
+ public CardinalException(String ex) {
+ super(ex);
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/form/DataRecord.java b/source/com/c2kernel/gui/tabs/outcome/form/DataRecord.java
new file mode 100755
index 0000000..9d0b633
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/form/DataRecord.java
@@ -0,0 +1,249 @@
+package com.c2kernel.gui.tabs.outcome.form;
+import java.awt.FlowLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import javax.swing.JLabel;
+import javax.swing.JTabbedPane;
+import javax.swing.SwingUtilities;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import org.exolab.castor.xml.schema.ComplexType;
+import org.exolab.castor.xml.schema.ElementDecl;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+import com.c2kernel.utils.Logger;
+
+public class DataRecord extends OutcomeStructure implements ChangeListener {
+
+ AttributeList myAttributes;
+ JTabbedPane DRPanel = null;
+ boolean deferred;
+ ArrayList deferredChildren = new ArrayList();
+ Document parentDoc;
+ GridBagConstraints position;
+ GridBagLayout gridbag;
+
+ public DataRecord(ElementDecl model, boolean readOnly, HelpPane help, boolean deferred) throws OutcomeException {
+ super(model, readOnly, help);
+ this.deferred = deferred;
+ if (!deferred) setupPanel();
+ }
+
+ public synchronized void activate() {
+ deferred = false;
+ try {
+ setupPanel();
+ if (myElement!=null) populateInstance();
+ } catch (OutcomeException ex) {
+ removeAll();
+ setLayout(new FlowLayout());
+ add(new JLabel("Error displaying outcome segment: "+ex.getMessage()));
+ }
+ validate();
+ }
+
+ private void setupPanel() throws OutcomeException {
+ // set up panel
+ gridbag = new java.awt.GridBagLayout();
+ setLayout(gridbag);
+ position = new GridBagConstraints();
+ position.anchor = GridBagConstraints.NORTHWEST;
+ position.fill = GridBagConstraints.NONE;
+ position.weightx = 1.0; position.weighty = 1.0;
+ position.gridx = 0; position.gridy = 0;
+ position.ipadx = 5; position.ipady = 5;
+ position.insets = new Insets(5,5,0,0);
+
+ // attributes at the top
+ myAttributes = new AttributeList(model, readOnly, helpPane);
+ position.gridwidth=3;
+ gridbag.setConstraints(myAttributes, position);
+ add(myAttributes);
+
+ ComplexType elementType;
+ try {
+ elementType = (ComplexType)model.getType();
+ }
+ catch (ClassCastException e) {
+ throw new StructuralException("DataRecord created with non-ComplexType");
+ }
+
+ //loop through all schema sub-elements
+ try {
+ enumerateElements(elementType);
+ } catch (OutcomeException e) {
+ throw new OutcomeException("Element "+model.getName()+" could not be created: "+e.getMessage());
+ }
+ }
+
+ public void addStructure(OutcomeStructure newElement) throws OutcomeException {
+ super.addStructure(newElement);
+ if (newElement == null) return;
+ if (newElement instanceof DataRecord) {
+ DataRecord newRecord = (DataRecord)newElement;
+ // set up enclosing tabbed pane for child drs
+ if (DRPanel == null) {
+ DRPanel = new JTabbedPane();
+ position.gridy++;
+ position.weightx=1.0;
+ position.fill=GridBagConstraints.HORIZONTAL;
+ position.gridwidth=3;
+ gridbag.setConstraints(DRPanel, position);
+ add(DRPanel);
+ // defer further tabs in this pane
+ deferChild = true;
+ }
+ DRPanel.addTab(newRecord.getName(), newRecord);
+ DRPanel.addChangeListener(newRecord);
+ }
+ else {
+ DRPanel = null;// have to make a new tabbed pane now
+ deferChild = false;
+ if (newElement instanceof Field) {
+ Field newField = (Field)newElement;
+ // make some nice columns
+ position.gridwidth=1;
+ position.gridy++;
+ position.gridx=0;
+ position.weightx=2;
+ position.weighty=0;
+ position.fill=GridBagConstraints.NONE;
+ gridbag.setConstraints(newField.getLabel(), position);
+ this.add(newField.getLabel());
+ position.gridy++;
+ position.weighty=1;
+ position.fill = GridBagConstraints.HORIZONTAL;
+ gridbag.setConstraints(newField.getCData(), position);
+ this.add(newField.getCData());
+ position.gridx++;
+ position.gridy--;
+ position.gridheight=2;
+ position.weightx=0;
+ position.fill=GridBagConstraints.NONE;
+ gridbag.setConstraints(newField.getAttributes(), position);
+ this.add(newField.getAttributes());
+ position.gridx=0;
+ position.gridheight=1;
+ position.gridy++;
+ }
+ else {
+ position.fill=GridBagConstraints.HORIZONTAL;
+ position.gridwidth=3;
+ position.weightx=1.0;
+ position.gridy++;
+ position.weighty=1.0;
+ gridbag.setConstraints(newElement, position);
+ add(newElement);
+ }
+ }
+ }
+
+ public void addInstance(Element myElement, Document parentDoc) throws OutcomeException {
+ Logger.msg(8, "Accepting DR "+myElement.getTagName());
+
+ if (this.myElement != null) throw new CardinalException("DataRecord "+this.getName()+" cannot repeat.");
+ this.myElement = myElement;
+ this.parentDoc = parentDoc;
+
+ if (!deferred)
+ populateInstance();
+ }
+
+ public void populateInstance() throws OutcomeException {
+ myAttributes.setInstance(myElement);
+
+ NodeList childElements = myElement.getChildNodes();
+
+ for (int i=0; i<childElements.getLength();i++) {
+ if (!(childElements.item(i) instanceof Element)) // ignore chardata here
+ continue;
+ Element thisElement = (Element) childElements.item(i);
+
+ // find the child structure with this name
+ OutcomeStructure thisStructure = (OutcomeStructure)subStructure.get(thisElement.getTagName());
+ if (thisStructure == null)
+ throw new StructuralException("DR "+model.getName()+" not expecting "+thisElement.getTagName());
+ thisStructure.addInstance(thisElement, parentDoc);
+ }
+
+ // make sure any dimensions have the minimum
+ for (Iterator e=subStructure.keySet().iterator(); e.hasNext();) {
+ String structureName = (String)e.next();
+ OutcomeStructure thisStructure = (OutcomeStructure)subStructure.get(structureName);
+ int count = 0;
+
+ if (thisStructure instanceof Dimension) {
+ Dimension thisDimension = (Dimension)thisStructure;
+ thisDimension.setParentElement(myElement);
+ count = thisDimension.getChildCount();
+ }
+ else
+ count = thisStructure.getElement()==null?0:1;
+
+ int total = thisStructure.getModel().getMinOccurs();
+ //if (total == 0) total++;
+ for (int i = count;i<total;i++) {
+ myElement.appendChild(thisStructure.initNew(parentDoc));
+ }
+ }
+ }
+
+ public Element initNew(Document parent) {
+ Logger.msg(6, "Creating DR "+model.getName());
+ if (deferred) activate();
+
+ // make a new Element
+ myElement = parent.createElement(model.getName());
+ // populate
+ for (Iterator e=order.iterator(); e.hasNext();) {
+ String structureName = (String)e.next();
+ OutcomeStructure thisStructure = (OutcomeStructure)subStructure.get(structureName);
+ if (thisStructure instanceof Dimension)
+ ((Dimension)thisStructure).setParentElement(myElement);
+ int count = 0;
+ while (count < thisStructure.getModel().getMinOccurs()) {
+ myElement.appendChild(thisStructure.initNew(parent));
+ count++;
+ }
+ }
+
+ // set up attributes
+ myAttributes.initNew(myElement);
+
+ return myElement;
+
+ }
+
+ public void stateChanged(ChangeEvent e) {
+ JTabbedPane targetPane = (JTabbedPane)e.getSource();
+ DataRecord targetTab = (DataRecord)targetPane.getSelectedComponent();
+ if (targetTab == this) {
+ helpPane.setHelp(getName(), getHelp());
+ if (deferred) SwingUtilities.invokeLater(
+ new Thread(new Runnable() {
+ public void run() {
+ activate();
+ }
+ }
+ ));
+ }
+ }
+
+ /**
+ * sets focus to first editable child
+ */
+ public void grabFocus() {
+ if (myAttributes.attrSet.size() > 0)
+ myAttributes.grabFocus();
+ else if (order.size()> 0)
+ ((OutcomeStructure)subStructure.get(order.get(0))).grabFocus();
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/form/Dimension.java b/source/com/c2kernel/gui/tabs/outcome/form/Dimension.java
new file mode 100755
index 0000000..8dfa7f5
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/form/Dimension.java
@@ -0,0 +1,377 @@
+package com.c2kernel.gui.tabs.outcome.form;
+import java.awt.*;
+import java.awt.FlowLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import javax.swing.*;
+import javax.swing.border.EtchedBorder;
+import javax.swing.table.JTableHeader;
+
+import org.exolab.castor.xml.schema.ElementDecl;
+import org.exolab.castor.xml.schema.Particle;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import com.c2kernel.gui.DomainKeyConsumer;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.utils.Logger;
+
+public class Dimension extends OutcomeStructure implements ActionListener {
+
+ DimensionTableModel tableModel;
+ Element parent;
+ GridBagConstraints position;
+ GridBagLayout gridbag;
+ JTabbedPane tabs;
+ JLabel msg;
+ DomKeyPushTable table;
+ Box tableBox;
+ ArrayList instances = new ArrayList(); // stores DimensionInstances if tabs
+ ArrayList elements = new ArrayList(); // stores current children
+
+ JButton addButton;
+ JButton delButton;
+
+ short mode;
+ protected static final short TABLE = 1;
+ protected static final short TABS = 2;
+
+
+ public Dimension(ElementDecl model, boolean readOnly, HelpPane help) {
+ super(model, readOnly, help);
+ // set up panel
+ gridbag = new java.awt.GridBagLayout();
+ setLayout(gridbag);
+ position = new GridBagConstraints();
+ position.anchor = GridBagConstraints.NORTHWEST;
+ position.fill = GridBagConstraints.HORIZONTAL;
+ position.weightx = 1.0; position.weighty = 0.0;
+ position.gridx = 0; position.gridy = 0;
+ position.ipadx = 0; position.ipady = 0;
+ position.insets = new Insets(0,0,0,0);
+
+ // TODO: an element or attribute of the dimension can be flagged as an index, so it can be used as a title for a tab
+
+ // set up the border
+ setBorder(BorderFactory.createTitledBorder(
+ BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), model.getName()));
+
+ msg = new JLabel("No elements");
+ msg.setFont(new Font("SansSerif", Font.ITALIC, msg.getFont().getSize()));
+ gridbag.setConstraints(msg, position);
+ add(msg);
+ position.gridy++;
+
+ // decide whether a table or tabs
+ try {
+ tableModel = new DimensionTableModel(model, readOnly);
+ Logger.msg(8, "DIM "+model.getName()+" - Will be a table");
+ mode = TABLE;
+ tableBox = Box.createVerticalBox();
+ table = new DomKeyPushTable(tableModel, this);
+ new MultiLinePasteAdapter(table, this);
+ if (readOnly) table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
+ table.setColumnSelectionAllowed(readOnly);
+ JTableHeader tableHeader = table.getTableHeader();
+ tableHeader.setReorderingAllowed(false);
+ tableBox.add(tableHeader);
+ tableBox.add(table);
+ gridbag.setConstraints(tableBox, position);
+ add(tableBox);
+ tableBox.setVisible(false);
+
+ } catch (StructuralException e) {
+ // use tabs
+ Logger.msg(8, "DIM "+model.getName()+" - Will be tabs: "+e.getMessage());
+ mode = TABS;
+ tabs = new JTabbedPane();
+ gridbag.setConstraints(tabs, position);
+ add(tabs);
+ tabs.setVisible(false);
+ }
+ if (!readOnly) {
+ JPanel rowAdjust = new JPanel(new FlowLayout());
+ addButton = new JButton("+");
+ addButton.setActionCommand("add");
+ addButton.addActionListener(this);
+ rowAdjust.add(addButton);
+
+ delButton = new JButton("-");
+ delButton.setActionCommand("del");
+ delButton.addActionListener(this);
+ delButton.setEnabled(false);
+ rowAdjust.add(delButton);
+
+
+ position.gridy++; position.weighty=0; position.weightx=0;
+ gridbag.setConstraints(rowAdjust, position);
+ this.add(rowAdjust);
+ }
+
+ }
+
+ public void setParentElement(Element parent) {
+ this.parent = parent;
+ }
+
+ public void addInstance(Element myElement, Document parentDoc) throws OutcomeException {
+ if (Logger.doLog(6))
+ Logger.msg(6, "DIM - adding instance "+ (elements.size()+1) +" for "+myElement.getTagName());
+ if (parent == null) setParentElement((Element)myElement.getParentNode());
+ // if table, pass to table model
+ if (mode == TABLE) {
+ tableModel.addInstance(myElement, -1);
+ elements.add(myElement);
+ }
+ else {
+ DimensionInstance target;
+ elements.add(myElement);
+ if (instances.size() < elements.size())
+ target = newInstance();
+ else
+ target = (DimensionInstance)instances.get(elements.size()-1);
+ target.addInstance(myElement, parentDoc);
+ }
+ checkButtons();
+ }
+
+ public int getChildCount() {
+ return elements.size();
+ }
+
+ public DimensionInstance newInstance() {
+ DimensionInstance newInstance = null;
+ try {
+ newInstance = new DimensionInstance(model, readOnly, helpPane, deferChild);
+ instances.add(newInstance);
+ newInstance.setTabNumber(instances.size());
+ newInstance.setParent(this);
+ deferChild = true;
+ tabs.addTab(newInstance.getName(), newInstance);
+ tabs.addChangeListener(newInstance);
+ } catch (OutcomeException e) {
+ // shouldn't happen, we've already done it once
+ Logger.error(e);
+ }
+ return newInstance;
+ }
+
+ public String validateStructure() {
+ if (mode == TABLE)
+ return table.validateStructure();
+ else {
+ StringBuffer errors = new StringBuffer();
+ for (Iterator iter = instances.iterator(); iter.hasNext();) {
+ OutcomeStructure element = (OutcomeStructure)iter.next();
+ errors.append(element.validateStructure());
+ }
+ return errors.toString();
+ }
+ }
+
+ public void checkButtons() {
+ // check if data visible
+ boolean dataVisible = elements.size() > 0;
+ if (mode == TABS) tabs.setVisible(dataVisible);
+ else tableBox.setVisible(dataVisible);
+ msg.setVisible(!dataVisible);
+
+ if (readOnly) return;
+
+ if (elements.size() <= model.getMinOccurs() || elements.size() == 0) {
+ delButton.setEnabled(false);
+ delButton.setToolTipText("Minimum row count of "+model.getMinOccurs()+" reached.");
+ } else {
+ delButton.setEnabled(true);
+ delButton.setToolTipText(null);
+ }
+
+ if (elements.size() < model.getMaxOccurs() || model.getMaxOccurs() == Particle.UNBOUNDED) {
+ addButton.setEnabled(true);
+ addButton.setToolTipText(null);
+ } else {
+ addButton.setEnabled(false);
+ addButton.setToolTipText("Maximum row count of "+model.getMaxOccurs()+" reached.");
+ }
+ }
+
+ public Element initNew(Document parent) {
+ Element newElement;
+
+ if (mode == TABLE) {
+ newElement = tableModel.initNew(parent, -1);
+ elements.add(newElement);
+ checkButtons();
+ return newElement;
+ }
+ else {
+ DimensionInstance newTab = null;
+ if (instances.size() < elements.size()+1)
+ newTab = newInstance();
+ else
+ newTab = (DimensionInstance)instances.get(elements.size()-1);
+ newElement = newTab.initNew(parent);
+ elements.add(newElement);
+ checkButtons();
+ return newElement;
+ }
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ int index;
+ if (mode == TABS) index = tabs.getSelectedIndex();
+ else {
+ index = table.getSelectedRow();
+ if (index == -1) index = tableModel.getRowCount();
+ }
+ try {
+ if (table == null || table.getCellEditor() == null || table.getCellEditor().stopCellEditing()) {
+ if (e.getActionCommand().equals("add"))
+ addRow(index);
+ else if (e.getActionCommand().equals("del"))
+ removeRow(index);
+ }
+ } catch (CardinalException ex) {
+ JOptionPane.showMessageDialog(null, ex.getMessage(), "Table error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+ public void addRow(int index) throws CardinalException {
+ if (elements.size() == model.getMaxOccurs())
+ throw new CardinalException("Maximum size of table reached");
+
+ if (mode == TABLE) {
+ Element newRow = tableModel.initNew(parent.getOwnerDocument(), index);
+ elements.add(index, newRow);
+ try {
+ Element following = (Element)elements.get(index+1);
+ parent.insertBefore(newRow, following);
+ } catch (IndexOutOfBoundsException ex) {
+ parent.appendChild(newRow);
+ }
+ table.clearSelection();
+ table.setRowSelectionInterval(index, index);
+ }
+ else {
+ Element newTab = initNew(parent.getOwnerDocument());
+ parent.appendChild(newTab);
+ }
+ checkButtons();
+
+ }
+
+ public void removeRow(int index) throws CardinalException {
+ if (elements.size() <= model.getMinOccurs())
+ throw new CardinalException("Minimum size of table reached");
+ if (mode == TABLE) {
+ parent.removeChild(tableModel.removeRow(index));
+ int selectRow = index;
+ if (index >= tableModel.getRowCount()) selectRow--;
+ if (tableModel.getRowCount() > 0) {
+ table.clearSelection();
+ table.setRowSelectionInterval(selectRow, selectRow);
+ }
+ }
+ else {
+ Element elementToGo = (Element)elements.get(index);
+ parent.removeChild(elementToGo);
+ instances.remove(index);
+ tabs.remove(index);
+ for (int i = index; i<instances.size(); i++) {
+ DimensionInstance thisInstance = (DimensionInstance)instances.get(i);
+ thisInstance.setTabNumber(i+1);
+ tabs.setTitleAt(i, thisInstance.getName());
+ }
+ }
+ elements.remove(index);
+ checkButtons();
+ }
+
+ private class DomKeyPushTable extends JTable implements DomainKeyConsumer, FocusListener {
+
+ Dimension dim;
+ public DomKeyPushTable(DimensionTableModel model, Dimension parent) {
+ super(model);
+ addFocusListener(this);
+ this.dim = parent;
+ }
+
+ public void push(DomainPath key) {
+ push(key.getName());
+ }
+
+ public void push(String name) {
+ int col = getSelectedColumn();
+ int row = getSelectedRow();
+ if (cellEditor != null)
+ cellEditor.stopCellEditing();
+ Logger.msg(8, "Pushing "+name+" to table at "+row+","+col);
+ if (col > -1 && row > -1) {
+ if (dataModel.getValueAt(row, col).toString().length()==0)
+ dataModel.setValueAt(name, row, col);
+ else {
+ if (row+1 == getRowCount()) {
+ try {
+ dim.addRow(row+1);
+ dataModel.setValueAt(name, row+1, col);
+ } catch (CardinalException ex) {
+ JOptionPane.showMessageDialog(null, ex.getMessage(), "Table error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+ if (row+1 < getRowCount()) {
+ Logger.msg(8, "Shifting selection to row "+(row+1));
+ changeSelection(row+1, col, false, false);
+ }
+ }
+ }
+
+ public void focusGained(FocusEvent e) {
+ if (!readOnly)
+ MainFrame.itemFinder.setConsumer(this, "Insert");
+ }
+
+ public void focusLost(FocusEvent e) {
+ // release the itemFinder
+ if (!readOnly)
+ MainFrame.itemFinder.clearConsumer(this);
+ }
+
+ public String validateStructure() {
+ if (cellEditor != null)
+ cellEditor.stopCellEditing();
+ return null;
+ }
+
+ public void changeSelection( int rowIndex, int columnIndex, boolean toggle, boolean extend) {
+ super.changeSelection(rowIndex, columnIndex, toggle, extend);
+ DimensionTableModel dimModel = (DimensionTableModel)dataModel;
+ helpPane.setHelp(dimModel.getColumnName(columnIndex), dimModel.getHelp(columnIndex));
+ }
+
+ }
+
+ public void grabFocus() {
+ if (mode == TABLE) {
+ if (table.getSelectedRow() == -1 && table.getRowCount() > 0) {
+ table.changeSelection(0, 0, false, false);
+ table.editCellAt(0,0);
+ }
+ table.requestFocus();
+ }
+ else if (instances.size()> 0)
+ ((DimensionInstance)instances.get(0)).grabFocus();
+ }
+
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/form/DimensionInstance.java b/source/com/c2kernel/gui/tabs/outcome/form/DimensionInstance.java
new file mode 100755
index 0000000..07fbe1b
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/form/DimensionInstance.java
@@ -0,0 +1,32 @@
+package com.c2kernel.gui.tabs.outcome.form;
+import org.exolab.castor.xml.schema.ElementDecl;
+
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+
+public class DimensionInstance extends DataRecord {
+
+ //probably will be needed to synch edits later
+ Dimension parentDimension;
+ int tabNumber;
+ String tabName = null;
+
+ public DimensionInstance(ElementDecl model, boolean readOnly , HelpPane help, boolean deferred) throws OutcomeException {
+ super(model, readOnly, help, deferred);
+ }
+
+ public void setTabNumber(int tabNumber) {
+ this.tabNumber=tabNumber;
+ }
+
+ public void setParent(Dimension parent) {
+ this.parentDimension = parent;
+ }
+
+ public String getName() {
+ //TODO appinfo for picking out attributes or child elements for tab name
+ if (tabName == null)
+ return Integer.toString(tabNumber);
+ else
+ return tabName;
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/form/DimensionTableModel.java b/source/com/c2kernel/gui/tabs/outcome/form/DimensionTableModel.java
new file mode 100755
index 0000000..b19c1d2
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/form/DimensionTableModel.java
@@ -0,0 +1,308 @@
+package com.c2kernel.gui.tabs.outcome.form;
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+import javax.swing.table.AbstractTableModel;
+
+import org.exolab.castor.xml.schema.*;
+import org.w3c.dom.*;
+
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+
+public class DimensionTableModel extends AbstractTableModel {
+
+ ElementDecl model;
+ ArrayList columnHeadings = new ArrayList();
+ ArrayList columnClasses = new ArrayList();
+ ArrayList columnDecls = new ArrayList();
+ ArrayList colReadOnly = new ArrayList();
+ ArrayList colHelp = new ArrayList();
+ ArrayList rows = new ArrayList();
+ ArrayList elements = new ArrayList();
+ boolean readOnly;
+
+ public DimensionTableModel(ElementDecl model, boolean readOnly) throws StructuralException {
+ XMLType modelContent = model.getType();
+
+ this.model = model;
+ this.readOnly = readOnly;
+ // use text node for simple types
+ if (modelContent.isSimpleType()) {
+ SimpleType elementType = (SimpleType)modelContent;
+ SimpleType baseType = elementType.getBuiltInBaseType();
+ addColumn(model.getName(), baseType, baseType.getTypeCode(), new Boolean(model.getFixedValue() != null));
+ }
+ else if (modelContent.isComplexType()) { // if complex type, process child elements
+ ComplexType elementType = (ComplexType)modelContent;
+
+ // find out if a CDATA type is used for this complex type
+ XMLType baseType = elementType.getBaseType();
+ while (!(baseType instanceof SimpleType) && baseType != null) {
+ baseType = baseType.getBaseType();
+ }
+ if (baseType != null) {
+ int typeCode = ((SimpleType)baseType).getTypeCode();
+ addColumn(model.getName(), baseType, typeCode, new Boolean(model.getFixedValue() != null));
+ }
+ // process attributes
+ for (Enumeration e = elementType.getAttributeDecls(); e.hasMoreElements();) {
+ AttributeDecl thisAttr = (AttributeDecl)e.nextElement();
+ addColumn(thisAttr.getName(), thisAttr, thisAttr.getSimpleType().getTypeCode(), new Boolean(thisAttr.isFixed()));
+ }
+
+ // enumerate child elements
+ enumerateElements(elementType);
+ }
+ }
+
+ public synchronized void addColumn(String heading, Annotated decl, int typeCode, Boolean readOnly) {
+ Logger.msg(8, "Column "+heading+" contains "+decl.getClass().getName()+" readOnly="+readOnly.toString());
+ columnHeadings.add(heading);
+ columnDecls.add(decl);
+ columnClasses.add(OutcomeStructure.getJavaClass(typeCode));
+ colReadOnly.add(readOnly);
+
+ // read help
+ String helpText;
+ if (decl instanceof SimpleType)
+ helpText = OutcomeStructure.extractHelp(model);
+ else
+ helpText = OutcomeStructure.extractHelp(decl);
+
+ if (helpText.length() == 0)
+ helpText = "<i>"+Language.translate("No help is available for this cell")+"</i>";
+
+ colHelp.add(helpText);
+
+ }
+
+
+ public void enumerateElements(ContentModelGroup group) throws StructuralException {
+ for (Enumeration childElements = group.enumerate(); childElements.hasMoreElements(); ) {
+ Particle thisParticle = (Particle)childElements.nextElement();
+ String extraHeader = "";
+ if (thisParticle instanceof Group) {
+ Group thisGroup = (Group)thisParticle;
+ Order order = thisGroup.getOrder();
+ if (order == Order.sequence || order == Order.all)
+ enumerateElements(thisGroup);
+ else // we only support sequences in data structures such as these
+ throw new StructuralException("Element "+thisGroup.getName()+". Expecting sequence or all. Got "+thisGroup.getOrder());
+ }
+ else if (thisParticle instanceof ElementDecl) {
+ ElementDecl thisElement = (ElementDecl)thisParticle;
+ int typeCode = SimpleTypesFactory.INVALID_TYPE;
+ //make sure not too complex
+ if (thisElement.getType() != null) {
+ if (thisElement.getType().isComplexType()) {
+ ComplexType elementType = (ComplexType)thisElement.getType();
+ if (elementType.getParticleCount() > 0 ||
+ thisElement.getMaxOccurs() > 1)
+ throw new StructuralException("Too deep for a table");
+ for (Enumeration attrs = elementType.getAttributeDecls(); attrs.hasMoreElements();) {
+ AttributeDecl thisAttr = (AttributeDecl)attrs.nextElement();
+ if (!thisAttr.isFixed())
+ throw new StructuralException("Non-fixed attributes of child elements not supported in tables.");
+ else
+ extraHeader=extraHeader+" ("+thisAttr.getName()+":"+(thisAttr.getFixedValue()!=null?thisAttr.getFixedValue():thisAttr.getDefaultValue())+")";
+ }
+ // find type
+ XMLType parentType = thisElement.getType();
+ while (!(parentType instanceof SimpleType) && parentType != null) {
+ parentType = parentType.getBaseType();
+ if (parentType != null) typeCode = ((SimpleType)parentType).getTypeCode();
+ }
+ }
+ else
+ typeCode = ((SimpleType)thisElement.getType()).getTypeCode();
+ }
+
+ //add to list
+ addColumn(thisElement.getName()+extraHeader, thisElement, typeCode, new Boolean(thisElement.getFixedValue() != null));
+ }
+ else throw new StructuralException("Particle "+thisParticle.getClass()+" not implemented");
+ }
+ }
+
+ public void addInstance(Element myElement, int index) throws OutcomeException {
+ if (index == -1) index = elements.size();
+ Object[] newRow = new Object[columnHeadings.size()];
+ for (int i=0; i<columnDecls.size(); i++) {
+ if (columnDecls.get(i) instanceof ElementDecl) { // sub element - get the node from it
+ ElementDecl thisElementDecl = (ElementDecl)columnDecls.get(i);
+ NodeList childElements = myElement.getElementsByTagName(thisElementDecl.getName());
+ switch (childElements.getLength()) {
+ case 1: // element exists - read the contents
+ Element childElement = (Element)childElements.item(0);
+ if (childElement.hasChildNodes()) {
+ Node thisNode = childElement.getFirstChild();
+ if (thisNode.getNodeType() == Node.TEXT_NODE)
+ newRow[i] = OutcomeStructure.getTypedValue(((Text)thisNode).getData(), (Class)columnClasses.get(i));
+ else
+ throw new StructuralException("First child of Field " + thisElementDecl.getName() + " was not Text. (NodeType:"+thisNode.getNodeType()+")");
+ }
+ else { // create text node
+ newRow[i] = this.setupDefaultElement(thisElementDecl, childElement, (Class)columnClasses.get(i));
+ }
+ break;
+ case 0: // element is missing - create it
+ Element newElement = myElement.getOwnerDocument().createElement(thisElementDecl.getName());
+ myElement.appendChild(newElement); //TODO: not in the right place in sequence. should insert it
+ newRow[i] = setupDefaultElement(thisElementDecl, newElement, (Class)columnClasses.get(i));
+ break;
+ default:
+ throw new CardinalException("Element "+thisElementDecl.getName()+" appeared more than once.");
+ }
+ }
+ else if (columnDecls.get(i) instanceof AttributeDecl) { //attribute
+ AttributeDecl thisAttrDecl = (AttributeDecl)columnDecls.get(i);
+ newRow[i] = OutcomeStructure.getTypedValue(myElement.getAttribute(thisAttrDecl.getName()), (Class)columnClasses.get(i));
+ }
+ else { // first child node
+ Node thisNode = myElement.getFirstChild();
+ if (thisNode == null) {
+ thisNode = myElement.getOwnerDocument().createTextNode("");
+ myElement.appendChild(thisNode);
+ }
+ if (thisNode.getNodeType() == Node.TEXT_NODE || thisNode.getNodeType() == Node.CDATA_SECTION_NODE)
+ newRow[i] = OutcomeStructure.getTypedValue(((Text)thisNode).getData(), (Class)columnClasses.get(i));
+ else
+ throw new StructuralException("First child of Column " + myElement.getTagName() + " was not Text");
+ }
+ }
+ elements.add(index, myElement);
+ rows.add(index, newRow);
+ fireTableRowsInserted(index, index);
+ }
+ public Class getColumnClass(int columnIndex) {
+ return (Class)columnClasses.get(columnIndex);
+ }
+
+ public String getColumnName(int columnIndex) {
+ return (String)columnHeadings.get(columnIndex);
+ }
+
+ public int getRowCount() {
+ return rows.size();
+ }
+
+ public int getColumnCount() {
+ return columnHeadings.size();
+ }
+
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ boolean isReadOnly = readOnly || ((Boolean)colReadOnly.get(columnIndex)).booleanValue();
+ return !isReadOnly;
+ }
+
+ public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+ Object[] thisRow = (Object[])rows.get(rowIndex);
+ thisRow[columnIndex]=aValue;
+ Element myElement = (Element)elements.get(rowIndex);
+ // update node
+ if (columnDecls.get(columnIndex) instanceof ElementDecl) { // sub element
+ ElementDecl thisDecl = (ElementDecl)columnDecls.get(columnIndex);
+ NodeList childElements = myElement.getElementsByTagName(thisDecl.getName());
+ // depend on one element with a Text child - this should have been enforced on init.
+ Text childNode = (Text)(childElements.item(0).getFirstChild());
+ childNode.setData(aValue.toString());
+ }
+ else if (columnDecls.get(columnIndex) instanceof AttributeDecl) { //attribute
+ AttributeDecl thisDecl = (AttributeDecl) columnDecls.get(columnIndex);
+ myElement.setAttribute(thisDecl.getName(), aValue.toString());
+ }
+ else { // first child node
+ Text textNode = (Text)myElement.getFirstChild();
+ textNode.setData(aValue.toString());
+ }
+ fireTableCellUpdated(rowIndex, columnIndex);
+ }
+
+ public Element removeRow(int rowIndex) {
+ Element elementToGo = (Element)elements.get(rowIndex);
+ elements.remove(rowIndex);
+ rows.remove(rowIndex);
+ fireTableRowsDeleted(rowIndex,rowIndex);
+ return elementToGo;
+ }
+
+ public Object setupDefaultElement(ElementDecl thisDecl, Element parent, Class type) {
+ Object newValue;
+ String defaultValue = thisDecl.getFixedValue();
+ if (defaultValue == null)
+ defaultValue = thisDecl.getDefaultValue();
+ if (readOnly)
+ newValue = "";
+ else
+ newValue = OutcomeStructure.getTypedValue(defaultValue, type);
+
+ Text newNode = parent.getOwnerDocument().createTextNode(newValue.toString());
+ parent.appendChild(newNode);
+ // fixed attributes
+ try {
+ ComplexType content = (ComplexType)thisDecl.getType();
+ for (Enumeration attrs = content.getAttributeDecls(); attrs.hasMoreElements();) {
+ AttributeDecl thisAttr = (AttributeDecl)attrs.nextElement();
+ parent.setAttribute(thisAttr.getName(), thisAttr.getFixedValue()!=null?thisAttr.getFixedValue():thisAttr.getDefaultValue());
+ }
+ } catch (ClassCastException ex) { } // only complex types have attributes
+ return newValue;
+ }
+
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ Object[] thisRow = (Object[])rows.get(rowIndex);
+ if (!(getColumnClass(columnIndex).equals(thisRow[columnIndex].getClass())))
+ Logger.warning(thisRow[columnIndex]+" should be "+getColumnClass(columnIndex)+" is a "+thisRow[columnIndex].getClass().getName());
+ return thisRow[columnIndex];
+ }
+
+ public String validateStructure() { // remove empty rows
+ for (int j=0; j < rows.size(); j++) {
+ Object[] elems = (Object[])rows.get(j);
+ boolean empty = true;
+ for (int i = 0; i < elems.length && empty; i++)
+ empty &= OutcomeStructure.isEmpty(elems[i]);
+ if (empty)
+ if (model.getMinOccurs() < rows.size())
+ removeRow(j);
+ else
+ return "Too many empty rows in table "+model.getName();
+ }
+ return null;
+ }
+
+ public Element initNew(Document parent, int index) {
+ if (index == -1) index = elements.size();
+ Object[] newRow = new Object[columnHeadings.size()];
+ Element myElement = parent.createElement(model.getName());
+ for (int i=0; i<columnDecls.size(); i++) {
+ if (columnDecls.get(i) instanceof ElementDecl) { // sub element
+ ElementDecl childElementDecl = (ElementDecl)columnDecls.get(i);
+ Element childElement = parent.createElement(childElementDecl.getName());
+ Object newValue = setupDefaultElement(childElementDecl, childElement, (Class)columnClasses.get(i));
+ myElement.appendChild(childElement);
+ newRow[i] = newValue;
+ }
+ else if (columnDecls.get(i) instanceof AttributeDecl) { //attribute
+ AttributeDecl thisAttrDecl = (AttributeDecl)columnDecls.get(i);
+ String newValue = thisAttrDecl.getFixedValue()!=null?thisAttrDecl.getFixedValue():thisAttrDecl.getDefaultValue();
+ newRow[i] = OutcomeStructure.getTypedValue(newValue, (Class)columnClasses.get(i));
+ myElement.setAttribute(thisAttrDecl.getName(), newRow[i].toString());
+ }
+ else { // first child node
+ newRow[i] = setupDefaultElement(model, myElement, (Class)columnClasses.get(i));
+ }
+ }
+ elements.add(index,myElement);
+ rows.add(index, newRow);
+ fireTableRowsInserted(index,index);
+ return myElement;
+ }
+
+ public String getHelp(int i) {
+ return (String)colHelp.get(i);
+ }
+
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/form/Field.java b/source/com/c2kernel/gui/tabs/outcome/form/Field.java
new file mode 100755
index 0000000..e1bc35c
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/form/Field.java
@@ -0,0 +1,137 @@
+package com.c2kernel.gui.tabs.outcome.form;
+import java.awt.Component;
+
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SwingConstants;
+
+import org.exolab.castor.xml.schema.ElementDecl;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Text;
+
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+import com.c2kernel.gui.tabs.outcome.form.field.StringEditField;
+import com.c2kernel.utils.Logger;
+
+
+public class Field extends OutcomeStructure {
+
+ StringEditField myElementPanel = null;
+ AttributeList myAttributes;
+ JLabel tagName;
+ Text textNode;
+ boolean fixed;
+ public static final JPanel nullPanel = new JPanel();
+
+ public Field(ElementDecl model, boolean readOnly, HelpPane helpPane) {
+ super(model, readOnly, helpPane);
+
+ try {
+ myElementPanel = StringEditField.getEditField(model);
+ Logger.msg(6, "Field type: "+myElementPanel.getClass().getName());
+ myElementPanel.setHelp(helpPane, help);
+ if (readOnly) myElementPanel.setEditable(false);
+
+ } catch (StructuralException e) { // no base type for field - only attributes
+ myElementPanel = null;
+ }
+
+ myAttributes = new AttributeList(model, readOnly, helpPane);
+
+ tagName = new JLabel(model.getName());
+ tagName.setVerticalAlignment(SwingConstants.BOTTOM);
+ }
+
+ public JComponent getLabel() {
+ return tagName;
+ }
+
+ public Component getCData() {
+ if (myElementPanel == null)
+ return nullPanel;
+ return myElementPanel.getControl();
+ }
+
+ public JComponent getAttributes() {
+ return myAttributes;
+ }
+
+ public void addStructure(OutcomeStructure newElement) throws StructuralException {
+ throw new StructuralException("Field "+model.getName()+" cannot have child structures");
+ }
+
+ public void addInstance(Element myElement, Document parentDoc) throws OutcomeException {
+ Logger.msg(6, "Accepting Field "+myElement.getTagName());
+ if (this.myElement != null) throw new CardinalException("Field "+this.getName()+" cannot repeat");
+ this.myElement = myElement;
+
+ try {
+ if (myElementPanel == null)
+ Logger.error("Field should be empty. Discarding contents.");
+ else {
+ if (myElement.hasChildNodes())
+ textNode = (Text)myElement.getFirstChild();
+ else {
+ textNode = parentDoc.createTextNode(getDefaultValue());
+ myElement.appendChild(textNode);
+ }
+
+ myElementPanel.setData(textNode);
+ }
+ } catch (ClassCastException ex) {
+ throw new StructuralException("First child node of Field " + this.getName() + " was not Text: "+myElement.getFirstChild().getNodeType());
+ }
+ myAttributes.setInstance(myElement);
+ }
+
+ // check if valid
+
+ public String validateStructure() {
+ myAttributes.validateAttributes();
+ if (myElementPanel != null) myElementPanel.updateNode();
+ Text contents = (Text)myElement.getFirstChild();
+ if (!myElement.hasAttributes() && model.getMinOccurs() < 1 &&
+ (contents == null || contents.getData().length() == 0))
+ // empty - should remove if optional
+ myElement.getParentNode().removeChild(myElement);
+ return null;
+ }
+
+ public Element initNew(Document parent) {
+ Logger.msg(6, "Creating Field "+this.getName());
+
+ // make a new Element
+ myElement = parent.createElement(this.getName());
+
+ // see if there is a default/fixed value
+ if (myElementPanel != null) {
+ // populate
+ String defaultVal = readOnly?"":getDefaultValue();
+ textNode = parent.createTextNode(defaultVal);
+ myElement.appendChild(textNode);
+ myElementPanel.setData(textNode);
+ }
+
+ // set up attributes
+ myAttributes.initNew(myElement);
+
+ return myElement;
+ }
+
+ private String getDefaultValue() {
+ String defaultValue = model.getFixedValue();
+ if (defaultValue == null) defaultValue = model.getDefaultValue();
+ if (defaultValue == null) defaultValue = myElementPanel.getDefaultValue();
+ return defaultValue;
+ }
+
+ public void grabFocus() {
+ if (myElementPanel != null)
+ myElementPanel.grabFocus();
+ else
+ myAttributes.grabFocus();
+ }
+
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/form/HelpPane.java b/source/com/c2kernel/gui/tabs/outcome/form/HelpPane.java
new file mode 100755
index 0000000..0f0f812
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/form/HelpPane.java
@@ -0,0 +1,55 @@
+package com.c2kernel.gui.tabs.outcome.form;
+
+import javax.swing.JEditorPane;
+import javax.swing.text.html.HTMLEditorKit;
+
+import com.c2kernel.utils.Language;
+
+/**************************************************************************
+ *
+ * $Revision: 1.3 $
+ * $Date: 2004/08/24 12:44:02 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class HelpPane extends JEditorPane {
+
+ public static final String header = "<h2><font color=\"blue\">"+Language.translate("Help")+"</font></h2>";
+
+ public HelpPane() {
+ super();
+ setEditable(false);
+ setEditorKit(new HTMLEditorKit());
+ setContentType("text/html");
+ setPreferredSize(new java.awt.Dimension(200,400));
+ }
+
+ public void setHelp(String title, String helpText) {
+ setText(header+"<h3>"+title+"</h3><br>"+toHTML(helpText));
+ }
+
+
+ /**
+ * Unfortunately JEditorPane will only display HTML3.2, whereas to embed HTML in an xsd we must
+ * use XHTML so it will be valid XML. This method does a quick and dirty removal of stuff that
+ * the JEditorPane cannot display
+ *
+ * @param xhtml
+ * @return
+ */
+ public static String toHTML(String xhtml) {
+ int startPos, endPos;
+ //remove xml header
+ while((startPos = xhtml.indexOf("<?")) != -1 &&
+ (endPos = xhtml.indexOf("?>")) != -1) {
+ xhtml = xhtml.substring(0,startPos)+xhtml.substring(endPos+2);
+ }
+ // remove slash in <tags/>
+ while ((startPos = xhtml.indexOf("/>")) != -1) {
+ xhtml = xhtml.substring(0, startPos)+xhtml.substring(startPos+1);
+ }
+ return xhtml;
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/form/MultiLinePasteAdapter.java b/source/com/c2kernel/gui/tabs/outcome/form/MultiLinePasteAdapter.java
new file mode 100755
index 0000000..d9f6b55
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/form/MultiLinePasteAdapter.java
@@ -0,0 +1,133 @@
+package com.c2kernel.gui.tabs.outcome.form;
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+
+import com.c2kernel.utils.Logger;
+
+import java.awt.datatransfer.*;
+import java.util.*;
+/**
+* ExcelAdapter enables Copy-Paste Clipboard functionality on JTables.
+* The clipboard data format used by the adapter is compatible with
+* the clipboard format used by Excel. This provides for clipboard
+* interoperability between enabled JTables and Excel.
+*/
+public class MultiLinePasteAdapter implements ActionListener {
+ private String rowstring, value;
+ private Clipboard system;
+ private StringSelection stsel;
+ private JTable jTable1;
+ private Dimension parent;
+ /**
+ * The Excel Adapter is constructed with a
+ * JTable on which it enables Copy-Paste and acts
+ * as a Clipboard listener.
+ */
+ public MultiLinePasteAdapter(JTable myJTable, Dimension parent) {
+ jTable1 = myJTable;
+ this.parent = parent;
+ KeyStroke copy =
+ KeyStroke.getKeyStroke(KeyEvent.VK_C, ActionEvent.CTRL_MASK, false);
+ // Identifying the copy KeyStroke user can modify this
+ // to copy on some other Key combination.
+ KeyStroke paste =
+ KeyStroke.getKeyStroke(KeyEvent.VK_V, ActionEvent.CTRL_MASK, false);
+ // Identifying the Paste KeyStroke user can modify this
+ //to copy on some other Key combination.
+ jTable1.registerKeyboardAction(
+ this,
+ "Copy",
+ copy,
+ JComponent.WHEN_FOCUSED);
+ jTable1.registerKeyboardAction(
+ this,
+ "Paste",
+ paste,
+ JComponent.WHEN_FOCUSED);
+ system = Toolkit.getDefaultToolkit().getSystemClipboard();
+ }
+ /**
+ * Public Accessor methods for the Table on which this adapter acts.
+ */
+ public JTable getJTable() {
+ return jTable1;
+ }
+ public void setJTable(JTable jTable1) {
+ this.jTable1 = jTable1;
+ }
+ /**
+ * This method is activated on the Keystrokes we are listening to
+ * in this implementation. Here it listens for Copy and Paste ActionCommands.
+ * Selections comprising non-adjacent cells result in invalid selection and
+ * then copy action cannot be performed.
+ * Paste is done by aligning the upper left corner of the selection with the
+ * 1st element in the current selection of the JTable.
+ */
+ public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand().compareTo("Copy") == 0) {
+ StringBuffer sbf = new StringBuffer();
+ // Check to ensure we have selected only a contiguous block of
+ // cells
+ int numcols = jTable1.getSelectedColumnCount();
+ int numrows = jTable1.getSelectedRowCount();
+ int[] rowsselected = jTable1.getSelectedRows();
+ int[] colsselected = jTable1.getSelectedColumns();
+ if (!((numrows - 1
+ == rowsselected[rowsselected.length - 1] - rowsselected[0]
+ && numrows == rowsselected.length)
+ && (numcols - 1
+ == colsselected[colsselected.length - 1] - colsselected[0]
+ && numcols == colsselected.length))) {
+ JOptionPane.showMessageDialog(
+ null,
+ "Invalid Copy Selection",
+ "Invalid Copy Selection",
+ JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ for (int i = 0; i < numrows; i++) {
+ for (int j = 0; j < numcols; j++) {
+ sbf.append(
+ jTable1.getValueAt(rowsselected[i], colsselected[j]));
+ if (j < numcols - 1)
+ sbf.append("\t");
+ }
+ sbf.append("\n");
+ }
+ stsel = new StringSelection(sbf.toString());
+ system = Toolkit.getDefaultToolkit().getSystemClipboard();
+ system.setContents(stsel, stsel);
+ }
+ if (e.getActionCommand().compareTo("Paste") == 0) {
+ Logger.msg(5, "Trying to Paste");
+ int startRow = (jTable1.getSelectedRows())[0];
+ int startCol = (jTable1.getSelectedColumns())[0];
+ try {
+ String trstring =
+ (String) (system.getContents(this).getTransferData(DataFlavor.stringFlavor));
+ Logger.msg(8, "String is:" + trstring);
+ StringTokenizer st1 = new StringTokenizer(trstring, "\n\r");
+ for (int i = 0; st1.hasMoreTokens(); i++) {
+ rowstring = st1.nextToken();
+ StringTokenizer st2 = new StringTokenizer(rowstring, "\t");
+ for (int j = 0; st2.hasMoreTokens(); j++) {
+ value = st2.nextToken();
+ if (startRow + i == jTable1.getRowCount())
+ parent.addRow(startRow+i);
+ if (startRow + i < jTable1.getRowCount()
+ && startCol + j < jTable1.getColumnCount())
+ jTable1.setValueAt(
+ value,
+ startRow + i,
+ startCol + j);
+ Logger.msg(5, "Putting "+value+" at row="+(startRow+i)+" column="+(startCol+j));
+ }
+ }
+ } catch (Exception ex) {
+ Logger.exceptionDialog(ex);
+ }
+
+ }
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/form/OutcomeEditor.java b/source/com/c2kernel/gui/tabs/outcome/form/OutcomeEditor.java
new file mode 100755
index 0000000..10c3542
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/form/OutcomeEditor.java
@@ -0,0 +1,214 @@
+package com.c2kernel.gui.tabs.outcome.form;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+
+import javax.swing.JButton;
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+
+import com.c2kernel.persistency.outcome.OutcomeValidator;
+import com.c2kernel.persistency.outcome.Schema;
+import com.c2kernel.utils.FileStringUtility;
+import com.c2kernel.utils.Logger;
+
+
+class OutcomeEditor extends JFrame implements ActionListener {
+
+ boolean readOnly = false;
+ File schemaFile = null;
+ File instanceFile = null;
+ JFileChooser chooser;
+ OutcomePanel outcome;
+ OutcomeValidator thisValid;
+
+ public OutcomeEditor(File schema, File instance, boolean readOnly) {
+ URL schemaURL = null;
+ URL instanceURL = null;
+ schemaFile = schema;
+ instanceFile = instance;
+ this.readOnly = readOnly;
+
+ try {
+ chooser = new JFileChooser();
+ chooser.setCurrentDirectory(new File(new File(".").getCanonicalPath()));
+ } catch (IOException e) {
+ System.out.println("Could not initialise file dialog");
+ System.exit(0);
+ }
+
+
+ this.setTitle("Outcome Editor");
+ GridBagLayout gridbag = new GridBagLayout();
+ getContentPane().setLayout(gridbag);
+
+ addWindowListener(
+ new java.awt.event.WindowAdapter() {
+ public void windowClosing(java.awt.event.WindowEvent evt) {
+ System.exit(0);
+ }
+ }
+ );
+ // select files if url is empty
+
+ if (schemaFile == null) { // prompt for schema
+ schemaFile = getFile("Choose Schema File", "xsd");
+ if (schemaFile == null) {
+ System.out.println("Cannot function without a schema");
+ System.exit(1);
+ }
+ }
+
+ try {
+ schemaURL = schemaFile.toURL();
+ } catch (Exception e) {
+ System.out.println("Invalid schema URL");
+ System.exit(1);
+ }
+
+ if (instanceFile == null) { // prompt for schema
+ instanceFile = getFile("Choose Instance File", "xml");
+ }
+
+ try {
+ instanceURL = instanceFile.toURL();
+ } catch (Exception e) { }
+
+ try {
+ if (instanceFile != null && instanceFile.exists())
+ outcome = new OutcomePanel(schemaURL, instanceURL, readOnly);
+ else
+ outcome = new OutcomePanel(schemaURL, readOnly);
+
+ Schema thisSchema = new Schema();
+ thisSchema.docType = schemaURL.getFile();
+ thisSchema.docVersion = -1;
+ thisSchema.schema = FileStringUtility.url2String(schemaURL);
+ thisValid = OutcomeValidator.getValidator(thisSchema);
+
+ } catch (Exception e) { e.printStackTrace(); System.exit(0);}
+
+
+ GridBagConstraints c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = 0;
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.fill = GridBagConstraints.BOTH;
+ c.weightx = 1.0; c.weighty = 1.0;
+ c.gridwidth = 2; c.ipadx = 5; c.ipady = 5;
+ gridbag.setConstraints(outcome, c);
+ this.getContentPane().add(outcome);
+
+ JButton saveButton = new JButton("Save");
+ saveButton.setActionCommand("save");
+ saveButton.addActionListener(this);
+ c.gridy++; c.weighty = 0; c.gridwidth = 1;
+ gridbag.setConstraints(saveButton, c);
+ this.getContentPane().add(saveButton);
+ if (readOnly) saveButton.setEnabled(false);
+
+ JButton saveAsButton = new JButton("Save As");
+ saveAsButton.setActionCommand("saveas");
+ saveAsButton.addActionListener(this);
+ c.gridx++; c.weighty = 0;
+ gridbag.setConstraints(saveAsButton, c);
+ this.getContentPane().add(saveAsButton);
+ if (readOnly) saveAsButton.setEnabled(false);
+ System.out.println("Building Outcome Panel. Please wait . . .");
+ outcome.run();
+ pack();
+ setVisible(true);
+ super.toFront();
+
+ }
+
+ public File getFile(String title, String fileType) {
+ File targetFile = null;
+ chooser.setFileFilter(new SimpleFilter(fileType));
+ chooser.setDialogTitle(title);
+ int returnVal = chooser.showDialog(this, "Select");
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ targetFile = chooser.getSelectedFile();
+ }
+ try {
+ System.out.println(fileType+"="+targetFile.toURL());
+ } catch (Exception ex) { }
+ return targetFile;
+ }
+
+ public static void usage() {
+ System.out.println("-schema file:///schema.xsd");
+ System.out.println("-inst file:///instance.xml");
+ System.out.println("Leave one out to get a file open box.");
+ System.exit(0);
+ }
+ public static void main( String[] argv ) {
+ Logger.addLogStream(System.out, 6);
+ File instance = null;
+ File schema = null;
+ boolean readOnly = false;
+ for (int i = 0; i < argv.length; i++) {
+ if (argv[i].equals("-schema"))
+ schema = new File(argv[++i]);
+ if (argv[i].equals("-inst"))
+ instance = new File(argv[++i]);
+ if (argv[i].equals("-readOnly"))
+ readOnly = true;
+ if (argv[i].equals("-help") || argv[i].equals("-h"))
+ usage();
+ }
+ new OutcomeEditor(schema, instance, readOnly);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand().indexOf("save") == 0) {
+ String output;
+ output = outcome.getOutcome();
+
+ String errors = thisValid.validate(output);
+ if (errors != null && errors.length() > 0) {
+ int choice = JOptionPane.showConfirmDialog(null, errors+"\n\nSave anyway?", "Errors validating document", JOptionPane.YES_NO_OPTION);
+ if (choice != JOptionPane.YES_OPTION)
+ return;
+ }
+
+ if (instanceFile == null || e.getActionCommand().equals("saveas")) {
+ instanceFile = getFile("Choose Instance File", "xml");
+ if (instanceFile == null) {
+ System.out.println(output);
+ return;
+ }
+ }
+ try {
+ FileOutputStream targetStream = new FileOutputStream(instanceFile);
+ targetStream.write(output.getBytes());
+ targetStream.close();
+ } catch (Exception ex) {ex.printStackTrace();}
+ }
+ }
+
+ private class SimpleFilter extends javax.swing.filechooser.FileFilter {
+ String extension;
+
+ public SimpleFilter(String extension) {
+ super();
+ this.extension = extension;
+ }
+
+ public String getDescription() {
+ return extension.toUpperCase()+" Files";
+ }
+
+ public boolean accept(File f) {
+ if ((f.isFile() && f.getName().endsWith(extension.toLowerCase())) || f.isDirectory()) {
+ return true;
+ }
+ return false;
+ }
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/form/OutcomePanel.java b/source/com/c2kernel/gui/tabs/outcome/form/OutcomePanel.java
new file mode 100755
index 0000000..4bb7347
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/form/OutcomePanel.java
@@ -0,0 +1,362 @@
+package com.c2kernel.gui.tabs.outcome.form;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.io.File;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.net.URL;
+import java.util.Enumeration;
+
+import javax.swing.Box;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTabbedPane;
+import javax.swing.JTextArea;
+import javax.swing.SwingConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.xml.serialize.Method;
+import org.apache.xml.serialize.OutputFormat;
+import org.apache.xml.serialize.XMLSerializer;
+import org.exolab.castor.xml.schema.ElementDecl;
+import org.exolab.castor.xml.schema.Schema;
+import org.exolab.castor.xml.schema.reader.SchemaReader;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.gui.tabs.outcome.InvalidOutcomeException;
+import com.c2kernel.gui.tabs.outcome.InvalidSchemaException;
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+import com.c2kernel.gui.tabs.outcome.OutcomeHandler;
+import com.c2kernel.gui.tabs.outcome.OutcomeNotInitialisedException;
+import com.c2kernel.utils.FileStringUtility;
+import com.c2kernel.utils.Logger;
+
+// will load the outcome as instructed by other bits of the gui
+// provides the 'save' button and creates the trees of objects to feed to the outcome form
+
+public class OutcomePanel extends JPanel implements OutcomeHandler
+{
+
+ Schema schemaSOM;
+ //ASModel schemaASModel;
+ Document outcomeDOM;
+ OutcomeStructure documentRoot;
+ DocumentBuilder parser;
+ boolean readOnly;
+ boolean useForm = true;
+ boolean panelBuilt = false;
+ boolean unsaved = false;
+ JScrollPane scrollpane = new JScrollPane();
+ HelpPane help = new HelpPane();
+
+ JTextArea basicView;
+
+ public OutcomePanel()
+ {
+ GridBagLayout gridbag = new java.awt.GridBagLayout();
+ setLayout(gridbag);
+
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setValidating(false);
+ dbf.setNamespaceAware(false);
+ try
+ {
+ parser = dbf.newDocumentBuilder();
+ }
+ catch (ParserConfigurationException e)
+ {
+ e.printStackTrace();
+ }
+
+ // Set up panel
+
+ JComponent pane;
+ if (!MainFrame.getPref("ShowHelp", "true").equals("true"))
+ pane = scrollpane;
+ else {
+ JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, scrollpane, help);
+ splitPane.setOneTouchExpandable(true);
+ splitPane.setDividerSize(9);
+ pane = splitPane;
+ }
+
+ GridBagConstraints c = new GridBagConstraints();
+
+ c.gridx = 0;
+ c.gridy = 0;
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.fill = GridBagConstraints.BOTH;
+ c.weightx = 1.0;
+ c.weighty = 1.0;
+ c.ipadx = 5;
+ c.ipady = 5;
+
+ gridbag.setConstraints(pane, c);
+ this.add(pane);
+ }
+
+ public OutcomePanel(boolean readOnly)
+ {
+ this();
+ setReadOnly(readOnly);
+ }
+
+ public OutcomePanel(String schema, boolean readOnly) throws OutcomeException
+ {
+ this(readOnly);
+ this.setDescription(schema);
+ }
+
+ public OutcomePanel(String schema, String outcome, boolean readOnly) throws OutcomeException
+ {
+ this(readOnly);
+ this.setDescription(schema);
+ this.setOutcome(outcome);
+ }
+
+ // Parse from URLS
+ public void setOutcome(URL outcomeURL) throws InvalidOutcomeException
+ {
+
+ try
+ {
+ setOutcome(new InputSource(outcomeURL.openStream()));
+ }
+ catch (IOException ex)
+ {
+ throw new InvalidOutcomeException("Error creating instance DOM tree: " + ex);
+ }
+ }
+
+ public void setDescription(URL schemaURL) throws InvalidSchemaException
+ {
+ Logger.msg(7, "OutcomePanel.setDescription() - schemaURL:" + schemaURL.toString());
+ try
+ {
+ setDescription(new InputSource(schemaURL.openStream()));
+ }
+ catch (IOException ex)
+ {
+ throw new InvalidSchemaException("Error creating exolab schema object: " + ex);
+ }
+
+ }
+
+ public OutcomePanel(URL schemaURL, boolean readOnly) throws OutcomeException
+ {
+ this(readOnly);
+ this.setDescription(schemaURL);
+ }
+
+ public OutcomePanel(URL schemaURL, URL outcomeURL, boolean readOnly) throws OutcomeException
+ {
+ this(readOnly);
+ this.setDescription(schemaURL);
+ this.setOutcome(outcomeURL);
+ }
+
+ // Parse from Strings
+ public void setOutcome(String outcome) throws InvalidOutcomeException
+ {
+
+ try
+ {
+ setOutcome(new InputSource(new StringReader(outcome)));
+ }
+ catch (IOException ex)
+ {
+ throw new InvalidOutcomeException("Error creating instance DOM tree: " + ex);
+ }
+ }
+
+ public void setDescription(String schema) throws InvalidSchemaException
+ {
+ if (schema == null)
+ throw new InvalidSchemaException("Null schema supplied");
+ try
+ {
+ setDescription(new InputSource(new StringReader(schema)));
+ }
+ catch (Exception ex)
+ {
+ Logger.error(ex);
+ }
+
+ }
+
+ public void setReadOnly(boolean readOnly)
+ {
+ this.readOnly = readOnly;
+ }
+
+ public void setDescription(InputSource schemaSource) throws InvalidSchemaException, IOException
+ {
+
+ SchemaReader mySchemaReader = new SchemaReader(schemaSource);
+ this.schemaSOM = mySchemaReader.read();
+ }
+
+ public void setOutcome(InputSource outcomeSource) throws InvalidOutcomeException, IOException
+ {
+ try
+ {
+ outcomeDOM = parser.parse(outcomeSource);
+ }
+ catch (SAXException ex)
+ {
+ throw new InvalidOutcomeException("Sax error parsing Outcome " + ex);
+ }
+ }
+
+ public void run()
+ {
+ Thread.currentThread().setName("Outcome Panel Builder");
+ try
+ {
+ makeDisplay();
+ }
+ catch (Exception oe)
+ {
+ scrollpane.setViewportView(new JLabel("Outcome View Generation Failed: " + oe.getMessage()));
+ Logger.error(oe);
+ }
+ }
+
+ public void makeDisplay()
+ {
+ try
+ {
+ initPanel();
+ }
+ catch (OutcomeException ex)
+ {
+ // something went wrong
+ useForm = false;
+ Box textPanel = Box.createVerticalBox();
+ JLabel errorMsg = new JLabel("Could not create outcome view: " + ex.getMessage());
+ errorMsg.setHorizontalAlignment(SwingConstants.LEFT);
+ textPanel.add(errorMsg);
+ textPanel.add(Box.createVerticalGlue());
+ if (outcomeDOM!=null) {
+ basicView = new JTextArea(serialize(outcomeDOM, true));
+ basicView.setEnabled(!readOnly);
+ textPanel.add(basicView);
+ }
+ scrollpane.setViewportView(textPanel);
+ }
+ }
+
+ public void initPanel() throws OutcomeException
+ {
+ Element docElement;
+ /*if (panelBuilt)
+ return;*/
+ Logger.msg(5, "Initialising Panel..");
+ scrollpane.setViewportView(new JLabel("Building outcome. Please hang on two ticks . . ."));
+ if (schemaSOM == null)
+ throw new InvalidSchemaException("A valid schema has not been supplied.");
+ // create root panel with element declaration and maybe root document element node
+
+ //find the root element declaration in the schema - may need to look for annotation??
+ ElementDecl rootElementDecl = null;
+ docElement = (outcomeDOM == null) ? null : outcomeDOM.getDocumentElement();
+
+ for (Enumeration globalElements = schemaSOM.getElementDecls(); globalElements.hasMoreElements();)
+ {
+ rootElementDecl = (ElementDecl) globalElements.nextElement();
+ // REVISIT: We don't detect which is the most likely root element if there is more than one root decl
+ // xmlspy looks for an element not referenced elsewhere. simple but hard
+ // if we already have a document then use its root element to find the right decl
+ if (docElement != null && docElement.getTagName().equals(rootElementDecl.getName()))
+ break;
+ }
+
+ if (rootElementDecl == null)
+ throw new InvalidSchemaException("No root elements defined");
+ documentRoot = new DataRecord(rootElementDecl, readOnly, help, false);
+
+ Logger.msg(5, "Finished structure. Populating...");
+ if (docElement == null)
+ {
+ outcomeDOM = parser.newDocument();
+ docElement = documentRoot.initNew(outcomeDOM);
+ outcomeDOM.appendChild(docElement);
+ }
+ else
+ documentRoot.addInstance(docElement, outcomeDOM);
+
+ // got a fully rendered Outcome! put it in the scrollpane
+ // initialise container panel
+
+ JTabbedPane outcomeTab = new JTabbedPane();
+ outcomeTab.addTab(rootElementDecl.getName(), documentRoot);
+ outcomeTab.setSelectedIndex(0);
+
+ scrollpane.setViewportView(outcomeTab);
+ panelBuilt = true;
+
+ revalidate();
+ doLayout();
+ if (!readOnly)
+ documentRoot.grabFocus();
+ }
+
+ public JPanel getPanel() throws OutcomeNotInitialisedException
+ {
+ return this;
+ }
+
+ public String getOutcome()
+ {
+ if (useForm)
+ {
+ documentRoot.validateStructure();
+ return serialize(outcomeDOM, false);
+ }
+ else
+ {
+ return basicView.getText();
+ }
+ }
+
+ static public String serialize(Document doc, boolean prettyPrint)
+ {
+ String serializedDoc = null;
+ OutputFormat format = new OutputFormat(Method.XML, null, prettyPrint);
+ StringWriter stringOut = new StringWriter();
+ XMLSerializer serial = new XMLSerializer(stringOut, format);
+ try
+ {
+ serial.asDOMSerializer();
+ serial.serialize(doc);
+ }
+ catch (java.io.IOException ex)
+ {
+ Logger.error(ex.toString());
+ }
+ serializedDoc = stringOut.toString();
+ return serializedDoc;
+ }
+
+ public boolean isUnsaved() {
+ return unsaved;
+ }
+
+ public void saved() {
+ unsaved = false;
+ }
+
+ public void export(File targetFile) throws Exception {
+ FileStringUtility.string2File(targetFile, getOutcome());
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/form/OutcomeStructure.java b/source/com/c2kernel/gui/tabs/outcome/form/OutcomeStructure.java
new file mode 100755
index 0000000..9333bf8
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/form/OutcomeStructure.java
@@ -0,0 +1,283 @@
+package com.c2kernel.gui.tabs.outcome.form;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import javax.swing.ImageIcon;
+import javax.swing.JPanel;
+
+import org.exolab.castor.types.AnyNode;
+import org.exolab.castor.xml.schema.Annotated;
+import org.exolab.castor.xml.schema.Annotation;
+import org.exolab.castor.xml.schema.ComplexType;
+import org.exolab.castor.xml.schema.ContentModelGroup;
+import org.exolab.castor.xml.schema.Documentation;
+import org.exolab.castor.xml.schema.ElementDecl;
+import org.exolab.castor.xml.schema.Group;
+import org.exolab.castor.xml.schema.ModelGroup;
+import org.exolab.castor.xml.schema.Order;
+import org.exolab.castor.xml.schema.Particle;
+import org.exolab.castor.xml.schema.SimpleType;
+import org.exolab.castor.xml.schema.SimpleTypesFactory;
+import org.exolab.castor.xml.schema.XMLType;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+
+// contains child outcome elements - creates new ones
+public abstract class OutcomeStructure extends JPanel {
+
+ ElementDecl model;
+ Element myElement = null;
+ boolean readOnly;
+ HashMap subStructure = new HashMap();
+ ArrayList order = new ArrayList();
+ String help = "<i>"+Language.translate("No help is available for this element")+"</i>";
+ HelpPane helpPane;
+ boolean deferChild = false;
+
+ public OutcomeStructure(ElementDecl model, boolean readOnly , HelpPane helpPane) {
+ this.model = model;
+ this.readOnly = readOnly;
+ this.helpPane = helpPane;
+ subStructure = new HashMap();
+ Logger.msg(8, "Creating " + model.getName() + " structure as " +
+ this.getClass().getName().substring(this.getClass().getName().lastIndexOf('.') + 1));
+
+ String doc = extractHelp(model);
+ if (doc.length() > 0) help = doc;
+ }
+
+ public boolean getReadOnly() {
+ return readOnly;
+ }
+ /** Contains the rules for deciding which OutcomeStructure will represent a chosen Element Declaration.
+ * In this order
+ * <ol>
+ * <li>if maxOccurs>1 then Dimension
+ * <li> SimpleTypes are Fields
+ * <li> No element children is a Field
+ * <li> Everything else is a DataRecord
+ * </ol>
+ */
+ public OutcomeStructure createStructure(ElementDecl model, boolean readOnly, HelpPane help) throws OutcomeException {
+ XMLType elementType = model.getType();
+ ComplexType elementComplexType;
+
+ if (model.getMaxOccurs() == 0) return null;
+
+ // if more than one can occur - dimension
+ if (model.getMaxOccurs() > 1
+ || model.getMaxOccurs() == Particle.UNBOUNDED
+ || model.getMinOccurs() == 0)
+ return new Dimension(model, readOnly, help);
+
+ // must have a type from now on
+ if (elementType == null)
+ throw new StructuralException("Element "+model.getName()+" is elementary yet has no type.");
+ // simple types will be fields
+ if (elementType instanceof SimpleType) return new Field(model, readOnly, help);
+
+ // otherwise is a complex type
+ try {
+ elementComplexType = (ComplexType)elementType;
+ }
+ catch (ClassCastException e) {
+ throw new StructuralException("Unknown XMLType for element " + model.getName());
+ }
+
+ //when no element children - field
+ if (elementComplexType.getParticleCount() == 0) return new Field(model, readOnly, help);
+
+ //everything else is a data record
+ return new DataRecord(model, readOnly, help, deferChild);
+ }
+
+ /** Extracts child Element declarations from a content group and recursively from any group
+ * (not Element) of that group. calls createStructure() to find the corresponding OutcomeStructure
+ * then adds it to this structure.
+ */
+ public void enumerateElements(ContentModelGroup group) throws OutcomeException {
+
+ // process base types first if complex type
+ //HACK: castor does not include elements from basetype, so we do it manually. if they fix it, this will duplicate child elements.
+ if (group instanceof ComplexType) {
+ XMLType base = ((ComplexType)group).getBaseType();
+ if (base instanceof ComplexType)
+ enumerateElements((ComplexType)base);
+ }
+
+ for (Enumeration elements = group.enumerate(); elements.hasMoreElements(); ) {
+ Particle thisParticle = (Particle)elements.nextElement();
+ if (thisParticle instanceof Group) {
+ Group thisGroup = (Group)thisParticle;
+ if (thisGroup instanceof ModelGroup) {
+ // HACK: Castor strangeness - model groups don't seem to resolve their own references. If fixed, this will still work
+ ModelGroup thisModel = (ModelGroup)thisGroup;
+ if (thisModel.hasReference()) thisGroup = thisModel.getReference();
+ }
+ Order thisOrder = thisGroup.getOrder();
+ if (thisOrder == Order.sequence || thisOrder == Order.all) enumerateElements(thisGroup);
+ else // we only support sequences in data structures such as these
+ throw new StructuralException("The '"+thisGroup.getOrder()+"' group is not supported");
+ }
+ else if (thisParticle instanceof ElementDecl) {
+ ElementDecl thisElement = (ElementDecl)thisParticle;
+ addStructure(createStructure(thisElement, readOnly, helpPane));
+ }
+ else throw new StructuralException("Particle " + thisParticle.getClass() + " not implemented");
+ }
+ }
+
+ /** Adds a generated OutcomeStructure as a child of this one. A separate structure as is often overridden.
+ */
+ public void addStructure(OutcomeStructure newElement) throws OutcomeException {
+ if (newElement == null) return;
+ subStructure.put(newElement.getName(), newElement);
+ order.add(newElement.getName());
+ }
+
+ /** After schema processing, addInstance() propogates the XML instance document down the layout.
+ * Most OutcomeStructures will throw an exception if called more than once, except Dimension, which is the only
+ * Outcome Structure to support maxOccurs>1
+ */
+ public abstract void addInstance(Element myElement, Document parentDoc) throws OutcomeException;
+
+ public Element getElement() {
+ return myElement;
+ }
+
+ public String getName() {
+ if (model == null) return null;
+ return model.getName();
+ }
+
+ public ElementDecl getModel() {
+ return model;
+ }
+
+ public String getHelp() {
+ return help;
+ }
+
+ public String validateStructure() {
+ StringBuffer errors = new StringBuffer();
+ for (Iterator iter = subStructure.values().iterator(); iter.hasNext();) {
+ OutcomeStructure element = (OutcomeStructure)iter.next();
+ errors.append(element.validateStructure());
+ }
+ return errors.toString();
+ }
+
+ public abstract Element initNew(Document parent);
+
+ public static String extractHelp(Annotated model) {
+ Enumeration e = model.getAnnotations();
+ StringBuffer doc = new StringBuffer();
+ if (e.hasMoreElements()) { // look for HTML
+ Annotation note = (Annotation)e.nextElement();
+ for (Enumeration g = note.getDocumentation(); g.hasMoreElements();) {
+ Documentation thisDoc = (Documentation)g.nextElement();
+ for (Enumeration h = thisDoc.getObjects(); h.hasMoreElements();) {
+ AnyNode node = (AnyNode)h.nextElement();
+ String line = node.toString();
+ if (line.length() == 0)
+ line = node.getStringValue();
+ if (line.length() > 0) {
+ doc.append(line).append("\n");
+ }
+ }
+ }
+ }
+
+ return doc.toString();
+ }
+
+ public abstract void grabFocus();
+
+ public static Class getJavaClass(int typeCode) {
+ switch (typeCode) {
+
+ // boolean
+ case SimpleTypesFactory.BOOLEAN_TYPE:
+ return Boolean.class;
+
+ // integers
+ case SimpleTypesFactory.INTEGER_TYPE:
+ case SimpleTypesFactory.NON_POSITIVE_INTEGER_TYPE:
+ case SimpleTypesFactory.NEGATIVE_INTEGER_TYPE:
+ case SimpleTypesFactory.NON_NEGATIVE_INTEGER_TYPE:
+ case SimpleTypesFactory.POSITIVE_INTEGER_TYPE:
+ case SimpleTypesFactory.INT_TYPE:
+ case SimpleTypesFactory.UNSIGNED_INT_TYPE:
+ case SimpleTypesFactory.SHORT_TYPE:
+ case SimpleTypesFactory.UNSIGNED_SHORT_TYPE:
+ case SimpleTypesFactory.LONG_TYPE:
+ case SimpleTypesFactory.UNSIGNED_LONG_TYPE:
+ case SimpleTypesFactory.BYTE_TYPE:
+ case SimpleTypesFactory.UNSIGNED_BYTE_TYPE:
+ return BigInteger.class;
+ // floats
+ case SimpleTypesFactory.FLOAT_TYPE:
+ case SimpleTypesFactory.DOUBLE_TYPE:
+ case SimpleTypesFactory.DECIMAL_TYPE:
+ return BigDecimal.class;
+
+ // images
+ case SimpleTypesFactory.BASE64BINARY_TYPE:
+ case SimpleTypesFactory.HEXBINARY_TYPE:
+ return ImageIcon.class;
+
+ // everything else is a string for now
+ default:
+ return String.class;
+ }
+ }
+
+ public static Object getTypedValue(String value, Class type) {
+ try {
+ if (type.equals(Boolean.class))
+ if (value == null || value.equals(""))
+ return Boolean.FALSE;
+ else
+ return Boolean.valueOf(value);
+ else if (type.equals(BigInteger.class))
+ if (value == null || value.equals(""))
+ return new BigInteger("0");
+ else
+ return new BigInteger(value);
+ else if (type.equals(BigDecimal.class))
+ if (value == null || value.equals(""))
+ return new BigDecimal(0);
+ else
+ return new BigDecimal(value);
+ } catch (Exception ex) {
+ Logger.error("Cannot convert value '"+value+"' to a "+type.getName());
+ }
+ return value==null?"":value;
+ }
+
+ public static boolean isEmpty(Object value) {
+ if (value == null) return true;
+
+ if (value instanceof String) {
+ if (((String)value).length() == 0) return true;
+ }
+ else if (value instanceof Boolean) {
+ if (((Boolean)value).booleanValue() == false) return true;
+ }
+ else if (value instanceof BigInteger) {
+ if (((BigInteger)value).intValue() == 0) return true;
+ }
+ else if (value instanceof BigDecimal) {
+ if (((BigDecimal)value).floatValue() == 0.0) return true;
+ }
+ return false;
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/form/StructuralException.java b/source/com/c2kernel/gui/tabs/outcome/form/StructuralException.java
new file mode 100755
index 0000000..5aff436
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/form/StructuralException.java
@@ -0,0 +1,12 @@
+package com.c2kernel.gui.tabs.outcome.form;
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+
+public class StructuralException extends OutcomeException {
+
+ public StructuralException() {
+ super();
+ }
+ public StructuralException(String ex) {
+ super(ex);
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/form/field/ArrayEditField.java b/source/com/c2kernel/gui/tabs/outcome/form/field/ArrayEditField.java
new file mode 100755
index 0000000..e7dc8bc
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/form/field/ArrayEditField.java
@@ -0,0 +1,166 @@
+package com.c2kernel.gui.tabs.outcome.form.field;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.text.JTextComponent;
+
+import org.exolab.castor.xml.schema.SimpleType;
+
+import com.c2kernel.utils.Language;
+
+/**************************************************************************
+ *
+ * $Revision: 1.7 $
+ * $Date: 2006/05/24 07:51:51 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class ArrayEditField extends StringEditField implements ActionListener {
+
+ Box arrayBox;
+ Box expandBox;
+ Box editBox;
+ JScrollPane arrayView;
+ JButton arrayButton;
+ JButton expandButton;
+ JButton contractButton;
+ JButton addButton;
+ JButton removeButton;
+ ArrayTableModel arrayModel;
+ JLabel arrayLabel = new JLabel("Array");
+ boolean panelShown = false;
+ boolean readOnly = false;
+
+ public ArrayEditField(SimpleType type) {
+ arrayBox = Box.createVerticalBox();
+ arrayBox.add(arrayLabel);
+ arrayButton = new JButton(Language.translate("Show"));
+ arrayButton.addActionListener(this);
+ arrayButton.setActionCommand("toggle");
+ arrayBox.add(arrayButton);
+
+ expandBox = Box.createHorizontalBox();
+ expandButton = new JButton(">>");
+ expandButton.setToolTipText("Increase the number of columns displaying this array");
+ expandButton.addActionListener(this);
+ expandButton.setActionCommand("extend");
+
+ contractButton = new JButton("<<");
+ contractButton.setToolTipText("Decrease the number of columns displaying this array");
+ contractButton.addActionListener(this);
+ contractButton.setActionCommand("contract");
+
+ expandBox.add(contractButton);
+ expandBox.add(Box.createHorizontalGlue());
+ expandBox.add(expandButton);
+
+ arrayModel = new ArrayTableModel(type);
+ if (arrayModel.getColumnCount() < 2) contractButton.setEnabled(false);
+ arrayView = new JScrollPane(new JTable(arrayModel));
+
+ editBox = Box.createHorizontalBox();
+ addButton = new JButton("+");
+ addButton.setToolTipText("Add a field to the end of this array");
+ addButton.addActionListener(this);
+ addButton.setActionCommand("add");
+ removeButton = new JButton("-");
+ removeButton.setToolTipText("Remove the last field from this array");
+ removeButton.addActionListener(this);
+ removeButton.setActionCommand("remove");
+ editBox.add(addButton);
+ editBox.add(Box.createHorizontalGlue());
+ editBox.add(removeButton);
+ }
+ /**
+ *
+ */
+ public String getDefaultValue() {
+ return "";
+ }
+ /**
+ *
+ */
+ public String getText() {
+ return arrayModel.getData();
+ }
+ /**
+ *
+ */
+ public void setText(String text) {
+ arrayModel.setData(text);
+ arrayLabel.setText("Array ("+arrayModel.getArrayLength()+" values)");
+ }
+ /**
+ *
+ */
+ public Component getControl() {
+ return arrayBox;
+ }
+ /**
+ *
+ */
+ public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand().equals("toggle")) {
+ arrayBox.removeAll();
+ if (panelShown) {
+ arrayBox.add(arrayLabel);
+ arrayBox.add(Box.createVerticalStrut(7));
+ arrayBox.add(arrayButton);
+ arrayButton.setText("Show");
+ }
+ else {
+ arrayBox.add(arrayLabel);
+ arrayBox.add(Box.createVerticalStrut(7));
+ arrayBox.add(arrayButton);
+ arrayBox.add(Box.createVerticalStrut(7));
+ arrayBox.add(expandBox);
+ arrayBox.add(Box.createVerticalStrut(7));
+ arrayBox.add(arrayView);
+ if (!readOnly) arrayBox.add(editBox);
+ arrayButton.setText("Hide");
+ }
+ panelShown = !panelShown;
+ arrayBox.validate();
+ }
+ else if (e.getActionCommand().equals("add")) {
+ arrayModel.addField();
+ arrayLabel.setText("Array ("+arrayModel.getArrayLength()+" values)");
+ }
+ else if (e.getActionCommand().equals("remove")) {
+ arrayModel.removeField();
+ arrayLabel.setText("Array ("+arrayModel.getArrayLength()+" values)");
+ }
+ else {
+ int currentCols = arrayModel.getColumnCount();
+ if (e.getActionCommand().equals("extend"))
+ currentCols++;
+ else if (e.getActionCommand().equals("contract"))
+ currentCols--;
+ arrayModel.setColumnCount(currentCols);
+ contractButton.setEnabled(currentCols > 1);
+ }
+
+ }
+
+ /**
+ *
+ */
+ public JTextComponent makeTextField() {
+ // not used by array
+ return null;
+ }
+ public void setEditable(boolean editable) {
+ readOnly = !editable;
+ arrayModel.setReadOnly(!readOnly);
+ }
+
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/form/field/ArrayTableModel.java b/source/com/c2kernel/gui/tabs/outcome/form/field/ArrayTableModel.java
new file mode 100755
index 0000000..0807f78
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/form/field/ArrayTableModel.java
@@ -0,0 +1,106 @@
+package com.c2kernel.gui.tabs.outcome.form.field;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+
+import javax.swing.table.AbstractTableModel;
+
+import org.exolab.castor.xml.schema.SimpleType;
+
+import com.c2kernel.gui.tabs.outcome.form.OutcomeStructure;
+import com.c2kernel.utils.Language;
+
+/**************************************************************************
+ *
+ * $Revision: 1.2 $
+ * $Date: 2006/05/24 07:51:53 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class ArrayTableModel extends AbstractTableModel {
+
+ ArrayList contents = new ArrayList();
+ Class type;
+ int numCols = 1;
+ boolean readOnly = false;
+
+ public ArrayTableModel(SimpleType type) {
+ super();
+ this.type = OutcomeStructure.getJavaClass(type.getTypeCode());
+ }
+
+ public void setReadOnly(boolean readOnly) {
+ this.readOnly = readOnly;
+ }
+
+ public void setData(String data) {
+ contents.clear();
+ StringTokenizer tok = new StringTokenizer(data);
+ while(tok.hasMoreTokens())
+ contents.add(OutcomeStructure.getTypedValue(tok.nextToken(), type));
+ fireTableStructureChanged();
+ }
+
+ public String getData() {
+ if (contents.size() == 0) return "";
+ Iterator iter = contents.iterator();
+ StringBuffer result = new StringBuffer(iter.next().toString());
+ while (iter.hasNext())
+ result.append(" ").append(iter.next().toString());
+ return result.toString();
+ }
+
+ public void addField() {
+ contents.add(OutcomeStructure.getTypedValue("", type));
+ fireTableStructureChanged();
+ }
+
+ public void removeField() {
+ contents.remove(contents.size()-1);
+ fireTableStructureChanged();
+ }
+
+ public Class getColumnClass(int columnIndex) {
+ return type;
+ }
+
+ public int getColumnCount() {
+ return numCols;
+ }
+
+ public int getArrayLength() {
+ return contents.size();
+ }
+
+ public void setColumnCount(int newCols) {
+ numCols = newCols;
+ fireTableStructureChanged();
+ }
+
+ public String getColumnName(int column) {
+ return Language.translate("Value");
+ }
+
+ public int getRowCount() {
+ return (contents.size()/numCols)+1;
+ }
+
+ public Object getValueAt(int arg0, int arg1) {
+ int index = arg1+(arg0 * numCols);
+ if (index >= contents.size())
+ return null;
+ return contents.get(arg1+(arg0 * numCols));
+ }
+
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ if (columnIndex+(rowIndex*numCols) > contents.size()-1) return false;
+ return !readOnly;
+ }
+
+ public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+ contents.set(columnIndex+(rowIndex*numCols), aValue);
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/form/field/BooleanEditField.java b/source/com/c2kernel/gui/tabs/outcome/form/field/BooleanEditField.java
new file mode 100755
index 0000000..5776f73
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/form/field/BooleanEditField.java
@@ -0,0 +1,68 @@
+package com.c2kernel.gui.tabs.outcome.form.field;
+
+import java.awt.Component;
+import java.awt.event.FocusEvent;
+
+import javax.swing.JCheckBox;
+import javax.swing.text.JTextComponent;
+
+import com.c2kernel.utils.Logger;
+
+/**************************************************************************
+ *
+ * $Revision: 1.7 $
+ * $Date: 2005/08/16 13:59:56 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+public class BooleanEditField extends StringEditField {
+
+ JCheckBox checkbox;
+
+ public BooleanEditField() {
+ checkbox = new JCheckBox();
+ checkbox.setSelected(false);
+ checkbox.addFocusListener(this);
+ }
+
+ public String getText() {
+ return String.valueOf(checkbox.isSelected());
+ }
+
+ public void setText(String text) {
+ boolean newState = false;
+ try {
+ newState = Boolean.valueOf(text).booleanValue();
+ } catch (Exception ex) {
+ Logger.error("Invalid value for checkbox: "+text);
+ }
+ checkbox.setSelected(newState);
+ }
+
+ public void setEditable(boolean editable) {
+ super.setEditable(editable);
+ checkbox.setEnabled(editable);
+ }
+
+ public Component getControl() {
+ return checkbox;
+ }
+
+ public String getDefaultValue() {
+ return "false";
+ }
+
+ /** don't reserve the item finder for a boolean */
+ public void focusGained(FocusEvent e) {
+ helpPane.setHelp(name, helpText);
+ }
+
+ /**
+ *
+ */
+ public JTextComponent makeTextField() {
+ // not used by boolean
+ return null;
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/form/field/ComboField.java b/source/com/c2kernel/gui/tabs/outcome/form/field/ComboField.java
new file mode 100755
index 0000000..2a0b34a
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/form/field/ComboField.java
@@ -0,0 +1,135 @@
+package com.c2kernel.gui.tabs.outcome.form.field;
+
+import java.awt.Component;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JComboBox;
+import javax.swing.text.JTextComponent;
+
+import org.exolab.castor.types.AnyNode;
+import org.exolab.castor.xml.schema.AttributeDecl;
+import org.exolab.castor.xml.schema.ElementDecl;
+import org.exolab.castor.xml.schema.Facet;
+import org.exolab.castor.xml.schema.SimpleType;
+
+import com.c2kernel.gui.tabs.outcome.form.StructuralException;
+import com.c2kernel.scripting.Script;
+import com.c2kernel.utils.Logger;
+
+/*******************************************************************************
+ *
+ * $Revision: 1.4 $ $Date: 2005/08/16 13:59:56 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research All
+ * rights reserved.
+ ******************************************************************************/
+
+public class ComboField extends StringEditField {
+
+ JComboBox comboField;
+ ListOfValues vals;
+ DefaultComboBoxModel comboModel;
+ AnyNode listNode;
+
+ public ComboField(SimpleType type, AnyNode listNode) {
+ super();
+ comboField = new JComboBox();
+ content = type;
+ this.listNode = listNode;
+ createLOV();
+ }
+
+ public String getDefaultValue() {
+ if (vals.getDefaultKey() != null)
+ return vals.get(vals.getDefaultKey()).toString();
+ else
+ return "";
+ }
+
+ public String getText() {
+ return vals.get(comboModel.getSelectedItem()).toString();
+ }
+
+ public JTextComponent makeTextField() {
+ // not used by this control
+ return null;
+ }
+
+ public void setText(String text) {
+ comboModel.setSelectedItem(text);
+ }
+
+ public Component getControl() {
+ return comboField;
+ }
+
+ private void createLOV() {
+ vals = new ListOfValues();
+
+ if (listNode != null) { // schema instructions for list building
+ String lovType = listNode.getLocalName();
+ String param = listNode.getFirstChild().getStringValue();
+ if (lovType.equals("ScriptList"))
+ populateLOVFromScript(param);
+ if (lovType.equals("PathList"))
+ populateLOVFromLDAP(param);
+ }
+
+ // handle enumerations
+ // TODO: should be ANDed with above results
+ if (content.hasFacet(Facet.ENUMERATION)) {
+ //ListOfValues andList = new ListOfValues();
+ Enumeration enums = content.getFacets(Facet.ENUMERATION);
+ while (enums.hasMoreElements()) {
+ Facet thisEnum = (Facet)enums.nextElement();
+ vals.put(thisEnum.getValue(), thisEnum.getValue(), false);
+ }
+ }
+
+ comboModel = new DefaultComboBoxModel(vals.keySet().toArray());
+ comboModel.setSelectedItem(vals.getDefaultKey());
+ comboField.setModel(comboModel);
+ }
+
+ /**
+ * @param param
+ */
+ private void populateLOVFromLDAP(String param) {
+ // TODO '/root/path;prop=val;prop=val'
+
+
+ }
+
+ private void populateLOVFromScript(String scriptName) {
+ try {
+ StringTokenizer tok = new StringTokenizer(scriptName, "_");
+ if (tok.countTokens() != 2)
+ throw new Exception("Invalid LOVScript name");
+ Script lovscript = new Script(tok.nextToken(), Integer.parseInt(tok.nextToken()));
+ lovscript.setInputParamValue("LOV", vals);
+ lovscript.execute();
+ } catch (Exception ex) {
+ Logger.exceptionDialog(ex);
+ }
+ }
+
+ public void setDecl(AttributeDecl model) throws StructuralException {
+ super.setDecl(model);
+ createLOV();
+ }
+
+ public void setDecl(ElementDecl model) throws StructuralException {
+ super.setDecl(model);
+ createLOV();
+ }
+
+ /**
+ *
+ */
+
+ public void setEditable(boolean editable) {
+ comboField.setEditable(editable);
+ }
+} \ No newline at end of file
diff --git a/source/com/c2kernel/gui/tabs/outcome/form/field/DecimalEditField.java b/source/com/c2kernel/gui/tabs/outcome/form/field/DecimalEditField.java
new file mode 100755
index 0000000..d77dff3
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/form/field/DecimalEditField.java
@@ -0,0 +1,115 @@
+package com.c2kernel.gui.tabs.outcome.form.field;
+
+import java.awt.Toolkit;
+import java.math.BigDecimal;
+
+import javax.swing.JTextField;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+import javax.swing.text.JTextComponent;
+import javax.swing.text.PlainDocument;
+
+/**************************************************************************
+ *
+ * $Revision: 1.3 $
+ * $Date: 2005/08/16 13:59:56 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+public class DecimalEditField extends StringEditField {
+
+ public DecimalEditField() {
+ super();
+ field.addFocusListener(this);
+ field.setToolTipText("This field must contains a decimal number e.g. 3.14159265");
+ }
+
+ public String getText() {
+ return field.getText();
+ }
+
+ public void setText(String text) {
+ field.setText(text);
+ }
+
+ public String getDefaultValue() {
+ return "0.0";
+ }
+
+ public JTextComponent makeTextField() {
+ return new DecimalTextField();
+ }
+
+ private class DecimalTextField extends JTextField {
+
+ public DecimalTextField() {
+ super();
+ setHorizontalAlignment(RIGHT);
+ }
+ protected Document createDefaultModel() {
+ return new Decimal();
+ }
+ }
+
+ private class Decimal extends PlainDocument {
+
+ BigDecimal currentVal = new BigDecimal(0.0);
+
+
+ public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
+
+ if (str == null || str.equals("")) {
+ return;
+ }
+
+ String proposedResult = null;
+
+ if (getLength() == 0) {
+ proposedResult = str;
+ } else {
+ StringBuffer currentBuffer = new StringBuffer( this.getText(0, getLength()) );
+ currentBuffer.insert(offs, str);
+ proposedResult = currentBuffer.toString();
+ }
+
+ try {
+ currentVal = parse(proposedResult);
+ super.insertString(offs, str, a);
+ } catch (Exception e) {
+ Toolkit.getDefaultToolkit().beep();
+ }
+
+ }
+
+ public void remove(int offs, int len) throws BadLocationException {
+
+ String currentText = this.getText(0, getLength());
+ String beforeOffset = currentText.substring(0, offs);
+ String afterOffset = currentText.substring(len + offs, currentText.length());
+ String proposedResult = beforeOffset + afterOffset;
+
+ if (proposedResult.length() == 0) { // empty is ok
+ super.remove(offs, len);
+ return;
+ }
+ try {
+ currentVal = parse(proposedResult);
+ super.remove(offs, len);
+ } catch (Exception e) {
+ Toolkit.getDefaultToolkit().beep();
+ }
+
+ }
+
+ public BigDecimal parse(String proposedResult) throws NumberFormatException {
+
+ BigDecimal value = new BigDecimal(0);
+ if ( proposedResult.length() != 0) {
+ value = new BigDecimal(proposedResult);
+ }
+ return value;
+ }
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/form/field/FieldConstraints.java b/source/com/c2kernel/gui/tabs/outcome/form/field/FieldConstraints.java
new file mode 100755
index 0000000..d09cd91
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/form/field/FieldConstraints.java
@@ -0,0 +1,51 @@
+package com.c2kernel.gui.tabs.outcome.form.field;
+
+import java.util.Enumeration;
+
+import org.exolab.castor.types.AnyNode;
+import org.exolab.castor.xml.schema.Annotation;
+import org.exolab.castor.xml.schema.AppInfo;
+import org.exolab.castor.xml.schema.XMLType;
+
+/**************************************************************************
+ *
+ * $Revision: 1.1 $
+ * $Date: 2005/04/26 06:48:12 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class FieldConstraints {
+
+ XMLType content;
+ ListOfValues lov;
+ int rows = 1;
+
+ public FieldConstraints(XMLType content) {
+ this.content = content;
+ Enumeration e = content.getAnnotations();
+ while (e.hasMoreElements()) {
+ Annotation note = (Annotation)e.nextElement();
+ for (Enumeration f = note.getAppInfo(); f.hasMoreElements();) {
+ addAppInfo((AppInfo)f.nextElement());
+ }
+ }
+ }
+
+ private void addAppInfo(AppInfo element) {
+ Enumeration e = element.getObjects();
+ while (e.hasMoreElements()) {
+ AnyNode node = (AnyNode)e.nextElement();
+
+ }
+ }
+
+ public ListOfValues getLOV() {
+ return lov;
+ }
+
+ public int getRows() {
+ return rows;
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/form/field/ImageEditField.java b/source/com/c2kernel/gui/tabs/outcome/form/field/ImageEditField.java
new file mode 100755
index 0000000..b0bb079
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/form/field/ImageEditField.java
@@ -0,0 +1,104 @@
+package com.c2kernel.gui.tabs.outcome.form.field;
+
+import java.awt.Component;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.FileInputStream;
+import java.lang.reflect.Array;
+
+import javax.swing.Box;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+
+import org.apache.xerces.impl.dv.util.Base64;
+
+import com.c2kernel.utils.Logger;
+
+public class ImageEditField extends StringEditField {
+
+ JLabel imageLabel;
+
+ Box imagePanel;
+
+ JButton browseButton;
+
+ String encodedImage;
+
+ static JFileChooser chooser = new JFileChooser();
+ static {
+ chooser.addChoosableFileFilter(new javax.swing.filechooser.FileFilter() {
+ public String getDescription() {
+ return "Image Files";
+ }
+
+ public boolean accept(File f) {
+ return (f.isDirectory() || (f.isFile() && (f.getName()
+ .endsWith(".gif")
+ || f.getName().endsWith(".jpg")
+ || f.getName().endsWith(".jpeg")
+ || f.getName().endsWith(".png"))));
+ }
+ });
+ }
+
+ public ImageEditField() {
+ super();
+ imageLabel = new JLabel();
+ imagePanel = Box.createVerticalBox();
+ browseButton = new JButton("Browse");
+ browseButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ int returnVal = chooser.showOpenDialog(null);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ File file = chooser.getSelectedFile();
+ try {
+ FileInputStream fis = new FileInputStream(file);
+ byte[] bArray = (byte[]) Array.newInstance(byte.class,
+ (int) file.length());
+ fis.read(bArray, 0, (int) file.length());
+ fis.close();
+
+ ImageIcon newImage = new ImageIcon(Toolkit
+ .getDefaultToolkit().createImage(bArray));
+ imageLabel.setIcon(newImage);
+ encodedImage = Base64.encode(bArray);
+ } catch (Exception ex) {
+ Logger.exceptionDialog(ex);
+ }
+ }
+ }
+ });
+ imagePanel.add(imageLabel);
+ imagePanel.add(Box.createVerticalStrut(5));
+ imagePanel.add(browseButton);
+ }
+
+ public String getDefaultValue() {
+ return "";
+ }
+
+ public Component getControl() {
+ return imagePanel;
+ }
+
+ public String getText() {
+ return encodedImage == null ? "" : encodedImage;
+ }
+
+ public void setText(String text) {
+ encodedImage = text;
+ if (text != null && text.length() > 0) {
+ byte[] decodedImage = Base64.decode(encodedImage);
+ imageLabel.setIcon(new ImageIcon(Toolkit.getDefaultToolkit()
+ .createImage(decodedImage)));
+ }
+ }
+
+ public void setEditable(boolean editable) {
+ browseButton.setVisible(false);
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/form/field/IntegerEditField.java b/source/com/c2kernel/gui/tabs/outcome/form/field/IntegerEditField.java
new file mode 100755
index 0000000..7c858a4
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/form/field/IntegerEditField.java
@@ -0,0 +1,113 @@
+package com.c2kernel.gui.tabs.outcome.form.field;
+
+import java.awt.Toolkit;
+import java.math.BigInteger;
+
+import javax.swing.JTextField;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+import javax.swing.text.JTextComponent;
+import javax.swing.text.PlainDocument;
+
+/**************************************************************************
+ *
+ * $Revision: 1.4 $
+ * $Date: 2005/08/16 13:59:56 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+public class IntegerEditField extends StringEditField {
+
+ public IntegerEditField() {
+ super();
+ field.setToolTipText("This field must contains a whole number e.g. 3");
+ }
+
+ public String getText() {
+ return field.getText();
+ }
+
+ public void setText(String text) {
+ field.setText(text);
+ }
+
+ public String getDefaultValue() {
+ return "0";
+ }
+
+ public JTextComponent makeTextField() {
+ return new IntegerTextField();
+ }
+
+ private class IntegerTextField extends JTextField {
+
+ public IntegerTextField() {
+ super();
+ setHorizontalAlignment(RIGHT);
+ }
+ protected Document createDefaultModel() {
+ return new IntegerDocument();
+ }
+ }
+
+ private class IntegerDocument extends PlainDocument {
+
+ BigInteger currentVal = new BigInteger("0");
+
+ public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
+
+ if (str == null || str.equals("")) {
+ return;
+ }
+
+ String proposedResult = null;
+
+ if (getLength() == 0) {
+ proposedResult = str;
+ } else {
+ StringBuffer currentBuffer = new StringBuffer( this.getText(0, getLength()) );
+ currentBuffer.insert(offs, str);
+ proposedResult = currentBuffer.toString();
+ }
+
+ try {
+ currentVal = parse(proposedResult);
+ super.insertString(offs, str, a);
+ } catch (Exception e) {
+ Toolkit.getDefaultToolkit().beep();
+ }
+
+ }
+
+ public void remove(int offs, int len) throws BadLocationException {
+
+ String currentText = this.getText(0, getLength());
+ String beforeOffset = currentText.substring(0, offs);
+ String afterOffset = currentText.substring(len + offs, currentText.length());
+ String proposedResult = beforeOffset + afterOffset;
+ if (proposedResult.length() == 0) { // empty is ok
+ super.remove(offs, len);
+ return;
+ }
+
+ try {
+ currentVal = parse(proposedResult);
+ super.remove(offs, len);
+ } catch (Exception e) {
+ Toolkit.getDefaultToolkit().beep();
+ }
+
+ }
+
+ public BigInteger parse(String proposedResult) throws NumberFormatException {
+
+ BigInteger value = new BigInteger("0");
+ if ( proposedResult.length() != 0) {
+ value = new BigInteger(proposedResult);
+ }
+ return value;
+ }
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/form/field/ListOfValues.java b/source/com/c2kernel/gui/tabs/outcome/form/field/ListOfValues.java
new file mode 100755
index 0000000..2557cbe
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/form/field/ListOfValues.java
@@ -0,0 +1,31 @@
+package com.c2kernel.gui.tabs.outcome.form.field;
+
+import java.util.HashMap;
+
+/**************************************************************************
+ *
+ * $Revision: 1.2 $
+ * $Date: 2005/04/26 06:48:12 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class ListOfValues extends HashMap {
+
+ String defaultKey = null;
+
+ public ListOfValues() {
+ super();
+ }
+
+ public String put(String key, String value, boolean isDefaultKey) {
+ if (isDefaultKey) defaultKey = key;
+ return (String)super.put(key, value);
+ }
+
+ public String getDefaultKey() {
+ return defaultKey;
+ }
+
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/form/field/LongStringEditField.java b/source/com/c2kernel/gui/tabs/outcome/form/field/LongStringEditField.java
new file mode 100755
index 0000000..b782c65
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/form/field/LongStringEditField.java
@@ -0,0 +1,38 @@
+package com.c2kernel.gui.tabs.outcome.form.field;
+
+import java.awt.Component;
+
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.text.JTextComponent;
+
+import com.c2kernel.utils.Language;
+
+
+/**************************************************************************
+ *
+ * $Revision$
+ * $Date$
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+public class LongStringEditField extends StringEditField {
+
+ JTextArea bigText;
+ JScrollPane bigScroller;
+ public LongStringEditField() {
+ super();
+ field.setToolTipText(Language.translate("This field can contain any string."));
+ }
+
+ public JTextComponent makeTextField() {
+ return new JTextArea();
+ }
+ public Component getControl() {
+ if (bigScroller == null) {
+ bigScroller = new JScrollPane(field);
+ }
+ return bigScroller;
+ }
+}
diff --git a/source/com/c2kernel/gui/tabs/outcome/form/field/StringEditField.java b/source/com/c2kernel/gui/tabs/outcome/form/field/StringEditField.java
new file mode 100755
index 0000000..310ee2e
--- /dev/null
+++ b/source/com/c2kernel/gui/tabs/outcome/form/field/StringEditField.java
@@ -0,0 +1,252 @@
+package com.c2kernel.gui.tabs.outcome.form.field;
+import java.awt.Component;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import javax.swing.ImageIcon;
+import javax.swing.JTextField;
+import javax.swing.text.JTextComponent;
+
+import org.exolab.castor.types.AnyNode;
+import org.exolab.castor.xml.schema.Annotation;
+import org.exolab.castor.xml.schema.AppInfo;
+import org.exolab.castor.xml.schema.AttributeDecl;
+import org.exolab.castor.xml.schema.ElementDecl;
+import org.exolab.castor.xml.schema.Facet;
+import org.exolab.castor.xml.schema.SimpleType;
+import org.exolab.castor.xml.schema.Structure;
+import org.exolab.castor.xml.schema.XMLType;
+import org.exolab.castor.xml.schema.simpletypes.ListType;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+import com.c2kernel.gui.DomainKeyConsumer;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+import com.c2kernel.gui.tabs.outcome.form.HelpPane;
+import com.c2kernel.gui.tabs.outcome.form.OutcomeStructure;
+import com.c2kernel.gui.tabs.outcome.form.StructuralException;
+import com.c2kernel.lookup.DomainPath;
+
+/** Superclass for the entry field for Field and AttributeList.
+ */
+public class StringEditField implements FocusListener, DomainKeyConsumer {
+
+ Node data;
+ Structure model;
+ protected SimpleType content;
+ HelpPane helpPane;
+ String helpText;
+ protected JTextComponent field;
+
+ boolean isValid = true;
+ boolean editable = true;
+ String name;
+
+
+ public StringEditField() {
+ field = makeTextField();
+ if (field != null)
+ field.addFocusListener(this);
+ }
+
+ private static StringEditField getFieldForType(SimpleType type) {
+ // handle lists special
+ if (type instanceof ListType)
+ return new ArrayEditField(type.getBuiltInBaseType());
+
+ // is a combobox
+ if (type.hasFacet(Facet.ENUMERATION))
+ return new ComboField(type, null);
+ //find LOVscript
+ Enumeration e = type.getAnnotations();
+ while (e.hasMoreElements()) {
+ Annotation note = (Annotation)e.nextElement();
+ for (Enumeration f = note.getAppInfo(); f.hasMoreElements();) {
+ AppInfo thisAppInfo = (AppInfo)f.nextElement();
+ for (Enumeration g = thisAppInfo.getObjects(); g.hasMoreElements();) {
+ AnyNode appInfoNode = (AnyNode)g.nextElement();
+ if (appInfoNode.getLocalName().equals("ScriptList")
+ || appInfoNode.getLocalName().equals("LDAPList")) {
+ return new ComboField(type, appInfoNode);
+ }
+ }
+ }
+ }
+ // find info on length before we go to the base type
+ long length = -1;
+ if (type.getLength()!=null) length = type.getLength().longValue();
+ else if (type.getMaxLength()!=null) length = type.getMaxLength().longValue();
+ else if (type.getMinLength()!=null) length = type.getMinLength().longValue();
+
+ // find base type if derived
+ if (!(type.isBuiltInType()))
+ type = type.getBuiltInBaseType();
+ // else derive the class
+ Class contentClass = OutcomeStructure.getJavaClass(type.getTypeCode());
+ // disable list edits for the moment
+ if (contentClass.equals(Boolean.class))
+ return new BooleanEditField();
+ else if (contentClass.equals(BigInteger.class))
+ return new IntegerEditField();
+ else if (contentClass.equals(BigDecimal.class))
+ return new DecimalEditField();
+ else if (contentClass.equals(ImageIcon.class))
+ return new ImageEditField();
+ else if (length > 60)
+ return new LongStringEditField();
+ else return new StringEditField();
+ }
+
+ public static StringEditField getEditField(AttributeDecl model) throws StructuralException {
+ StringEditField newField = getFieldForType(model.getSimpleType());
+ newField.setDecl(model);
+ return newField;
+ }
+
+ public static StringEditField getEditField(ElementDecl model) throws StructuralException {
+ try {
+ XMLType baseType = model.getType();
+ while (!(baseType instanceof SimpleType))
+ baseType = baseType.getBaseType();
+ StringEditField newField = getFieldForType((SimpleType)baseType);
+ newField.setDecl(model);
+ return newField;
+ } catch (Exception ex) {
+ throw new StructuralException("No type defined in model");
+ }
+ }
+
+ public void setDecl(AttributeDecl model) throws StructuralException {
+ this.model=model;
+ this.content=model.getSimpleType();
+ this.name = model.getName();
+ if (model.isFixed()) setEditable(false);
+ }
+
+ public void setDecl(ElementDecl model) throws StructuralException {
+ this.model=model;
+ this.name = model.getName();
+ XMLType type = model.getType();
+
+ // derive base type
+ if (type.isSimpleType())
+ this.content = (SimpleType)type;
+ else
+ this.content = (SimpleType)(type.getBaseType());
+
+ if (this.content == null) throw new StructuralException("No declared base type of element");
+
+ //
+ if (model.getFixedValue() != null) setEditable(false);
+
+ }
+
+ public void setData(Attr newData) throws StructuralException {
+ if (!(newData.getName().equals(name)))
+ throw new StructuralException("Tried to add a "+newData.getName()+" into a "+name+" attribute.");
+
+ this.data = newData;
+ setText(newData.getValue());
+ }
+
+ public void setData(Text newData) {
+ String contents = newData.getData();
+ this.data = newData;
+ setText(contents);
+ }
+
+ public void setData(String newData) throws OutcomeException {
+ if (data == null) throw new OutcomeException("No node exists");
+ setText(newData);
+ updateNode();
+
+ }
+
+ public Structure getModel() {
+ return model;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Node getData() {
+ return data;
+ }
+
+ public String getDefaultValue() {
+ return "";
+ }
+
+ public void setHelp(HelpPane helpPane, String helpText) {
+ this.helpPane = helpPane;
+ this.helpText = helpText;
+ }
+
+ public void focusLost(FocusEvent e) {
+ if (MainFrame.itemFinder != null)
+ MainFrame.itemFinder.clearConsumer(this);
+ updateNode();
+ }
+
+ public void focusGained(FocusEvent e) {
+ helpPane.setHelp(name, helpText);
+ if (editable && MainFrame.itemFinder != null)
+ MainFrame.itemFinder.setConsumer(this, "Insert");
+ }
+
+ public void updateNode() {
+ if (data == null) return;
+ if (data instanceof Text) {
+ ((Text)data).setData(getText());
+ }
+ else { //attribute
+ ((Attr)data).setValue(getText());
+ }
+ }
+
+ /**
+ * Read domkey from barcode input
+ */
+ public void push(DomainPath key) {
+ setText(key.getName());
+ }
+
+ /**
+ * Read string from barcode input
+ */
+ public void push(String key) {
+ setText(key);
+ }
+
+ public void setEditable(boolean editable) {
+ this.editable = editable;
+ if (field != null)
+ field.setEditable(editable);
+ }
+
+ public String getText() {
+ return field.getText();
+ }
+
+ public void setText(String text) {
+ field.setText(text);
+ }
+
+ public JTextComponent makeTextField() {
+ return new JTextField();
+ }
+
+ public Component getControl() {
+ return field;
+ }
+
+ public void grabFocus() {
+ getControl().requestFocus();
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/ActivityDef.java b/source/com/c2kernel/lifecycle/ActivityDef.java
new file mode 100755
index 0000000..fd6f646
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/ActivityDef.java
@@ -0,0 +1,135 @@
+package com.c2kernel.lifecycle;
+import java.util.Vector;
+
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.lifecycle.instance.Activity;
+import com.c2kernel.lifecycle.instance.WfVertex;
+import com.c2kernel.lifecycle.instance.stateMachine.StateMachine;
+import com.c2kernel.utils.FileStringUtility;
+/**
+ * @version $Revision: 1.45 $ $Date: 2005/10/05 07:39:36 $
+ * @author $Author: abranson $
+ */
+public class ActivityDef extends WfVertexDef implements C2KLocalObject
+{
+ private int mId = -1;
+ private String mName = "";
+ private String mVersion = "";
+ public boolean changed = false;
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public ActivityDef()
+ {
+ mErrors = new Vector(0, 1);
+ setProperties(new WfCastorHashMap());
+ setIsLayoutable(false);
+ getProperties().put(StateMachine.SKIPPABLE, new Boolean(false));
+ getProperties().put(StateMachine.REPEATABLE, new Boolean(false));
+ getProperties().put(StateMachine.IGNORABLE, new Boolean(false));
+ }
+ /**
+ * @see com.c2kernel.graph.model.Vertex#setID(int)
+ */
+ public void setID(int id)
+ {
+ mId = id;
+ if (mName.equals(""))
+ setName(String.valueOf(id));
+ }
+ /**
+ * @see com.c2kernel.graph.model.Vertex#getID()
+ */
+ public int getID()
+ {
+ return mId;
+ }
+ /**
+ * @see com.c2kernel.graph.model.Vertex#setName(java.lang.String)
+ */
+ public void setName(String n)
+ {
+ mName = n;
+ }
+ /**
+ * @see com.c2kernel.graph.model.Vertex#getName()
+ */
+ public String getName()
+ {
+ return mName;
+ }
+
+ public void setVersion(String v)
+ {
+ mVersion = v;
+ }
+ /**
+ * @see com.c2kernel.graph.model.Vertex#getName()
+ */
+ public String getVersion()
+ {
+ return mVersion;
+ }
+ /**
+ * @see com.c2kernel.lifecycle.WfVertexDef#getErrors()
+ */
+ public String getErrors()
+ {
+ return super.getErrors();
+ }
+ /**
+ * Method linkToSlot.
+ *
+ * @param actSl
+ * @param name
+ */
+ public void linkToSlot(ActivitySlotDef actSl, String name, String name2)
+ {
+ actSl.setActivityDef(FileStringUtility.convert(name));
+ actSl.getProperties().put("Name", name2.replace('/', '_'));
+ actSl.setName(name+" slot");
+ setName(FileStringUtility.convert(name));
+ }
+ /**
+ * @see com.c2kernel.lifecycle.WfVertexDef#verify()
+ */
+ public boolean verify()
+ {
+ return true;
+ }
+ /**
+ * @see com.c2kernel.entity.C2KLocalObject#getClusterType()
+ */
+ public String getClusterType()
+ {
+ return null;
+ }
+ public String getActName()
+ {
+ return getName();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.c2kernel.lifecycle.commonInterface.ActType#getDescName()
+ */
+ public String getDescName()
+ {
+ return getName();
+ }
+
+ public WfVertex instantiate() throws ObjectNotFoundException, InvalidDataException{
+ return instantiate(getName());
+ }
+ public WfVertex instantiate(String name) throws ObjectNotFoundException, InvalidDataException
+ {
+ Activity act = new Activity();
+ configureInstance(act);
+ act.setName(name);
+ act.setType(getName());
+ return act;
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/ActivitySlotDef.java b/source/com/c2kernel/lifecycle/ActivitySlotDef.java
new file mode 100755
index 0000000..10f6778
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/ActivitySlotDef.java
@@ -0,0 +1,155 @@
+package com.c2kernel.lifecycle;
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.graph.traversal.GraphTraversal;
+import com.c2kernel.lifecycle.instance.Activity;
+import com.c2kernel.lifecycle.instance.WfVertex;
+import com.c2kernel.utils.KeyValuePair;
+import com.c2kernel.utils.LocalObjectLoader;
+/**
+ * @version $Revision: 1.46 $ $Date: 2005/10/05 07:39:36 $
+ * @author $Author: abranson $
+ */
+public class ActivitySlotDef extends WfVertexDef
+{
+ private String activityDef;
+
+ /**
+ * Method setActivityDef.
+ *
+ * @param oActivityDef
+ */
+ public void setActivityDef(String oActivityDef)
+ {
+ activityDef = oActivityDef;
+ }
+ /**
+ * Method getActivityDef.
+ *
+ * @return String
+ */
+ public String getActivityDef()
+ {
+ return activityDef;
+ }
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public ActivitySlotDef()
+ {
+ getProperties().put("Name", "");
+ getProperties().put("Version", "last");
+ }
+
+ public ActivityDef getTheActivityDef() throws ObjectNotFoundException, InvalidDataException
+ {
+ ActivityDef actDef = LocalObjectLoader.getActDef(getActivityDef(), getActVersion());
+ if (actDef instanceof CompositeActivityDef)
+ mIsComposite = true;
+ return actDef;
+ }
+ /**
+ * @see com.c2kernel.lifecycle.WfVertexDef#verify()
+ */
+ /** launch the verification of the ActivityDef */
+ public boolean verify()
+ {
+ mErrors.removeAllElements();
+ boolean err = true;
+ int nbInEdgres = getInEdges().length;
+ int nbOutEdges = getOutEdges().length;
+ if (nbInEdgres == 0 && this.getID() != getParent().getChildrenGraphModel().getStartVertexId())
+ {
+ mErrors.add("Unreachable");
+ err = false;
+ }
+ else if (nbInEdgres > 1)
+ {
+ mErrors.add("Bad nb of previous");
+ err = false;
+ }
+ else if (nbOutEdges > 1)
+ {
+ mErrors.add("too many next");
+ err = false;
+ }
+ else if (nbOutEdges == 0)
+ {
+ if (!((CompositeActivityDef) getParent()).hasGoodNumberOfActivity())
+ {
+ mErrors.add("too many endpoints");
+ err = false;
+ }
+ }
+ else
+ {
+ Vertex[] outV = getOutGraphables();
+ Vertex[] anteVertices = GraphTraversal.getTraversal(getParent().getChildrenGraphModel(), this, GraphTraversal.kUp, false);
+ boolean errInLoop = false;
+ for (int i = 0; i < outV.length; i++)
+ {
+ for (int j = 0; j < anteVertices.length; j++)
+ if (!loop() && outV[i].getID() == anteVertices[j].getID())
+ errInLoop = true;
+ }
+ if (errInLoop)
+ {
+ mErrors.add("Problem in Loop");
+ err = false;
+ }
+ }
+ return err;
+ }
+ /**
+ * Method getNextWfVertices.
+ *
+ * @return WfVertexDef[]
+ */
+ public WfVertexDef[] getNextWfVertices()
+ {
+ return (WfVertexDef[]) getOutGraphables();
+ }
+ /**
+ * @see com.c2kernel.graph.model.GraphableVertex#isLayoutable()
+ */
+ /**
+ * @see com.c2kernel.graph.model.GraphableVertex#getIsLayoutable()
+ */
+ public boolean isLayoutable()
+ {
+ return true;
+ }
+ /**
+ * Method getInfo.
+ *
+ * @return CastorHashMap
+ */
+ public void configureInstance(Activity act)
+ {
+ KeyValuePair[] k = getProperties().getKeyValuePairs();
+ for (int i = 0; i < k.length; i++)
+ act.getProperties().put(k[i].getKey(), k[i].getValue());
+ act.setCentrePoint(getCentrePoint());
+ act.setOutlinePoints(getOutlinePoints());
+ act.setInEdgeIds(getInEdgeIds());
+ act.setOutEdgeIds(getOutEdgeIds());
+ act.setName(getActName());
+ act.setID(getID());
+ }
+
+ public String getActName()
+ {
+ return (String) getProperties().get("Name");
+ }
+ public String getActVersion()
+ {
+ return (String) getProperties().get("Version");
+ }
+
+ public WfVertex instantiate() throws ObjectNotFoundException, InvalidDataException {
+ Activity newActivity = (Activity)getTheActivityDef().instantiate();
+ configureInstance(newActivity);
+ return newActivity;
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/AndSplitDef.java b/source/com/c2kernel/lifecycle/AndSplitDef.java
new file mode 100755
index 0000000..6692163
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/AndSplitDef.java
@@ -0,0 +1,111 @@
+package com.c2kernel.lifecycle;
+
+import java.util.Vector;
+
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.graph.traversal.GraphTraversal;
+import com.c2kernel.lifecycle.instance.AndSplit;
+import com.c2kernel.lifecycle.instance.WfVertex;
+/**
+ * @version $Revision: 1.19 $ $Date: 2005/09/29 10:18:31 $
+ * @author $Author: abranson $
+ */
+
+public class AndSplitDef extends WfVertexDef
+{
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public AndSplitDef()
+ {
+ mErrors = new Vector(0, 1);
+ getProperties().put("RoutingScriptName", "");
+ getProperties().put("RoutingScriptVersion", "");
+ }
+
+ /**
+ * @see com.c2kernel.lifecycle.WfVertexDef#verify()
+ */
+ public boolean verify()
+ {
+ mErrors.removeAllElements();
+ boolean err = true;
+ int nbInEdges = getInEdges().length;
+ if (nbInEdges == 0 && this.getID() != getParent().getChildrenGraphModel().getStartVertexId())
+ {
+ mErrors.add("Unreachable");
+ err = false;
+ }
+ else if (nbInEdges > 1)
+ {
+ mErrors.add("Bad nb of previous");
+ err = false;
+ }
+ else
+ {
+ if (getOutEdges().length <= 1)
+ {
+ mErrors.add("not enough next");
+ err = false;
+ }
+ else if (!(this instanceof LoopDef))
+ {
+ Vertex[] outV = getOutGraphables();
+ Vertex[] anteVertices =
+ GraphTraversal.getTraversal(getParent().getChildrenGraphModel(), this, GraphTraversal.kUp, false);
+ boolean loop = false;
+ boolean errInLoop = true;
+ for (int i = 0; i < outV.length; i++)
+ {
+ for (int j = 0; j < anteVertices.length; j++)
+ if (!loop && outV[i].getID() == anteVertices[j].getID())
+ {
+ if (outV[i] instanceof LoopDef)
+ {
+ loop = true;
+ j = anteVertices.length;
+ i = outV.length;
+ }
+ else
+ {
+ errInLoop = false;
+ }
+ }
+ }
+ if (errInLoop && loop)
+ {
+ mErrors.add("Problem in Loop");
+ err = false;
+ }
+ }
+ }
+ return err;
+ }
+
+ public boolean loop()
+ {
+ boolean loop2 = false;
+ if (!loopTested)
+ {
+ loopTested = true;
+ if (getOutGraphables().length != 0)
+ {
+ Vertex[] outVertices = getOutGraphables();
+ for (int i = 0; i < outVertices.length; i++)
+ {
+ WfVertexDef tmp = (WfVertexDef) getOutGraphables()[i];
+ loop2 = loop2 || tmp.loop();
+ }
+ }
+ }
+ loopTested = false;
+ return loop2;
+ }
+
+ public WfVertex instantiate() {
+ AndSplit newSplit = new AndSplit();
+ configureInstance(newSplit);
+ return newSplit;
+ }
+
+}
diff --git a/source/com/c2kernel/lifecycle/CompositeActivityDef.java b/source/com/c2kernel/lifecycle/CompositeActivityDef.java
new file mode 100755
index 0000000..a46cc50
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/CompositeActivityDef.java
@@ -0,0 +1,225 @@
+package com.c2kernel.lifecycle;
+import java.awt.Point;
+
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.graph.model.GraphModel;
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.graph.model.GraphableVertex;
+import com.c2kernel.graph.model.TypeNameAndConstructionInfo;
+import com.c2kernel.lifecycle.gui.model.WfVertexDefOutlineCreator;
+import com.c2kernel.lifecycle.instance.CompositeActivity;
+import com.c2kernel.lifecycle.instance.Next;
+import com.c2kernel.lifecycle.instance.WfVertex;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+/**
+ * @version $Revision: 1.93 $ $Date: 2005/10/05 07:39:36 $
+ * @author $Author: abranson $
+ */
+public class CompositeActivityDef extends ActivityDef
+{
+ private final TypeNameAndConstructionInfo[] mVertexTypeNameAndConstructionInfo =
+ {
+ new TypeNameAndConstructionInfo(Language.translate("Atomic"), "Atomic"),
+ new TypeNameAndConstructionInfo(Language.translate("Composite"), "Composite"),
+ new TypeNameAndConstructionInfo(Language.translate("AND Split"), "And"),
+ new TypeNameAndConstructionInfo(Language.translate("OR Split"), "Or"),
+ new TypeNameAndConstructionInfo(Language.translate("XOR Split"), "XOr"),
+ new TypeNameAndConstructionInfo(Language.translate("Junction"), "Join"),
+ new TypeNameAndConstructionInfo(Language.translate("Loop"), "Loop"),
+ };
+ private final TypeNameAndConstructionInfo[] mEdgeTypeNameAndConstructionInfo =
+ {
+ new TypeNameAndConstructionInfo(Language.translate("Next Edge"), "Next")
+ };
+ public TypeNameAndConstructionInfo[] getVertexTypeNameAndConstructionInfo()
+ {
+ return mVertexTypeNameAndConstructionInfo;
+ }
+ public TypeNameAndConstructionInfo[] getEdgeTypeNameAndConstructionInfo()
+ {
+ return mEdgeTypeNameAndConstructionInfo;
+ }
+
+ public CompositeActivityDef()
+ {
+ super();
+ setChildrenGraphModel(new GraphModel(new WfVertexDefOutlineCreator()));
+ setIsComposite(true);
+ }
+
+ /**
+ * Method addNextDef.
+ *
+ * @param origin
+ * @param terminus
+ * @return NextDef
+ */
+ public NextDef addNextDef(WfVertexDef origin, WfVertexDef terminus)
+ {
+ NextDef returnNxt = new NextDef(origin, terminus);
+ getChildrenGraphModel().addEdgeAndCreateId(returnNxt, origin, terminus);
+ return returnNxt;
+ }
+ /**
+ * Method addExistingActivityDef.
+ *
+ * @param actDef
+ * @param point
+ */
+ public ActivitySlotDef addExistingActivityDef(String name, ActivityDef actDef, GraphPoint point)
+ {
+ changed = true;
+ ActivitySlotDef child = new ActivitySlotDef();
+ addChild(child, point);
+ actDef.linkToSlot(child, actDef.getName(), name);
+ return child;
+ }
+ /**
+ * Method newChild.
+ *
+ * @param Name
+ * @param Type
+ * @param location
+ * @return WfVertexDef
+ */
+ public WfVertexDef newChild(String Name, String Type, Point location)
+ {
+ changed = true;
+ WfVertexDef child;
+ if (Type.equals("Or"))
+ {
+ child = new OrSplitDef();
+ addChild(child, location);
+ Logger.msg(5, Type + " " + child.getID() + " added to " + this.getID());
+ }
+ else if (Type.equals("XOr"))
+ {
+ child = new XOrSplitDef();
+ addChild(child, location);
+ Logger.msg(5, Type + " " + child.getID() + " added to " + this.getID());
+ }
+ else if (Type.equals("And"))
+ {
+ child = new AndSplitDef();
+ addChild(child, location);
+ Logger.msg(5, Type + " " + child.getID() + " added to " + this.getID());
+ }
+ else if (Type.equals("Loop"))
+ {
+ child = new LoopDef();
+ addChild(child, location);
+ Logger.msg(5, Type + " " + child.getID() + " added to " + this.getID());
+ }
+ else if (Type.equals("Atomic"))
+ {
+ child = new ActivitySlotDef();
+ ActivityDef act = new ActivityDef();
+ act.changed = true;
+ addChild(child, location);
+ act.linkToSlot((ActivitySlotDef) child, Name, Name);
+ act.getProperties().put("Description", Name);
+ Logger.msg(5, Type + " " + child.getID() + " added to " + this.getID());
+ }
+ else if (Type.equals("Join"))
+ {
+ child = new JoinDef();
+ child.getProperties().put("Type", "Join");
+ addChild(child, location);
+ Logger.msg(5, Type + " " + child.getID() + " added to " + this.getID());
+ }
+ else if (Type.equals("Route"))
+ {
+ child = new JoinDef();
+ child.getProperties().put("Type", "Route");
+ addChild(child, location);
+ Logger.msg(5, Type + " " + child.getID() + " added to " + this.getID());
+ }
+ else
+ {
+ child = new ActivitySlotDef();
+ CompositeActivityDef act = new CompositeActivityDef();
+ act.changed = true;
+ addChild(child, location);
+ act.linkToSlot((ActivitySlotDef) child, Name, Name);
+ Logger.msg(5, Type + " " + child.getID() + " added to " + this.getID());
+ }
+ return child;
+ }
+ /**
+ * Method instantiateAct.
+ *
+ * @return CompositeActivity
+ */
+ public WfVertex instantiate() throws ObjectNotFoundException, InvalidDataException {
+ return instantiate(getName());
+ }
+
+ public WfVertex instantiate(String name) throws ObjectNotFoundException, InvalidDataException
+ {
+ CompositeActivity cAct = new CompositeActivity();
+ cAct.setType(getName());
+ cAct.setName(name);
+ GraphableVertex[] vertexDefs = getLayoutableChildren();
+ WfVertex[] wfVertices = new WfVertex[vertexDefs.length];
+ for (int i = 0; i < vertexDefs.length; i++)
+ {
+ WfVertexDef vertDef = (WfVertexDef)vertexDefs[i];
+ wfVertices[i] = vertDef.instantiate();
+ wfVertices[i].setParent(cAct);
+ }
+ Next[] nexts = new Next[getChildrenGraphModel().getEdges().length];
+ for (int i = 0; i < getChildrenGraphModel().getEdges().length; i++)
+ {
+ NextDef nextDef = (NextDef) getChildrenGraphModel().getEdges()[i];
+ nexts[i] = nextDef.instantiate();
+ nexts[i].setParent(cAct);
+ }
+ cAct.getChildrenGraphModel().setStartVertexId(getChildrenGraphModel().getStartVertexId());
+ cAct.getChildrenGraphModel().setEdges(nexts);
+ cAct.getChildrenGraphModel().setVertices(wfVertices);
+ cAct.getChildrenGraphModel().setNextId(getChildrenGraphModel().getNextId());
+ cAct.getChildrenGraphModel().resetVertexOutlines();
+ return cAct;
+ }
+
+ /**
+ * Method hasGoodNumberOfActivity.
+ *
+ * @return boolean
+ */
+
+ public boolean hasGoodNumberOfActivity()
+ {
+ int endingAct = 0;
+ GraphableVertex[] graphableVertices = this.getLayoutableChildren();
+ if (graphableVertices != null)
+ for (int i = 0; i < graphableVertices.length; i++)
+ {
+ WfVertexDef vertex = (WfVertexDef) graphableVertices[i];
+ if (getChildrenGraphModel().getOutEdges(vertex).length == 0)
+ endingAct++;
+ }
+ if (endingAct > 1)
+ return false;
+ return true;
+ }
+
+ /**
+ * @see com.c2kernel.graph.model.GraphableVertex#getPath()
+ */
+ public String getPath()
+ {
+ if (getParent() == null)
+ return getName();
+ return super.getPath();
+ }
+
+ //deprecated
+ public String[] getCastorNonLayoutableChildren() {
+ return new String[0];
+ }
+
+ public void setCastorNonLayoutableChildren(String[] dummy) { }
+}
diff --git a/source/com/c2kernel/lifecycle/JoinDef.java b/source/com/c2kernel/lifecycle/JoinDef.java
new file mode 100755
index 0000000..71bc95c
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/JoinDef.java
@@ -0,0 +1,65 @@
+package com.c2kernel.lifecycle;
+
+import com.c2kernel.lifecycle.instance.Join;
+import com.c2kernel.lifecycle.instance.WfVertex;
+
+/**
+ * @version $Revision: 1.18 $ $Date: 2005/09/29 10:18:31 $
+ * @author $Author: abranson $
+ */
+public class JoinDef extends WfVertexDef
+{
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public JoinDef()
+ {
+ }
+ /**
+ * @see com.c2kernel.lifecycle.WfVertexDef#verify()
+ */
+ public boolean verify()
+ {
+ mErrors.removeAllElements();
+ int nbOutEdges = getOutEdges().length;
+ int nbInEdges = getInEdges().length;
+ String type = (String) getProperties().get("Type");
+ if (nbInEdges < 1)
+ {
+ mErrors.add("not enough previous");
+ return false;
+ }
+ if (type != null && type.equals("Route"))
+ {
+ if (nbInEdges > 1)
+ {
+ mErrors.add("Bad nb of previous");
+ return false;
+ }
+ }
+ if (nbOutEdges > 1)
+ {
+ mErrors.add("too many next");
+ return false;
+ }
+ if (nbOutEdges == 0)
+ {
+ if (!((CompositeActivityDef) getParent()).hasGoodNumberOfActivity())
+ {
+ mErrors.add("too many endpoints");
+ return false;
+ }
+ }
+ return true;
+ }
+ public boolean isJoin()
+ {
+ return true;
+ }
+
+ public WfVertex instantiate() {
+ Join newJoin = new Join();
+ configureInstance(newJoin);
+ return newJoin;
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/LoopDef.java b/source/com/c2kernel/lifecycle/LoopDef.java
new file mode 100755
index 0000000..bee97c5
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/LoopDef.java
@@ -0,0 +1,74 @@
+package com.c2kernel.lifecycle;
+
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.graph.traversal.GraphTraversal;
+import com.c2kernel.lifecycle.instance.Loop;
+import com.c2kernel.lifecycle.instance.WfVertex;
+
+/**
+ * @version $Revision: 1.19 $ $Date: 2005/09/29 10:18:31 $
+ * @author $Author: abranson $
+ */
+
+public class LoopDef extends XOrSplitDef
+{
+ public boolean hasLoop = false;
+ public int isNext = 0;
+
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public LoopDef()
+ {
+ super();
+ }
+
+ /**
+ * @see com.c2kernel.lifecycle.WfVertexDef#loop()
+ */
+ public boolean loop()
+ {
+ return true;
+ }
+
+ /**
+ * @see com.c2kernel.lifecycle.WfVertexDef#verify()
+ */
+ public boolean verify()
+ {
+ if (!super.verify()) return false;
+ Vertex[] nexts = getOutGraphables();
+ Vertex[] anteVertices =
+ GraphTraversal.getTraversal(this.getParent().getChildrenGraphModel(), this, GraphTraversal.kUp, false);
+ int k = 0;
+ int l = 0;
+ Vertex[] brothers = getParent().getChildren();
+ for (int i = 0; i < brothers.length; i++)
+ if (brothers[i] instanceof LoopDef) l++;
+ for (int i = 0; i < nexts.length; i++)
+ for (int j = 0; j < anteVertices.length; j++)
+ if (nexts[i].equals(anteVertices[j]))
+ k++;
+ if (k != 1 && !(l>1))
+ {
+ mErrors.add("bad number of pointing back nexts");
+ return false;
+ }
+// if (nexts.length>2) {
+// mErrors.add("you must only have 2 nexts");
+// return false;
+// }
+ return true;
+ }
+
+ public boolean isLoop() {
+ return true;
+ }
+
+ public WfVertex instantiate() {
+ Loop newLoop = new Loop();
+ configureInstance(newLoop);
+ return newLoop;
+ }
+
+}
diff --git a/source/com/c2kernel/lifecycle/NextDef.java b/source/com/c2kernel/lifecycle/NextDef.java
new file mode 100755
index 0000000..6bddabf
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/NextDef.java
@@ -0,0 +1,94 @@
+package com.c2kernel.lifecycle;
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.graph.model.GraphableEdge;
+import com.c2kernel.lifecycle.instance.Next;
+/**
+ * @version $Revision: 1.32 $ $Date: 2006/03/03 13:52:21 $
+ * @author $Author: abranson $
+ */
+public class NextDef extends GraphableEdge
+{
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public NextDef()
+ {
+ }
+ /**
+ * Method verify.
+ *
+ * @return boolean
+ */
+ public boolean verify()
+ {
+ return true;
+ }
+ /**
+ * Method NextDef.
+ *
+ * @param pre
+ * @param nex
+ */
+ /** create and initialize a link between an Activities */
+ public NextDef(WfVertexDef pre, WfVertexDef nex)
+ {
+ setParent(pre.getParent());
+ if (pre instanceof OrSplitDef || pre instanceof XOrSplitDef)
+ {
+ int num = pre.getOutGraphables().length;
+ try
+ {
+ num = Integer.parseInt((String) pre.getProperties().get("LastNum"));
+ }
+ catch (Exception e)
+ {
+ }
+ getProperties().put("Alias", String.valueOf(num));
+ pre.getProperties().put("LastNum", String.valueOf(num + 1));
+ }
+ }
+ public boolean containsPoint(GraphPoint p)
+ {
+ GraphPoint originPoint = getOriginPoint();
+ GraphPoint terminusPoint = getTerminusPoint();
+ GraphPoint midPoint = new GraphPoint();
+ if (("Broken +".equals(getProperties().get("Type"))))
+ {
+ midPoint.x = (originPoint.x + terminusPoint.x) / 2;
+ midPoint.y = (originPoint.y + terminusPoint.y) / 2;
+ }
+ else if (("Broken -".equals(getProperties().get("Type"))))
+ {
+ boolean arrowOnY = !(originPoint.y - terminusPoint.y < 60 && originPoint.y - terminusPoint.y > -60);
+ midPoint.x = arrowOnY ? terminusPoint.x : (originPoint.x + terminusPoint.x) / 2;
+ midPoint.y = arrowOnY ? (originPoint.y + terminusPoint.y) / 2 : originPoint.y;
+ }
+ else if (("Broken |".equals(getProperties().get("Type"))))
+ {
+ boolean arrowOnY = !(originPoint.y - terminusPoint.y < 60 && originPoint.y - terminusPoint.y > -60);
+ midPoint.x = arrowOnY ? originPoint.x : (originPoint.x + terminusPoint.x) / 2;
+ midPoint.y = arrowOnY ? (originPoint.y + terminusPoint.y) / 2 : terminusPoint.y;
+ }
+ else
+ {
+ midPoint.x = originPoint.x + (terminusPoint.x - originPoint.x) / 2;
+ midPoint.y = originPoint.y + (terminusPoint.y - originPoint.y) / 2;
+ }
+ int minX = midPoint.x - 10;
+ int minY = midPoint.y - 10;
+ int maxX = midPoint.x + 10;
+ int maxY = midPoint.y + 10;
+ return (p.x >= minX) && (p.x <= maxX) && (p.y >= minY) && (p.y <= maxY);
+ }
+
+ public Next instantiate() {
+ Next next = new Next();
+ next.setID(getID());
+ next.setOriginVertexId(getOriginVertexId());
+ next.setTerminusVertexId(getTerminusVertexId());
+ next.setProperties(getProperties());
+ next.setOriginPoint(getOriginPoint());
+ next.setTerminusPoint(getTerminusPoint());
+ return next;
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/OrSplitDef.java b/source/com/c2kernel/lifecycle/OrSplitDef.java
new file mode 100755
index 0000000..14931a1
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/OrSplitDef.java
@@ -0,0 +1,23 @@
+package com.c2kernel.lifecycle;
+import com.c2kernel.lifecycle.instance.OrSplit;
+import com.c2kernel.lifecycle.instance.WfVertex;
+/**
+ * @version $Revision: 1.13 $ $Date: 2005/12/01 14:23:15 $
+ * @author $Author: abranson $
+ */
+public class OrSplitDef extends AndSplitDef
+{
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public OrSplitDef()
+ {
+ super();
+ }
+
+ public WfVertex instantiate() {
+ OrSplit newSplit = new OrSplit();
+ configureInstance(newSplit);
+ return newSplit;
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/WfCastorHashMap.java b/source/com/c2kernel/lifecycle/WfCastorHashMap.java
new file mode 100755
index 0000000..1e6a308
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/WfCastorHashMap.java
@@ -0,0 +1,33 @@
+package com.c2kernel.lifecycle;
+import com.c2kernel.lifecycle.instance.stateMachine.StateMachine;
+import com.c2kernel.utils.CastorHashMap;
+/**
+ * @version $Revision: 1.29 $ $Date: 2005/05/20 13:07:13 $
+ * @author $Author: abranson $
+ */
+public class WfCastorHashMap extends CastorHashMap
+{
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public WfCastorHashMap()
+ {
+ put(StateMachine.AUTOSTART, new Boolean(true));
+ put(StateMachine.SKIPPABLE, new Boolean(true));
+ put(StateMachine.REPEATABLE, new Boolean(true));
+ put(StateMachine.IGNORABLE, new Boolean(false));
+ put("AlwaysUseOutcome", new Boolean(false));
+ put("Viewpoint", "");
+ put("Show time", new Boolean(true));
+ put("Description", "");
+ put("Mail Message", "");
+ put("Mail event", "");
+ put("Agent Role", "");
+ put("Agent Name", "");
+ put("SchemaType", "");
+ put("SchemaVersion", "");
+ put("ScriptName", "");
+ put("ScriptVersion", "");
+ put("Viewpoint", "");
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/WfVertexDef.java b/source/com/c2kernel/lifecycle/WfVertexDef.java
new file mode 100755
index 0000000..a7bfd5a
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/WfVertexDef.java
@@ -0,0 +1,83 @@
+package com.c2kernel.lifecycle;
+
+import java.util.Vector;
+
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.graph.model.GraphableVertex;
+import com.c2kernel.lifecycle.instance.WfVertex;
+import com.c2kernel.utils.KeyValuePair;
+
+/**
+ * @version $Revision: 1.22 $ $Date: 2005/11/15 15:56:38 $
+ * @author $Author: abranson $
+ */
+public abstract class WfVertexDef extends GraphableVertex
+{
+ public Vector mErrors;
+
+ protected boolean loopTested;
+
+ /**
+ * @see java.lang.Object#Object()
+ */
+ /** @label wf */
+ public WfVertexDef()
+ {
+ mErrors = new Vector(0, 1);
+ setIsLayoutable(true);
+ }
+
+ public abstract WfVertex instantiate() throws ObjectNotFoundException, InvalidDataException;
+
+ public void configureInstance(WfVertex newVertex) {
+ KeyValuePair[] k = getProperties().getKeyValuePairs();
+ for (int i = 0; i < k.length; i++)
+ newVertex.getProperties().put(k[i].getKey(), k[i].getValue());
+ newVertex.setID(getID());
+ if (getIsLayoutable()) {
+ newVertex.setInEdgeIds(getInEdgeIds());
+ newVertex.setOutEdgeIds(getOutEdgeIds());
+ newVertex.setCentrePoint(getCentrePoint());
+ newVertex.setOutlinePoints(getOutlinePoints());
+ }
+ }
+
+ /**
+ * Method verify.
+ *
+ * @return boolean
+ */
+ public abstract boolean verify();
+
+ /**
+ * Method getErrors.
+ *
+ * @return String
+ */
+ public String getErrors()
+ {
+ if (mErrors.size() == 0)
+ return "No error";
+ else
+ return (String) mErrors.elementAt(0);
+ }
+
+ /**
+ * Method loop.
+ *
+ * @return boolean
+ */
+ public boolean loop()
+ {
+ boolean loop2 = false;
+ if (!loopTested)
+ {
+ loopTested = true;
+ if (getOutGraphables().length != 0)
+ loop2 = ((WfVertexDef) getOutGraphables()[0]).loop();
+ }
+ loopTested = false;
+ return loop2;
+ }
+} \ No newline at end of file
diff --git a/source/com/c2kernel/lifecycle/XOrSplitDef.java b/source/com/c2kernel/lifecycle/XOrSplitDef.java
new file mode 100755
index 0000000..550fb88
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/XOrSplitDef.java
@@ -0,0 +1,28 @@
+
+package com.c2kernel.lifecycle;
+
+import com.c2kernel.lifecycle.instance.WfVertex;
+import com.c2kernel.lifecycle.instance.XOrSplit;
+
+
+/**
+ * @version $Revision: 1.14 $ $Date: 2005/09/29 10:18:31 $
+ * @author $Author: abranson $
+ */
+
+public class XOrSplitDef extends AndSplitDef
+{
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public XOrSplitDef()
+ {
+ super();
+ }
+
+ public WfVertex instantiate() {
+ XOrSplit newSplit = new XOrSplit();
+ configureInstance(newSplit);
+ return newSplit;
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/chooser/ActivityChooser.java b/source/com/c2kernel/lifecycle/chooser/ActivityChooser.java
new file mode 100755
index 0000000..f79dedf
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/chooser/ActivityChooser.java
@@ -0,0 +1,200 @@
+/*
+ * Created on 1 sept. 2003
+ *
+ * To change the template for this generated file go to Window>Preferences>Java>Code Generation>Code and Comments
+ */
+package com.c2kernel.lifecycle.chooser;
+
+import java.awt.Container;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.HashMap;
+
+import javax.swing.BorderFactory;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+import com.c2kernel.lifecycle.ActivityDef;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.LocalObjectLoader;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.Resource;
+
+/**
+ * @author Developpement
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class ActivityChooser extends JFrame
+{
+ private LDAPFileChooser mLDAPFileChooserActivity = null;
+
+ private JButton mButtonOK = null;
+
+ private JButton mButtonCancel = null;
+
+ private JPanel mJPanelVertical = null;
+
+ private JPanel mJPanelHorizontal = null;
+
+ private String mMessage = "Choose or modify";
+
+ private WorkflowDialogue mParent = null;
+
+ private JLabel label = null;
+
+ HashMap mhashmap = null;
+
+ public ActivityChooser(String message, String title, Image img, WorkflowDialogue parent, HashMap hashmap)
+ {
+ super(title);
+ mMessage = message;
+ img = Resource.getImageResource("graph/newvertex_large.png").getImage();
+ setIconImage(img);
+ mParent = parent;
+ mhashmap = hashmap;
+ initialize();
+ }
+
+ private JButton getJButtonOK()
+ {
+ if (mButtonOK == null)
+ mButtonOK = new JButton(Language.translate("OK"));
+ return mButtonOK;
+ }
+
+ private JButton getJButtonCancel()
+ {
+ if (mButtonCancel == null)
+ mButtonCancel = new JButton(Language.translate("Cancel"));
+ return mButtonCancel;
+ }
+
+ private LDAPFileChooser getLDAPFileChooserActivity()
+ {
+ if (mLDAPFileChooserActivity == null)
+ {
+ try
+ {
+ mLDAPFileChooserActivity = new LDAPFileChooser(LDAPFileChooser.ACTIVITY_CHOOSER);
+ mLDAPFileChooserActivity.setName("LDAPFileChooserRouting");
+ mLDAPFileChooserActivity.setEditable(false);
+ //mLDAPFileChooserActivity.setBounds(125, 13, 400, 19);
+ } catch (Exception mExc)
+ {
+ Logger.error(mExc);
+ }
+ }
+ return mLDAPFileChooserActivity;
+ }
+
+ private void initialize()
+ {
+ getJButtonOK().addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ try
+ {
+ ActivityDef act = LocalObjectLoader.getActDef(mLDAPFileChooserActivity.getEntryName(), "last");
+ } catch (Exception ex)
+ {
+ }
+ Logger.debug(5, "mLDAPFileChooserActivity.getEntryName()" + mLDAPFileChooserActivity.getEntryName());
+ setCursor(new Cursor(Cursor.WAIT_CURSOR));
+ mParent.loadThisWorkflow(mLDAPFileChooserActivity.getEntryName(), mhashmap);
+ setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
+ close();
+ }
+ });
+ getJButtonCancel().addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ close();
+ }
+ });
+ //getContentPane().add(getJPanelVertical());
+ Container contentPane = getContentPane();
+ contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
+ contentPane.add(getJPanelVertical());
+ contentPane.add(getJPanelHorizontal());
+ contentPane.add(Box.createGlue());
+ Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
+ setLocation((d.width - getWidth()) / 2, (d.height - getHeight()) / 2);
+ setResizable(true);
+ pack();
+ setSize(new Dimension(getWidth(), getJButtonCancel().getHeight() + getLDAPFileChooserActivity().getHeight() + label.getHeight() + 100));
+ setVisible(true);
+ setVisible(true);
+ }
+
+ private void close()
+ {
+ mParent = null;
+ this.setEnabled(false);
+ this.setVisible(false);
+ }
+
+ private JPanel getJPanelVertical()
+ {
+ if (mJPanelVertical == null)
+ {
+ try
+ {
+ Logger.debug(8, "Panel button");
+ mJPanelVertical = new JPanel();
+ mJPanelVertical.setName("JPanelV");
+ mJPanelVertical.setLayout(new BoxLayout(mJPanelVertical, BoxLayout.Y_AXIS));
+ label = new JLabel(mMessage);
+ JPanel labelP = new JPanel();
+ labelP.setLayout(new BoxLayout(labelP, BoxLayout.X_AXIS));
+ labelP.add(label);
+ labelP.add(Box.createGlue());
+ mJPanelVertical.add(labelP);
+ mJPanelVertical.add(Box.createRigidArea(new Dimension(0, 5)));
+ mJPanelVertical.add(getLDAPFileChooserActivity(), getLDAPFileChooserActivity().getName());
+ //mJPanelVertical.add(Box.createRigidArea(new Dimension(0,
+ // 10)));
+ mJPanelVertical.add(Box.createGlue());
+ mJPanelVertical.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+ mJPanelVertical.setVisible(true);
+ } catch (java.lang.Throwable mExc)
+ {
+ //handleException(mExc);
+ }
+ }
+ return mJPanelVertical;
+ }
+
+ private JPanel getJPanelHorizontal()
+ {
+ if (mJPanelHorizontal == null)
+ {
+ try
+ {
+ Logger.debug(8, "Panel button");
+ mJPanelHorizontal = new JPanel();
+ mJPanelHorizontal.setName("JPanelH");
+ mJPanelHorizontal.setLayout(new BoxLayout(mJPanelHorizontal, BoxLayout.X_AXIS));
+ mJPanelHorizontal.add(getJButtonOK(), getJButtonOK().getName());
+ mJPanelHorizontal.add(Box.createRigidArea(new Dimension(10, 0)));
+ mJPanelHorizontal.add(getJButtonCancel(), getJButtonCancel().getName());
+ mJPanelHorizontal.setVisible(true);
+ } catch (java.lang.Throwable mExc)
+ {
+ //handleException(mExc);
+ }
+ }
+ return mJPanelHorizontal;
+ }
+} \ No newline at end of file
diff --git a/source/com/c2kernel/lifecycle/chooser/LDAPEntryChooser.java b/source/com/c2kernel/lifecycle/chooser/LDAPEntryChooser.java
new file mode 100755
index 0000000..c2cdb0c
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/chooser/LDAPEntryChooser.java
@@ -0,0 +1,70 @@
+package com.c2kernel.lifecycle.chooser;
+/**
+ * @version $Revision: 1.2 $ $Date: 2005/12/01 14:23:15 $
+ * @author $Author: abranson $
+ */
+
+import java.awt.Dimension;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+
+import javax.swing.JComboBox;
+
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Logger;
+
+public class LDAPEntryChooser extends JComboBox
+{
+
+ DomainPath mDomainPath = null;
+ ArrayList<String> allItems = new ArrayList<String>();
+
+ public LDAPEntryChooser(DomainPath domPath, boolean editable)
+ {
+ super();
+ setEditable(editable);
+ mDomainPath = domPath;
+ initialise();
+ }
+
+ private void initialise()
+ {
+ try
+ {
+ Enumeration children = Gateway.getLDAPLookup().searchAliases(mDomainPath);
+ while (children.hasMoreElements())
+ {
+ DomainPath domPath = (DomainPath)children.nextElement();
+ allItems.add(domPath.getName());
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.exceptionDialog(ex);
+ }
+
+ Collections.sort(allItems);
+ addItem("");
+ for (String element : allItems) {
+ addItem(element);
+ }
+
+ }
+
+ public void reload()
+ {
+ removeAllItems();
+ initialise();
+ }
+
+ public synchronized Dimension getSize()
+ {
+ if ("1".equals(Gateway.getProperty("ResizeCombo")))
+ return new Dimension(super.getSize().width<400?400:super.getSize().width,super.getSize().height);
+ return super.getSize();
+ }
+
+}
diff --git a/source/com/c2kernel/lifecycle/chooser/LDAPFileChooser.java b/source/com/c2kernel/lifecycle/chooser/LDAPFileChooser.java
new file mode 100755
index 0000000..08f4387
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/chooser/LDAPFileChooser.java
@@ -0,0 +1,119 @@
+package com.c2kernel.lifecycle.chooser;
+import java.awt.Dimension;
+import java.awt.event.ItemListener;
+import java.util.HashMap;
+
+import javax.swing.BoxLayout;
+import javax.swing.JPanel;
+
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.utils.Logger;
+
+//import fr.agilium.gui.tabs.wfPropertiesViewer.JPanelTabbedProperties;
+/**
+ * @version $Revision: 1.2 $ $Date: 2005/06/27 15:16:12 $
+ * @author $Author: abranson $
+ */
+
+public class LDAPFileChooser extends JPanel
+{
+ public static String SCRIPT_CHOOSER = "Script";
+ public static String SCHEMA_CHOOSER = "Schema";
+ public static String ACTIVITY_CHOOSER = "Activity";
+ private String chooserMode = null;
+ private HashMap mHashList = null;
+ public LDAPEntryChooser mLec;
+ private boolean mEditable = false;
+ DomainPath domainPath;
+ String itemQuery = null;
+ boolean showversion = true;
+
+ public LDAPFileChooser(String choose)
+ {
+ super();
+ chooserMode = choose;
+ initialise();
+ }
+
+ private void initialise()
+ {
+ if (chooserMode.equals(SCHEMA_CHOOSER))
+ {
+ itemQuery = ClusterStorage.VIEWPOINT + "/Schema/all";
+ domainPath = new DomainPath("/desc/OutcomeDesc/");
+ }
+ else if (chooserMode.equals(SCRIPT_CHOOSER))
+ {
+ itemQuery = ClusterStorage.VIEWPOINT + "/Script/all";
+ domainPath = new DomainPath("/desc/Script/");
+ }
+ else if (chooserMode.equals(ACTIVITY_CHOOSER))
+ {
+ domainPath = new DomainPath("/desc/ActivityDesc/");
+ showversion = false;
+ }
+ else
+ return;
+ mLec = new LDAPEntryChooser(domainPath, mEditable);
+
+ mLec.setPreferredSize(new Dimension(220, 19));
+ mLec.setMaximumSize(new Dimension(3000, 22));
+ mLec.setMinimumSize(new Dimension(50, 19));
+ //mLec.getRenderer().getListCellRendererComponent();
+
+ BoxLayout blyt = new BoxLayout(this, BoxLayout.X_AXIS);
+ setLayout(blyt);
+ add(mLec);
+ mLec.setVisible(true);
+ this.validate();
+ this.setVisible(true);
+
+ }
+
+ public String getEntryName()
+ {
+ return (String) mLec.getSelectedItem();
+ }
+
+ public void addItemListener(ItemListener il)
+ {
+ mLec.addItemListener(il);
+ }
+ public void setSelectedItem(String name, String version)
+ {
+ Logger.debug(5,"setSelectedItem " + name + " " + version);
+ if (name == null||name.equals("-1")) name="";
+ mLec.setSelectedItem(name);
+ }
+
+ public void reload()
+ {
+ mLec.reload();
+ }
+
+ public void removeAllItems()
+ {
+ mLec.removeAllItems();
+ }
+
+ /**
+ * @param b
+ */
+ public void setEditable(boolean b)
+ {
+ mEditable = b;
+ mLec.setEditable(b);
+ }
+
+ public void updateUI()
+ {
+ if (mLec!=null) mLec.updateUI();
+ super.updateUI();
+ }
+
+ public void setEnabled(boolean enabled)
+ {
+ mLec.setEnabled(enabled);
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/chooser/WorkflowDialogue.java b/source/com/c2kernel/lifecycle/chooser/WorkflowDialogue.java
new file mode 100755
index 0000000..8453ad2
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/chooser/WorkflowDialogue.java
@@ -0,0 +1,20 @@
+/*
+ * Created on 2 sept. 2003
+ *
+ * To change the template for this generated file go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+package com.c2kernel.lifecycle.chooser;
+
+import java.util.HashMap;
+
+/**
+ * @author Developpement
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public interface WorkflowDialogue
+{
+ public void loadThisWorkflow(String name, HashMap hashMap);
+}
diff --git a/source/com/c2kernel/lifecycle/gui/model/WfDefGraphPanel.java b/source/com/c2kernel/lifecycle/gui/model/WfDefGraphPanel.java
new file mode 100755
index 0000000..973fcbf
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/gui/model/WfDefGraphPanel.java
@@ -0,0 +1,58 @@
+/*Created on 21 nov. 2003 */
+package com.c2kernel.lifecycle.gui.model;
+
+import java.awt.Graphics2D;
+
+import com.c2kernel.graph.model.DirectedEdge;
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.graph.view.DirectedEdgeRenderer;
+import com.c2kernel.graph.view.GraphPanel;
+import com.c2kernel.graph.view.VertexRenderer;
+import com.c2kernel.lifecycle.NextDef;
+
+/** @author XSeb74*/
+public class WfDefGraphPanel extends GraphPanel
+{
+ public WfDefGraphPanel(DirectedEdgeRenderer d,VertexRenderer v)
+ {
+ super(d,v);
+ }
+ // Draws the highlight of the specified edge
+ protected void drawEdgeHighlight(Graphics2D g2d, DirectedEdge edge)
+ {
+ GraphPoint originPoint = edge.getOriginPoint();
+ GraphPoint terminusPoint = edge.getTerminusPoint();
+ GraphPoint midPoint = new GraphPoint();
+
+ if ("Straight".equals(((NextDef)edge).getProperties().get("Type")) || ((NextDef)edge).getProperties().get("Type") == null)
+ {
+ midPoint.x = originPoint.x + (terminusPoint.x - originPoint.x) / 2;
+ midPoint.y = originPoint.y + (terminusPoint.y - originPoint.y) / 2;
+ }
+ else if (("Broken +".equals(((NextDef)edge).getProperties().get("Type"))))
+ {
+ midPoint.x = (originPoint.x + terminusPoint.x) / 2;
+ midPoint.y = (originPoint.y + terminusPoint.y) / 2;
+ }
+ else if (("Broken -".equals(((NextDef)edge).getProperties().get("Type"))))
+ {
+ boolean arrowOnY = !(originPoint.y - terminusPoint.y < 60 && originPoint.y - terminusPoint.y > -60);
+ midPoint.x = arrowOnY ? terminusPoint.x : (originPoint.x + terminusPoint.x) / 2;
+ midPoint.y = arrowOnY ? (originPoint.y + terminusPoint.y) / 2 : originPoint.y;
+ }
+ else if (("Broken |".equals(((NextDef)edge).getProperties().get("Type"))))
+ {
+ boolean arrowOnY = !(originPoint.y - terminusPoint.y < 60 && originPoint.y - terminusPoint.y > -60);
+ midPoint.x = arrowOnY ? originPoint.x : (originPoint.x + terminusPoint.x) / 2;
+ midPoint.y = arrowOnY ? (originPoint.y + terminusPoint.y) / 2 : terminusPoint.y;
+ }
+ int minX = midPoint.x - 10;
+ int minY = midPoint.y - 10;
+ int maxX = midPoint.x + 10;
+ int maxY = midPoint.y + 10;
+ g2d.drawLine(minX, minY, maxX, minY);
+ g2d.drawLine(maxX, minY, maxX, maxY);
+ g2d.drawLine(maxX, maxY, minX, maxY);
+ g2d.drawLine(minX, maxY, minX, minY);
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/gui/model/WfEdgeDefFactory.java b/source/com/c2kernel/lifecycle/gui/model/WfEdgeDefFactory.java
new file mode 100755
index 0000000..d6fd41c
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/gui/model/WfEdgeDefFactory.java
@@ -0,0 +1,29 @@
+package com.c2kernel.lifecycle.gui.model;
+import com.c2kernel.graph.model.DirectedEdge;
+import com.c2kernel.graph.model.EdgeFactory;
+import com.c2kernel.graph.model.GraphModelManager;
+import com.c2kernel.graph.model.TypeNameAndConstructionInfo;
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.lifecycle.NextDef;
+import com.c2kernel.lifecycle.WfVertexDef;
+public class WfEdgeDefFactory implements EdgeFactory
+{
+ public void create(
+ GraphModelManager graphModelManager,
+ Vertex origin,
+ Vertex terminus,
+ TypeNameAndConstructionInfo typeNameAndConstructionInfo)
+ {
+ if (validCreation(graphModelManager, origin, terminus))
+ {
+ NextDef nextDef = new NextDef((WfVertexDef) origin, (WfVertexDef) terminus);
+ graphModelManager.getModel().addEdgeAndCreateId(nextDef, origin, terminus);
+ }
+ }
+ private boolean validCreation(GraphModelManager graphModelManager, Vertex origin, Vertex terminus)
+ {
+ DirectedEdge[] connectingEdgesAToB = graphModelManager.getModel().getConnectingEdges(origin.getID(), terminus.getID());
+ DirectedEdge[] connectingEdgesBToA = graphModelManager.getModel().getConnectingEdges(terminus.getID(), origin.getID());
+ return (origin != terminus) && (connectingEdgesAToB.length == 0) && (connectingEdgesBToA.length == 0);
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/gui/model/WfVertexDefFactory.java b/source/com/c2kernel/lifecycle/gui/model/WfVertexDefFactory.java
new file mode 100755
index 0000000..0cb60e7
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/gui/model/WfVertexDefFactory.java
@@ -0,0 +1,93 @@
+package com.c2kernel.lifecycle.gui.model;
+import java.awt.Point;
+import java.util.HashMap;
+
+import javax.swing.JOptionPane;
+
+import com.c2kernel.graph.model.GraphModelManager;
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.graph.model.TypeNameAndConstructionInfo;
+import com.c2kernel.graph.model.VertexFactory;
+import com.c2kernel.lifecycle.ActivityDef;
+import com.c2kernel.lifecycle.CompositeActivityDef;
+import com.c2kernel.lifecycle.chooser.ActivityChooser;
+import com.c2kernel.lifecycle.chooser.WorkflowDialogue;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.LocalObjectLoader;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.Resource;
+public class WfVertexDefFactory implements VertexFactory, WorkflowDialogue
+{
+ protected CompositeActivityDef mCompositeActivityDef = null;
+ public void create(GraphModelManager graphModelManager, Point location, TypeNameAndConstructionInfo typeNameAndConstructionInfo)
+ {
+ String vertexTypeId = null;
+ if (mCompositeActivityDef != null && typeNameAndConstructionInfo.mInfo instanceof String)
+ {
+ vertexTypeId = (String) typeNameAndConstructionInfo.mInfo;
+ if (vertexTypeId.equals("Atomic") || vertexTypeId.equals("Composite"))
+ {
+ // ask for a name
+ HashMap mhm = new HashMap();
+ mhm.put("P1", vertexTypeId);
+ mhm.put("P2", location);
+ //************************************************
+ ActivityChooser a =
+ new ActivityChooser(
+ Language.translate("Please enter a Type for the new activityDef"),
+ Language.translate("New " + vertexTypeId + " Activity"),
+ Resource.getImageResource("graph/newvertex_large.png").getImage(),
+ this,
+ mhm);
+ a.setVisible(true);
+ }
+ else
+ mCompositeActivityDef.newChild("", vertexTypeId, location);
+ }
+ }
+ public void loadThisWorkflow(String newName, HashMap hashMap)
+ {
+ String vertexTypeId = (String) hashMap.get("P1");
+ Point location = (Point) hashMap.get("P2");
+ if (newName == null || newName.equals(""))
+ return;
+ Logger.debug(5, newName);
+ ActivityDef act = (ActivityDef) mCompositeActivityDef.search(mCompositeActivityDef.getID() + "/" + newName);
+ if (act != null)
+ {
+ String unicName = newName;
+ while (unicName == null
+ || unicName == ""
+ || mCompositeActivityDef.search(mCompositeActivityDef.getID() + "/" + unicName) != null)
+ unicName =
+ (String) JOptionPane.showInputDialog(
+ null,
+ Language.translate("Please type a Name"),
+ Language.translate("New " + vertexTypeId + " Activity"),
+ JOptionPane.QUESTION_MESSAGE,
+ Resource.getImageResource("graph/newvertex_large.png"),
+ null,
+ null);
+ act = (ActivityDef) mCompositeActivityDef.search(mCompositeActivityDef.getID() + "/" + newName);
+ mCompositeActivityDef.addExistingActivityDef(unicName, act, new GraphPoint(location.x, location.y));
+ }
+ else
+ {
+ try
+ {
+ act = LocalObjectLoader.getActDef(newName, "last");
+ }
+ catch (Exception ex)
+ {
+ Logger.exceptionDialog(ex);
+ return;
+ }
+ mCompositeActivityDef.newChild(newName, vertexTypeId, location);
+ }
+ }
+ public void setCreationContext(Object newContext)
+ {
+ if (newContext != null && newContext instanceof CompositeActivityDef)
+ mCompositeActivityDef = (CompositeActivityDef) newContext;
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/gui/model/WfVertexDefOutlineCreator.java b/source/com/c2kernel/lifecycle/gui/model/WfVertexDefOutlineCreator.java
new file mode 100755
index 0000000..3727f35
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/gui/model/WfVertexDefOutlineCreator.java
@@ -0,0 +1,50 @@
+package com.c2kernel.lifecycle.gui.model;
+
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.graph.model.VertexOutlineCreator;
+import com.c2kernel.lifecycle.ActivitySlotDef;
+
+public class WfVertexDefOutlineCreator implements VertexOutlineCreator
+{
+ private final int mActivityWidth = 130;
+ private final int mActivityHeight = 60;
+ private final int mSplitJoinWidth = 60;
+ private final int mSplitJoinHeight = 25;
+
+ public void setOutline(Vertex vertex)
+ {
+ GraphPoint centrePoint = vertex.getCentrePoint();
+ GraphPoint[] outlinePoints = new GraphPoint[ 4 ];
+ int vertexWidth = 0;
+ int vertexHeight = 0;
+
+
+ if ( vertex instanceof ActivitySlotDef )
+ {
+ vertexWidth = mActivityWidth;
+ vertexHeight = mActivityHeight;
+ }
+ else
+ {
+ vertexWidth = mSplitJoinWidth;
+ vertexHeight = mSplitJoinHeight;
+ }
+
+ outlinePoints[ 0 ] = new GraphPoint();
+ outlinePoints[ 0 ].x = centrePoint.x - vertexWidth / 2;
+ outlinePoints[ 0 ].y = centrePoint.y - vertexHeight / 2;
+ outlinePoints[ 1 ] = new GraphPoint();
+ outlinePoints[ 1 ].x = centrePoint.x + vertexWidth / 2;
+ outlinePoints[ 1 ].y = centrePoint.y - vertexHeight / 2;
+ outlinePoints[ 2 ] = new GraphPoint();
+ outlinePoints[ 2 ].x = centrePoint.x + vertexWidth / 2;
+ outlinePoints[ 2 ].y = centrePoint.y + vertexHeight / 2;
+ outlinePoints[ 3 ] = new GraphPoint();
+ outlinePoints[ 3 ].x = centrePoint.x - vertexWidth / 2;
+ outlinePoints[ 3 ].y = centrePoint.y + vertexHeight / 2;
+
+ vertex.setOutlinePoints( outlinePoints );
+ }
+}
+
diff --git a/source/com/c2kernel/lifecycle/gui/view/ActivitySlotDefRenderer.java b/source/com/c2kernel/lifecycle/gui/view/ActivitySlotDefRenderer.java
new file mode 100755
index 0000000..5746673
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/gui/view/ActivitySlotDefRenderer.java
@@ -0,0 +1,70 @@
+package com.c2kernel.lifecycle.gui.view;
+
+import java.awt.Color;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.Paint;
+
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.graph.view.VertexRenderer;
+import com.c2kernel.lifecycle.ActivitySlotDef;
+import com.c2kernel.utils.Language;
+
+public class ActivitySlotDefRenderer implements VertexRenderer
+{
+ private Paint mInactivePaint = new Color(255, 255, 255);
+ private Paint mErrorPaint = new Color( 255, 50, 0 );
+ private Paint mCompositePaint= new Color(200, 200, 255);
+ private Paint mTextPaint = Color.black;
+
+
+ public void draw( Graphics2D g2d, Vertex vertex)
+ {
+ ActivitySlotDef activitySlotDef = ( ActivitySlotDef )vertex;
+ boolean hasError = activitySlotDef.verify();
+ boolean isComposite = false;
+ isComposite = activitySlotDef.getIsComposite();
+ GraphPoint centrePoint = activitySlotDef.getCentrePoint();
+ int vertexHeight = activitySlotDef.getHeight();
+ int vertexWidth = activitySlotDef.getWidth();
+
+ String[] linesOfText = new String[2+(hasError?0:1)];
+ FontMetrics metrics = g2d.getFontMetrics();
+ int lineWidth = 0;
+ int lineHeight = metrics.getHeight();
+ int linesHeight = lineHeight * linesOfText.length;
+ int linesStartY = centrePoint.y - linesHeight / 2 + lineHeight * 2 / 3;
+ int x = 0;
+ int y = 0;
+ int i = 0;
+
+ linesOfText[0]="("+activitySlotDef.getActivityDef()+")";
+ linesOfText[1]=(String)activitySlotDef.getProperties().get("Name");
+
+ if (!hasError)linesOfText[2]=Language.translate(activitySlotDef.getErrors());
+
+ g2d.setPaint( !hasError ? mErrorPaint : isComposite ? mCompositePaint : mInactivePaint );
+ g2d.fill3DRect
+ (
+ centrePoint.x - vertexWidth / 2,
+ centrePoint.y - vertexHeight / 2,
+ vertexWidth,
+ vertexHeight,
+ true
+ );
+
+ g2d.setPaint( mTextPaint );
+
+ // Draw the lines of text
+ for ( i = 0; i < linesOfText.length; i++ )
+ {
+ if (linesOfText[i] == null) linesOfText[i] = "";
+ lineWidth = metrics.stringWidth( linesOfText[ i ] );
+ x = centrePoint.x - lineWidth / 2;
+ y = linesStartY + i * lineHeight;
+ g2d.drawString( linesOfText[ i ], x, y );
+ }
+ }
+}
+
diff --git a/source/com/c2kernel/lifecycle/gui/view/CompActDefOutcomeHandler.java b/source/com/c2kernel/lifecycle/gui/view/CompActDefOutcomeHandler.java
new file mode 100755
index 0000000..cb0ef59
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/gui/view/CompActDefOutcomeHandler.java
@@ -0,0 +1,218 @@
+package com.c2kernel.lifecycle.gui.view;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+
+import javax.swing.JButton;
+import javax.swing.JFileChooser;
+import javax.swing.JPanel;
+import javax.swing.JSplitPane;
+
+import com.c2kernel.graph.layout.DefaultGraphLayoutGenerator;
+import com.c2kernel.graph.view.EditorPanel;
+import com.c2kernel.graph.view.VertexPropertyPanel;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.gui.tabs.outcome.*;
+import com.c2kernel.lifecycle.CompositeActivityDef;
+import com.c2kernel.lifecycle.gui.model.WfDefGraphPanel;
+import com.c2kernel.lifecycle.gui.model.WfEdgeDefFactory;
+import com.c2kernel.lifecycle.gui.model.WfVertexDefFactory;
+import com.c2kernel.lifecycle.gui.model.WfVertexDefOutlineCreator;
+import com.c2kernel.lifecycle.instance.gui.view.FindActDefPanel;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.FileStringUtility;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.Resource;
+
+/**************************************************************************
+ *
+ * $Revision: 1.14 $
+ * $Date: 2005/09/07 13:46:31 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class CompActDefOutcomeHandler
+ extends JPanel
+ implements OutcomeHandler {
+
+ protected JButton mLoadButton = new JButton(Resource.getImageResource("graph/load.png"));
+ protected JButton mLayoutButton = new JButton(Resource.getImageResource("graph/autolayout.png"));
+ protected JButton[] mOtherToolBarButtons = { mLayoutButton, mLoadButton };
+
+ protected CompositeActivityDef mCompActDef = null;
+ protected WfEdgeDefFactory mWfEdgeDefFactory = new WfEdgeDefFactory();
+ protected WfVertexDefFactory mWfVertexDefFactory = new WfVertexDefFactory();
+
+ protected EditorPanel mEditorPanel;
+ protected VertexPropertyPanel mPropertyPanel;
+ protected JSplitPane mSplitPane;
+ boolean unsaved;
+
+ public CompActDefOutcomeHandler() {
+ super();
+ mPropertyPanel = loadPropertyPanel();
+ mPropertyPanel.createLayout(new FindActDefPanel());
+ mEditorPanel =
+ new EditorPanel(
+ mWfEdgeDefFactory,
+ mWfVertexDefFactory,
+ new WfVertexDefOutlineCreator(),
+ true,
+ mOtherToolBarButtons,
+ new WfDefGraphPanel(new WfDirectedEdgeDefRenderer(),
+ new WfVertexDefRenderer()));
+ }
+
+ protected void createLayout()
+ {
+ mLoadButton.setToolTipText("Load from local disc");
+ mLayoutButton.setToolTipText("Auto-Layout");
+
+ // Add the editor pane
+ GridBagLayout gridbag = new GridBagLayout();
+ setLayout(gridbag);
+ GridBagConstraints c = new GridBagConstraints();
+ c.gridx = 0;
+ c.gridy = 1;
+ c.fill = GridBagConstraints.BOTH;
+ c.weighty = 2.0;
+ c.weightx = 2.0;
+ mSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, mEditorPanel, mPropertyPanel);
+ mSplitPane.setDividerSize(5);
+ gridbag.setConstraints(mSplitPane, c);
+ add(mSplitPane);
+ }
+
+ protected void createListeners()
+ {
+ mLoadButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent ae) {
+ File selectedFile = null;
+
+ int returnValue = MainFrame.xmlChooser.showOpenDialog(null);
+
+ switch (returnValue)
+ {
+ case JFileChooser.APPROVE_OPTION :
+ selectedFile = MainFrame.xmlChooser.getSelectedFile();
+ try {
+ String newWf = FileStringUtility.file2String(selectedFile);
+ setOutcome(newWf);
+ setUpGraphEditor();
+ } catch (Exception e) {
+ Logger.exceptionDialog(e);
+ }
+ case JFileChooser.CANCEL_OPTION :
+ case JFileChooser.ERROR_OPTION :
+
+ default :
+ }
+ }
+ });
+
+ mLayoutButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent ae) {
+ DefaultGraphLayoutGenerator.layoutGraph(mEditorPanel.mGraphModelManager.getModel());
+ }
+ });
+ }
+
+ public void setUpGraphEditor() {
+ mEditorPanel.mGraphModelManager.setModel(mCompActDef.getChildrenGraphModel());
+ // Give the editor panel the edge and vertex types
+ mEditorPanel.updateVertexTypes(mCompActDef.getVertexTypeNameAndConstructionInfo());
+ mEditorPanel.updateEdgeTypes(mCompActDef.getEdgeTypeNameAndConstructionInfo());
+ mEditorPanel.enterSelectMode();
+ mWfVertexDefFactory.setCreationContext(mCompActDef);
+ }
+
+ /**
+ *
+ */
+ public void setOutcome(String outcome) throws InvalidOutcomeException {
+ try {
+ CompositeActivityDef newAct = (CompositeActivityDef)CastorXMLUtility.unmarshall(outcome);
+ if (mCompActDef != null)
+ newAct.setName(mCompActDef.getName());
+ mCompActDef = newAct;
+ } catch (Exception ex) {
+ Logger.error(ex);
+ throw new InvalidOutcomeException(ex.getMessage());
+ }
+ }
+ /**
+ *
+ */
+ public void setDescription(String description)
+ throws InvalidSchemaException {
+ // ignore - always the same
+ }
+ /**
+ *
+ */
+ public void setReadOnly(boolean readOnly) {
+ mLayoutButton.setEnabled(!readOnly);
+ mLoadButton.setEnabled(!readOnly);
+ mEditorPanel.setEditable(!readOnly);
+ mPropertyPanel.setEditable(!readOnly);
+ }
+ /**
+ *
+ */
+ public JPanel getPanel() throws OutcomeNotInitialisedException {
+ return this;
+ }
+ /**
+ *
+ */
+ public String getOutcome() throws OutcomeException {
+ try {
+ return CastorXMLUtility.marshall(mCompActDef);
+ } catch (Exception ex) {
+ throw new OutcomeException(ex.getMessage());
+ }
+ }
+ /**
+ *
+ */
+ public void run() {
+ Thread.currentThread().setName("Composite Act Def Viewer");
+ createLayout();
+ createListeners();
+ mPropertyPanel.setGraphModelManager(mEditorPanel.mGraphModelManager);
+ setUpGraphEditor();
+ }
+
+ public VertexPropertyPanel loadPropertyPanel()
+ {
+ String wfPanelClass = Gateway.getProperty("WfPropertyPanel");
+ if (wfPanelClass != null) {
+ try {
+ Class panelClass = Class.forName(wfPanelClass);
+ return (VertexPropertyPanel)panelClass.newInstance();
+ } catch (Exception ex) {
+ Logger.error("Could not load wf props panel:"+wfPanelClass);
+ Logger.error(ex);
+ }
+ }
+ return new VertexPropertyPanel();
+ }
+
+ public boolean isUnsaved() {
+ return unsaved;
+ }
+
+ public void saved() {
+ unsaved = false;
+ }
+
+ public void export(File targetFile) throws Exception {
+ ElemActDefOutcomeHandler.exportAct(targetFile.getParentFile(), mCompActDef);
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/gui/view/ElemActDefOutcomeHandler.java b/source/com/c2kernel/lifecycle/gui/view/ElemActDefOutcomeHandler.java
new file mode 100755
index 0000000..a30491e
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/gui/view/ElemActDefOutcomeHandler.java
@@ -0,0 +1,152 @@
+package com.c2kernel.lifecycle.gui.view;
+
+import java.io.File;
+
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+
+import com.c2kernel.graph.model.GraphableVertex;
+import com.c2kernel.graph.view.VertexPropertyPanel;
+import com.c2kernel.gui.tabs.outcome.InvalidOutcomeException;
+import com.c2kernel.gui.tabs.outcome.InvalidSchemaException;
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+import com.c2kernel.gui.tabs.outcome.OutcomeHandler;
+import com.c2kernel.gui.tabs.outcome.OutcomeNotInitialisedException;
+import com.c2kernel.lifecycle.ActivityDef;
+import com.c2kernel.lifecycle.ActivitySlotDef;
+import com.c2kernel.lifecycle.CompositeActivityDef;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.FileStringUtility;
+import com.c2kernel.utils.LocalObjectLoader;
+import com.c2kernel.utils.Logger;
+
+/**************************************************************************
+ *
+ * $Revision: 1.5 $
+ * $Date: 2005/10/05 07:39:37 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class ElemActDefOutcomeHandler extends VertexPropertyPanel implements OutcomeHandler {
+
+ ActivityDef act;
+ boolean unsaved;
+ public ElemActDefOutcomeHandler() {
+ super();
+ createLayout(null);
+ }
+
+ /**
+ *
+ */
+ public void setOutcome(String outcome) throws InvalidOutcomeException {
+ try {
+ act = (ActivityDef)CastorXMLUtility.unmarshall(outcome);
+ setVertex(act);
+ } catch (Exception ex) {
+ Logger.error(ex);
+ throw new InvalidOutcomeException();
+ }
+ }
+
+ /**
+ *
+ */
+ public void setDescription(String description)
+ throws InvalidSchemaException {
+ // ignore
+ }
+
+ /**
+ *
+ */
+ public void setReadOnly(boolean readOnly) {
+ setEditable(!readOnly);
+
+ }
+
+ /**
+ *
+ */
+ public JPanel getPanel() throws OutcomeNotInitialisedException {
+ return this;
+ }
+
+ /**
+ *
+ */
+ public String getOutcome() throws OutcomeException {
+ try {
+ return CastorXMLUtility.marshall(act);
+ } catch (Exception ex) {
+ Logger.error(ex);
+ throw new OutcomeException();
+ }
+ }
+
+ /**
+ *
+ */
+ public void run() {
+ validate();
+ }
+
+ public boolean isUnsaved() {
+ return unsaved;
+ }
+
+ public void saved() {
+ unsaved = false;
+ }
+
+ public void export(File targetFile) throws Exception {
+ exportAct(targetFile.getParentFile(), act);
+ }
+
+ public static void exportAct(File dir, ActivityDef actDef) throws Exception {
+ FileStringUtility.string2File(new File(dir, actDef.getActName()+".xml"), CastorXMLUtility.marshall(actDef));
+ // Export associated schema
+ exportSchema((String)actDef.getProperties().get("SchemaType"), (String)actDef.getProperties().get("SchemaVersion"), dir);
+ // Export associated script
+ exportScript((String)actDef.getProperties().get("ScriptName"), (String)actDef.getProperties().get("ScriptVersion"), dir);
+
+ //Export child act if composite
+ if (actDef instanceof CompositeActivityDef) {
+ CompositeActivityDef compActDef = (CompositeActivityDef)actDef;
+ for (int i=0; i<compActDef.getChildren().length; i++) {
+ GraphableVertex vert = compActDef.getChildren()[i];
+ exportScript((String)vert.getProperties().get("ScriptName"), (String)vert.getProperties().get("ScriptVersion"), dir);
+ exportScript((String)vert.getProperties().get("RoutingScriptName"), (String)vert.getProperties().get("RoutingScriptVersion"), dir);
+ }
+ GraphableVertex[] childDefs = compActDef.getLayoutableChildren();
+ for (int i=0; i<childDefs.length; i++) {
+ if (childDefs[i] instanceof ActivitySlotDef)
+ exportAct(dir, ((ActivitySlotDef)childDefs[i]).getTheActivityDef());
+ }
+ }
+ }
+
+ public static void exportScript(String name, String version, File dir) {
+ if (name == null || name.length()==0) return;
+ try {
+ FileStringUtility.string2File(new File(dir, name+"_"+version+".xml"),
+ LocalObjectLoader.getScript(name, version));
+ } catch (Exception ex) {
+ Logger.error(ex);
+ JOptionPane.showMessageDialog(null, "Could not export script "+name+"_"+version, "Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+ public static void exportSchema(String name, String version, File dir) {
+ if (name == null || name.length()==0) return;
+ try {
+ FileStringUtility.string2File(new File(dir, name+"_"+version+".xsd"),
+ LocalObjectLoader.getSchema(name, Integer.parseInt(version)).schema);
+ } catch (Exception ex) {
+ Logger.error(ex);
+ JOptionPane.showMessageDialog(null, "Could not export schema "+name+"_"+version, "Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/gui/view/SplitJoinDefRenderer.java b/source/com/c2kernel/lifecycle/gui/view/SplitJoinDefRenderer.java
new file mode 100755
index 0000000..1c6f1ba
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/gui/view/SplitJoinDefRenderer.java
@@ -0,0 +1,137 @@
+package com.c2kernel.lifecycle.gui.view;
+
+import java.awt.Color;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.Paint;
+
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.graph.view.VertexRenderer;
+import com.c2kernel.lifecycle.AndSplitDef;
+import com.c2kernel.lifecycle.JoinDef;
+import com.c2kernel.lifecycle.LoopDef;
+import com.c2kernel.lifecycle.OrSplitDef;
+import com.c2kernel.lifecycle.WfVertexDef;
+import com.c2kernel.lifecycle.XOrSplitDef;
+import com.c2kernel.utils.Language;
+
+
+public class SplitJoinDefRenderer implements VertexRenderer
+{
+ private Paint mTextPaint = Color.black;
+ private Paint mBoxPaint = new Color( 204, 204, 204 );
+ private Paint mErrorPaint = new Color( 255, 50, 0 );
+ private boolean mTextOffsetsNotInitialised = true;
+ private int mTextYOffset = 0;
+ private String mAndText = "And";
+ private int mAndTextXOffset = 0;
+ private String mOrText = "Or";
+ private int mOrTextXOffset = 0;
+ private String mXOrText = "XOr";
+ private int mXOrTextXOffset = 0;
+ private String mJoinText = "Join";
+ private int mJoinTextXOffset = 0;
+ private String mLoopText = "Loop";
+ private int mLoopTextXOffset = 0;
+ private String mRouteText = "";
+ private int mRouteTextXOffset = 0;
+ private String mXXXText = "XXX";
+ private int mXXXTextXOffset = 0;
+
+ public void draw( Graphics2D g2d, Vertex vertex)
+ {
+ GraphPoint centrePoint = vertex.getCentrePoint();
+ String text = null;
+ int textXOffset = 0;
+ int vertexHeight = vertex.getHeight();
+ int vertexWidth = vertex.getWidth();
+ boolean hasError = !((WfVertexDef)vertex).verify();
+
+
+ if ( mTextOffsetsNotInitialised )
+ {
+ initialiseTextOffsets( g2d );
+ mTextOffsetsNotInitialised = false;
+ }
+ if ( vertex instanceof LoopDef )
+ {
+ text = Language.translate(mLoopText);
+ textXOffset = mLoopTextXOffset;
+ }
+ else if ( vertex instanceof XOrSplitDef )
+ {
+ text = Language.translate(mXOrText);
+ textXOffset = mXOrTextXOffset;
+ }
+ else if ( vertex instanceof OrSplitDef )
+ {
+ text = Language.translate(mOrText);
+ textXOffset = mOrTextXOffset;
+ }
+ else if ( vertex instanceof AndSplitDef )
+ {
+ text = Language.translate(mAndText);
+ textXOffset = mAndTextXOffset;
+ }
+ else if ( vertex instanceof JoinDef)
+ {
+ String type= (String)((JoinDef)vertex).getProperties().get("Type");
+ if (type!=null && type.equals("Route"))
+ {
+ text = mRouteText;
+ textXOffset = mRouteTextXOffset;
+ }
+ else
+ {
+ text = Language.translate(mJoinText);
+ textXOffset = mJoinTextXOffset;
+ }
+ }
+ else
+ {
+ text = mXXXText;
+ textXOffset = mXXXTextXOffset;
+ }
+
+
+ g2d.setPaint( hasError ? mErrorPaint : mBoxPaint );
+ g2d.fillRect
+ (
+ centrePoint.x - vertexWidth / 2,
+ centrePoint.y - vertexHeight / 2,
+ vertexWidth,
+ vertexHeight
+ );
+ g2d.setPaint( mTextPaint );
+ g2d.drawRect
+ (
+ centrePoint.x - vertexWidth / 2,
+ centrePoint.y - vertexHeight / 2,
+ vertexWidth,
+ vertexHeight
+ );
+ g2d.drawString( text, centrePoint.x - textXOffset, centrePoint.y + mTextYOffset );
+ if (hasError) {
+ g2d.setPaint( mErrorPaint );
+ String errors = Language.translate(((WfVertexDef)vertex).getErrors());
+ int errorWidth = g2d.getFontMetrics().stringWidth( errors );
+ g2d.drawString( errors, centrePoint.x - ( errorWidth / 2), centrePoint.y + vertexHeight );
+ }
+ }
+
+ private void initialiseTextOffsets( Graphics2D g2d )
+ {
+ FontMetrics metrics = g2d.getFontMetrics();
+
+
+ mTextYOffset = metrics.getHeight() / 3;
+ mAndTextXOffset = metrics.stringWidth( Language.translate(mAndText) ) / 2;
+ mOrTextXOffset = metrics.stringWidth( Language.translate(mOrText) ) / 2;
+ mXOrTextXOffset = metrics.stringWidth( Language.translate(mXOrText) ) / 2;
+ mJoinTextXOffset = metrics.stringWidth( Language.translate(mJoinText) ) / 2;
+ mLoopTextXOffset = metrics.stringWidth( Language.translate(mJoinText) ) / 2;
+ mRouteTextXOffset = metrics.stringWidth( Language.translate(mRouteText) ) / 2;
+ }
+}
+
diff --git a/source/com/c2kernel/lifecycle/gui/view/WfDirectedEdgeDefRenderer.java b/source/com/c2kernel/lifecycle/gui/view/WfDirectedEdgeDefRenderer.java
new file mode 100755
index 0000000..7eb646f
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/gui/view/WfDirectedEdgeDefRenderer.java
@@ -0,0 +1,132 @@
+package com.c2kernel.lifecycle.gui.view;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.GeneralPath;
+import com.c2kernel.graph.model.DirectedEdge;
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.graph.view.DirectedEdgeRenderer;
+import com.c2kernel.lifecycle.NextDef;
+public class WfDirectedEdgeDefRenderer implements DirectedEdgeRenderer
+{
+ private GeneralPath mArrowTemplate = new GeneralPath();
+ public WfDirectedEdgeDefRenderer()
+ {
+ mArrowTemplate.moveTo(-5, 5);
+ mArrowTemplate.lineTo(0, 0);
+ mArrowTemplate.lineTo(5, 5);
+ }
+ public void draw(Graphics2D g2d, DirectedEdge directedEdge)
+ {
+ GraphPoint originPoint = directedEdge.getOriginPoint();
+ GraphPoint terminusPoint = directedEdge.getTerminusPoint();
+ GraphPoint midPoint = new GraphPoint();
+ AffineTransform transform = new AffineTransform();
+ Shape arrow = null;
+ NextDef nextDef = (NextDef) directedEdge;
+ boolean hasError = !nextDef.verify();
+ String text = (String) nextDef.getProperties().get("Alias");
+ g2d.setPaint(hasError ? Color.red : Color.black);
+ if (("Broken +".equals(nextDef.getProperties().get("Type"))))
+ {
+ g2d.drawLine(originPoint.x, originPoint.y, originPoint.x, (originPoint.y + terminusPoint.y) / 2);
+ g2d.drawLine(originPoint.x, (originPoint.y + terminusPoint.y) / 2, terminusPoint.x, (originPoint.y + terminusPoint.y) / 2);
+ g2d.drawLine(terminusPoint.x, (originPoint.y + terminusPoint.y) / 2, terminusPoint.x, terminusPoint.y);
+ midPoint.x = (originPoint.x + terminusPoint.x) / 2;
+ midPoint.y = (originPoint.y + terminusPoint.y) / 2;
+ transform.translate(midPoint.x, midPoint.y);
+ transform.rotate(
+ calcArrowAngle(
+ originPoint.x,
+ originPoint.x - terminusPoint.x > -5
+ && originPoint.x - terminusPoint.x < 5 ? originPoint.y : (originPoint.y + terminusPoint.y) / 2,
+ terminusPoint.x,
+ originPoint.x - terminusPoint.x > -5
+ && originPoint.x - terminusPoint.x < 5 ? terminusPoint.y : (originPoint.y + terminusPoint.y) / 2));
+ }
+ else if (("Broken -".equals(nextDef.getProperties().get("Type"))))
+ {
+ g2d.drawLine(originPoint.x, originPoint.y, terminusPoint.x, originPoint.y);
+ g2d.drawLine(terminusPoint.x, originPoint.y, terminusPoint.x, terminusPoint.y);
+ boolean arrowOnY = !(originPoint.y - terminusPoint.y < 60 && originPoint.y - terminusPoint.y > -60);
+ midPoint.x = arrowOnY ? terminusPoint.x : (originPoint.x + terminusPoint.x) / 2;
+ midPoint.y = arrowOnY ? (originPoint.y + terminusPoint.y) / 2 : originPoint.y;
+ transform.translate(midPoint.x, midPoint.y);
+ transform
+ .rotate(
+ calcArrowAngle(
+ arrowOnY ? terminusPoint.x : originPoint.x,
+ arrowOnY ? originPoint.y : originPoint.y,
+ arrowOnY ? terminusPoint.x : terminusPoint.x,
+ arrowOnY ? terminusPoint.y : originPoint.y));
+ }
+ else if (("Broken |".equals(nextDef.getProperties().get("Type"))))
+ {
+ g2d.drawLine(originPoint.x, originPoint.y, originPoint.x, terminusPoint.y);
+ g2d.drawLine(originPoint.x, terminusPoint.y, terminusPoint.x, terminusPoint.y);
+ boolean arrowOnY = !(originPoint.y - terminusPoint.y < 60 && originPoint.y - terminusPoint.y > -60);
+ midPoint.x = arrowOnY ? originPoint.x : (originPoint.x + terminusPoint.x) / 2;
+ midPoint.y = arrowOnY ? (originPoint.y + terminusPoint.y) / 2 : terminusPoint.y;
+ transform.translate(midPoint.x, midPoint.y);
+ transform
+ .rotate(
+ calcArrowAngle(
+ arrowOnY ? terminusPoint.x : originPoint.x,
+ arrowOnY ? originPoint.y : originPoint.y,
+ arrowOnY ? terminusPoint.x : terminusPoint.x,
+ arrowOnY ? terminusPoint.y : originPoint.y));
+ }
+ else
+ {
+ g2d.drawLine(originPoint.x, originPoint.y, terminusPoint.x, terminusPoint.y);
+ midPoint.x = originPoint.x + (terminusPoint.x - originPoint.x) / 2;
+ midPoint.y = originPoint.y + (terminusPoint.y - originPoint.y) / 2;
+ transform.translate(midPoint.x, midPoint.y);
+ transform.rotate(calcArrowAngle(originPoint.x, originPoint.y, terminusPoint.x, terminusPoint.y));
+ }
+
+ arrow = mArrowTemplate.createTransformedShape(transform);
+ g2d.draw(arrow);
+ if (text != null)
+ g2d.drawString(text, midPoint.x + 10, midPoint.y);
+ }
+ private double calcArrowAngle(int originX, int originY, int terminusX, int terminusY)
+ {
+ double width = terminusX - originX;
+ double height = terminusY - originY;
+ if ((width == 0) && (height > 0))
+ {
+ return Math.PI;
+ }
+ if ((width == 0) && (height < 0))
+ {
+ return 0;
+ }
+ if ((width > 0) && (height == 0))
+ {
+ return Math.PI / 2.0;
+ }
+ if ((width < 0) && (height == 0))
+ {
+ return -1.0 * Math.PI / 2.0;
+ }
+ if ((width > 0) && (height > 0))
+ {
+ return Math.PI / 2.0 + Math.atan(Math.abs(height) / Math.abs(width));
+ }
+ if ((width > 0) && (height < 0))
+ {
+ return Math.atan(Math.abs(width) / Math.abs(height));
+ }
+ if ((width < 0) && (height < 0))
+ {
+ return -1.0 * Math.atan(Math.abs(width) / Math.abs(height));
+ }
+ if ((width < 0) && (height > 0))
+ {
+ return -1.0 * (Math.PI / 2.0 + Math.atan(Math.abs(height) / Math.abs(width)));
+ }
+ return 0.0;
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/gui/view/WfVertexDefRenderer.java b/source/com/c2kernel/lifecycle/gui/view/WfVertexDefRenderer.java
new file mode 100755
index 0000000..5f17888
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/gui/view/WfVertexDefRenderer.java
@@ -0,0 +1,29 @@
+package com.c2kernel.lifecycle.gui.view;
+
+import java.awt.Graphics2D;
+
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.graph.view.VertexRenderer;
+import com.c2kernel.lifecycle.ActivitySlotDef;
+import com.c2kernel.lifecycle.AndSplitDef;
+import com.c2kernel.lifecycle.JoinDef;
+
+public class WfVertexDefRenderer implements VertexRenderer
+{
+ protected ActivitySlotDefRenderer mActivitySlotDefRenderer = new ActivitySlotDefRenderer();
+ protected SplitJoinDefRenderer mSplitJoinDefRenderer = new SplitJoinDefRenderer();
+
+
+ public void draw( Graphics2D g2d, Vertex vertex)
+ {
+ if ( vertex instanceof ActivitySlotDef )
+ {
+ mActivitySlotDefRenderer.draw( g2d, vertex);
+ }
+ else if ( ( vertex instanceof AndSplitDef ) || ( vertex instanceof JoinDef ) )
+ {
+ mSplitJoinDefRenderer.draw( g2d, vertex);
+ }
+ }
+}
+
diff --git a/source/com/c2kernel/lifecycle/instance/Activity.java b/source/com/c2kernel/lifecycle/instance/Activity.java
new file mode 100755
index 0000000..458c0a5
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/Activity.java
@@ -0,0 +1,689 @@
+package com.c2kernel.lifecycle.instance;
+import java.util.ArrayList;
+import java.util.Vector;
+
+import com.c2kernel.common.AccessRightsException;
+import com.c2kernel.common.GTimeStamp;
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.InvalidTransitionException;
+import com.c2kernel.common.ObjectAlreadyExistsException;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.agent.Job;
+import com.c2kernel.events.Event;
+import com.c2kernel.events.History;
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.lifecycle.WfCastorHashMap;
+import com.c2kernel.lifecycle.instance.stateMachine.StateMachine;
+import com.c2kernel.lifecycle.instance.stateMachine.States;
+import com.c2kernel.lifecycle.instance.stateMachine.Transitions;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.lookup.InvalidEntityPathException;
+import com.c2kernel.lookup.LDAPRoleManager;
+import com.c2kernel.lookup.RolePath;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.persistency.TransactionManager;
+import com.c2kernel.persistency.outcome.Outcome;
+import com.c2kernel.persistency.outcome.Viewpoint;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.scripting.ScriptingEngineException;
+import com.c2kernel.utils.DateUtility;
+import com.c2kernel.utils.Logger;
+/**
+ * @version $Revision: 1.222 $ $Date: 2005/10/05 07:39:37 $
+ * @author $Author: abranson $
+ */
+public class Activity extends WfVertex
+{
+ /**
+ * vector of errors (Strings) that is constructed each time verify() is launched
+ */
+ protected Vector mErrors;
+ /** @associates a State machine engine */
+ private StateMachine machine;
+ /** true is avalaibe to be executed */
+ public boolean active = false;
+ /** used in verify() */
+ private boolean loopTested;
+ //public Vector eventIds;
+ /** Storage of eventIds thrown by the Activity */
+ public EventStorage eventIds;
+ private GTimeStamp mStartDate;
+ private GTimeStamp mActiveDate;
+ private String mType;
+ private EntityPath mEntityPath;
+ public Activity()
+ {
+ super();
+ setProperties(new WfCastorHashMap());
+ mErrors = new Vector(0, 1);
+ machine = new StateMachine(this);
+ eventIds = new EventStorage();
+ mStartDate = new GTimeStamp();
+ mActiveDate = new GTimeStamp();
+ DateUtility.setToNow(mActiveDate);
+ DateUtility.setToNow(mStartDate);
+ }
+ /** @return the SystemKey of the item that contains the workflow */
+ public EntityPath getItemEntityPath()
+ {
+ if (mEntityPath == null)
+ try
+ {
+ Integer i = (Integer) (getWf().getProperties().get("ItemSystemKey"));
+ if (i == null)
+ return null; // no item yet
+ EntityPath entityPath = new EntityPath(i.intValue());
+ mEntityPath = entityPath;
+ }
+ catch (InvalidEntityPathException ex)
+ {
+ Logger.error("InvalidEntityPathException::Activity::getItemSystemKey() " + ex.toString());
+ return null;
+ }
+ return mEntityPath;
+ }
+ /** @return the StateMachine */
+ public StateMachine getMachine()
+ {
+ return machine;
+ }
+ /** sets the StateMachine (Only for Serialisation) */
+ public void setMachine(StateMachine sm)
+ {
+ machine = sm;
+ }
+ /** add the activity which id is idNext as next of the current one */
+ void addNext(String idNext)
+ {
+ new Next(this, (WfVertex) getParent().search(idNext));
+ }
+ /**
+ * adds a New link between the current Activity and the WfVertex passed in param
+ */
+ public Next addNext(WfVertex vertex)
+ {
+ return new Next(this, vertex);
+ }
+ /** return the current State of the State machine */
+ public int getCurrentState()
+ {
+ return machine.getCurrentState();
+ }
+ /** return the current State of the State machine (Used in Serialisation) */
+ public int getState()
+ {
+ if (machine == null)
+ machine = new StateMachine(this);
+ return getCurrentState();
+ }
+ /** Sets a new State in a State machine */
+ public void setState(int stat)
+ {
+ if (machine == null)
+ machine = new StateMachine(this);
+ machine.state = stat;
+ }
+ /** check the abiltity of the agent passed in param to act on the activity */
+ //return's the agentName
+ public String checkAccessRights(AgentPath agent) throws AccessRightsException
+ {
+ String agentID = getCurrentAgentName();
+ boolean authorised = agentID.equals(agent.getAgentName());
+ String actRole = getCurrentAgentRole();
+ if (!authorised)
+ {
+ authorised = actRole == null || actRole.equals("") || actRole.equals("all");
+ }
+ if (!authorised)
+ {
+ RolePath[] roles = agent.getRoles();
+ for (int i = 0; !authorised && i < roles.length; i++)
+ {
+ if (roles[i].getName().equalsIgnoreCase("Admin"))
+ authorised = true;
+ if (roles[i].getName().equalsIgnoreCase(actRole))
+ authorised = true;
+ if (roles[i].getName().equalsIgnoreCase("Guest"))
+ throw new AccessRightsException("Guest execution forbidden");
+ }
+ }
+ if (!authorised)
+ throw new AccessRightsException("Activity::checkAccessRights() - Agent does not hold the correct role.");
+ return agent.getAgentName();
+ }
+ /** cf Item request */
+ public void request(AgentPath agent, int transitionID, String requestData) throws AccessRightsException, InvalidTransitionException, InvalidDataException, ObjectAlreadyExistsException
+ {
+ int state = getState();
+ String agentName = checkAccessRights(agent);
+ if (machine.traverse(transitionID))
+ {
+ setReservation(transitionID, agentName);
+ sendEventStoreOutcome(transitionID, requestData, agent);
+ if (transitionID == Transitions.REPEAT)
+ {
+ setActive(true);
+ if (getIsComposite())
+ {
+ WfVertex v = (WfVertex) ((CompositeActivity) this).search(getPath() + "/" + ((CompositeActivity) this).getChildGraphModel().getStartVertexId());
+ v.reinit(getID());
+ try
+ {
+ runfirst(agent);
+ }
+ catch (ScriptingEngineException e)
+ {
+ Logger.error(e);
+ }
+ }
+ }
+ if (transitionID == Transitions.COMPLETE && state == States.RSTARTED)
+ setActive(false);
+ if (transitionID == Transitions.START)
+ start();
+ if ((transitionID == Transitions.SKIP && getActive())
+ || transitionID == Transitions.DONE
+ || (transitionID == Transitions.COMPLETE && state == States.STARTED)
+ || transitionID == Transitions.PROCEED)
+ try
+ {
+ try
+ {
+ GTimeStamp t = DateUtility.setToNow(new GTimeStamp());
+ }
+ catch (Exception e)
+ {
+ }
+ runNext(agent);
+ }
+ catch (ScriptingEngineException e)
+ {
+ Logger.error(e);
+ }
+ // run post execution script now
+ try
+ {
+ String postSubmitScr = (String) getProperties().get("PostExecScriptName");
+ String postSubmitVer = (String) getProperties().get("PostExecScriptVersion");
+ if (postSubmitScr != null && (transitionID == Transitions.COMPLETE || transitionID == Transitions.DONE))
+ evaluateScript(postSubmitScr, postSubmitVer);
+ }
+ catch (ScriptingEngineException ex)
+ {
+ Logger.error(ex);
+ }
+ //refresh all the job lists
+ pushJobsToAgents();
+ }
+ else
+ throw new InvalidTransitionException("Activity is in the wrong state.");
+ }
+ public void setReservation(int transitionID, String agentName)
+ {
+ String actAgentName = (String) getProperties().get("Agent Name");
+ switch (transitionID)
+ {
+ // these transition reserve the activity
+ case Transitions.REASSIGN :
+ case Transitions.RESERVE :
+ case Transitions.START :
+ actAgentName = agentName;
+ break;
+ // these clear any current reservation
+ case Transitions.COMPLETE :
+ case Transitions.DONE :
+ case Transitions.IGNORE :
+ case Transitions.SKIP :
+ actAgentName = "";
+ // other transitions have no effect on the reservations
+ default :
+ }
+ getProperties().put("Agent Name", actAgentName);
+ }
+ public String getTransitions()
+ {
+ String result = "<PossibleTransitions>";
+ int i;
+ for (i = 0; i < machine.possibleTransition().length; i++)
+ {
+ result += machine.possibleTransition()[i] + ",";
+ }
+ //cuts out the last comma(',') if required
+ if (i > 0)
+ {
+ result = result.substring(0, result.length() - 1);
+ }
+ result += "</PossibleTransitions>";
+ return result;
+ }
+ /** launch the verification of the activity */
+ public boolean verify()
+ {
+ mErrors.removeAllElements();
+ int nbInEdgres = getInEdges().length;
+ int nbOutEdges = getOutEdges().length;
+ if (nbInEdgres == 0 && this.getID() != getParent().getChildrenGraphModel().getStartVertexId())
+ {
+ mErrors.add("Unreachable");
+ return false;
+ }
+ else if (nbInEdgres > 1)
+ {
+ mErrors.add("Bad nb of previous");
+ return false;
+ }
+ else if (nbOutEdges > 1)
+ {
+ mErrors.add("too many next");
+ return false;
+ }
+ else if (nbOutEdges == 0)
+ {
+ if (!((CompositeActivity) getParent()).hasGoodNumberOfActivity())
+ {
+ mErrors.add("too many endpoints");
+ return false;
+ }
+ }
+// else
+// {
+// Vertex[] outV = getOutGraphables();
+// Vertex[] anteVertices = GraphTraversal.getTraversal(getParent().getChildrenGraphModel(), this, GraphTraversal.kUp, false);
+// boolean errInLoop = false;
+// for (int i = 0; i < outV.length; i++)
+// {
+// for (int j = 0; j < anteVertices.length; j++)
+// if (!loop() && outV[i].getID() == anteVertices[j].getID())
+// errInLoop = true;
+// }
+// if (errInLoop)
+// {
+// mErrors.add("Error In Loop");
+// return false;
+// }
+// }
+ return true;
+ }
+ /** Used in verify() */
+ public boolean loop()
+ {
+ boolean loop2 = false;
+ if (!loopTested)
+ {
+ loopTested = true;
+ if (getOutGraphables().length != 0)
+ loop2 = ((WfVertex) getOutGraphables()[0]).loop();
+ }
+ loopTested = false;
+ return loop2;
+ }
+ /** sets the next activity available if possible */
+ public void runNext(AgentPath agent) throws ScriptingEngineException
+ {
+ setActive(false);
+ try
+ {
+ Vertex[] outVertices = getOutGraphables();
+ Vertex[] outVertices2 = getOutGraphables();
+ boolean hasNoNext = false;
+ boolean out = false;
+ while (!out)
+ if (outVertices2.length > 0)
+ {
+ if (outVertices2[0] instanceof Join)
+ outVertices2 = ((WfVertex) outVertices2[0]).getOutGraphables();
+ else
+ out = true;
+ }
+ else
+ {
+ hasNoNext = true;
+ out = true;
+ }
+ Logger.debug(8, outVertices + " " + outVertices2);
+ if (!hasNoNext)
+ ((WfVertex) outVertices[0]).run(agent);
+ else
+ {
+ if (getParent() != null && getParent().getName().equals("domain")) // workflow
+ // finished
+ setActive(true);
+ else
+ {
+ CompositeActivity parent = (CompositeActivity) getParent();
+ if (parent != null)
+ parent.runNext(agent);
+ }
+ }
+ }
+ catch (ScriptingEngineException s)
+ {
+ setActive(true);
+ throw s;
+ }
+ }
+ /** @return the only Next of the Activity */
+ public Next getNext()
+ {
+ if (getOutEdges().length > 0)
+ return (Next) getOutEdges()[0];
+ else
+ return null;
+ }
+ /** reinitialises the Activity and propagate (for Loop) */
+ public void reinit(int idLoop)
+ {
+ Logger.debug(7, "reinit " + getItemEntityPath().getSysKey() + " " + getPath());
+ Vertex[] outVertices = getOutGraphables();
+ machine.state = States.WAITING;
+ if (outVertices.length > 0)
+ {
+ WfVertex nextAct = (WfVertex) outVertices[0];
+ nextAct.reinit(idLoop);
+ }
+ }
+ /** return the String that identifies the errors found in th activity */
+ public String getErrors()
+ {
+ String errors = "";
+ if (mErrors.size() == 0)
+ return "No error";
+ return (String) mErrors.elementAt(0);
+ }
+ /**
+ * called by precedent Activity runNext() for setting the activity able to be executed
+ */
+ public void run(AgentPath agent) throws ScriptingEngineException
+ {
+ Logger.debug(8, getPath() + " run " + getCurrentState());
+ if (!getActive())
+ setActive(true);
+
+ if (getMachine().getCurrentState() == States.FINISHED)
+ {
+ runNext(agent);
+ }
+ else
+ {
+ DateUtility.setToNow(mActiveDate);
+ if (((Boolean) getProperties().get(StateMachine.AUTOSTART)).booleanValue() && machine.state == States.WAITING)
+ {
+ machine.traverse(Transitions.START);
+ start();
+ }
+ pushJobsToAgents();
+ }
+ }
+ /**
+ * sets the activity available to be executed on start of Workflow or composite activity (when it is the first one of the (sub)process
+ */
+ public void runfirst(AgentPath agent) throws ScriptingEngineException
+ {
+ Logger.debug(8, getPath() + " runfirst");
+ run(agent);
+ }
+ /** @return the current ability to be executed */
+ public boolean getActive()
+ {
+ return active;
+ }
+ /** sets the ability to be executed */
+ public void setActive(boolean acti)
+ {
+ active = acti;
+ }
+ /** @return the Description field of properties */
+ public String getDescription()
+ {
+ if (getProperties().containsKey("Description"))
+ return (String) (getProperties().get("Description"));
+ return "No description";
+ }
+ public String getCurrentAgentName()
+ {
+ return (String) getProperties().get("Agent Name");
+ }
+ public String getCurrentAgentRole()
+ {
+ return (String) getProperties().get("Agent Role");
+ }
+ /**
+ * @return an array of Steps that matches the querry
+ * @param agentID
+ * Agent concerned by the query
+ * @param agentRole
+ * Agent concerned by the query @int stateID state to test in the query, use -1 for all
+ * @param filter
+ * if tru will be filtered by agent, else won't
+ */
+ public Activity[] query(AgentPath agent, int stateID, boolean filter)
+ {
+ if (getCurrentState() == stateID || stateID == -1)
+ {
+ Activity[] steps = { this };
+ if (!filter)
+ return steps;
+ else
+ {
+ try
+ {
+ checkAccessRights(agent);
+ return steps;
+ }
+ catch (AccessRightsException e)
+ {
+ //case that agent is not allowed
+ Logger.msg(7, "Activity :: AccessRightsException in " + this.getItemEntityPath() + "/" + this.getPath());
+ }
+ }
+ }
+ return new Activity[0];
+ }
+ /**
+ * returns the lists of jobs for the activity and children (cf com.c2kernel.entity.Job)
+ */
+ public ArrayList calculateJobs(AgentPath agent, boolean recurse)
+ {
+ return calculateJobsBase(agent, false);
+ } //
+ public ArrayList calculateAllJobs(AgentPath agent, boolean recurse)
+ {
+ return calculateJobsBase(agent, true);
+ }
+ private ArrayList calculateJobsBase(AgentPath agent, boolean all)
+ {
+ Logger.msg(7, "calculateJobs - " + getPath());
+ int[] transitions = {
+ };
+ ArrayList jobs = new ArrayList();
+ try
+ {
+ String agentName = checkAccessRights(agent);
+ String currentAgentName = getCurrentAgentName();
+ boolean isCurrent = currentAgentName == null || currentAgentName.equals("") || agentName.equals(currentAgentName);
+ if ((all || getActive()) && !getName().equals("domain"))
+ transitions = machine.possibleTransition();
+ Logger.msg(7, "Activity.calculateJobs() - Got " + transitions.length + " transitions.");
+ for (int i = 0; i < transitions.length; i++)
+ {
+ Logger.msg(7, "Creating Job object for transition " + transitions[i]);
+ if ((isCurrent && !(transitions[i] == Transitions.REASSIGN && agentName.equals(currentAgentName))) || (transitions[i] == Transitions.REASSIGN && !agentName.equals(currentAgentName)))
+ jobs.add(new Job(getItemEntityPath().getSysKey(), getPath(), transitions[i], getCurrentState(), machine.simulate(transitions[i]), getName(), getProperties(), getType(), agentName));
+ }
+ }
+ catch (AccessRightsException ex)
+ {
+ Logger.msg(6, "Agent "+ agent.getAgentName() +" is not allowed to interact with "+getItemEntityPath().getSysKey()+":"+getPath());
+ } // empty joblist then
+ return jobs;
+ }
+ //
+ //methods written by kovax
+ //
+ /** Adds an event to the AuditTrail of the Item if any */
+ private Event auditEvent(int transitionID, AgentPath agent)
+ {
+ EntityPath entityPath = getItemEntityPath();
+ if (entityPath != null)
+ {
+ Event event = null;
+ History hist = null;
+ try
+ {
+ hist = (History) Gateway.getStorage().get(entityPath.getSysKey(), ClusterStorage.HISTORY, this);
+ event = hist.addEvent(agent.getAgentName(), getCurrentAgentRole(), transitionID, getName(), getPath(), getType(), getCurrentState());
+ Logger.msg(7, "Activity::auditEvent() - Event:" + event.getName() + " was added to the AuditTrail");
+ }
+ catch (Exception ex)
+ {
+ Logger.error("Activity::auditEvent() - Item '" + entityPath.toString() + "'!");
+ Logger.error(ex);
+ }
+ return event;
+ }
+ else
+ return null;
+ } /**
+ * Stores the request data as an outcome of the Item It does a great deal of storing outcomes in different configuration
+ */ //requestdata is xmlstring
+ private String storeOutcome(int eventID, String requestData)
+ {
+ EntityPath entityPath = getItemEntityPath();
+ if (entityPath != null)
+ {
+ String schemaType = (String) getProperties().get("SchemaType");
+ if (schemaType == null || schemaType.length() == 0) // no
+ // outcome
+ // required
+ return null;
+ int schemaVersion = 0;
+ String versionString = (String) getProperties().get("SchemaVersion");
+ try
+ {
+ schemaVersion = Integer.parseInt(versionString);
+ }
+ catch (Exception e)
+ {
+ Logger.error("Activity.storeOutcome() - invalid schemaVersion " + versionString);
+ }
+ Logger.msg(5, "Activity::storeOutcome() - type:" + schemaType + " version:" + schemaVersion);
+ try
+ {
+ Outcome newOutcome = new Outcome(eventID, requestData, schemaType, schemaVersion);
+ Gateway.getStorage().put(entityPath.getSysKey(), newOutcome, this);
+ // update specific view if defined
+ String specificView = (String) getProperties().get("Viewpoint");
+ if (specificView != null && !specificView.equals(""))
+ {
+ Viewpoint currentView = new Viewpoint(entityPath.getSysKey(), schemaType, specificView, schemaVersion, eventID);
+ Gateway.getStorage().put(entityPath.getSysKey(), currentView, this);
+ } // update last view
+ Viewpoint currentView = new Viewpoint(entityPath.getSysKey(), schemaType, "last", schemaVersion, eventID);
+ Gateway.getStorage().put(entityPath.getSysKey(), currentView, this);
+ return schemaType + "/" + schemaVersion + "/" + eventID;
+ }
+ catch (Exception ex)
+ {
+ Logger.error("ActivityBase::storeOutcome() - Item '" + entityPath.toString() + "'!");
+ Logger.error(ex);
+ }
+ return null;
+ }
+ else
+ return null;
+ } /** the method to be called by the requestAction() method */
+ public void sendEventStoreOutcome(int transitionID, String requestData, AgentPath agent)
+ {
+ int eventID = -1;
+ Event event = null;
+ event = auditEvent(transitionID, agent);
+ if (event != null)
+ eventID = event.getID();
+ if (Boolean.TRUE.equals(getProperties().get("AlwaysUseOutcome")) || transitionID == Transitions.DONE || transitionID == Transitions.COMPLETE)
+ storeOutcome(eventID, requestData);
+ EntityPath entityPath = getItemEntityPath();
+ TransactionManager storage = Gateway.getStorage();
+ if (entityPath != null)
+ {
+ storage.commit(this);
+ }
+ }
+ public void pushJobsToAgents()
+ {
+ String agentRole = getCurrentAgentRole();
+ if (agentRole == null || agentRole.length()==0) return;
+
+ LDAPRoleManager roleMan = Gateway.getLDAPLookup().getRoleManager();
+ RolePath myRole;
+ try {
+ myRole = roleMan.getRolePath(agentRole);
+ } catch (ObjectNotFoundException ex) { // non-existent role
+ Logger.msg(7, "Activity.pushJobsToAgents() - Activity role '"+agentRole+" not found.");
+ return;
+ }
+
+ if (myRole.hasJobList())
+ new JobPusher(this, myRole).start();
+ }
+
+
+ /**
+ * Returns the activeDate.
+ *
+ * @return GTimeStamp
+ */
+ public GTimeStamp getActiveDate()
+ {
+ return mActiveDate;
+ } /**
+ * Returns the startDate.
+ *
+ * @return GTimeStamp
+ */
+ public GTimeStamp getStartDate()
+ {
+ return mStartDate;
+ } /**
+ * Sets the activeDate.
+ *
+ * @param activeDate
+ * The activeDate to set
+ */
+ public void setActiveDate(GTimeStamp activeDate)
+ {
+ mActiveDate = activeDate;
+ } /**
+ * Sets the startDate.
+ *
+ * @param startDate
+ * The startDate to set
+ */
+ public void setStartDate(GTimeStamp startDate)
+ {
+ mStartDate = startDate;
+ } /**
+ * Returns the type.
+ *
+ * @return String
+ */
+ public String getType()
+ {
+ return mType;
+ } /**
+ * Sets the type.
+ *
+ * @param type
+ * The type to set
+ */
+ public void setType(String type)
+ {
+ mType = type;
+ }
+ private void start()
+ {
+ Logger.debug(8, getPath() + " start");
+ DateUtility.setToNow(mStartDate);
+ }
+
+}
diff --git a/source/com/c2kernel/lifecycle/instance/AdvancementCalculator.java b/source/com/c2kernel/lifecycle/instance/AdvancementCalculator.java
new file mode 100755
index 0000000..ea47721
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/AdvancementCalculator.java
@@ -0,0 +1,228 @@
+/* Created on 11 mars 2004 */
+package com.c2kernel.lifecycle.instance;
+import java.io.Serializable;
+import java.util.Hashtable;
+
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.lifecycle.instance.stateMachine.States;
+//import com.c2kernel.utils.Logger;
+/** @author XSeb74 */
+public class AdvancementCalculator implements Serializable
+{
+ private CompositeActivity activity;
+ private Hashtable isMarked;
+ private Hashtable HasNextMarked;
+ public Hashtable hasprevActive;
+ private long mCurrentNbActExp = 0;
+ private long mMaximuNbActexp = 0;
+ private long mNbActpassed = 0;
+ private long mNbActpassedWithCurrent = 0;
+ private long mNbActLeftWithCurrent = 0;
+ private long mNbActLeftWithoutCurrent = 0;
+ private boolean mIsbranchActive = false;
+ private boolean mIsbranchFinished = true;
+ private boolean mHasPrevActive = false;
+ public AdvancementCalculator()
+ {
+ isMarked = new Hashtable();
+ HasNextMarked = new Hashtable();
+ hasprevActive = new Hashtable();
+ }
+ public void calculate(CompositeActivity act)
+ {
+// Logger.debug(0, act.getName()+" >>>>>>>>>");
+ if (act instanceof Workflow)
+ {
+ calculate((CompositeActivity) act.search("workflow/domain"));
+ return;
+ }
+ activity = act;
+ Vertex v = activity.getChildGraphModel().getStartVertex();
+ check(v, this);
+ isMarked = new Hashtable();
+ calc(v, this);
+// Logger.debug(0, act.getName()+" <<<<<<<<<");
+ }
+ private void check(Vertex v, AdvancementCalculator current)
+ {
+ current.isMarked.put(v, "");
+ Vertex[] nexts = current.activity.getChildGraphModel().getOutVertices(v);
+ for (int i = 0; i < nexts.length; i++)
+ if (current.isMarked.get(nexts[i]) != null)
+ current.HasNextMarked.put(v, nexts[i]);
+ else
+ check(nexts[i], current);
+ int j=0;
+ for (int i = 0; i < nexts.length; i++)
+ if (current.HasNextMarked.get(nexts[i]) != null)
+ j++;
+ if (j != 0 && j==nexts.length) current.HasNextMarked.put(v, nexts[0]);
+ }
+ private void calc(Vertex v, AdvancementCalculator current)
+ {
+ if (current.isMarked.get(v) != null && !(v instanceof Join))
+ return;
+ if (v instanceof Activity)
+ {
+ current.isMarked.put(v, current);
+ Activity act = (Activity) v;
+ if (v instanceof CompositeActivity)
+ {
+ CompositeActivity cact = (CompositeActivity) v;
+ AdvancementCalculator adv = new AdvancementCalculator();
+ adv.isMarked = current.isMarked;
+ adv.HasNextMarked = current.HasNextMarked;
+ adv.calculate(cact);
+ current.mCurrentNbActExp += adv.mCurrentNbActExp;
+ current.mMaximuNbActexp += adv.mMaximuNbActexp;
+ current.mNbActpassed += adv.mNbActpassed;
+ current.mNbActpassedWithCurrent += adv.mNbActpassedWithCurrent;
+ current.mIsbranchActive = current.mIsbranchActive || adv.mIsbranchActive||act.getActive();
+ current.mNbActLeftWithCurrent += adv.mNbActLeftWithCurrent;
+ current.mNbActLeftWithoutCurrent += adv.mNbActLeftWithoutCurrent;
+ current.mHasPrevActive = adv.mHasPrevActive||act.getActive();
+ if (adv.hasprevActive.size()!=0) current.mHasPrevActive=true;
+ }
+ else
+ {
+ current.mCurrentNbActExp += 1;
+ current.mMaximuNbActexp += 1;
+ if (act.getCurrentState() == States.FINISHED)
+ {
+ current.mNbActpassed += 1;
+ current.mNbActpassedWithCurrent += 1;
+ }
+ else if (act.getActive()&&act.getState()<States.REPEATSTATESTART)
+ {
+ current.mIsbranchActive = true;
+ current.mIsbranchFinished = false;
+ current.mHasPrevActive = true;
+// Logger.debug(0, "set HasprevActive to true " + act.getName());
+ current.mNbActpassedWithCurrent += 1;
+ current.mNbActLeftWithCurrent += 1;
+ }
+ else
+ {
+ current.mIsbranchFinished = false;
+ current.mNbActLeftWithCurrent += 1;
+ current.mNbActLeftWithoutCurrent += 1;
+ }
+ }
+ }
+ Vertex[] nexts = current.activity.getChildGraphModel().getOutVertices(v);
+ if (v instanceof Split)
+ {
+ current.isMarked.put(v, current);
+ AdvancementCalculator[] advs = new AdvancementCalculator[nexts.length];
+ for (int i = 0; i < nexts.length; i++)
+ {
+ advs[i] = new AdvancementCalculator();
+ advs[i].mHasPrevActive = current.mHasPrevActive;
+ advs[i].isMarked = current.isMarked;
+ advs[i].HasNextMarked = current.HasNextMarked;
+ advs[i].activity = current.activity;
+ if ((v instanceof Loop) && (current.HasNextMarked.get(nexts[i]) != null))
+// Logger.debug(0, v.getID() + " " + nexts[i].getID() + " HasNextMarked")
+ ;
+ else
+ calc(nexts[i], advs[i]);
+ }
+ long maximuNbActexp = 0;
+ long currentNbActExp = 0;
+ long NbActpassed = 0;
+ long NbActpassedWithCurrent = 0;
+ long NbActLeftWithCurrent = 0;
+ long NbActLeftWithoutCurrent = 0;
+ boolean isbranchFinished = true;
+ boolean hasNobranchFinished = true;
+ boolean hasNoBranchActive = true;
+ for (int i = 0; i < advs.length; i++)
+ {
+ if (advs[i].mIsbranchActive)
+ hasNoBranchActive = false;
+ if (advs[i].mIsbranchFinished)
+ hasNobranchFinished = false;
+ }
+ for (int i = 0; i < advs.length; i++)
+ {
+
+ if (maximuNbActexp < advs[i].mMaximuNbActexp)
+ maximuNbActexp = advs[i].mMaximuNbActexp;
+ if (advs[i].mIsbranchActive || advs[i].mIsbranchFinished || (hasNoBranchActive && hasNobranchFinished))
+ {
+ if (NbActpassed < advs[i].mNbActpassed)
+ NbActpassed = advs[i].mNbActpassed;
+ if (NbActpassedWithCurrent < advs[i].mNbActpassedWithCurrent)
+ NbActpassedWithCurrent = advs[i].mNbActpassedWithCurrent;
+ if (NbActLeftWithCurrent < advs[i].mNbActLeftWithCurrent)
+ NbActLeftWithCurrent = advs[i].mNbActLeftWithCurrent;
+ if (NbActLeftWithoutCurrent < advs[i].mNbActLeftWithoutCurrent)
+ NbActLeftWithoutCurrent += advs[i].mNbActLeftWithoutCurrent;
+ if (currentNbActExp < advs[i].mCurrentNbActExp)
+ currentNbActExp = advs[i].mCurrentNbActExp;
+ }
+ }
+ current.mCurrentNbActExp += currentNbActExp;
+ current.mNbActpassedWithCurrent += NbActpassedWithCurrent;
+ current.mMaximuNbActexp += maximuNbActexp;
+ current.mNbActpassed += NbActpassed;
+ current.mIsbranchActive = current.mIsbranchActive || !hasNoBranchActive;
+ current.mNbActLeftWithCurrent += NbActLeftWithCurrent;
+ current.mNbActLeftWithoutCurrent += NbActLeftWithoutCurrent;
+ return;
+ }
+ if (v instanceof Join)
+ {
+ AdvancementCalculator adv;
+ if (current.isMarked.get(v) == null)
+ {
+ adv = new AdvancementCalculator();
+ adv.isMarked = current.isMarked;
+ adv.HasNextMarked = current.HasNextMarked;
+ adv.activity = current.activity;
+ adv.mHasPrevActive = current.mHasPrevActive;
+ current.isMarked.put(v, adv);
+ if (nexts.length == 1)
+ calc(nexts[0], adv);
+ }
+ else
+ adv = (AdvancementCalculator) current.isMarked.get(v);
+ current.mCurrentNbActExp += adv.mCurrentNbActExp;
+ current.mMaximuNbActexp += adv.mMaximuNbActexp;
+ current.mNbActpassed += adv.mNbActpassed;
+ current.mNbActpassedWithCurrent += adv.mNbActpassedWithCurrent;
+ current.mIsbranchActive = current.mIsbranchActive || (current.mMaximuNbActexp == 0 && adv.mIsbranchActive);
+ if (current.mHasPrevActive)
+ hasprevActive.put(String.valueOf(v.getID()), v);
+ current.mNbActLeftWithCurrent += adv.mNbActLeftWithCurrent;
+ current.mNbActLeftWithoutCurrent += adv.mNbActLeftWithoutCurrent;
+ return;
+ }
+ if (nexts.length != 0)
+ calc(nexts[0], current);
+ }
+ public long getLongestWayInAct()
+ {
+ return mMaximuNbActexp;
+ }
+ public long getCurrentLongestWayInAct()
+ {
+ return mCurrentNbActExp;
+ }
+ public long getNbActLeftWithActive()
+ {
+ return mNbActLeftWithCurrent;
+ }
+ public long getNbActLeftWithoutActive()
+ {
+ return mNbActLeftWithoutCurrent;
+ }
+ public long getNbActPassedWithoutActive()
+ {
+ return mNbActpassed;
+ }
+ public long getNbActPassedWithActive()
+ {
+ return mNbActpassedWithCurrent;
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/AndSplit.java b/source/com/c2kernel/lifecycle/instance/AndSplit.java
new file mode 100755
index 0000000..7a2055d
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/AndSplit.java
@@ -0,0 +1,26 @@
+package com.c2kernel.lifecycle.instance;
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.scripting.ScriptingEngineException;
+/**
+ * @version $Revision: 1.16 $ $Date: 2005/05/10 15:14:54 $
+ * @author $Author: abranson $
+ */
+public class AndSplit extends Split
+{
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public AndSplit()
+ {
+ super();
+ }
+ public void runNext(AgentPath agent) throws ScriptingEngineException
+ {
+ AdvancementCalculator adv = new AdvancementCalculator();
+ adv.calculate((CompositeActivity) getParent());
+ Vertex[] outVertices = getOutGraphables();
+ for (int i = 0; i < outVertices.length; i++)
+ ((WfVertex) outVertices[i]).run(agent);
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/CompositeActivity.java b/source/com/c2kernel/lifecycle/instance/CompositeActivity.java
new file mode 100755
index 0000000..5292127
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/CompositeActivity.java
@@ -0,0 +1,448 @@
+package com.c2kernel.lifecycle.instance;
+
+import java.awt.Point;
+import java.util.ArrayList;
+import java.util.Vector;
+
+import com.c2kernel.common.AccessRightsException;
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.InvalidTransitionException;
+import com.c2kernel.common.ObjectAlreadyExistsException;
+import com.c2kernel.graph.model.GraphModel;
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.graph.model.GraphableVertex;
+import com.c2kernel.lifecycle.instance.gui.model.WfVertexOutlineCreator;
+import com.c2kernel.lifecycle.instance.stateMachine.StateMachine;
+import com.c2kernel.lifecycle.instance.stateMachine.States;
+import com.c2kernel.lifecycle.instance.stateMachine.Transitions;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.scripting.ScriptingEngineException;
+import com.c2kernel.utils.Logger;
+
+/**
+ * @version $Revision: 1.86 $ $Date: 2005/10/05 07:39:37 $
+ * @author $Author: abranson $
+ */
+public class CompositeActivity extends Activity
+{
+ /**
+ * @see java.lang.Object#Object()
+ */
+ /*
+ * --------------------------------------------
+ * ----------------CONSTRUCTOR-----------------
+ * --------------------------------------------
+ */
+ public CompositeActivity()
+ {
+ super();
+ setChildrenGraphModel(new GraphModel(new WfVertexOutlineCreator()));
+ setIsComposite(true);
+ }
+
+ /**
+ * @see com.c2kernel.lifecycle.instance.WfVertex#verify()
+ */
+ /*
+ * -------------------------------------------- --------------Other
+ * Functions--------------- --------------------------------------------
+ */
+ /** launch the verification of the subprocess() */
+ public boolean verify()
+ {
+ boolean err = super.verify();
+ GraphableVertex[] vChildren = getChildren();
+ for (int i = 0; i < vChildren.length; i++)
+ {
+ if (!((WfVertex) vChildren[i]).verify())
+ {
+ mErrors.add("error in children");
+ return false;
+ }
+ }
+ return err;
+ }
+
+ /**
+ * Method initChild.
+ *
+ * @param act
+ * @param first
+ * @param point
+ */
+ /**
+ * Create an initialize a Activity attached to the current activity
+ *
+ * @param first :
+ * if true, the activity Waiting will be one of the first
+ * launched by the parent activity
+ */
+ public void initChild(Activity act, boolean first, Point point)
+ {
+ this.addChild(act, new GraphPoint(point.x, point.y));
+ if (first)
+ {
+ getChildrenGraphModel().setStartVertexId(act.getID());
+ Logger.msg(5, "com.c2kernel.lifecycle.CompositeActivity :: " + getID() + " is first");
+ }
+ }
+
+ /**
+ * Method newChild.
+ *
+ * @param Name
+ * @param Type
+ * @param point
+ * @return WfVertex
+ */
+ public WfVertex newExistingChild(Activity child, String Name, Point point)
+ {
+ child.setName(Name);
+ addChild(child, new GraphPoint(point.x, point.y));
+ return child;
+ }
+
+ /**
+ * Method newChild.
+ *
+ * @param Name
+ * @param Type
+ * @param point
+ * @return WfVertex
+ */
+ public WfVertex newChild(String Name, String Type, Point point)
+ {
+ WfVertex v = newChild(Type, point);
+ v.setName(Name);
+ return v;
+ }
+
+ /**
+ * Method newChild.
+ *
+ * @param vertexTypeId
+ * @param point
+ * @return WfVertex
+ */
+ public WfVertex newChild(String vertexTypeId, Point point)
+ {
+ WfVertex wfVertex = null;
+ if (vertexTypeId.equals("Atomic"))
+ {
+ wfVertex = newAtomChild("False id", false, point);
+ } else if (vertexTypeId.equals("Composite"))
+ {
+ wfVertex = newCompChild("False id", false, point);
+ } else if (vertexTypeId.endsWith("Split"))
+ {
+ if (vertexTypeId.startsWith("Or"))
+ {
+ wfVertex = newSplitChild("Or", point);
+ } else if (vertexTypeId.startsWith("XOr"))
+ {
+ wfVertex = newSplitChild("XOr", point);
+ } else if (vertexTypeId.startsWith("Loop"))
+ {
+ wfVertex = newSplitChild("Loop", point);
+ } else
+ {
+ wfVertex = newSplitChild("And", point);
+ }
+ } else if (vertexTypeId.equals("Join"))
+ {
+ wfVertex = newJoinChild(point);
+ } else if (vertexTypeId.equals("Route"))
+ {
+ wfVertex = newRouteChild(point);
+ }
+ return wfVertex;
+ }
+
+ /**
+ * Method newCompChild.
+ *
+ * @param id
+ * @param first
+ * @param point
+ * @return CompositeActivity Create an initialize a composite Activity
+ * attached to the current activity
+ */
+ public CompositeActivity newCompChild(String id, boolean first, Point point)
+ {
+ CompositeActivity act = new CompositeActivity();
+ initChild(act, first, point);
+ act.setName(id);
+ return act;
+ }
+
+ /**
+ * Method newAtomChild.
+ *
+ * @param id
+ * @param first
+ * @param point
+ * @return Activity Create an initialize an Atomic Activity attached to the
+ * current activity
+ *
+ */
+ public Activity newAtomChild(String id, boolean first, Point point)
+ {
+ Activity act = new Activity();
+ initChild(act, first, point);
+ act.setName(id);
+ return act;
+ }
+
+ /**
+ * Method newSplitChild.
+ *
+ * @param Type
+ * @param point
+ * @return Split
+ */
+ public Split newSplitChild(String Type, Point point)
+ {
+ Split split;
+ if (Type.equals("Or"))
+ {
+ split = new OrSplit();
+ } else if (Type.equals("XOr"))
+ {
+ split = new XOrSplit();
+ } else if (Type.equals("Loop"))
+ {
+ split = new Loop();
+ } else
+ {
+ split = new AndSplit();
+ }
+ addChild(split, new GraphPoint(point.x, point.y));
+ return split;
+ }
+
+ /**
+ * Method newJoinChild.
+ *
+ * @param point
+ * @return Join
+ */
+ public Join newJoinChild(Point point)
+ {
+ Join join = new Join();
+ join.getProperties().put("Type", "Join");
+ addChild(join, new GraphPoint(point.x, point.y));
+ return join;
+ }
+
+ public Join newRouteChild(Point point)
+ {
+ Join join = new Join();
+ join.getProperties().put("Type", "Route");
+ addChild(join, new GraphPoint(point.x, point.y));
+ return join;
+ }
+
+ /**
+ * Method search.
+ *
+ * @param ids
+ * @return WfVertex
+ */
+ WfVertex search(int ids)
+ {
+ for (int i = 0; i < getChildren().length; i++)
+ {
+ WfVertex ver = (WfVertex) getChildren()[i];
+ if (ver instanceof Split)
+ {
+ if (ver.getID() == ids)
+ {
+ return ver;
+ }
+ }
+ if (ver instanceof Join)
+ {
+ if (ver.getID() == ids)
+ {
+ return ver;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @see com.c2kernel.lifecycle.instance.WfVertex#run()
+ */
+ public void run(AgentPath agent) throws ScriptingEngineException
+ {
+ super.run(agent);
+ if (getChildrenGraphModel().getStartVertex() != null && getMachine().getCurrentState() != States.FINISHED && ((Boolean) getProperties().get(StateMachine.AUTOSTART)).booleanValue())
+ {
+ WfVertex first = (WfVertex) getChildrenGraphModel().getStartVertex();
+ ((WfVertex) getChildrenGraphModel().getStartVertex()).run(agent);
+ }
+ }
+
+ public void runNext(AgentPath agent) throws ScriptingEngineException
+ {
+ if (getMachine().state != States.FINISHED)
+ getMachine().traverse(Transitions.COMPLETE);
+ super.runNext(agent);
+ }
+
+ /**
+ * @see com.c2kernel.lifecycle.instance.Activity#query(com.c2kernel.common.AgentInfo,
+ * java.lang.String, boolean)
+ */
+ public Activity[] query(AgentPath agent, int stateID, boolean filter)
+ {
+ Vector steps = new Vector();
+ Activity[] returnArray = null;
+ for (int i = 0; i < getChildren().length; i++)
+ {
+ if (getChildren()[i] instanceof Activity)
+ steps.addElement(((Activity) getChildren()[i]).query(agent, stateID, filter));
+ }
+ int j = 0;
+ for (int i = 0; i < steps.size(); i++)
+ j += ((Activity[]) steps.elementAt(i)).length;
+ Activity[] tmp = super.query(agent, stateID, filter);
+ if (tmp.length == 1)
+ {
+ returnArray = new Activity[j + 1];
+ returnArray[j] = tmp[0];
+ } else
+ returnArray = new Activity[j];
+ j = 0;
+ for (int i = 0; i < steps.size(); i++)
+ {
+ Activity[] stepArray = (Activity[]) steps.elementAt(i);
+ for (int k = 0; k < stepArray.length; k++)
+ returnArray[j++] = stepArray[k];
+ }
+ return returnArray;
+ }
+
+ /**
+ * @see com.c2kernel.lifecycle.instance.Activity#calculateJobs()
+ */
+ public ArrayList calculateJobs(AgentPath agent, boolean recurse)
+ {
+ ArrayList jobs = new ArrayList();
+ boolean childActive = false;
+ if (recurse)
+ for (int i = 0; i < getChildren().length; i++)
+ if (getChildren()[i] instanceof Activity)
+ {
+ Activity child = (Activity) getChildren()[i];
+ jobs.addAll(child.calculateJobs(agent, recurse));
+ childActive |= child.active;
+ }
+ if (!childActive)
+ jobs.addAll(super.calculateJobs(agent, recurse));
+ return jobs;
+ }
+
+ public ArrayList calculateAllJobs(AgentPath agent, boolean recurse)
+ {
+ ArrayList jobs = new ArrayList();
+ if (recurse)
+ for (int i = 0; i < getChildren().length; i++)
+ if (getChildren()[i] instanceof Activity)
+ {
+ Activity child = (Activity) getChildren()[i];
+ jobs.addAll(child.calculateAllJobs(agent, recurse));
+ }
+ jobs.addAll(super.calculateAllJobs(agent, recurse));
+ return jobs;
+ }
+
+ /**
+ * Method addNext.
+ *
+ * @param origin
+ * @param terminus
+ * @return Next
+ */
+ public Next addNext(WfVertex origin, WfVertex terminus)
+ {
+ return new Next(origin, terminus);
+ }
+
+ /**
+ * Method addNext.
+ *
+ * @param originID
+ * @param terminusID
+ * @return Next
+ */
+ public Next addNext(int originID, int terminusID)
+ {
+ Next n = new Next();
+ n.setParent(this);
+ getChildrenGraphModel().addEdgeAndCreateId(n, originID, terminusID);
+ return n;
+ }
+
+ /**
+ * Method hasGoodNumberOfActivity.
+ *
+ * @return boolean
+ */
+ public boolean hasGoodNumberOfActivity()
+ {
+ int endingAct = 0;
+ for (int i = 0; i < getChildren().length; i++)
+ {
+ WfVertex vertex = (WfVertex) getChildren()[i];
+ if (getChildrenGraphModel().getOutEdges(vertex).length == 0)
+ endingAct++;
+ }
+ if (endingAct > 1)
+ return false;
+ return true;
+ }
+
+ /**
+ * @see com.c2kernel.lifecycle.instance.Activity#getType()
+ */
+ public String getType()
+ {
+ if (getName().equals("domain"))
+ return "domain";
+ return super.getType();
+ }
+
+ /**
+ *
+ */
+ public void reinit(int idLoop)
+ {
+ super.reinit(idLoop);
+ if (getChildrenGraphModel().getStartVertex() != null && getMachine().getCurrentState() != States.FINISHED)
+ ((WfVertex) getChildrenGraphModel().getStartVertex()).reinit(idLoop);
+ }
+
+ public void request(AgentPath agent, int transitionID, String requestData) throws AccessRightsException, InvalidTransitionException, InvalidDataException, ObjectAlreadyExistsException
+ {
+ if (getChildrenGraphModel().getStartVertex() != null && getMachine().getCurrentState() != States.FINISHED && transitionID == Transitions.START)
+ try
+ {
+ ((WfVertex) getChildrenGraphModel().getStartVertex()).run(agent);
+ } catch (ScriptingEngineException e)
+ {
+ Logger.error(e);
+ }
+ super.request(agent, transitionID, requestData);
+ }
+ public void refreshJobs()
+ {
+ GraphableVertex[] children = getChildren();
+ for (int i = 0; i < children.length; i++)
+ if (children[i] instanceof CompositeActivity)
+ ((CompositeActivity) children[i]).refreshJobs();
+ else if (children[i] instanceof Activity)
+ ((Activity) children[i]).pushJobsToAgents();
+ }
+} \ No newline at end of file
diff --git a/source/com/c2kernel/lifecycle/instance/EventList.java b/source/com/c2kernel/lifecycle/instance/EventList.java
new file mode 100755
index 0000000..be255fb
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/EventList.java
@@ -0,0 +1,19 @@
+package com.c2kernel.lifecycle.instance;
+
+import java.io.Serializable;
+
+/**
+ * @version $Revision: 1.9 $ $Date: 2005/06/08 19:47:59 $
+ * @author $Author: abranson $
+ */
+public class EventList implements Serializable {
+ private int[] dummy = new int[0];
+ public int transition=-1;
+
+ public int[] getNums() {
+ return dummy;
+ }
+
+ public void setNums(int[] nums) {
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/EventStorage.java b/source/com/c2kernel/lifecycle/instance/EventStorage.java
new file mode 100755
index 0000000..a78a2bf
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/EventStorage.java
@@ -0,0 +1,24 @@
+package com.c2kernel.lifecycle.instance;
+import java.io.Serializable;
+import java.util.Hashtable;
+
+/**
+ * @version $Revision: 1.15 $ $Date: 2005/06/08 19:48:00 $
+ * @author $Author: abranson $
+ */
+public class EventStorage implements Serializable
+{
+ private Hashtable mLists;
+ private EventList[] dummy = new EventList[0];
+ public Integer lastTransitionStored;
+
+ public EventList[] getLists()
+ {
+ return dummy;
+ }
+
+ public void setLists(EventList[] lists)
+ {
+ }
+
+}
diff --git a/source/com/c2kernel/lifecycle/instance/JobPusher.java b/source/com/c2kernel/lifecycle/instance/JobPusher.java
new file mode 100755
index 0000000..e58170d
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/JobPusher.java
@@ -0,0 +1,69 @@
+package com.c2kernel.lifecycle.instance;
+
+import java.util.Enumeration;
+import java.util.Iterator;
+
+import com.c2kernel.entity.Agent;
+import com.c2kernel.entity.AgentHelper;
+import com.c2kernel.entity.agent.Job;
+import com.c2kernel.entity.agent.JobArrayList;
+import com.c2kernel.lifecycle.instance.stateMachine.Transitions;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.lookup.RolePath;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.Logger;
+
+final class JobPusher extends Thread {
+ private final Activity activity;
+ private final RolePath myRole;
+
+ JobPusher(Activity activity, RolePath role) {
+ this.activity = activity;
+ this.myRole = role;
+ }
+
+ public void run()
+ {
+ Thread.currentThread().setName("Agent job pusher for "+activity.getName()+" to role "+myRole);
+ for (Enumeration e = myRole.getChildren(); e.hasMoreElements();)
+ {
+ AgentPath nextAgent = (AgentPath)e.nextElement();
+ Logger.msg(7, "Activity.pushJobsToAgents() - Calculating jobs for " + nextAgent.getAgentName());
+ try
+ {
+ // get joblist for user
+ JobArrayList jobList = new JobArrayList(this.activity.calculateJobs(nextAgent, false));
+ // only transmit start, complete and resume jobs
+ for (Iterator element = jobList.list.iterator(); element.hasNext();)
+ {
+ Job thisJob = (Job) element.next();
+ if (thisJob.getPossibleTransition() != Transitions.START
+ && thisJob.getPossibleTransition() != Transitions.COMPLETE
+ && thisJob.getPossibleTransition() != Transitions.RESUME
+ && thisJob.getPossibleTransition() != Transitions.SUSPEND
+ && thisJob.getPossibleTransition() != Transitions.REASSIGN)
+ element.remove();
+ }
+ Logger.msg(7, "Activity.pushJobsToAgents() - User will receive " + jobList.list.size() + " jobs");
+ String stringJobs = CastorXMLUtility.marshall(jobList);
+ // push it to the agent
+ org.omg.CORBA.Object agentIOR = nextAgent.getIOR();
+ Agent thisAgent = AgentHelper.narrow(agentIOR);
+ Logger.debug("Calling agent "+thisAgent.getSystemKey()+" from "+activity.getPath());
+ thisAgent.refreshJobList(this.activity.getItemEntityPath().getSysKey(), activity.getPath(), stringJobs);
+ }
+ catch (Exception ex)
+ {
+ Logger.error(
+ "Agent "
+ + nextAgent.getAgentName()
+ + " of role "
+ + myRole
+ + " could not be found to be informed of a change in "
+ + this.activity.getItemEntityPath().getSysKey());
+ Logger.error(ex);
+ }
+ }
+
+ }
+} \ No newline at end of file
diff --git a/source/com/c2kernel/lifecycle/instance/Join.java b/source/com/c2kernel/lifecycle/instance/Join.java
new file mode 100755
index 0000000..205d264
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/Join.java
@@ -0,0 +1,207 @@
+package com.c2kernel.lifecycle.instance;
+import java.util.Vector;
+
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.graph.traversal.GraphTraversal;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.scripting.ScriptingEngineException;
+/**
+ * @version $Revision: 1.52 $ $Date: 2005/05/10 15:14:54 $
+ * @author $Author: abranson $
+ */
+public class Join extends WfVertex
+{
+ public Vector mErrors;
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public Join()
+ {
+ super();
+ mErrors = new Vector(0, 1);
+ }
+ private boolean loopTested;
+ public int counter = 0;
+ private String mItemSystemKey = "";
+ /**
+ * @see com.c2kernel.lifecycle.instance.WfVertex#runNext()
+ */
+ public void runNext(AgentPath agent) throws ScriptingEngineException
+ {
+ AdvancementCalculator adv = new AdvancementCalculator();
+ adv.calculate((CompositeActivity) getParent());
+ if (adv.hasprevActive.get(String.valueOf(getID())) == null)
+ {
+ Vertex[] outVertices = getOutGraphables();
+ if (outVertices.length > 0)
+ {
+ WfVertex nextAct = (WfVertex) outVertices[0];
+ nextAct.run(agent);
+ }
+ else
+ super.runNext(agent);
+ }
+ }
+ /**
+ * Method addNext.
+ *
+ * @param idNext
+ */
+ public void addNext(String idNext)
+ {
+ new Next(this, (WfVertex) getParent().search(idNext));
+ }
+ /**
+ * @see com.c2kernel.lifecycle.instance.WfVertex#reinit(int)
+ */
+ public void reinit(int idLoop)
+ {
+ Vertex[] outVertices = getOutGraphables();
+ if (outVertices.length == 1)
+ {
+ WfVertex nextAct = (WfVertex) outVertices[0];
+ nextAct.reinit(idLoop);
+ }
+ }
+ /**
+ * Method getItemSystemKey.
+ *
+ * @return String
+ */
+ /*
+ * public CompositeActivity process() { return parent.process(); }
+ */
+ public String getItemSystemKey()
+ {
+ return mItemSystemKey;
+ }
+ /**
+ * Method setItemSystemKey.
+ *
+ * @param itemSystemKey
+ */
+ public void setItemSystemKey(String itemSystemKey)
+ {
+ mItemSystemKey = itemSystemKey;
+ }
+ /**
+ * @see com.c2kernel.lifecycle.instance.WfVertex#verify()
+ */
+ // public void initItemSystemKey(String systemKey) {
+ // this.setItemSystemKey(systemKey);
+ // }
+ public boolean verify()
+ {
+ mErrors.removeAllElements();
+ int nbOutEdges = getOutEdges().length;
+ int nbInEdges = getInEdges().length;
+ String type = (String) getProperties().get("Type");
+ if (nbInEdges < 1)
+ {
+ mErrors.add("not enough previous");
+ return false;
+ }
+ if (type != null && type.equals("Route"))
+ {
+ if (nbInEdges > 1)
+ {
+ mErrors.add("Bad nb of previous");
+ return false;
+ }
+ }
+ if (nbOutEdges > 1)
+ {
+ mErrors.add("too many next");
+ return false;
+ }
+ if (nbOutEdges == 0)
+ {
+ if (!((CompositeActivity) getParent()).hasGoodNumberOfActivity())
+ {
+ mErrors.add("too many endpoints");
+ return false;
+ }
+ }
+ Vertex[] outV = getOutGraphables();
+ Vertex[] anteVertices = GraphTraversal.getTraversal(getParent().getChildrenGraphModel(), this, GraphTraversal.kUp, false);
+ boolean loop = false;
+ boolean errInLoop = false;
+ for (int i = 0; i < outV.length; i++)
+ {
+ for (int j = 0; j < anteVertices.length; j++)
+ if (!loop && outV[i].getID() == anteVertices[j].getID())
+ {
+ if (outV[i] instanceof Loop)
+ {
+ loop = true;
+ j = anteVertices.length;
+ i = outV.length;
+ }
+ else
+ {
+ errInLoop = true;
+ }
+ }
+ }
+ if (errInLoop && loop)
+ {
+ mErrors.add("Problem in Loop");
+ return false;
+ }
+ return true;
+ }
+ /**
+ * @see com.c2kernel.lifecycle.instance.WfVertex#getErrors()
+ */
+ public String getErrors()
+ {
+ if (mErrors.size() == 0)
+ return "No error";
+ else
+ return (String) mErrors.elementAt(0);
+ }
+ /**
+ * @see com.c2kernel.lifecycle.instance.WfVertex#run()
+ */
+ public void run(AgentPath agent) throws ScriptingEngineException
+ {
+ runNext(agent);
+ }
+ /**
+ * @see com.c2kernel.lifecycle.instance.WfVertex#addNext(com.c2kernel.lifecycle.instance.WfVertex)
+ */
+ public Next addNext(WfVertex vertex)
+ {
+ return new Next(this, vertex);
+ }
+ /**
+ * @see com.c2kernel.lifecycle.instance.WfVertex#loop()
+ */
+ public boolean loop()
+ {
+ boolean loop2 = false;
+ if (!loopTested)
+ {
+ loopTested = true;
+ if (getOutGraphables().length != 0)
+ loop2 = ((WfVertex) getOutGraphables()[0]).loop();
+ }
+ else
+ loop2 = true;
+ loopTested = false;
+ return loop2;
+ }
+ public void runfirst(AgentPath agent) throws ScriptingEngineException
+ {
+ runNext(agent);
+ }
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.c2kernel.graph.model.Vertex#isJoin()
+ */
+ public boolean isJoin()
+ {
+ return true;
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/Loop.java b/source/com/c2kernel/lifecycle/instance/Loop.java
new file mode 100755
index 0000000..556a9ca
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/Loop.java
@@ -0,0 +1,104 @@
+package com.c2kernel.lifecycle.instance;
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.graph.traversal.GraphTraversal;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.scripting.ScriptingEngineException;
+import com.c2kernel.utils.Logger;
+/**
+ * @version $Revision: 1.35 $ $Date: 2005/05/10 15:14:54 $
+ * @author $Author: abranson $
+ */
+public class Loop extends XOrSplit
+{
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public Loop()
+ {
+ super();
+ }
+ /**
+ * @see com.c2kernel.lifecycle.instance.WfVertex#loop()
+ */
+ public boolean loop()
+ {
+ return true;
+ }
+ public void followNext(Next activeNext, AgentPath agent) throws ScriptingEngineException
+ {
+ WfVertex v = activeNext.getTerminusVertex();
+ if (!isInPrev(v))
+ v.run(agent);
+ else
+ {
+ v.reinit(getID());
+ v.run(agent);
+ }
+ }
+ /**
+ * @see com.c2kernel.lifecycle.instance.WfVertex#reinit(int)
+ */
+ public void reinit(int idLoop)
+ {
+ Logger.msg(8, "Loop.reinit");
+ if (idLoop == getID())
+ return;
+ else
+ {
+ Vertex[] outVertices = getOutGraphables();
+ for (int j = 0; j < outVertices.length; j++)
+ {
+ if (!isInPrev(outVertices[j]))
+ ((WfVertex) outVertices[j]).reinit(idLoop);
+ }
+ }
+ }
+ /**
+ * @see com.c2kernel.lifecycle.instance.WfVertex#verify()
+ */
+ public boolean verify()
+ {
+ boolean err = super.verify();
+ Vertex[] nexts = getOutGraphables();
+ Vertex[] anteVertices = GraphTraversal.getTraversal(getParent().getChildrenGraphModel(), this, GraphTraversal.kUp, false);
+ int k = 0;
+ int l = 0;
+ Vertex[] brothers = getParent().getChildren();
+ for (int i = 0; i < brothers.length; i++)
+ if (brothers[i] instanceof Loop)
+ l++;
+ for (int i = 0; i < nexts.length; i++)
+ {
+ for (int j = 0; j < anteVertices.length; j++)
+ if (nexts[i].getID() == anteVertices[j].getID())
+ k++;
+ }
+ if (k != 1 && !(l > 1))
+ {
+ mErrors.add("bad number of pointing back nexts");
+ return false;
+ }
+ // if (nexts.length>2) {
+ // mErrors.add("you must only have 2 nexts");
+ // return false;
+ // }
+ return err;
+ }
+ private boolean isInPrev(Vertex vertex)
+ {
+ int id = vertex.getID();
+ Vertex[] anteVertices = GraphTraversal.getTraversal(getParent().getChildrenGraphModel(), this, GraphTraversal.kUp, false);
+ for (int i = 0; i < anteVertices.length; i++)
+ {
+ if (anteVertices[i].getID() == id)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ public boolean isLoop()
+ {
+ return true;
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/Next.java b/source/com/c2kernel/lifecycle/instance/Next.java
new file mode 100755
index 0000000..059dbf8
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/Next.java
@@ -0,0 +1,82 @@
+package com.c2kernel.lifecycle.instance;
+
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.graph.model.GraphableEdge;
+
+/**
+ * @version $Revision: 1.58 $ $Date: 2005/05/10 15:14:54 $
+ * @author $Author: abranson $
+ */
+/** this class represents the link between 2 successive activities */
+public class Next extends GraphableEdge
+{
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public Next()
+ {
+ super();
+ }
+
+ /**
+ * Method Next.
+ * @param pre
+ * @param nex
+ */
+ /** create and initialize a link between an Activities */
+ public Next(WfVertex pre, WfVertex nex)
+ {
+ super(pre, nex);
+ getProperties().put("Alias","");
+ getProperties().put("Type","Straight");
+ }
+
+ /**
+ * Method verify.
+ * @return boolean
+ */
+ public boolean verify()
+ {
+ return true;
+ }
+ public WfVertex getTerminusVertex()
+ {
+ return (WfVertex)((CompositeActivity)getParent()).getWf().search(getParent().getPath()+"/"+this.getTerminusVertexId());
+ }
+ public boolean containsPoint(GraphPoint p)
+ {
+ GraphPoint originPoint = getOriginPoint();
+ GraphPoint terminusPoint = getTerminusPoint();
+ GraphPoint midPoint = new GraphPoint();
+
+ if (("Broken +".equals(getProperties().get("Type"))))
+ {
+ midPoint.x = (originPoint.x + terminusPoint.x) / 2;
+ midPoint.y = (originPoint.y + terminusPoint.y) / 2;
+ }
+ else if (("Broken -".equals(getProperties().get("Type"))))
+ {
+ boolean arrowOnY = !(originPoint.y - terminusPoint.y < 60 && originPoint.y - terminusPoint.y > -60);
+ midPoint.x = arrowOnY ? terminusPoint.x : (originPoint.x + terminusPoint.x) / 2;
+ midPoint.y = arrowOnY ? (originPoint.y + terminusPoint.y) / 2 : originPoint.y;
+ }
+ else if (("Broken |".equals(getProperties().get("Type"))))
+ {
+ boolean arrowOnY = !(originPoint.y - terminusPoint.y < 60 && originPoint.y - terminusPoint.y > -60);
+ midPoint.x = arrowOnY ? originPoint.x : (originPoint.x + terminusPoint.x) / 2;
+ midPoint.y = arrowOnY ? (originPoint.y + terminusPoint.y) / 2 : terminusPoint.y;
+ }
+ else
+ {
+ midPoint.x = originPoint.x + (terminusPoint.x - originPoint.x) / 2;
+ midPoint.y = originPoint.y + (terminusPoint.y - originPoint.y) / 2;
+ }
+
+ int minX = midPoint.x - 10;
+ int minY = midPoint.y - 10;
+ int maxX = midPoint.x + 10;
+ int maxY = midPoint.y + 10;
+
+ return (p.x >= minX) && (p.x <= maxX) && (p.y >= minY) && (p.y <= maxY);
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/OrSplit.java b/source/com/c2kernel/lifecycle/instance/OrSplit.java
new file mode 100755
index 0000000..f0fcdd5
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/OrSplit.java
@@ -0,0 +1,62 @@
+package com.c2kernel.lifecycle.instance;
+import java.util.StringTokenizer;
+
+import com.c2kernel.graph.model.DirectedEdge;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.scripting.ScriptingEngineException;
+import com.c2kernel.utils.Logger;
+/**
+ * @version $Revision: 1.22 $ $Date: 2005/05/10 15:14:54 $
+ * @author $Author: abranson $
+ */
+public class OrSplit extends Split
+{
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public OrSplit()
+ {
+ super();
+ }
+ public void runNext(AgentPath agent) throws ScriptingEngineException
+ {
+ String nexts =
+ this
+ .evaluateScript((String) getProperties().get("RoutingScriptName"), (String) getProperties().get("RoutingScriptVersion"))
+ .toString();
+ StringTokenizer tok = new StringTokenizer(nexts, ",");
+ Logger.msg(7, tok.countTokens() + " nexts to activate:" + nexts);
+ int active = 0;
+ try
+ {
+ DirectedEdge[] outEdges = getOutEdges();
+ AdvancementCalculator adv = new AdvancementCalculator();
+ adv.calculate((CompositeActivity)getParent());
+ while (tok.hasMoreTokens())
+ {
+ String thisNext = tok.nextToken();
+ Logger.msg(7, "Finding next " + thisNext);
+ for (int i = 0; i < outEdges.length; i++)
+ {
+ Next nextEdge = (Next) outEdges[i];
+ if (thisNext != null && thisNext.equals(nextEdge.getProperties().get("Alias")))
+ {
+ WfVertex term = nextEdge.getTerminusVertex();
+ term.run(agent);
+ Logger.msg(7, "Running " + nextEdge.getProperties().get("Alias"));
+ active++;
+ }
+ }
+ }
+ // if no active nexts throw exception
+ }
+ catch (Exception e)
+ {
+ Logger.error(e);
+ }
+ if (active == 0)
+ throw new ScriptingEngineException("No nexts were activated!");
+ }
+
+
+}
diff --git a/source/com/c2kernel/lifecycle/instance/ParserWF.java b/source/com/c2kernel/lifecycle/instance/ParserWF.java
new file mode 100755
index 0000000..c3d718d
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/ParserWF.java
@@ -0,0 +1,357 @@
+package com.c2kernel.lifecycle.instance;
+
+import java.awt.Point;
+import java.io.IOException;
+import java.util.Vector;
+
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.utils.CastorHashMap;
+import com.c2kernel.utils.Logger;
+
+/**
+ * @version $Revision: 1.26 $ $Date: 2006/03/03 13:52:21 $
+ * @author $Author: abranson $
+ */
+public class ParserWF
+{
+ static Vector nexts;
+ static String file = "";
+ static int i;
+ static CastorHashMap mInfo = new CastorHashMap();
+
+ /**
+ * Method addStep.
+ * @param act
+ * @param xmlfile
+ * @return CompositeActivity
+ * @throws IOException
+ */
+ /**
+ * @associates <{com.c2kernel.lifecycle.instance.Workflow}>
+ * @label creates
+ */
+ public static CompositeActivity addStep(CompositeActivity act, String xmlfile, AgentPath agent) throws IOException
+ {
+ nexts = new Vector(1, 1);
+ i = 0;
+ file = xmlfile;
+ int c;
+ while (i < file.length() - 5)
+ {
+ if (file.substring(i, i + 5).equals("<STEP"))
+ {
+ readStep(act);
+ }
+ else
+ {
+ i++;
+ }
+ }
+ boolean flag = false;
+ for (int j = 0; j < nexts.size(); j++)
+ {
+ for (int k = j + 1; k < nexts.size(); k++)
+ {
+ if (((String[]) nexts.elementAt(j))[0].equals(((String[]) nexts.elementAt(k))[0]))
+ {
+ int tmp = act.newSplitChild("And", new Point(0, 0)).getID();
+ ((WfVertex) act.search(((String[]) nexts.elementAt(k))[0])).addNext(act.search(tmp));
+ ((Split) act.search(tmp)).addNext((WfVertex) act.search(((String[]) nexts.elementAt(k))[1]));
+ ((Split) act.search(tmp)).addNext((WfVertex) act.search(((String[]) nexts.elementAt(j))[1]));
+ nexts.removeElementAt(k--);
+ flag = true;
+ }
+ }
+ if (flag)
+ {
+ nexts.removeElementAt(j--);
+ }
+ flag = false;
+ }
+ for (int j = 0; j < nexts.size(); j++)
+ {
+ for (int k = j + 1; k < nexts.size(); k++)
+ {
+ if (((String[]) nexts.elementAt(j))[1].equals(((String[]) nexts.elementAt(k))[1]))
+ {
+ int tmp = act.newJoinChild(new Point(0, 0)).getID();
+ ((WfVertex) act.search(((String[]) nexts.elementAt(j))[0])).addNext(act.search(tmp));
+ ((WfVertex) act.search(((String[]) nexts.elementAt(k))[0])).addNext(act.search(tmp));
+ ((Join) act.search(tmp)).addNext(((String[]) nexts.elementAt(j))[1]);
+ nexts.removeElementAt(k--);
+ flag = true;
+ }
+ }
+ if (flag)
+ {
+ nexts.removeElementAt(j--);
+ }
+ flag = false;
+ }
+ for (int j = 0; j < nexts.size(); j++)
+ {
+ Logger.msg(
+ 7,
+ "try to add next " + ((String[]) nexts.elementAt(j))[1] + " to " + ((String[]) nexts.elementAt(j))[0]);
+ ((Activity) act.search(((String[]) nexts.elementAt(j))[0])).addNext(((String[]) nexts.elementAt(j))[1]);
+ }
+ if (act instanceof Workflow)
+ try
+ {
+ act.run(agent);
+ }
+ catch (Exception ex)
+ {
+ Logger.error(ex);
+ }
+ return act;
+ }
+
+ private static void readStep(CompositeActivity parent)
+ {
+ Activity act = null;
+ String[] step = new String[15];
+ for (int j = 0; j < 15; j++)
+ {
+ step[j] = "";
+ }
+ i += 5;
+ while (!file.substring(i, i + 7).equals("</STEP>"))
+ {
+ if (file.substring(i, i + 5).equals("<STEP"))
+ {
+ Logger.msg(7, "<STEP");
+ if (!step[14].equals("done"))
+ {
+ act = parent.newCompChild(step[0], step[12].startsWith("true"), new Point(0, 0));
+ }
+ readStep((CompositeActivity) act);
+ step[14] = "done";
+ }
+ else if (file.substring(i, i + 3).equals("Id="))
+ {
+ Logger.msg(7, "Id=");
+ i += 4;
+ int j = 0;
+ while (file.charAt(i + j) != '"')
+ {
+ j++;
+ }
+ step[0] = file.substring(i, i + j);
+ i += (j + 1);
+ }
+ else if (file.substring(i, i + 6).equals("Alias="))
+ {
+ Logger.msg(7, "Alias=");
+ i += 7;
+ int j = 0;
+ while (file.charAt(i + j) != '"')
+ {
+ j++;
+ }
+ step[10] = file.substring(i, i + j);
+ i += (j + 1);
+ }
+ else if (file.substring(i, i + 9).equals("Resource="))
+ {
+ Logger.msg(7, "Ressource=");
+ i += 10;
+ int j = 0;
+ while (file.charAt(i + j) != '"')
+ {
+ j++;
+ }
+ step[1] = file.substring(i, i + j);
+ i += (j + 1);
+ }
+ else if (file.substring(i, i + 6).equals("First="))
+ {
+ Logger.msg(7, "First=");
+ i += 7;
+ int j = 0;
+ ;
+ while (file.charAt(i + j) != '"')
+ {
+ j++;
+ }
+ step[12] = file.substring(i, i + j);
+ i += (j + 1);
+ }
+ else if (file.substring(i, i + 3).equals("LC="))
+ {
+ Logger.msg(7, "LC=");
+ i += 4;
+ int j = 0;
+ ;
+ while (file.charAt(i + j) != '"')
+ {
+ j++;
+ }
+ step[2] = file.substring(i, i + j);
+ i += (j + 1);
+ }
+ else if (file.substring(i, i + 3).equals("WC="))
+ {
+ Logger.msg(7, "WC=");
+ i += 4;
+ int j = 0;
+ ;
+ while (file.charAt(i + j) != '"')
+ {
+ j++;
+ }
+ step[3] = file.substring(i, i + j);
+ i += (j + 1);
+ }
+ else if (file.substring(i, i + 6).equals("Posts="))
+ {
+ Logger.msg(7, "Posts=");
+ i += 7;
+ int j = 0;
+ ;
+ while (file.charAt(i + j) != '"')
+ {
+ j++;
+ }
+ step[4] = file.substring(i, i + j);
+ i += (j + 1);
+ }
+ else if (file.substring(i, i + 17).equals("Preparation-Time="))
+ {
+ Logger.msg(7, "Preparation-Time=");
+ i += 18;
+ int j = 0;
+ ;
+ while (file.charAt(i + j) != '"')
+ {
+ j++;
+ }
+ step[5] = file.substring(i, i + j);
+ i += (j + 1);
+ }
+ else if (file.substring(i, i + 12).equals("Active-Time="))
+ {
+ Logger.msg(7, "Active-Time=");
+ i += 13;
+ int j = 0;
+ ;
+ while (file.charAt(i + j) != '"')
+ {
+ j++;
+ }
+ step[6] = file.substring(i, i + j);
+ i += (j + 1);
+ }
+ else if (file.substring(i, i + 13).equals("OP-Startdate="))
+ {
+ Logger.msg(7, "OP-Startdate=");
+ i += 14;
+ int j = 0;
+ ;
+ while (file.charAt(i + j) != '"')
+ {
+ j++;
+ }
+ step[7] = file.substring(i, i + j);
+ i += (j + 1);
+ }
+ else if (file.substring(i, i + 11).equals("OP-Enddate="))
+ {
+ Logger.msg(7, "OP-Enddate=");
+ i += 12;
+ int j = 0;
+ ;
+ while (file.charAt(i + j) != '"')
+ {
+ j++;
+ }
+ step[8] = file.substring(i, i + j);
+ i += (j + 1);
+ }
+ else if (file.substring(i, i + 13).equals("<DESCRIPTION>"))
+ {
+ Logger.msg(7, "<DESCRIPTION>");
+ i += 13;
+ int j = 0;
+ ;
+ while (file.charAt(i + j) != '<')
+ {
+ j++;
+ }
+ step[9] = file.substring(i, i + j);
+ i += (j + 14);
+ }
+ else if (file.substring(i, i + 6).equals("<NEXT>"))
+ {
+ Logger.msg(7, "<NEXT>");
+ i += 6;
+ int j = 0;
+ ;
+ String[] tmp = new String[2];
+ while (file.charAt(i + j) != '<')
+ {
+ j++;
+ }
+ tmp[0] = step[0];
+ tmp[0] = parent.getPath() + "/" + tmp[0];
+ tmp[1] = file.substring(i, i + j);
+ tmp[1] = parent.getPath() + "/" + tmp[1];
+ nexts.addElement(tmp);
+ i += (j + 8);
+ Logger.msg(7, "</NEXT>");
+ }
+ else if (file.substring(i, i + 5).equals("Path="))
+ {
+ Logger.msg(7, "Path=");
+ i += 6;
+ int j = 0;
+ ;
+ step[11] = file.substring(i, i + j);
+ while (file.charAt(i + j) != '"')
+ {
+ j++;
+ }
+ i += (j + 1);
+ }
+ else
+ {
+ i++;
+ }
+ }
+ i += 7;
+ if (!step[14].equals("done"))
+ act = parent.newAtomChild(step[0], step[12].startsWith("true"), new Point(0, 0));
+ Logger.msg(7, "Step Created");
+
+ try
+ {
+ Logger.msg(7, "Starting to create info");
+ if (!step[1].equals(""))
+ act.getProperties().put("Agent ID", step[1]);
+ if (!step[2].equals(""))
+ act.getProperties().put("Lc", step[2]);
+ if (!step[3].equals(""))
+ act.getProperties().put("Wc", step[3]);
+ if (!step[4].equals(""))
+ act.getProperties().put("Posts", step[4]);
+ if (!step[5].equals(""))
+ act.getProperties().put("PreparationTime", step[5]);
+ if (!step[6].equals(""))
+ act.getProperties().put("ActiveTime", step[6]);
+ if (!step[7].equals(""))
+ act.getProperties().put("OpStartdate", step[7]);
+ if (!step[8].equals(""))
+ act.getProperties().put("OpEnddate", step[8]);
+ if (!step[9].equals(""))
+ act.getProperties().put("Description", step[9]);
+ Logger.msg(7, "create info for " + act.getID());
+ Logger.msg(7, "Finished to create info");
+ }
+ catch (Exception e)
+ {
+ Logger.error(e);
+ }
+ file = file.substring(i);
+ i = 0;
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/Split.java b/source/com/c2kernel/lifecycle/instance/Split.java
new file mode 100755
index 0000000..1f269af
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/Split.java
@@ -0,0 +1,217 @@
+package com.c2kernel.lifecycle.instance;
+
+import java.util.Vector;
+
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.graph.traversal.GraphTraversal;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.scripting.ScriptingEngineException;
+
+/**
+ * @version $Revision: 1.47 $ $Date: 2006/05/29 13:17:45 $
+ * @author $Author: abranson $
+ */
+public abstract class Split extends WfVertex
+{
+ public Vector mErrors;
+
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public Split()
+ {
+ mErrors = new Vector(0, 1);
+ getProperties().put("RoutingScriptName", "");
+ getProperties().put("RoutingScriptVersion", "");
+ }
+
+ private boolean loopTested;
+
+ private int mItemSystemKey = -1;
+
+ /**
+ * @see com.c2kernel.lifecycle.instance.WfVertex#runNext()
+ */
+ public abstract void runNext(AgentPath agent) throws ScriptingEngineException;
+
+ /**
+ * Method addNext.
+ *
+ * @param idNext
+ */
+ void addNext(String idNext)
+ {
+ new Next(this, (WfVertex) getParent().search(idNext));
+ }
+
+ /**
+ * @see com.c2kernel.lifecycle.instance.WfVertex#addNext(com.c2kernel.lifecycle.instance.WfVertex)
+ */
+ public Next addNext(WfVertex vertex)
+ {
+ Next nxt = new Next(this, vertex);
+ int num = getOutGraphables().length;
+ try
+ {
+ num = Integer.parseInt((String) getProperties().get("LastNum"));
+ } catch (Exception e)
+ {
+ }
+ nxt.getProperties().put("Alias", String.valueOf(num));
+ getProperties().put("LastNum", String.valueOf(num + 1));
+ return nxt;
+ }
+
+ /**
+ * Method getItemSystemKey.
+ *
+ * @return int
+ */
+ public int getItemSystemKey()
+ {
+ return mItemSystemKey;
+ }
+
+ /**
+ * Method setItemSystemKey.
+ *
+ * @param itemSystemKey
+ */
+ public void setItemSystemKey(int itemSystemKey)
+ {
+ mItemSystemKey = itemSystemKey;
+ }
+
+ /**
+ * @see com.c2kernel.lifecycle.instance.WfVertex#reinit(int)
+ */
+ // public void initItemSystemKey(String systemKey) {
+ // setItemSystemKey(systemKey);
+ // }
+ public void reinit(int idLoop)
+ {
+ Vertex[] outVertices = getOutGraphables();
+ for (int i = 0; i < outVertices.length; i++)
+ ((WfVertex) outVertices[i]).reinit(idLoop);
+ }
+
+ /**
+ * @see com.c2kernel.lifecycle.instance.WfVertex#verify()
+ */
+ public boolean verify()
+ {
+ mErrors.removeAllElements();
+ int nbInEdgres = getParent().getChildrenGraphModel().getInEdges(this).length;
+ if (nbInEdgres == 0 && this.getID() != getParent().getChildrenGraphModel().getStartVertexId())
+ {
+ mErrors.add("not enough previous");
+ return false;
+ }
+ if (nbInEdgres > 1)
+ {
+ mErrors.add("Bad nb of previous");
+ return false;
+ }
+ if (getOutEdges().length <= 1 && !(this instanceof Loop))
+ {
+ mErrors.add("not enough next");
+ return false;
+ }
+ if (!(this instanceof Loop))
+ {
+ Vertex[] outV = getOutGraphables();
+ Vertex[] anteVertices = GraphTraversal.getTraversal(getParent().getChildrenGraphModel(), this, GraphTraversal.kUp, false);
+ boolean loop = false;
+ boolean errInLoop = true;
+ for (int i = 0; i < outV.length; i++)
+ {
+ for (int j = 0; j < anteVertices.length; j++)
+ if (!loop && outV[i].getID() == anteVertices[j].getID())
+ {
+ if (outV[i] instanceof Loop)
+ {
+ loop = true;
+ j = anteVertices.length;
+ i = outV.length;
+ } else
+ {
+ errInLoop = false;
+ }
+ }
+ }
+ if (errInLoop && loop)
+ {
+ mErrors.add("Problem in Loop");
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @see com.c2kernel.lifecycle.instance.WfVertex#getErrors()
+ */
+ public String getErrors()
+ {
+ if (mErrors.size() == 0)
+ return "No error";
+ else
+ return (String) mErrors.elementAt(0);
+ }
+
+ /**
+ * @see com.c2kernel.lifecycle.instance.WfVertex#run()
+ */
+ public void run(AgentPath agent) throws ScriptingEngineException
+ {
+ runNext(agent);
+ }
+
+ /**
+ * @see com.c2kernel.lifecycle.instance.WfVertex#loop()
+ */
+ public boolean loop()
+ {
+ boolean loop2 = false;
+ if (!loopTested)
+ {
+ loopTested = true;
+ if (getOutGraphables().length != 0)
+ {
+ Vertex[] outVertices = getOutGraphables();
+ for (int i = 0; i < outVertices.length; i++)
+ {
+ WfVertex tmp = (WfVertex) getOutGraphables()[i];
+ loop2 = loop2 || tmp.loop();
+ }
+ }
+ }
+ loopTested = false;
+ return loop2;
+ }
+
+ public String[] nextNames()
+ {
+ Vertex[] vs = getOutGraphables();
+ String[] result = new String[vs.length];
+ for (int i = 0; i < vs.length; i++)
+ result[i] = vs[i].getName();
+ return result;
+ }
+
+ protected boolean isInTable(String test, String[] list)
+ {
+ if (test == null)
+ return false;
+ for (int i = 0; i < list.length; i++)
+ if (test.equals(list[i]))
+ return true;
+ return false;
+ }
+
+ public void runfirst(AgentPath agent) throws ScriptingEngineException
+ {
+ runNext(agent);
+ }
+
+} \ No newline at end of file
diff --git a/source/com/c2kernel/lifecycle/instance/WfVertex.java b/source/com/c2kernel/lifecycle/instance/WfVertex.java
new file mode 100755
index 0000000..7285916
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/WfVertex.java
@@ -0,0 +1,181 @@
+package com.c2kernel.lifecycle.instance;
+
+
+
+import java.util.HashMap;
+
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.graph.model.GraphableVertex;
+import com.c2kernel.lifecycle.instance.stateMachine.Transitions;
+import com.c2kernel.lifecycle.routingHelpers.ViewpointDataHelper;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.scripting.Script;
+import com.c2kernel.scripting.ScriptingEngineException;
+import com.c2kernel.utils.KeyValuePair;
+import com.c2kernel.utils.Logger;
+
+/**
+ * @version $Revision: 1.38 $ $Date: 2005/09/07 13:46:31 $
+ * @author $Author: abranson $
+ */
+public abstract class WfVertex extends GraphableVertex
+{
+ /**sets the activity available to be executed on start of Workflow or composite activity (when it is the first one of the
+ * (sub)process*/
+ public abstract void runfirst(AgentPath agent) throws ScriptingEngineException;
+
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public WfVertex()
+ {
+ super();
+ setIsLayoutable(true);
+ setIsComposite(false);
+ }
+
+ /**
+ * Method runNext.
+ */
+ public void runNext(AgentPath agent) throws ScriptingEngineException
+ {
+ try
+ {
+ ((CompositeActivity)getParent()).request(agent, Transitions.COMPLETE, null);
+ }
+ catch (Exception e)
+ {
+ //Logger.error(e);
+ }
+
+ }
+
+ /**
+ * Method reinit.
+ * @param idLoop
+ */
+ public abstract void reinit( int idLoop );
+
+ /**
+ * Method verify.
+ * @return boolean
+ */
+ public abstract boolean verify();
+
+ /**
+ * Method getErrors.
+ * @return String
+ */
+ public abstract String getErrors();
+
+ /**
+ * Method run.
+ */
+ public abstract void run(AgentPath agent) throws ScriptingEngineException;
+
+ /**
+ * Method loop.
+ * @return boolean
+ */
+ public abstract boolean loop();
+
+ /**
+ * Method addNext.
+ * @param vertex
+ */
+ public abstract Next addNext(WfVertex vertex);
+
+ protected Object evaluateScript(String scriptName, String scriptVersion) throws ScriptingEngineException
+ {
+
+ try
+ {
+ EntityPath entity = ((CompositeActivity) getParent()).getWf().getItemEntityPath();
+ Script script = getScript(scriptName, scriptVersion);
+
+ KeyValuePair[] k = getProperties().getKeyValuePairs();
+ HashMap requiredInput = script.getAllInputParams();
+ for (int i = 0; i < k.length; i++)
+ {
+ if (requiredInput.containsKey(k[i].getKey()))
+ {
+ String value = k[i].getStringValue();
+ Object inputParam = value;
+
+ if (value.startsWith("viewpoint//"))
+ {
+ value = value.substring(11);
+ if (value.startsWith("."))
+ value = entity.getSysKey() + value.substring(1);
+ try {
+ inputParam = ViewpointDataHelper.get(value)[0];
+ } catch (ArrayIndexOutOfBoundsException ex) {
+ throw new InvalidDataException("Could not retrieve data from viewpoint: "+value, "");
+ }
+ }
+ if (value.startsWith("property//"))
+ {
+ value = value.substring(10);
+ try {
+ inputParam = Gateway.getStorage().get(entity.getSysKey(), ClusterStorage.PROPERTY+"/"+value, null);
+ } catch (ObjectNotFoundException ex) {
+ inputParam = null;
+ }
+ }
+ Logger.msg(5, "Split.evaluateScript() - Setting param " + k[i].getKey() + " to " + inputParam.toString());
+ script.setInputParamValue(k[i].getKey(), inputParam);
+ }
+ }
+
+ if (requiredInput.containsKey("item")) {
+ script.setInputParamValue("item", Gateway.getProxyManager().getProxy(entity));
+ }
+ if (requiredInput.containsKey("agent")) {
+ AgentPath systemAgent = Gateway.getLDAPLookup().getRoleManager().getAgentPath("system");
+ script.setInputParamValue("agent", Gateway.getProxyManager().getProxy(systemAgent));
+ }
+ Object retVal = script.execute();
+ Logger.msg(2, "Split.evaluateScript() - Script returned "+retVal);
+ if (retVal == null) retVal = "";
+ return retVal;
+ }
+ catch (Exception e)
+ {
+ Logger.msg(1, "Split.evaluateScript() - Error: Script " + scriptName);
+ Logger.error(e);
+ throw new ScriptingEngineException();
+ }
+ }
+
+ private Script getScript(String name, String version) throws ScriptingEngineException
+ {
+ Script script;
+ try
+ {
+ script = new Script(name, Integer.parseInt(version));
+ }
+ catch (NumberFormatException e)
+ { // version not valid
+ int split = name.indexOf(":");
+ if (split > -1)
+ {
+ script = new Script(name.substring(0, split), name.substring(split + 1));
+ }
+ else
+ throw new ScriptingEngineException("Could not find script " + name + " v" + version);
+ }
+
+ return script;
+ }
+
+
+ public Workflow getWf()
+ {
+ return ((CompositeActivity)getParent()).getWf();
+ }
+}
+
diff --git a/source/com/c2kernel/lifecycle/instance/Workflow.java b/source/com/c2kernel/lifecycle/instance/Workflow.java
new file mode 100755
index 0000000..a7066d8
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/Workflow.java
@@ -0,0 +1,198 @@
+package com.c2kernel.lifecycle.instance;
+import java.awt.Point;
+import java.util.ArrayList;
+import com.c2kernel.common.AccessRightsException;
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.InvalidTransitionException;
+import com.c2kernel.common.ObjectAlreadyExistsException;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.graph.model.TypeNameAndConstructionInfo;
+import com.c2kernel.lifecycle.instance.predefined.PredefinedStepContainer;
+import com.c2kernel.lifecycle.instance.stateMachine.Transitions;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.scripting.ScriptingEngineException;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+/**
+ * @version $Revision: 1.64 $ $Date: 2005/09/30 07:09:48 $
+ * @author $Author: abranson $
+ */
+public class Workflow extends CompositeActivity implements C2KLocalObject
+{
+ /** TypeNameAndConstructionInfo[] variables added by Steve */
+ private final TypeNameAndConstructionInfo[] mVertexTypeNameAndConstructionInfo =
+ {
+ new TypeNameAndConstructionInfo(Language.translate("AND Split"), "AndSplit"),
+ new TypeNameAndConstructionInfo(Language.translate("OR Split"), "OrSplit"),
+ new TypeNameAndConstructionInfo(Language.translate("XOR Split"), "XOrSplit"),
+ new TypeNameAndConstructionInfo(Language.translate("Join"), "Join"),
+ new TypeNameAndConstructionInfo(Language.translate("Loop"), "LoopSplit"),
+ new TypeNameAndConstructionInfo(Language.translate("Atomic"), "Atomic"),
+ new TypeNameAndConstructionInfo(Language.translate("Composite"), "Composite")
+ };
+ private final TypeNameAndConstructionInfo[] mEdgeTypeNameAndConstructionInfo =
+ {
+ new TypeNameAndConstructionInfo(Language.translate("Next Edge"), "Next")
+ };
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public Workflow()
+ {
+ getProperties().put("ItemSystemKey", null);
+ }
+
+ public Workflow(CompositeActivity domain) {
+ this();
+ domain.setName("domain");
+ initChild(domain, true, new Point(150, 100));
+ PredefinedStepContainer act = new PredefinedStepContainer();
+ addChild(act, new GraphPoint(300, 100));
+ }
+
+ /**
+ * Method getVertexTypeNameAndConstructionInfo.
+ *
+ * @return TypeNameAndConstructionInfo[]
+ */
+ /** getVertexTypeNameAndConstructionInfo() added by Steve */
+ public TypeNameAndConstructionInfo[] getVertexTypeNameAndConstructionInfo()
+ {
+ return mVertexTypeNameAndConstructionInfo;
+ }
+ /**
+ * Method getEdgeTypeNameAndConstructionInfo.
+ *
+ * @return TypeNameAndConstructionInfo[]
+ */
+ /** getVertexTypeNameAndConstructionInfo() added by Steve */
+ public TypeNameAndConstructionInfo[] getEdgeTypeNameAndConstructionInfo()
+ {
+ return mEdgeTypeNameAndConstructionInfo;
+ }
+ /**
+ * Method requestAction.
+ *
+ * @param agentInfo
+ * @param stepPath
+ * @param transitionID
+ * @param reguestData
+ * @throws ObjectNotFoundException
+ * @throws AccessRightsException
+ * @throws InvalidTransitionException
+ * @throws InvalidDataException
+ */
+ //requestData is xmlstring
+ public void requestAction(AgentPath agent, String stepPath, int transitionID, String requestData)
+ throws ObjectNotFoundException, AccessRightsException, InvalidTransitionException, InvalidDataException, ObjectAlreadyExistsException
+ {
+ Logger.msg(3, "Action: " + Transitions.getTransitionName(transitionID) + " " + stepPath + " by " + agent.getAgentName());
+ if (search(stepPath) != null)
+ ((Activity) search(stepPath)).request(agent, transitionID, requestData);
+ else
+ throw new ObjectNotFoundException(stepPath + " not found", "");
+ }
+
+ /**
+ * @see com.c2kernel.graph.model.GraphableVertex#getPath()
+ */
+ public String getPath()
+ {
+ return "workflow";
+ }
+ /**
+ * @see com.c2kernel.graph.model.Vertex#getName()
+ */
+ public String getName()
+ {
+ return "workflow";
+ }
+ /**
+ * @see com.c2kernel.lifecycle.instance.Activity#getType()
+ */
+ public String getType()
+ {
+ return "workflow";
+ }
+ /**
+ * @see com.c2kernel.graph.model.Vertex#setName(java.lang.String)
+ */
+ public void setName(String name)
+ {
+ }
+ /**
+ * @see com.c2kernel.lifecycle.instance.WfVertex#verify()
+ */
+ public boolean verify()
+ {
+ for (int i = 0; i < getChildren().length; i++)
+ {
+ if (!((WfVertex) getChildren()[i]).verify())
+ {
+ mErrors.add("error in children");
+ return false;
+ }
+ }
+ return true;
+ }
+ /**
+ * @see com.c2kernel.lifecycle.instance.Activity#getWf()
+ */
+ public Workflow getWf()
+ {
+ return this;
+ }
+ /**
+ * Method initialise.
+ *
+ * @param systemKey
+ */
+ public void initialise(int systemKey, AgentPath agent)
+ {
+ this.getProperties().put("ItemSystemKey", new Integer(systemKey));
+ try
+ {
+ runfirst(agent);
+ }
+ catch (ScriptingEngineException ex)
+ {
+ Logger.error(ex);
+ }
+ }
+ /**
+ * Method calculateJobs.
+ *
+ * @param type
+ * @return JobList
+ */
+ /**
+ * if type = 0 only domain steps will be queried if type = 1 only predefined steps will be queried else both will be queried
+ */
+ public ArrayList calculateJobs(AgentPath agent, int type)
+ {
+ ArrayList jobs = new ArrayList();
+ if (type != 1)
+ jobs.addAll(((CompositeActivity) search("workflow/domain")).calculateJobs(agent, true));
+ if (type != 0)
+ jobs.addAll(((CompositeActivity) search("workflow/predefined")).calculateJobs(agent, true));
+ return jobs;
+ }
+ /**
+ * @see com.c2kernel.lifecycle.instance.CompositeActivity#hasGoodNumberOfActivity()
+ */
+ public boolean hasGoodNumberOfActivity()
+ {
+ return true;
+ }
+ /**
+ * @see com.c2kernel.entity.C2KLocalObject#getClusterType()
+ */
+ public String getClusterType()
+ {
+ return ClusterStorage.LIFECYCLE;
+ }
+
+}
diff --git a/source/com/c2kernel/lifecycle/instance/XOrSplit.java b/source/com/c2kernel/lifecycle/instance/XOrSplit.java
new file mode 100755
index 0000000..bd999af
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/XOrSplit.java
@@ -0,0 +1,54 @@
+package com.c2kernel.lifecycle.instance;
+
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+
+import com.c2kernel.graph.model.DirectedEdge;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.scripting.ScriptingEngineException;
+
+/**
+ * @version $Revision: 1.23 $ $Date: 2006/03/03 13:52:21 $
+ * @author $Author: abranson $
+ */
+public class XOrSplit extends Split
+{
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public XOrSplit()
+ {
+ super();
+ }
+
+ public void runNext(AgentPath agent) throws ScriptingEngineException
+ {
+ ArrayList nextsToFollow = new ArrayList();
+ String nexts = this.evaluateScript(
+ (String) getProperties().get("RoutingScriptName"),
+ (String) getProperties().get("RoutingScriptVersion")).toString();
+
+ StringTokenizer tok = new StringTokenizer(nexts,",");
+ String[] nextsTab = new String[tok.countTokens()];
+ for (int i=0;i<nextsTab.length;i++)
+ nextsTab[i] = tok.nextToken();
+
+ DirectedEdge[] outEdges = getOutEdges();
+ for (int i = 0; i < outEdges.length; i++)
+ {
+ if (isInTable((String)((Next)outEdges[i]).getProperties().get("Alias"), nextsTab))
+ nextsToFollow.add(outEdges[i]);
+ }
+// Logger.debug(0, getID()+" following "+nexts);
+ if (nextsToFollow.size() != 1)
+ throw new ScriptingEngineException("not good number of active next");
+
+ followNext((Next)nextsToFollow.get(0), agent);
+
+ }
+
+ public void followNext(Next activeNext, AgentPath agent) throws ScriptingEngineException {
+ activeNext.getTerminusVertex().run(agent);
+ }
+
+}
diff --git a/source/com/c2kernel/lifecycle/instance/gui/model/WfEdgeFactory.java b/source/com/c2kernel/lifecycle/instance/gui/model/WfEdgeFactory.java
new file mode 100755
index 0000000..f79d312
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/gui/model/WfEdgeFactory.java
@@ -0,0 +1,34 @@
+package com.c2kernel.lifecycle.instance.gui.model;
+
+import com.c2kernel.graph.model.DirectedEdge;
+import com.c2kernel.graph.model.EdgeFactory;
+import com.c2kernel.graph.model.GraphModelManager;
+import com.c2kernel.graph.model.TypeNameAndConstructionInfo;
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.lifecycle.instance.WfVertex;
+
+public class WfEdgeFactory implements EdgeFactory
+{
+ public void create
+ (
+ GraphModelManager graphModelManager,
+ Vertex origin,
+ Vertex terminus,
+ TypeNameAndConstructionInfo typeNameAndConstructionInfo
+ )
+ {
+ if ( validCreation( graphModelManager, origin, terminus ) )
+ ((WfVertex)origin).addNext((WfVertex)terminus);
+
+ }
+
+ private boolean validCreation( GraphModelManager graphModelManager, Vertex origin, Vertex terminus )
+ {
+ DirectedEdge[] connectingEdgesAToB = graphModelManager.getModel().getConnectingEdges( origin.getID() , terminus.getID() );
+ DirectedEdge[] connectingEdgesBToA = graphModelManager.getModel().getConnectingEdges( terminus.getID(), origin.getID() );
+
+
+ return ( origin != terminus ) && ( connectingEdgesAToB.length == 0 ) && ( connectingEdgesBToA.length == 0 );
+ }
+}
+
diff --git a/source/com/c2kernel/lifecycle/instance/gui/model/WfGraphPanel.java b/source/com/c2kernel/lifecycle/instance/gui/model/WfGraphPanel.java
new file mode 100755
index 0000000..752e1fa
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/gui/model/WfGraphPanel.java
@@ -0,0 +1,58 @@
+/*Created on 21 nov. 2003 */
+package com.c2kernel.lifecycle.instance.gui.model;
+
+import java.awt.Graphics2D;
+
+import com.c2kernel.graph.model.DirectedEdge;
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.graph.view.DirectedEdgeRenderer;
+import com.c2kernel.graph.view.GraphPanel;
+import com.c2kernel.graph.view.VertexRenderer;
+import com.c2kernel.lifecycle.instance.Next;
+
+/** @author XSeb74*/
+public class WfGraphPanel extends GraphPanel
+{
+ public WfGraphPanel(DirectedEdgeRenderer d,VertexRenderer v)
+ {
+ super(d,v);
+ }
+ // Draws the highlight of the specified edge
+ protected void drawEdgeHighlight(Graphics2D g2d, DirectedEdge edge)
+ {
+ GraphPoint originPoint = edge.getOriginPoint();
+ GraphPoint terminusPoint = edge.getTerminusPoint();
+ GraphPoint midPoint = new GraphPoint();
+
+ if ("Straight".equals(((Next)edge).getProperties().get("Type")) || ((Next)edge).getProperties().get("Type") == null)
+ {
+ midPoint.x = originPoint.x + (terminusPoint.x - originPoint.x) / 2;
+ midPoint.y = originPoint.y + (terminusPoint.y - originPoint.y) / 2;
+ }
+ else if (("Broken +".equals(((Next)edge).getProperties().get("Type"))))
+ {
+ midPoint.x = (originPoint.x + terminusPoint.x) / 2;
+ midPoint.y = (originPoint.y + terminusPoint.y) / 2;
+ }
+ else if (("Broken -".equals(((Next)edge).getProperties().get("Type"))))
+ {
+ boolean arrowOnY = !(originPoint.y - terminusPoint.y < 60 && originPoint.y - terminusPoint.y > -60);
+ midPoint.x = arrowOnY ? terminusPoint.x : (originPoint.x + terminusPoint.x) / 2;
+ midPoint.y = arrowOnY ? (originPoint.y + terminusPoint.y) / 2 : originPoint.y;
+ }
+ else if (("Broken |".equals(((Next)edge).getProperties().get("Type"))))
+ {
+ boolean arrowOnY = !(originPoint.y - terminusPoint.y < 60 && originPoint.y - terminusPoint.y > -60);
+ midPoint.x = arrowOnY ? originPoint.x : (originPoint.x + terminusPoint.x) / 2;
+ midPoint.y = arrowOnY ? (originPoint.y + terminusPoint.y) / 2 : terminusPoint.y;
+ }
+ int minX = midPoint.x - 10;
+ int minY = midPoint.y - 10;
+ int maxX = midPoint.x + 10;
+ int maxY = midPoint.y + 10;
+ g2d.drawLine(minX, minY, maxX, minY);
+ g2d.drawLine(maxX, minY, maxX, maxY);
+ g2d.drawLine(maxX, maxY, minX, maxY);
+ g2d.drawLine(minX, maxY, minX, minY);
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/gui/model/WfVertexFactory.java b/source/com/c2kernel/lifecycle/instance/gui/model/WfVertexFactory.java
new file mode 100755
index 0000000..020d694
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/gui/model/WfVertexFactory.java
@@ -0,0 +1,88 @@
+package com.c2kernel.lifecycle.instance.gui.model;
+import java.awt.Point;
+import java.util.HashMap;
+
+import javax.swing.JOptionPane;
+
+import com.c2kernel.graph.model.GraphModelManager;
+import com.c2kernel.graph.model.TypeNameAndConstructionInfo;
+import com.c2kernel.graph.model.VertexFactory;
+import com.c2kernel.lifecycle.ActivityDef;
+import com.c2kernel.lifecycle.chooser.ActivityChooser;
+import com.c2kernel.lifecycle.chooser.WorkflowDialogue;
+import com.c2kernel.lifecycle.instance.Activity;
+import com.c2kernel.lifecycle.instance.CompositeActivity;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.LocalObjectLoader;
+import com.c2kernel.utils.Resource;
+public class WfVertexFactory implements VertexFactory, WorkflowDialogue
+{
+ protected CompositeActivity mRootAct = null;
+ public void create(GraphModelManager graphModelManager, Point location, TypeNameAndConstructionInfo typeNameAndConstructionInfo)
+ {
+ String vertexTypeId = null;
+ if (mRootAct != null && typeNameAndConstructionInfo.mInfo instanceof String)
+ {
+ vertexTypeId = (String) typeNameAndConstructionInfo.mInfo;
+ if (vertexTypeId.equals("Atomic") || vertexTypeId.equals("Composite"))
+ {
+ HashMap mhm = new HashMap();
+ mhm.put("P1", vertexTypeId);
+ mhm.put("P2", location);
+ //************************************************
+ ActivityChooser a =
+ new ActivityChooser(
+ Language.translate("Please enter a Type for the new activity"),
+ Language.translate("New " + vertexTypeId + " Activity"),
+ Resource.getImageResource("graph/newvertex_large.png").getImage(),
+ this,
+ mhm);
+ a.setVisible(true);
+ }
+ else
+ mRootAct.newChild(vertexTypeId, location);
+ }
+ }
+ public void setCreationContext(Object newContext)
+ {
+ if (newContext != null && newContext instanceof CompositeActivity)
+ mRootAct = (CompositeActivity) newContext;
+ }
+ public void loadThisWorkflow(String newName, HashMap hashMap)
+ {
+ String vertexTypeId = (String) hashMap.get("P1");
+ Point location = (Point) hashMap.get("P2");
+ if (newName == null)
+ return;
+
+
+ String unicName = newName;
+ while (mRootAct.search(mRootAct.getPath() + "/" + unicName) != null)
+ {
+ unicName =
+ (String) JOptionPane.showInputDialog(
+ null,
+ Language.translate("Activity name not unique. Please give another."),
+ Language.translate("New " + vertexTypeId + " Activity"),
+ JOptionPane.QUESTION_MESSAGE,
+ Resource.getImageResource("graph/newvertex_large.png"),
+ null,
+ null);
+ if (newName == null || newName.equals(""))
+ return;
+ }
+ Activity act = null;
+ try
+ {
+ ActivityDef actD = LocalObjectLoader.getActDef(newName, "last");
+ act = (Activity)actD.instantiate(unicName);
+ }
+ catch (Exception e)
+ {
+ }
+ if (act == null)
+ mRootAct.newChild(unicName, vertexTypeId, location);
+ else
+ mRootAct.newExistingChild(act, unicName, location);
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/gui/model/WfVertexOutlineCreator.java b/source/com/c2kernel/lifecycle/instance/gui/model/WfVertexOutlineCreator.java
new file mode 100755
index 0000000..dd4b8af
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/gui/model/WfVertexOutlineCreator.java
@@ -0,0 +1,51 @@
+package com.c2kernel.lifecycle.instance.gui.model;
+
+import java.io.Serializable;
+
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.graph.model.VertexOutlineCreator;
+import com.c2kernel.lifecycle.instance.Activity;
+
+public class WfVertexOutlineCreator implements VertexOutlineCreator,Serializable
+{
+ private final int mActivityWidth = 130;
+ private final int mActivityHeight = 60;
+ private final int mSplitJoinWidth = 60;
+ private final int mSplitJoinHeight = 25;
+
+ public void setOutline(Vertex vertex)
+ {
+ GraphPoint centrePoint = vertex.getCentrePoint();
+ GraphPoint[] outlinePoints = new GraphPoint[ 4 ];
+ int vertexWidth = 0;
+ int vertexHeight = 0;
+
+ if(vertex instanceof Activity)
+ {
+ vertexWidth = mActivityWidth;
+ vertexHeight = mActivityHeight;
+ }
+ else
+ {
+ vertexWidth = mSplitJoinWidth;
+ vertexHeight = mSplitJoinHeight;
+ }
+
+ outlinePoints[ 0 ] = new GraphPoint();
+ outlinePoints[ 0 ].x = centrePoint.x - vertexWidth / 2;
+ outlinePoints[ 0 ].y = centrePoint.y - vertexHeight / 2;
+ outlinePoints[ 1 ] = new GraphPoint();
+ outlinePoints[ 1 ].x = centrePoint.x + vertexWidth / 2;
+ outlinePoints[ 1 ].y = centrePoint.y - vertexHeight / 2;
+ outlinePoints[ 2 ] = new GraphPoint();
+ outlinePoints[ 2 ].x = centrePoint.x + vertexWidth / 2;
+ outlinePoints[ 2 ].y = centrePoint.y + vertexHeight / 2;
+ outlinePoints[ 3 ] = new GraphPoint();
+ outlinePoints[ 3 ].x = centrePoint.x - vertexWidth / 2;
+ outlinePoints[ 3 ].y = centrePoint.y + vertexHeight / 2;
+
+ vertex.setOutlinePoints( outlinePoints );
+ }
+}
+
diff --git a/source/com/c2kernel/lifecycle/instance/gui/view/ActivityRenderer.java b/source/com/c2kernel/lifecycle/instance/gui/view/ActivityRenderer.java
new file mode 100755
index 0000000..a67b4fd
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/gui/view/ActivityRenderer.java
@@ -0,0 +1,116 @@
+package com.c2kernel.lifecycle.instance.gui.view;
+import java.awt.Color;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.Paint;
+import java.awt.Polygon;
+
+import com.c2kernel.common.GTimeStamp;
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.graph.view.VertexRenderer;
+import com.c2kernel.lifecycle.instance.Activity;
+import com.c2kernel.lifecycle.instance.stateMachine.States;
+import com.c2kernel.utils.DateUtility;
+import com.c2kernel.utils.Language;
+public class ActivityRenderer implements VertexRenderer
+{
+ private Paint mActivePaint = new Color(100, 255, 100);
+ private Paint mActiveCompPaint = new Color(100, 255, 255);
+ private Paint mInactivePaint = new Color(255, 255, 255);
+ private Paint mInactiveCompPaint = new Color(200, 200, 255);
+ private Paint mErrorPaint = new Color(255, 50, 0);
+ private Paint mTextPaint = Color.black;
+ public void draw(Graphics2D g2d, Vertex vertex)
+ {
+ Activity activity = (Activity) vertex;
+ boolean active = activity.getActive();
+ boolean hasError = !activity.verify();
+ boolean isComposite = activity.getIsComposite();
+ GraphPoint centrePoint = activity.getCentrePoint();
+ String description = activity.getDescription();
+ String[] linesOfText = new String[3];
+ linesOfText[0] = "(" + activity.getType() + ")";
+ linesOfText[1] = activity.getName();
+ if (hasError)
+ linesOfText[2] = Language.translate(activity.getErrors());
+ else
+ {
+ int cs = activity.getCurrentState();
+ if (cs == States.WAITING && activity.getActive())
+ linesOfText[2] =
+ Language.translate(States.getStateName(cs))
+ + (((Boolean) activity.getProperties().get("Show time")).booleanValue()
+ ? " " + getWaitTime(activity.getActiveDate())
+ : "");
+ else if (cs == States.STARTED)
+ linesOfText[2] =
+ Language.translate(States.getStateName(cs))
+ + (((Boolean) activity.getProperties().get("Show time")).booleanValue()
+ ? " " + getWaitTime(activity.getStartDate())
+ : "");
+ else
+ linesOfText[2] = Language.translate(States.getStateName(cs));
+ }
+
+ FontMetrics metrics = g2d.getFontMetrics();
+ int lineWidth = 0;
+ int lineHeight = metrics.getHeight();
+ int linesHeight = lineHeight * linesOfText.length;
+ int linesStartY = centrePoint.y - linesHeight / 2 + lineHeight * 2 / 3;
+ int x = 0;
+ int y = 0;
+ int i = 0;
+ GraphPoint[] outline = vertex.getOutlinePoints();
+ Paint actColour;
+ if (hasError)
+ actColour = mErrorPaint;
+ else if (active)
+ if (isComposite)
+ actColour = mActiveCompPaint;
+ else
+ actColour = mActivePaint;
+ else if (isComposite)
+ actColour = mInactiveCompPaint;
+ else
+ actColour = mInactivePaint;
+ g2d.setPaint(actColour);
+ //g2d.fill3DRect( centrePoint.x - mSize.width / 2, centrePoint.y - mSize.height / 2, mSize.width, mSize.height, true );
+ g2d.fill(graphPointsToPolygon(outline));
+ g2d.setPaint(mTextPaint);
+ for (i = 0; i < linesOfText.length; i++)
+ {
+ lineWidth = metrics.stringWidth(linesOfText[i]);
+ x = centrePoint.x - lineWidth / 2;
+ y = linesStartY + i * lineHeight;
+ g2d.drawString(linesOfText[i], x, y);
+ }
+ }
+ private Polygon graphPointsToPolygon(GraphPoint[] points)
+ {
+ Polygon polygon = new Polygon();
+ int i = 0;
+ for (i = 0; i < points.length; i++)
+ {
+ polygon.addPoint(points[i].x, points[i].y);
+ }
+ return polygon;
+ }
+ private String getWaitTime(GTimeStamp date)
+ {
+ GTimeStamp now = new GTimeStamp();
+ DateUtility.setToNow(now);
+ long diff = DateUtility.diff(now, date);
+ long secondes = diff % 60;
+ long minutes = (diff / 60) % 60;
+ long hours = (diff / 3600) % 24;
+ long days = (diff / 3600 / 24);
+ if (days > 0)
+ return days + " " + Language.translate("d") + " " + hours + " " + Language.translate("h");
+ if (hours > 0)
+ return hours + " " + Language.translate("h") + " " + minutes + " " + Language.translate("min");
+ if (minutes > 0)
+ return minutes + " " + Language.translate("min");
+ return secondes + " " + Language.translate("sec");
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/gui/view/FindActDefPanel.java b/source/com/c2kernel/lifecycle/instance/gui/view/FindActDefPanel.java
new file mode 100755
index 0000000..5cb00bf
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/gui/view/FindActDefPanel.java
@@ -0,0 +1,69 @@
+package com.c2kernel.lifecycle.instance.gui.view;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.graph.view.SelectedVertexPanel;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.lifecycle.ActivitySlotDef;
+import com.c2kernel.lookup.DomainPath;
+
+/**************************************************************************
+ *
+ * $Revision: 1.3 $
+ * $Date: 2005/12/01 14:23:15 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class FindActDefPanel extends SelectedVertexPanel {
+
+ JButton findButton;
+ ActivitySlotDef currentAct;
+
+ public FindActDefPanel() {
+ super();
+ findButton = new JButton("Open Definition");
+ findButton.setEnabled(false);
+ add(findButton);
+ findButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ try {
+ DomainPath actPath = (DomainPath)new DomainPath("/desc/ActivityDesc/").find(currentAct.getActivityDef());
+ MainFrame.treeBrowser.push(actPath);
+ } catch (ObjectNotFoundException e1) { }
+ }
+ });
+ }
+
+ /**
+ *
+ */
+
+ public void select(Vertex vert) {
+ if (vert instanceof ActivitySlotDef) {
+ findButton.setEnabled(true);
+ currentAct = (ActivitySlotDef)vert;
+ }
+ else
+ clear();
+
+ }
+
+ /**
+ *
+ */
+
+ public void clear() {
+ findButton.setEnabled(false);
+ currentAct = null;
+ }
+
+}
diff --git a/source/com/c2kernel/lifecycle/instance/gui/view/SplitJoinRenderer.java b/source/com/c2kernel/lifecycle/instance/gui/view/SplitJoinRenderer.java
new file mode 100755
index 0000000..4c3f8bf
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/gui/view/SplitJoinRenderer.java
@@ -0,0 +1,141 @@
+package com.c2kernel.lifecycle.instance.gui.view;
+
+import java.awt.Color;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.Paint;
+
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.graph.view.VertexRenderer;
+import com.c2kernel.lifecycle.instance.AndSplit;
+import com.c2kernel.lifecycle.instance.Join;
+import com.c2kernel.lifecycle.instance.Loop;
+import com.c2kernel.lifecycle.instance.OrSplit;
+import com.c2kernel.lifecycle.instance.WfVertex;
+import com.c2kernel.lifecycle.instance.XOrSplit;
+import com.c2kernel.utils.Language;
+
+public class SplitJoinRenderer implements VertexRenderer
+{
+ private Paint mTextPaint = Color.black;
+ private Paint mBoxPaint = new Color( 204, 204, 204 );
+ private Paint mErrorPaint = new Color( 255, 0, 0 );
+ private boolean mTextOffsetsNotInitialised = true;
+ private int mTextYOffset = 0;
+ private String mAndText = "And";
+ private int mAndTextXOffset = 0;
+ private String mOrText = "Or";
+ private int mOrTextXOffset = 0;
+ private String mLoopText = "Loop";
+ private int mLoopTextXOffset = 0;
+ private String mXOrText = "XOr";
+ private int mXOrTextXOffset = 0;
+ private String mJoinText = "Join";
+ private int mJoinTextXOffset = 0;
+ private String mRouteText = "";
+ private int mRouteTextXOffset = 0;
+ private String mXXXText = "XXX";
+ private int mXXXTextXOffset = 0;
+
+
+ public void draw( Graphics2D g2d, Vertex vertex)
+ {
+ GraphPoint centrePoint = vertex.getCentrePoint();
+ String text = null;
+ int textXOffset = 0;
+ int vertexHeight = vertex.getHeight();
+ int vertexWidth = vertex.getWidth();
+
+
+ if ( mTextOffsetsNotInitialised )
+ {
+ initialiseTextOffsets( g2d );
+ mTextOffsetsNotInitialised = false;
+ }
+ if ( vertex instanceof AndSplit )
+ {
+ text = Language.translate(mAndText);
+ textXOffset = mAndTextXOffset;
+ }
+ else if ( vertex instanceof OrSplit )
+ {
+ text = Language.translate(mOrText);
+ textXOffset = mOrTextXOffset;
+ }
+ else if ( vertex instanceof Loop )
+ {
+ text = Language.translate(mLoopText);
+ textXOffset = mLoopTextXOffset;
+ }
+ else if ( vertex instanceof XOrSplit )
+ {
+ text = Language.translate(mXOrText);
+ textXOffset = mXOrTextXOffset;
+ }
+ else if ( vertex instanceof Join )
+ {
+ text = Language.translate(mJoinText);
+ textXOffset = mJoinTextXOffset;
+ }
+ else if ( vertex instanceof Join)
+ {
+ String type= (String)((Join)vertex).getProperties().get("Type");
+ if (type!=null && type.equals("Route"))
+ {
+ text = mRouteText;
+ textXOffset = mRouteTextXOffset;
+ }
+ else
+ {
+ text = Language.translate(mJoinText);
+ textXOffset = mJoinTextXOffset;
+ }
+ }
+ else
+ {
+ text = mXXXText;
+ textXOffset = mXXXTextXOffset;
+ }
+
+ boolean hasErrors = ((WfVertex)vertex).verify();
+ g2d.setPaint( hasErrors ? mBoxPaint : mErrorPaint );
+ g2d.fillRect
+ (
+ centrePoint.x - vertexWidth / 2,
+ centrePoint.y - vertexHeight / 2,
+ vertexWidth,
+ vertexHeight
+ );
+ g2d.setPaint( mTextPaint );
+ g2d.drawRect
+ (
+ centrePoint.x - vertexWidth / 2,
+ centrePoint.y - vertexHeight / 2,
+ vertexWidth,
+ vertexHeight
+ );
+ g2d.drawString( text, centrePoint.x - textXOffset, centrePoint.y + mTextYOffset );
+
+ if (!hasErrors) {
+ g2d.setPaint( mErrorPaint );
+ String errors = Language.translate(((WfVertex)vertex).getErrors());
+ int errorWidth = g2d.getFontMetrics().stringWidth( errors );
+ g2d.drawString( errors, centrePoint.x - ( errorWidth / 2), centrePoint.y + vertexHeight );
+ }
+ }
+
+ private void initialiseTextOffsets( Graphics2D g2d )
+ {
+ FontMetrics metrics = g2d.getFontMetrics();
+
+
+ mTextYOffset = metrics.getHeight() / 3;
+ mAndTextXOffset = metrics.stringWidth( Language.translate(mAndText) ) / 2;
+ mOrTextXOffset = metrics.stringWidth( Language.translate(mOrText) ) / 2;
+ mXOrTextXOffset = metrics.stringWidth( Language.translate(mXOrText) ) / 2;
+ mJoinTextXOffset = metrics.stringWidth( Language.translate(mJoinText) ) / 2;
+ mLoopTextXOffset = metrics.stringWidth( Language.translate(mLoopText) ) / 2;
+ }
+}
+
diff --git a/source/com/c2kernel/lifecycle/instance/gui/view/TransitionPanel.java b/source/com/c2kernel/lifecycle/instance/gui/view/TransitionPanel.java
new file mode 100755
index 0000000..fc0cd99
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/gui/view/TransitionPanel.java
@@ -0,0 +1,184 @@
+package com.c2kernel.lifecycle.instance.gui.view;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+
+import com.c2kernel.entity.agent.Job;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.graph.view.SelectedVertexPanel;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.gui.tabs.EntityTabPane;
+import com.c2kernel.gui.tabs.execution.Executor;
+import com.c2kernel.lifecycle.instance.Activity;
+import com.c2kernel.lifecycle.instance.stateMachine.StateMachine;
+import com.c2kernel.lifecycle.instance.stateMachine.States;
+import com.c2kernel.lifecycle.instance.stateMachine.Transitions;
+import com.c2kernel.utils.Logger;
+
+/**************************************************************************
+ *
+ * $Revision: 1.8 $
+ * $Date: 2005/09/07 13:46:31 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class TransitionPanel extends SelectedVertexPanel implements ActionListener {
+ protected Activity mCurrentAct;
+ protected GridBagLayout gridbag;
+ protected GridBagConstraints c;
+ protected Box transBox;
+ protected JComboBox executors;
+ protected JComboBox states = new JComboBox(States.states);
+ protected JCheckBox active = new JCheckBox();
+ protected JLabel status = new JLabel();
+ protected ItemProxy mItem;
+
+ public TransitionPanel() {
+ super();
+ gridbag = new GridBagLayout();
+ setLayout(gridbag);
+ c = new GridBagConstraints();
+ c.gridx=0; c.gridy=0;
+ c.weightx=1; c.weighty=0;
+ c.fill=GridBagConstraints.HORIZONTAL;
+
+ JLabel title = new JLabel("Available Transitions");
+ title.setFont(EntityTabPane.titleFont);
+ gridbag.setConstraints(title, c);
+ add(title);
+
+ c.gridy++;
+ gridbag.setConstraints(status, c);
+ add(status);
+ c.gridy++;
+
+ transBox = Box.createHorizontalBox();
+ gridbag.setConstraints(transBox, c);
+ add(transBox);
+
+ c.weightx=0; c.gridx++;
+ executors = MainFrame.getExecutionPlugins();
+ if (executors.getItemCount() > 1) {
+ gridbag.setConstraints(executors, c);
+ add(executors);
+ }
+
+
+
+ if (MainFrame.isAdmin) {
+ c.gridx=0; c.gridy++;
+ title = new JLabel("State Hacking");
+ title.setFont(EntityTabPane.titleFont);
+ gridbag.setConstraints(title, c);
+ add(title);
+ Box hackBox = Box.createHorizontalBox();
+ hackBox.add(states);
+ hackBox.add(Box.createHorizontalGlue());
+ hackBox.add(new JLabel("Active:"));
+ hackBox.add(active);
+ c.gridy++;
+ gridbag.setConstraints(hackBox, c);
+ add(hackBox);
+ states.addActionListener(this);
+ active.addActionListener(this);
+ }
+
+ clear();
+
+ }
+ /**
+ *
+ */
+ public void select(Vertex vert) {
+ clear();
+ if (!(vert instanceof Activity)) return;
+ mCurrentAct = (Activity)vert;
+ states.setSelectedIndex(mCurrentAct.getCurrentState());
+ states.setEnabled(true);
+ active.setSelected(mCurrentAct.active);
+ active.setEnabled(true);
+ Logger.msg("Retrieving possible transitions for activity "+mCurrentAct.getName());
+ int[] transitions = mCurrentAct.getMachine().possibleTransition();
+ if (transitions.length == 0) {
+ status.setText("None");
+ return;
+ }
+ for (int i = 0; i < transitions.length; i++) {
+ String trans= Transitions.getTransitionName(transitions[i]);
+ if (!(transitions[i]==Transitions.DONE) && !(transitions[i]==Transitions.COMPLETE)) {
+ String buttonLabel = trans.substring(0,1).toUpperCase()+trans.substring(1);
+ JButton thisTrans = new JButton(buttonLabel);
+ thisTrans.setActionCommand("Trans:"+String.valueOf(transitions[i]));
+ thisTrans.addActionListener(this);
+ transBox.add(thisTrans);
+ transBox.add(Box.createHorizontalGlue());
+ }
+ status.setText(transitions.length+" transitions possible.");
+ }
+ revalidate();
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ if (e.getSource() == active && mCurrentAct != null) {
+ mCurrentAct.active = active.isSelected();
+ return;
+ }
+ if (e.getSource() == states && mCurrentAct != null) {
+ mCurrentAct.getMachine().state = states.getSelectedIndex();
+ return;
+ }
+ if (!e.getActionCommand().startsWith("Trans:")) return;
+ int transition = Integer.parseInt(e.getActionCommand().substring(6));
+ Logger.msg("Requesting transition "+transition);
+ Job thisJob = new Job(mItem.getSystemKey(),
+ mCurrentAct.getPath(),
+ transition,
+ new StateMachine(mCurrentAct).simulate(transition),
+ mCurrentAct.getCurrentState(),
+ mCurrentAct.getName(),
+ mCurrentAct.getProperties(),
+ mCurrentAct.getType(),
+ MainFrame.userAgent.getName());
+ try {
+ Executor selectedExecutor = (Executor)executors.getSelectedItem();
+ selectedExecutor.execute(thisJob, status);
+ } catch (Exception ex) {
+ String className = ex.getClass().getName();
+ className = className.substring(className.lastIndexOf('.')+1);
+ Logger.error(ex);
+ JOptionPane.showMessageDialog(null, ex.getMessage(), className, JOptionPane.ERROR_MESSAGE);
+ }
+
+ }
+
+ public void clear() {
+ mCurrentAct = null;
+ transBox.removeAll();
+ status.setText("No activity selected");
+ states.setSelectedIndex(0);
+ states.setEnabled(false);
+ active.setSelected(false);
+ active.setEnabled(false);
+ revalidate();
+ }
+
+
+ /**
+ * @param item The mItem to set.
+ */
+ public void setItem(ItemProxy item) {
+ mItem = item;
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/gui/view/WfDirectedEdgeRenderer.java b/source/com/c2kernel/lifecycle/instance/gui/view/WfDirectedEdgeRenderer.java
new file mode 100755
index 0000000..09dba77
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/gui/view/WfDirectedEdgeRenderer.java
@@ -0,0 +1,128 @@
+package com.c2kernel.lifecycle.instance.gui.view;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.GeneralPath;
+import com.c2kernel.graph.model.DirectedEdge;
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.graph.view.DirectedEdgeRenderer;
+import com.c2kernel.lifecycle.instance.Next;
+public class WfDirectedEdgeRenderer implements DirectedEdgeRenderer
+{
+ private GeneralPath mArrowTemplate = new GeneralPath();
+ public WfDirectedEdgeRenderer()
+ {
+ mArrowTemplate.moveTo(-5, 5);
+ mArrowTemplate.lineTo(0, 0);
+ mArrowTemplate.lineTo(5, 5);
+ }
+ public void draw(Graphics2D g2d, DirectedEdge directedEdge)
+ {
+ GraphPoint originPoint = directedEdge.getOriginPoint();
+ GraphPoint terminusPoint = directedEdge.getTerminusPoint();
+ GraphPoint midPoint = new GraphPoint();
+ AffineTransform transform = new AffineTransform();
+ Shape arrow = null;
+ Next next = (Next) directedEdge;
+ String text = (String) next.getProperties().get("Alias");
+ g2d.setPaint(Color.black);
+ if (("Broken +".equals(next.getProperties().get("Type"))))
+ {
+ g2d.drawLine(originPoint.x, originPoint.y, originPoint.x, (originPoint.y + terminusPoint.y) / 2);
+ g2d.drawLine(originPoint.x, (originPoint.y + terminusPoint.y) / 2, terminusPoint.x, (originPoint.y + terminusPoint.y) / 2);
+ g2d.drawLine(terminusPoint.x, (originPoint.y + terminusPoint.y) / 2, terminusPoint.x, terminusPoint.y);
+ midPoint.x = (originPoint.x + terminusPoint.x) / 2;
+ midPoint.y = (originPoint.y + terminusPoint.y) / 2;
+ transform.translate(midPoint.x, midPoint.y);
+ transform.rotate(
+ calcArrowAngle(
+ originPoint.x,
+ originPoint.x - terminusPoint.x > -5
+ && originPoint.x - terminusPoint.x < 5 ? originPoint.y : (originPoint.y + terminusPoint.y) / 2,
+ terminusPoint.x,
+ originPoint.x - terminusPoint.x > -5
+ && originPoint.x - terminusPoint.x < 5 ? terminusPoint.y : (originPoint.y + terminusPoint.y) / 2));
+ }
+ else if (("Broken -".equals(next.getProperties().get("Type"))))
+ {
+ g2d.drawLine(originPoint.x, originPoint.y, terminusPoint.x, originPoint.y);
+ g2d.drawLine(terminusPoint.x, originPoint.y, terminusPoint.x, terminusPoint.y);
+ boolean arrowOnY = !(originPoint.y - terminusPoint.y < 60 && originPoint.y - terminusPoint.y > -60);
+ midPoint.x = arrowOnY ? terminusPoint.x : (originPoint.x + terminusPoint.x) / 2;
+ midPoint.y = arrowOnY ? (originPoint.y + terminusPoint.y) / 2 : originPoint.y;
+ transform.translate(midPoint.x, midPoint.y);
+ transform.rotate(
+ calcArrowAngle(
+ arrowOnY ? terminusPoint.x : originPoint.x,
+ arrowOnY ? originPoint.y : originPoint.y,
+ arrowOnY ? terminusPoint.x : terminusPoint.x,
+ arrowOnY ? terminusPoint.y : originPoint.y));
+ }
+ else if (("Broken |".equals(next.getProperties().get("Type"))))
+ {
+ g2d.drawLine(originPoint.x, originPoint.y, originPoint.x, terminusPoint.y);
+ g2d.drawLine(originPoint.x, terminusPoint.y, terminusPoint.x, terminusPoint.y);
+ boolean arrowOnY = !(originPoint.y - terminusPoint.y < 60 && originPoint.y - terminusPoint.y > -60);
+ midPoint.x = arrowOnY ? originPoint.x : (originPoint.x + terminusPoint.x) / 2;
+ midPoint.y = arrowOnY ? (originPoint.y + terminusPoint.y) / 2 : terminusPoint.y;
+ transform.translate(midPoint.x, midPoint.y);
+ transform.rotate(
+ calcArrowAngle(
+ arrowOnY ? terminusPoint.x : originPoint.x,
+ arrowOnY ? originPoint.y : originPoint.y,
+ arrowOnY ? terminusPoint.x : terminusPoint.x,
+ arrowOnY ? terminusPoint.y : originPoint.y));
+ }
+ else
+ {
+ g2d.drawLine(originPoint.x, originPoint.y, terminusPoint.x, terminusPoint.y);
+ midPoint.x = originPoint.x + (terminusPoint.x - originPoint.x) / 2;
+ midPoint.y = originPoint.y + (terminusPoint.y - originPoint.y) / 2;
+ transform.translate(midPoint.x, midPoint.y);
+ transform.rotate(calcArrowAngle(originPoint.x, originPoint.y, terminusPoint.x, terminusPoint.y));
+ }
+ arrow = mArrowTemplate.createTransformedShape(transform);
+ g2d.draw(arrow);
+ if (text != null)
+ g2d.drawString(text, midPoint.x + 10, midPoint.y);
+ }
+ private double calcArrowAngle(int originX, int originY, int terminusX, int terminusY)
+ {
+ double width = terminusX - originX;
+ double height = terminusY - originY;
+ if ((width == 0) && (height > 0))
+ {
+ return Math.PI;
+ }
+ if ((width == 0) && (height < 0))
+ {
+ return 0;
+ }
+ if ((width > 0) && (height == 0))
+ {
+ return Math.PI / 2.0;
+ }
+ if ((width < 0) && (height == 0))
+ {
+ return -1.0 * Math.PI / 2.0;
+ }
+ if ((width > 0) && (height > 0))
+ {
+ return Math.PI / 2.0 + Math.atan(Math.abs(height) / Math.abs(width));
+ }
+ if ((width > 0) && (height < 0))
+ {
+ return Math.atan(Math.abs(width) / Math.abs(height));
+ }
+ if ((width < 0) && (height < 0))
+ {
+ return -1.0 * Math.atan(Math.abs(width) / Math.abs(height));
+ }
+ if ((width < 0) && (height > 0))
+ {
+ return -1.0 * (Math.PI / 2.0 + Math.atan(Math.abs(height) / Math.abs(width)));
+ }
+ return 0.0;
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/gui/view/WfVertexRenderer.java b/source/com/c2kernel/lifecycle/instance/gui/view/WfVertexRenderer.java
new file mode 100755
index 0000000..1e731e0
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/gui/view/WfVertexRenderer.java
@@ -0,0 +1,22 @@
+package com.c2kernel.lifecycle.instance.gui.view;
+
+import java.awt.Graphics2D;
+
+import com.c2kernel.graph.model.Vertex;
+import com.c2kernel.graph.view.VertexRenderer;
+import com.c2kernel.lifecycle.instance.Activity;
+import com.c2kernel.lifecycle.instance.Join;
+import com.c2kernel.lifecycle.instance.Split;
+
+public class WfVertexRenderer implements VertexRenderer
+{
+ protected ActivityRenderer mActivityRenderer = new ActivityRenderer();
+ protected SplitJoinRenderer mSplitJoinRenderer = new SplitJoinRenderer();
+
+ public void draw( Graphics2D g2d, Vertex vertex)
+ {
+ if ( vertex instanceof Activity ) { mActivityRenderer.draw( g2d, vertex); }
+ else if ( ( vertex instanceof Split ) || ( vertex instanceof Join ) ) { mSplitJoinRenderer.draw( g2d, vertex ); }
+ }
+}
+
diff --git a/source/com/c2kernel/lifecycle/instance/predefined/AddC2KObject.java b/source/com/c2kernel/lifecycle/instance/predefined/AddC2KObject.java
new file mode 100755
index 0000000..27759be
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/predefined/AddC2KObject.java
@@ -0,0 +1,74 @@
+/**************************************************************************
+ * AddC2KObject
+ *
+ * $Workfile$
+ * $Revision: 1.31 $
+ * $Date: 2004/10/21 08:02:19 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.lifecycle.instance.predefined;
+
+import com.c2kernel.common.AccessRightsException;
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.InvalidTransitionException;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.Logger;
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2004/10/21 08:02:19 $
+ * @version $Revision: 1.31 $
+ **************************************************************************/
+public class AddC2KObject extends PredefinedStep
+{
+ /**************************************************************************
+ * Constructor for Castror
+ **************************************************************************/
+ public AddC2KObject()
+ {
+ super();
+ }
+
+ //requestdata is xmlstring
+ public void request( AgentPath agent, int transitionID, String requestData)
+ throws AccessRightsException,
+ InvalidTransitionException,
+ InvalidDataException
+ {
+
+ Logger.msg(1, "AddC2KObject::request() - Starting.");
+
+ checkAccessRights(agent);
+ EntityPath entityPath = getItemEntityPath();
+
+ if (entityPath!=null)
+ {
+ try
+ {
+
+ Logger.msg(5, "AddC2KObject::request() - data:" + getDataList(requestData)[0]);
+
+ C2KLocalObject obj = (C2KLocalObject)CastorXMLUtility.unmarshall(getDataList(requestData)[0]);
+ Gateway.getStorage().put(entityPath.getSysKey(), obj, null );
+ sendEventStoreOutcome(transitionID, requestData, agent);
+ }
+ catch( Exception ex )
+ {
+ Logger.error("AddC2KObject::request() - during unmarshall.");
+ Logger.error(ex);
+ throw new InvalidDataException(ex.toString(), "");
+ }
+
+ Logger.msg(1, "AddC2KObject::request() - DONE.");
+ }
+ else
+ throw new InvalidDataException("EntityPath is null.", "");
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/predefined/AddDomainPath.java b/source/com/c2kernel/lifecycle/instance/predefined/AddDomainPath.java
new file mode 100755
index 0000000..6756895
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/predefined/AddDomainPath.java
@@ -0,0 +1,66 @@
+/**************************************************************************
+ * AddDomainPath
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.lifecycle.instance.predefined;
+
+
+
+
+import com.c2kernel.common.AccessRightsException;
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.InvalidTransitionException;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.lookup.InvalidEntityPathException;
+import com.c2kernel.lookup.LDAPLookup;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Logger;
+
+public class AddDomainPath extends PredefinedStep
+{
+ public AddDomainPath()
+ {
+ super();
+ }
+
+ //requestdata is xmlstring
+ public void request( AgentPath agent, int transitionID, String requestData)
+ throws AccessRightsException,
+ InvalidTransitionException,
+ InvalidDataException
+ {
+ Logger.msg(8,"AddAlias::request()");
+ LDAPLookup lookupManager = Gateway.getLDAPLookup();
+
+ Logger.msg(1,"AddAlias::request() - Starting.");
+
+ checkAccessRights(agent);
+
+ try
+ {
+ EntityPath entityPath = getItemEntityPath();
+ DomainPath domainPath = new DomainPath(getDataList(requestData)[0], entityPath);
+ lookupManager.add(domainPath);
+ Logger.msg(8,"AddDomainPath::request() - systemKey:" + entityPath.getSysKey() +
+ ". Adding dompath. DONE.");
+ }
+ catch (InvalidEntityPathException ex)
+ {
+ Logger.error(ex);
+ throw new InvalidDataException(ex.toString(), "");
+ }
+ catch( Exception ex )
+ {
+ Logger.error("AddDomainPath::request() - during anyHelper.extract.");
+ Logger.error(ex);
+ throw new InvalidDataException(ex.toString(), "");
+ }
+
+ sendEventStoreOutcome(transitionID, requestData, agent);
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/predefined/AddStepsFromDescription.java b/source/com/c2kernel/lifecycle/instance/predefined/AddStepsFromDescription.java
new file mode 100755
index 0000000..c4fab0c
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/predefined/AddStepsFromDescription.java
@@ -0,0 +1,55 @@
+package com.c2kernel.lifecycle.instance.predefined;
+
+//Java
+import java.awt.Point;
+
+import com.c2kernel.common.AccessRightsException;
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.InvalidTransitionException;
+import com.c2kernel.lifecycle.CompositeActivityDef;
+import com.c2kernel.lifecycle.instance.CompositeActivity;
+import com.c2kernel.lifecycle.instance.Workflow;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.Logger;
+
+public class AddStepsFromDescription extends PredefinedStep
+{
+ public AddStepsFromDescription()
+ {
+ super();
+ }
+
+ public void request( AgentPath agent, int transitionID, String requestData)
+ throws AccessRightsException, InvalidTransitionException, InvalidDataException
+ {
+ Workflow lifeCycle = getWf();
+
+ Logger.msg(1, "AddStepsFromDescription::request() - Starting ");
+
+ checkAccessRights(agent);
+
+ try
+ {
+
+ Logger.msg(8, "AddStepsFromDescription::request() - data:" + getDataList(requestData)[0]);
+ lifeCycle.getChildGraphModel().removeVertex(lifeCycle.search("workflow/domain"));
+ CompositeActivityDef actDef = (CompositeActivityDef) CastorXMLUtility.unmarshall(getDataList(requestData)[0]);
+ CompositeActivity domain = (CompositeActivity)actDef.instantiate();
+ lifeCycle.initChild(domain, true, new Point(150, 100));
+ domain.setName("domain");
+ domain.setType(actDef.getName());
+ lifeCycle.run(agent);
+ Gateway.getStorage().put(getItemEntityPath().getSysKey(), lifeCycle, null);
+ Logger.msg(1, "AddStepsFromDescription::request() - DONE.");
+ sendEventStoreOutcome(transitionID, requestData, agent);
+ }
+ catch (Exception ex)
+ {
+ Logger.error("AddStepsFromDescription::request() - during unmarshall.");
+ Logger.error(ex);
+ throw new InvalidDataException("AddStepsFromDescription::request() - during unmarshall.", "");
+ }
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/predefined/AssignItemToSlot.java b/source/com/c2kernel/lifecycle/instance/predefined/AssignItemToSlot.java
new file mode 100755
index 0000000..88f89c3
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/predefined/AssignItemToSlot.java
@@ -0,0 +1,116 @@
+/**************************************************************************
+ * AssignItemToSlot
+ *
+ * $Workfile$
+ * $Revision: 1.8 $
+ * $Date: 2004/10/21 08:02:19 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.lifecycle.instance.predefined;
+
+import java.util.Iterator;
+
+import com.c2kernel.collection.Collection;
+import com.c2kernel.collection.CollectionMember;
+import com.c2kernel.collection.MembershipException;
+import com.c2kernel.common.AccessRightsException;
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.InvalidTransitionException;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.persistency.ClusterStorageException;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Logger;
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2004/10/21 08:02:19 $
+ * @version $Revision: 1.8 $
+ **************************************************************************/
+public class AssignItemToSlot extends PredefinedStep
+{
+ /**************************************************************************
+ * Constructor for Castor
+ **************************************************************************/
+ public AssignItemToSlot()
+ {
+ super();
+ }
+
+
+ /**
+ * Params:
+ * 0 - collection name
+ * 1 - slot number
+ * 2 - target entity key
+ */
+ public void request(AgentPath agent, int transitionID, String requestData)
+ throws AccessRightsException,
+ InvalidTransitionException,
+ InvalidDataException
+ {
+ EntityPath entityPath = getItemEntityPath();
+ String collName;
+ int slotNo;
+ int entityKey;
+ Collection coll;
+
+ Logger.msg(1, "AssignItemToSlot::request() - Starting.");
+
+ checkAccessRights(agent);
+
+ // extract parameters
+ try {
+ entityPath = getItemEntityPath();
+ String[] params = getDataList(requestData);
+ collName = params[0];
+ slotNo = Integer.parseInt(params[1]);
+ entityKey = Integer.parseInt(params[2]);
+ } catch (Exception e) {
+ throw new InvalidDataException("Invalid parameters", "");
+ }
+
+ // load collection
+ try {
+ coll = (Collection)Gateway.getStorage().get(entityPath.getSysKey(), ClusterStorage.COLLECTION+"/"+collName, null);
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new InvalidDataException("Error loading collection "+collName, "");
+ }
+
+ // find member and assign entity
+ boolean stored = false;
+ for (Iterator iter = coll.getMembers().list.iterator(); iter.hasNext();) {
+ CollectionMember member = (CollectionMember)iter.next();
+ if (member.getID() == slotNo) {
+ if (member.getEntityKey() > -1)
+ throw new InvalidDataException("Member slot not empty", "");
+ try {
+ member.assignEntity(entityKey);
+ } catch (MembershipException e) {
+ throw new InvalidDataException("Entity "+entityKey+" does not fit in this slot", "");
+ }
+ stored = true;
+ break;
+ }
+ }
+ if (!stored) {
+ throw new InvalidDataException("Member slot "+slotNo+" not found.", "");
+ }
+
+
+ try {
+ Gateway.getStorage().put(entityPath.getSysKey(), coll, null);
+ } catch (ClusterStorageException e) {
+ Logger.error(e);
+ throw new InvalidDataException("Error storing collection", "");
+ }
+ sendEventStoreOutcome(transitionID, requestData, agent);
+
+ Logger.msg(1, "AssignItemToSlot::request() - DONE.");
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/predefined/CreateItemFromDescription.java b/source/com/c2kernel/lifecycle/instance/predefined/CreateItemFromDescription.java
new file mode 100755
index 0000000..eddec34
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/predefined/CreateItemFromDescription.java
@@ -0,0 +1,181 @@
+/**************************************************************************
+ * CreateItemFromDescription
+ *
+ * $Workfile$
+ * $Revision: 1.47 $
+ * $Date: 2005/10/13 08:13:58 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.lifecycle.instance.predefined;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import com.c2kernel.collection.Collection;
+import com.c2kernel.collection.CollectionDescription;
+import com.c2kernel.collection.CollectionMember;
+import com.c2kernel.common.AccessRightsException;
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.InvalidTransitionException;
+import com.c2kernel.common.ObjectAlreadyExistsException;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.CorbaServer;
+import com.c2kernel.entity.TraceableEntity;
+import com.c2kernel.lifecycle.CompositeActivityDef;
+import com.c2kernel.lifecycle.instance.stateMachine.Transitions;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.lookup.LDAPLookup;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.persistency.TransactionManager;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.property.Property;
+import com.c2kernel.property.PropertyArrayList;
+import com.c2kernel.property.PropertyDescription;
+import com.c2kernel.property.PropertyDescriptionList;
+import com.c2kernel.property.PropertyUtility;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.LocalObjectLoader;
+import com.c2kernel.utils.Logger;
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2005/10/13 08:13:58 $
+ * @version $Revision: 1.47 $
+ **************************************************************************/
+public class CreateItemFromDescription extends PredefinedStep
+{
+ public CreateItemFromDescription()
+ {
+ super();
+ }
+
+ //requestdata is xmlstring
+ public void request(AgentPath agent, int transitionID, String requestData)
+ throws AccessRightsException, InvalidTransitionException, InvalidDataException,ObjectAlreadyExistsException
+ {
+ String[] input = getDataList(requestData);
+ String newName = input[0];
+ String domPath = input[1];
+ CompositeActivityDef wfDef;
+ String wfDefName = null;
+ if (input.length > 2) // override wf
+ wfDefName = input[2];
+
+ PropertyArrayList props = new PropertyArrayList();
+ Logger.msg(1, "AddNewItem::request() - Starting.");
+ TransactionManager storage = Gateway.getStorage();
+ LDAPLookup lookup = Gateway.getLDAPLookup();
+ EntityPath myPath = getItemEntityPath();
+ checkAccessRights(agent);
+
+ try {
+ // check if the path is already taken
+ DomainPath context = new DomainPath(new DomainPath(domPath), newName);
+ Logger.debug(8,"context "+context.getSysKey()+" "+context.getPath()+" "+context.getString());
+ if (context.getSysKey()!=-1)
+ throw new ObjectAlreadyExistsException("The item name " +newName+ " exists already.");
+
+ // get init objects
+ String[] collNames = storage.getClusterContents(myPath.getSysKey(), ClusterStorage.COLLECTION);
+ ArrayList collections = new ArrayList();
+
+
+ // loop through collections to instantiate
+ for (int i = 0; i < collNames.length; i++) {
+ Collection thisCol = (Collection)storage.get(myPath.getSysKey(), ClusterStorage.COLLECTION+"/"+collNames[i], null);
+ if (thisCol instanceof CollectionDescription) {
+ CollectionDescription thisDesc = (CollectionDescription)thisCol;
+ collections.add(CastorXMLUtility.marshall(thisDesc.newInstance()));
+ }
+ else if (thisCol.getName().equals("Workflow") && wfDefName == null) {
+ ArrayList members = thisCol.getMembers().list;
+ // get the first member from the wf collection
+ CollectionMember wfMember = (CollectionMember)members.get(0);
+ wfDefName = wfMember.resolveEntity().getName();
+ }
+ }
+
+ // load workflow def
+ if (wfDefName == null)
+ throw new InvalidDataException("No workflow given or defined", "");
+
+ try {
+ wfDef = (CompositeActivityDef)LocalObjectLoader.getActDef(wfDefName, "last");
+ } catch (ObjectNotFoundException ex) {
+ throw new InvalidDataException("Workflow def '"+wfDefName+"' item not found", "");
+ } catch (ClassCastException ex) {
+ throw new InvalidDataException("Activity def '"+wfDefName+"' was not Composite", "");
+ }
+
+
+ // copy properties -- intend to create from propdesc
+ PropertyDescriptionList pdList = PropertyUtility.getPropertyDescriptionOutcome(myPath.getSysKey());
+ for (int i = 0; i < pdList.list.size(); i++) {
+ PropertyDescription pd = (PropertyDescription) pdList.list.get(i);
+ String propName = pd.getName();
+ String propVal = pd.getDefaultValue();
+ if (propName.equals("Name"))
+ propVal = newName;
+ props.list.add( new Property(propName, propVal));
+ }
+ props.list.add( new Property("Creator", agent.getAgentName()));
+
+ /* ITEM CREATION */
+
+ // generate new entity key
+ Logger.msg(6, "CreateItemFromDescription - Requesting new sysKey");
+ EntityPath entityPath = lookup.getNextKeyManager().generateNextEntityKey();
+
+ // resolve the item factory
+ Logger.msg(6, "CreateItemFromDescription - Resolving item factory");
+
+ // create the Item object
+ Logger.msg(3, "CreateItemFromDescription - Creating Item");
+ CorbaServer factory = Gateway.getCorbaServer();
+ if (factory == null) throw new AccessRightsException("This process cannot create new Items", "");
+ TraceableEntity newItem = (TraceableEntity)factory.createEntity(entityPath);
+ Gateway.getLDAPLookup().add(entityPath);
+
+
+ // initialise it with its properties and workflow
+
+ Logger.msg(3, "CreateItemFromDescription - Initializing Item");
+
+ newItem.initialise(
+ agent.getSysKey(),
+ CastorXMLUtility.marshall(props),
+ CastorXMLUtility.marshall(wfDef.instantiate()));
+
+ // add collections
+ if (collections.size() > 0) {
+ Logger.msg(6, "CreateItemFromDescription - Adding Collections");
+ String[] colls = new String[1];
+ for (Iterator iter = collections.iterator(); iter.hasNext();) {
+ colls[0] = (String)iter.next();
+ newItem.requestAction(agent.getSysKey(), "workflow/predefined/AddC2KObject", Transitions.COMPLETE, PredefinedStep.bundleData(colls));
+ }
+ }
+
+ // add its domain path
+ Logger.msg(3, "CreateItemFromDescription - Creating "+context);
+ context.setEntity(entityPath);
+ Gateway.getLDAPLookup().add(context);
+ } catch (ObjectAlreadyExistsException e) {
+ Logger.error(e);
+ throw e;
+ } catch (AccessRightsException e) {
+ Logger.error(e);
+ throw e;
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new InvalidDataException(e.getMessage(), "");
+ }
+
+ sendEventStoreOutcome(transitionID, requestData, agent);
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/predefined/Erase.java b/source/com/c2kernel/lifecycle/instance/predefined/Erase.java
new file mode 100755
index 0000000..5c04f93
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/predefined/Erase.java
@@ -0,0 +1,83 @@
+/**************************************************************************
+ * RemoveC2KObject
+ *
+ * $Workfile$
+ * $Revision: 1.10 $
+ * $Date: 2005/11/15 15:56:38 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.lifecycle.instance.predefined;
+
+
+
+import java.util.Enumeration;
+
+import com.c2kernel.common.AccessRightsException;
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.InvalidTransitionException;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.property.Property;
+import com.c2kernel.utils.Logger;
+
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2005/11/15 15:56:38 $
+ * @version $Revision: 1.10 $
+ **************************************************************************/
+public class Erase extends PredefinedStep
+{
+ public Erase()
+ {
+ super();
+ }
+
+ //requestdata is xmlstring
+ public void request(AgentPath agent, int transitionID, String requestData)
+ throws AccessRightsException,
+ InvalidTransitionException,
+ InvalidDataException
+ {
+ Logger.msg(1, "Erase::request() - Starting.");
+
+ checkAccessRights(agent);
+ try
+ {
+ EntityPath entityPath = getItemEntityPath();
+
+ // find entity name
+ Property name = (Property)Gateway.getStorage().get(entityPath.getSysKey(), ClusterStorage.PROPERTY+"/Name", null);
+
+ // get all domain paths
+ Enumeration domPaths = Gateway.getLDAPLookup().search(new DomainPath(), name.getValue());
+ while (domPaths.hasMoreElements()) {
+ DomainPath path = (DomainPath)domPaths.nextElement();
+ // delete them
+ if (path.getSysKey() == entityPath.getSysKey())
+ Gateway.getLDAPLookup().delete(path);
+ }
+
+ //clear out all storages
+ Gateway.getStorage().removeCluster(entityPath.getSysKey(), "", null);
+
+ //remove domain path
+ Gateway.getLDAPLookup().delete(entityPath);
+ }
+ catch( Exception ex )
+ {
+
+ Logger.error(ex);
+ throw new InvalidDataException(ex.toString(), "");
+ }
+
+ Logger.msg(1, "Erase::request() - DONE.");
+ }
+
+}
diff --git a/source/com/c2kernel/lifecycle/instance/predefined/Import.java b/source/com/c2kernel/lifecycle/instance/predefined/Import.java
new file mode 100755
index 0000000..36b7fc9
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/predefined/Import.java
@@ -0,0 +1,68 @@
+/**************************************************************************
+ * AddDomainPath
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.lifecycle.instance.predefined;
+
+import com.c2kernel.common.*;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.utils.Logger;
+
+/**************************************************************************
+ *
+ * $Revision: 1.21 $
+ * $Date: 2005/06/02 12:17:22 $
+ *
+ * Params: Schemaname_version:Viewpoint (optional), Outcome
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+public class Import extends PredefinedStep
+{
+ public Import()
+ {
+ super();
+ }
+
+ //requestdata is xmlstring
+ public void request( AgentPath agent, int transitionID, String requestData)
+ throws AccessRightsException,
+ InvalidTransitionException,
+ InvalidDataException
+ {
+ Logger.msg(8,"Import::request()");
+
+ Logger.msg(1,"Import::request() - Starting.");
+
+ checkAccessRights(agent);
+
+ String[] params = getDataList(requestData);
+
+
+ int split1 = params[0].indexOf('_');
+ int split2 = params[0].indexOf(':');
+
+ String schemaName = params[0].substring(0, split1);
+ String viewpoint = "last";
+ int schemaVersion;
+ if (split2 > -1) {
+ schemaVersion = Integer.parseInt(params[0].substring(split1+1, split2));
+ viewpoint = params[0].substring(split2+1);
+ }
+ else
+ schemaVersion = Integer.parseInt(params[0].substring(split1+1));
+
+ // set type & ver
+ getProperties().put("SchemaType", schemaName);
+ getProperties().put("SchemaVersion", String.valueOf(schemaVersion));
+ getProperties().put("Viewpoint", viewpoint);
+
+ requestData = params[1];
+
+ sendEventStoreOutcome(transitionID, requestData, agent);
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/predefined/PredefinedStep.java b/source/com/c2kernel/lifecycle/instance/predefined/PredefinedStep.java
new file mode 100755
index 0000000..8d95438
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/predefined/PredefinedStep.java
@@ -0,0 +1,149 @@
+package com.c2kernel.lifecycle.instance.predefined;
+import java.io.StringReader;
+import java.io.StringWriter;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.apache.xml.serialize.Method;
+import org.apache.xml.serialize.OutputFormat;
+import org.apache.xml.serialize.XMLSerializer;
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.xml.sax.InputSource;
+import com.c2kernel.lifecycle.instance.Activity;
+import com.c2kernel.utils.Logger;
+/***********************************************************************************************************************************************************************************************************************************************************************************************************
+ * @author $Author: sgaspard $ $Date: 2004/09/21 10:32:17 $
+ * @version $Revision: 1.14 $
+ **********************************************************************************************************************************************************************************************************************************************************************************************************/
+public class PredefinedStep extends Activity
+{
+ /*******************************************************************************************************************************************************************************************************************************************************************************************************
+ * predefined Steps are always Active, and have only one transition subclasses could override this method (if necessary)
+ ******************************************************************************************************************************************************************************************************************************************************************************************************/
+ private boolean isPredefined = false;
+ public boolean getActive()
+ {
+ if (isPredefined)
+ return true;
+ else
+ return super.getActive();
+ }
+ public String getTransitions()
+ {
+ if (isPredefined)
+ return "<PossibleTransitions>done</PossibleTransitions>";
+ else
+ return super.getTransitions();
+ }
+ public String getErrors()
+ {
+ if (isPredefined)
+ return getName();
+ else
+ return super.getErrors();
+ }
+ public boolean verify()
+ {
+ if (isPredefined)
+ return true;
+ else
+ return super.verify();
+ }
+ /**
+ * Returns the isPredefined.
+ *
+ * @return boolean
+ */
+ public boolean getIsPredefined()
+ {
+ return isPredefined;
+ }
+ /**
+ * Sets the isPredefined.
+ *
+ * @param isPredefined
+ * The isPredefined to set
+ */
+ public void setIsPredefined(boolean isPredefined)
+ {
+ this.isPredefined = isPredefined;
+ }
+ public String getType()
+ {
+ return getName();
+ }
+ // generic bundling of parameters
+ static public String bundleData(String[] data)
+ {
+ try
+ {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ Document dom = builder.newDocument();
+ Element root = dom.createElement("PredefinedStepOutcome");
+ dom.appendChild(root);
+ for (int i = 0; i < data.length; i++)
+ {
+ Element param = dom.createElement("param");
+ Text t = dom.createTextNode(data[i]);
+ param.appendChild(t);
+ root.appendChild(param);
+ }
+ // xalan method - use internal xerces one instead
+// TransformerFactory transFactory = TransformerFactory.newInstance();
+// Transformer transformer = transFactory.newTransformer();
+// StringWriter stringOut = new StringWriter();
+// transformer.transform(new DOMSource(dom), new StreamResult(stringOut));
+// return stringOut.toString();
+
+ OutputFormat format = new OutputFormat(Method.XML, null, false);
+ StringWriter stringOut = new StringWriter();
+ XMLSerializer serial = new XMLSerializer(stringOut, format);
+ serial.asDOMSerializer();
+ serial.serialize(dom);
+ return stringOut.toString();
+ }
+ catch (Exception e)
+ {
+ Logger.error(e);
+ StringBuffer xmlData = new StringBuffer().append("<PredefinedStepOutcome>");
+ for (int i = 0; i < data.length; i++)
+ xmlData.append("<param><![CDATA[").append(data[i]).append("]]></param>");
+ xmlData.append("</PredefinedStepOutcome>");
+ return xmlData.toString();
+ }
+ }
+ // generic bundling of single parameter
+ static public String bundleData(String data)
+ {
+ return "<PredefinedStepOutcome><param><![CDATA[" + data + "]]></param></PredefinedStepOutcome>";
+ }
+ static public String[] getDataList(String xmlData)
+ {
+ try
+ {
+ Document scriptDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader(xmlData)));
+ NodeList nodeList = scriptDoc.getElementsByTagName("param");
+ String[] result = new String[nodeList.getLength()];
+ for (int i = 0; i < nodeList.getLength(); i++)
+ {
+ Node n = nodeList.item(i).getFirstChild();
+ if (n instanceof CDATASection)
+ result[i] = ((CDATASection) n).getData();
+ else if (n instanceof Text)
+ result[i] = ((Text) n).getData();
+ }
+ return result;
+ }
+ catch (Exception ex)
+ {
+ Logger.error("Exception::PredefinedStep::getDataList()");
+ Logger.error(ex);
+ }
+ return null;
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/predefined/PredefinedStepContainer.java b/source/com/c2kernel/lifecycle/instance/predefined/PredefinedStepContainer.java
new file mode 100755
index 0000000..10a9d12
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/predefined/PredefinedStepContainer.java
@@ -0,0 +1,57 @@
+package com.c2kernel.lifecycle.instance.predefined;
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.lifecycle.instance.CompositeActivity;
+public class PredefinedStepContainer extends CompositeActivity
+{
+ protected int num = 0;
+
+ public PredefinedStepContainer()
+ {
+ super();
+ setName("predefined");
+ getProperties().put("Description", "Contains all predefined Steps");
+ createChildren();
+ }
+ public void createChildren()
+ {
+ predInit("CreateItemFromDescription", "Create a new item using this item as its description", new CreateItemFromDescription());
+ predInit("AddDomainPath", "Adds a new path to this entity in the LDAP domain tree", new AddDomainPath());
+ predInit("RemoveDomainPath", "Removes an existing path to this Entity from the LDAP domain tree", new RemoveDomainPath());
+ predInit("AddStepsFromDescription", "Creates the domain-specific LifeCycle from a description", new AddStepsFromDescription());
+ predInit("ReplaceDomainWorkflow", "Replaces the domain CA with the supplied one. Used by the GUI to save new Wf layout", new ReplaceDomainWorkflow());
+ predInit("AddC2KObject", "Adds a new named C2Kernel object to this Item", new AddC2KObject());
+ predInit("WriteProperty", "Writes a property to the Item", new WriteProperty());
+ predInit("RemoveC2KObject", "Removes the named C2Kernel object from this Item.", new RemoveC2KObject());
+ predInit("AssignItemToSlot", "Assigns the referenced entity to a pre-existing slot in a collection of this one", new AssignItemToSlot());
+ predInit("Erase", "Deletes all objects and domain paths for this item.", new Erase());
+ predInit("Import", "Imports an outcome into the Item, with a given schema and viewpoint", new Import());
+ }
+
+ public void predInit(String alias, String Description, PredefinedStep act)
+ {
+ act.setName(alias);
+ act.setType(alias);
+ act.getProperties().put("Description", Description);
+ act.getProperties().put("SchemaType", "PredefinedStepOutcome");
+ act.getProperties().put("SchemaVersion", "0");
+ act.setCentrePoint(new GraphPoint());
+ act.setIsPredefined(true);
+ addChild(act, new GraphPoint(100, 75 * ++num));
+ }
+ public boolean verify()
+ {
+ return true;
+ }
+ public String getErrors()
+ {
+ return "predefined";
+ }
+ public boolean getActive()
+ {
+ return true;
+ }
+ public String getTransitions()
+ {
+ return "<PossibleTransitions></PossibleTransitions>";
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/predefined/RemoveC2KObject.java b/source/com/c2kernel/lifecycle/instance/predefined/RemoveC2KObject.java
new file mode 100755
index 0000000..8004488
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/predefined/RemoveC2KObject.java
@@ -0,0 +1,66 @@
+/**************************************************************************
+ * RemoveC2KObject
+ *
+ * $Workfile$
+ * $Revision: 1.28 $
+ * $Date: 2005/11/15 15:56:38 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.lifecycle.instance.predefined;
+
+
+
+import com.c2kernel.common.AccessRightsException;
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.InvalidTransitionException;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Logger;
+
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2005/11/15 15:56:38 $
+ * @version $Revision: 1.28 $
+ **************************************************************************/
+public class RemoveC2KObject extends PredefinedStep
+{
+ public RemoveC2KObject()
+ {
+ super();
+ }
+
+ //requestdata is xmlstring
+ public void request(AgentPath agent, int transitionID, String requestData)
+ throws AccessRightsException,
+ InvalidTransitionException,
+ InvalidDataException
+ {
+ Logger.msg(1, "RemoveC2KObject::request() - Starting.");
+
+ checkAccessRights(agent);
+ String path = null;
+ try
+ {
+ path = getDataList(requestData)[0];
+ EntityPath entityPath = getItemEntityPath();
+
+ Logger.msg(5, "RemoveC2KObject::request() - path:"+path);
+
+ Gateway.getStorage().remove( entityPath.getSysKey(), path, null );
+ sendEventStoreOutcome(transitionID, requestData, agent);
+ }
+ catch( Exception ex )
+ {
+ Logger.error("RemoveC2KObject::request() - invalid data - path:"+path);
+ Logger.error(ex);
+ throw new InvalidDataException(ex.toString(), "");
+ }
+
+ Logger.msg(1, "RemoveC2KObject::request() - DONE.");
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/predefined/RemoveDomainPath.java b/source/com/c2kernel/lifecycle/instance/predefined/RemoveDomainPath.java
new file mode 100755
index 0000000..af118e5
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/predefined/RemoveDomainPath.java
@@ -0,0 +1,58 @@
+/**************************************************************************
+ * AddDomainPath
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.lifecycle.instance.predefined;
+
+
+
+
+import com.c2kernel.common.AccessRightsException;
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.InvalidTransitionException;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.lookup.LDAPLookup;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Logger;
+
+public class RemoveDomainPath extends PredefinedStep
+{
+ public RemoveDomainPath()
+ {
+ super();
+ }
+
+ //requestdata is xmlstring
+ public void request( AgentPath agent, int transitionID, String requestData)
+ throws AccessRightsException,
+ InvalidTransitionException,
+ InvalidDataException
+ {
+ Logger.msg(8,"RemoveDomainPath::request()");
+ LDAPLookup lookupManager = Gateway.getLDAPLookup();
+
+ Logger.msg(1,"RemoveDomainPath::request() - Starting.");
+
+ checkAccessRights(agent);
+
+ try
+ {
+ DomainPath domainPath = new DomainPath(getDataList(requestData)[0]);
+ lookupManager.delete(domainPath);
+ Logger.msg(8,"AddAlias::request() - context:" + domainPath.toString() + " DONE.");
+
+ }
+ catch( Exception ex )
+ {
+ Logger.error("AddAlias::request() - during anyHelper.extract.");
+ Logger.error(ex);
+ throw new InvalidDataException(ex.toString(), "");
+ }
+
+ sendEventStoreOutcome(transitionID, requestData, agent);
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/predefined/ReplaceDomainWorkflow.java b/source/com/c2kernel/lifecycle/instance/predefined/ReplaceDomainWorkflow.java
new file mode 100755
index 0000000..e8c6a6f
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/predefined/ReplaceDomainWorkflow.java
@@ -0,0 +1,52 @@
+package com.c2kernel.lifecycle.instance.predefined;
+
+//Java
+import java.awt.Point;
+
+import com.c2kernel.common.AccessRightsException;
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.InvalidTransitionException;
+import com.c2kernel.lifecycle.instance.CompositeActivity;
+import com.c2kernel.lifecycle.instance.Workflow;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.Logger;
+
+public class ReplaceDomainWorkflow extends PredefinedStep
+{
+ public ReplaceDomainWorkflow()
+ {
+ super();
+ }
+
+ public void request( AgentPath agent, int transitionID, String requestData)
+ throws AccessRightsException, InvalidTransitionException, InvalidDataException
+ {
+ Workflow lifeCycle = getWf();
+
+ Logger.msg(1, "ReplaceDomainWorkflow::request() - Starting ");
+
+ checkAccessRights(agent);
+
+ try
+ {
+
+ Logger.msg(8, "ReplaceDomainWorkflow::request() - data:" + getDataList(requestData)[0]);
+ lifeCycle.getChildGraphModel().removeVertex(lifeCycle.search("workflow/domain"));
+ CompositeActivity domain = (CompositeActivity) CastorXMLUtility.unmarshall(getDataList(requestData)[0]);
+ lifeCycle.initChild(domain, true, new Point(150, 100));
+ Gateway.getStorage().put(getItemEntityPath().getSysKey(), lifeCycle, null);
+ Logger.msg(1, "ReplaceDomainWorkflow::request() - DONE.");
+ sendEventStoreOutcome(transitionID, requestData, agent);
+ // refresh jobs
+ lifeCycle.refreshJobs();
+ }
+ catch (Exception ex)
+ {
+ Logger.error("ReplaceDomainWorkflow::request() - during unmarshall.");
+ Logger.error(ex);
+ throw new InvalidDataException("ReplaceDomainWorkflow::request() - during unmarshall.", null);
+ }
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/predefined/ServerPredefinedStepContainer.java b/source/com/c2kernel/lifecycle/instance/predefined/ServerPredefinedStepContainer.java
new file mode 100755
index 0000000..363d1fc
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/predefined/ServerPredefinedStepContainer.java
@@ -0,0 +1,40 @@
+package com.c2kernel.lifecycle.instance.predefined;
+
+import com.c2kernel.graph.model.GraphPoint;
+import com.c2kernel.lifecycle.instance.predefined.entitycreation.CreateNewAgent;
+import com.c2kernel.lifecycle.instance.predefined.entitycreation.CreateNewItem;
+
+/**************************************************************************
+ *
+ * $Revision: 1.2 $
+ * $Date: 2005/06/02 10:19:33 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+// public static final String codeRevision = "$Revision: 1.2 $ $Date: 2005/06/02 10:19:33 $ $Author: abranson $";
+public class ServerPredefinedStepContainer extends PredefinedStepContainer {
+
+
+ public void createChildren()
+ {
+ super.createChildren();
+ serverPredInit("CreateNewItem", "Creates a new Item in this Server without description.", new CreateNewItem(), "NewItem");
+ serverPredInit("CreateNewAgent", "Creates a new Item in this Server without description.", new CreateNewAgent(), "NewAgent");
+ }
+
+ public void serverPredInit(String alias, String Description, PredefinedStep act, String schema)
+ {
+ act.setName(alias);
+ act.setType(alias);
+ act.getProperties().put("Description", Description);
+ act.getProperties().put("SchemaType", schema);
+ act.getProperties().put("SchemaVersion", "0");
+ act.getProperties().put("AgentRole", "Admin");
+ act.setCentrePoint(new GraphPoint());
+ act.setIsPredefined(true);
+ addChild(act, new GraphPoint(100, 75 * ++num));
+ }
+
+}
diff --git a/source/com/c2kernel/lifecycle/instance/predefined/WriteProperty.java b/source/com/c2kernel/lifecycle/instance/predefined/WriteProperty.java
new file mode 100755
index 0000000..da526a2
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/predefined/WriteProperty.java
@@ -0,0 +1,76 @@
+/**************************************************************************
+ * WriteProperty
+ *
+ * $Workfile$
+ * $Revision: 1.3 $
+ * $Date: 2004/10/21 08:02:19 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.lifecycle.instance.predefined;
+
+import com.c2kernel.common.AccessRightsException;
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.InvalidTransitionException;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.property.Property;
+import com.c2kernel.utils.Logger;
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2004/10/21 08:02:19 $
+ * @version $Revision: 1.3 $
+ **************************************************************************/
+public class WriteProperty extends PredefinedStep
+{
+ /**************************************************************************
+ * Constructor for Castror
+ **************************************************************************/
+ public WriteProperty()
+ {
+ super();
+ }
+
+ //requestdata is xmlstring
+ public void request( AgentPath agent, int transitionID, String requestData)
+ throws AccessRightsException,
+ InvalidTransitionException,
+ InvalidDataException
+ {
+
+ Logger.msg(1, "WriteProperty::request() - Starting.");
+
+ checkAccessRights(agent);
+ EntityPath entityPath = getItemEntityPath();
+
+ if (entityPath!=null)
+ {
+ String[] params = getDataList(requestData);
+ if (params.length != 2)
+ throw new InvalidDataException("WriteProperty::request() - need 2 params - name and value", "");
+ try
+ {
+
+ Logger.msg(5, "WriteProperty::request() - name:" + params[0] +" val:"+params[1]);
+
+ Property newProp = new Property(params[0], params[1]);
+ Gateway.getStorage().put(entityPath.getSysKey(), newProp, null );
+ sendEventStoreOutcome(transitionID, requestData, agent);
+ }
+ catch( Exception ex )
+ {
+ Logger.error("WriteProperty::request() - during unmarshall.");
+ Logger.error(ex);
+ throw new InvalidDataException(ex.toString(), "");
+ }
+
+ Logger.msg(1, "WriteProperty::request() - DONE.");
+ }
+ else
+ throw new InvalidDataException("EntityPath is null.", "");
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/Aggregation.java b/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/Aggregation.java
new file mode 100755
index 0000000..4abb0e6
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/Aggregation.java
@@ -0,0 +1,26 @@
+package com.c2kernel.lifecycle.instance.predefined.entitycreation;
+
+import java.util.ArrayList;
+
+public class Aggregation implements java.io.Serializable {
+
+ public boolean isDescription;
+ public ArrayList aggregationMemberList;
+ public String name;
+
+ public Aggregation() {
+ super();
+ aggregationMemberList = new ArrayList();
+ }
+
+ public Aggregation(String name, boolean isDescription) {
+ this();
+ this.name = name;
+ this.isDescription = isDescription;
+ }
+
+ public com.c2kernel.collection.Aggregation create() {
+ // TODO: create aggregation
+ return new com.c2kernel.collection.AggregationInstance();
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/AggregationMember.java b/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/AggregationMember.java
new file mode 100755
index 0000000..87baa1d
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/AggregationMember.java
@@ -0,0 +1,21 @@
+package com.c2kernel.lifecycle.instance.predefined.entitycreation;
+
+public class AggregationMember implements java.io.Serializable {
+
+ public int slotNo;
+ public String itemDescriptionPath;
+ public String itemPath;
+ public Geometry geometry;
+
+
+ public AggregationMember() {
+ super();
+ }
+
+ public AggregationMember(int slotNo, String itemDescPath, String itemPath, Geometry geometry) {
+ this.slotNo = slotNo;
+ this.itemDescriptionPath = itemDescPath;
+ this.itemPath = itemPath;
+ this.geometry = geometry;
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/CreateNewAgent.java b/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/CreateNewAgent.java
new file mode 100755
index 0000000..b0eaaec
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/CreateNewAgent.java
@@ -0,0 +1,46 @@
+/**************************************************************************
+ * AddDomainPath
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.lifecycle.instance.predefined.entitycreation;
+
+
+
+
+import com.c2kernel.common.AccessRightsException;
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.InvalidTransitionException;
+import com.c2kernel.lifecycle.instance.predefined.PredefinedStep;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.Logger;
+
+public class CreateNewAgent extends PredefinedStep
+{
+ public CreateNewAgent()
+ {
+ super();
+ }
+
+ //requestdata is xmlstring
+ public void request( AgentPath agent, int transitionID, String requestData)
+ throws AccessRightsException,
+ InvalidTransitionException,
+ InvalidDataException
+ {
+ checkAccessRights(agent);
+
+ try {
+ NewAgent newAgent = (NewAgent)CastorXMLUtility.unmarshall(requestData);
+ newAgent.create(agent.getSysKey());
+ } catch (Exception ex) {
+ Logger.error(ex);
+ throw new InvalidDataException("Error creating agent", "");
+ }
+
+ sendEventStoreOutcome(transitionID, requestData, agent);
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/CreateNewItem.java b/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/CreateNewItem.java
new file mode 100755
index 0000000..49f8ada
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/CreateNewItem.java
@@ -0,0 +1,45 @@
+/**************************************************************************
+ * CreateNewItem
+ *
+ * Copyright (C) 2005 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.lifecycle.instance.predefined.entitycreation;
+
+
+
+
+import com.c2kernel.common.AccessRightsException;
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.InvalidTransitionException;
+import com.c2kernel.lifecycle.instance.predefined.PredefinedStep;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.Logger;
+
+public class CreateNewItem extends PredefinedStep
+{
+ public CreateNewItem()
+ {
+ super();
+ }
+
+ //requestdata is xmlstring
+ public void request( AgentPath agent, int transitionID, String requestData)
+ throws AccessRightsException,
+ InvalidTransitionException,
+ InvalidDataException
+ {
+ checkAccessRights(agent);
+
+ try {
+ NewItem item = (NewItem)CastorXMLUtility.unmarshall(requestData);
+ item.create(agent.getSysKey());
+ } catch (Exception ex) {
+ Logger.error(ex);
+ throw new InvalidDataException("Error creating item", "");
+ }
+ sendEventStoreOutcome(transitionID, requestData, agent);
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/Dependency.java b/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/Dependency.java
new file mode 100755
index 0000000..0896534
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/Dependency.java
@@ -0,0 +1,46 @@
+package com.c2kernel.lifecycle.instance.predefined.entitycreation;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import com.c2kernel.collection.MembershipException;
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.property.PropertyUtility;
+
+public class Dependency implements java.io.Serializable {
+
+ public String name;
+ public boolean isDescription;
+ public String itemDescriptionPath;
+ public ArrayList dependencyMemberList;
+
+ public Dependency() {
+ super();
+ dependencyMemberList = new ArrayList();
+ }
+
+ public Dependency(String itemDesc) {
+ this();
+ this.itemDescriptionPath = itemDesc;
+ }
+
+ /**
+ * @return
+ */
+ public com.c2kernel.collection.Dependency create() throws MembershipException{
+ com.c2kernel.collection.Dependency newDep = new com.c2kernel.collection.Dependency(name);
+ if (itemDescriptionPath != null) {
+ PropertyUtility.getPropertyDescriptionOutcome(new DomainPath(itemDescriptionPath).getSysKey());
+ //TODO: set props and class identifiers
+ }
+ for (Iterator mems = dependencyMemberList.iterator(); mems.hasNext();) {
+ DependencyMember thisMem = (DependencyMember) mems.next();
+ int syskey = new DomainPath(thisMem.itemPath).getSysKey();
+ if (syskey == -1)
+ throw new MembershipException("Cannot find "+thisMem.itemPath+" specified for collection.");
+ newDep.addMember(syskey);
+ }
+ return newDep;
+ }
+
+}
diff --git a/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/DependencyMember.java b/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/DependencyMember.java
new file mode 100755
index 0000000..00ac445
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/DependencyMember.java
@@ -0,0 +1,18 @@
+
+package com.c2kernel.lifecycle.instance.predefined.entitycreation;
+
+public class DependencyMember implements java.io.Serializable {
+
+
+ public String itemPath;
+
+ public DependencyMember() {
+ super();
+ }
+
+ public DependencyMember(String itemPath) {
+ this.itemPath = itemPath;
+
+ }
+
+}
diff --git a/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/Geometry.java b/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/Geometry.java
new file mode 100755
index 0000000..25a1455
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/Geometry.java
@@ -0,0 +1,29 @@
+
+
+package com.c2kernel.lifecycle.instance.predefined.entitycreation;
+
+
+
+public class Geometry implements java.io.Serializable {
+
+
+ public int x;
+
+ public int y;
+
+ public int width;
+
+ public int height;
+
+ public Geometry() {
+ super();
+ }
+
+ public Geometry(int x, int y, int width, int height) {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ }
+
+}
diff --git a/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/NewAgent.java b/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/NewAgent.java
new file mode 100755
index 0000000..fa575a3
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/NewAgent.java
@@ -0,0 +1,65 @@
+package com.c2kernel.lifecycle.instance.predefined.entitycreation;
+
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import com.c2kernel.common.CannotManageException;
+import com.c2kernel.common.ObjectAlreadyExistsException;
+import com.c2kernel.common.ObjectCannotBeUpdated;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.agent.ActiveEntity;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.lookup.RolePath;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.property.PropertyArrayList;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.Logger;
+
+public class NewAgent implements java.io.Serializable {
+
+ public String name;
+
+ public String password;
+
+ public ArrayList roles;
+
+ public NewAgent() {
+ super();
+ roles = new ArrayList();
+ }
+
+ public NewAgent(String name, String password) {
+ this.name = name;
+ this.password = password;
+ }
+
+ protected void create(int agentId) throws ObjectNotFoundException, ObjectCannotBeUpdated, NoSuchAlgorithmException, CannotManageException, ObjectAlreadyExistsException {
+ AgentPath newAgent = Gateway.getLDAPLookup().getNextKeyManager().generateNextAgentKey();
+ newAgent.setAgentName(name);
+ newAgent.setPassword(password);
+ ActiveEntity newAgentEnt = (ActiveEntity)Gateway.getCorbaServer().createEntity(newAgent);
+ Gateway.getLDAPLookup().add(newAgent);
+ // assemble properties
+ PropertyArrayList propList = new PropertyArrayList();
+ propList.list.add(new com.c2kernel.property.Property("Name", name));
+ propList.list.add(new com.c2kernel.property.Property("Type", "Agent"));
+ try {
+ newAgentEnt.initialise(CastorXMLUtility.marshall(propList));
+ } catch (Exception ex) {
+ Logger.error(ex);
+ throw new CannotManageException("Error initialising new agent");
+ }
+ for (Iterator iter = roles.iterator(); iter.hasNext();) {
+ String role = (String) iter.next();
+ RolePath thisRole;
+ try {
+ thisRole = Gateway.getLDAPLookup().getRoleManager().getRolePath(role);
+ } catch (ObjectNotFoundException ex) {
+ thisRole = Gateway.getLDAPLookup().getRoleManager().createRole(role, false);
+ }
+ thisRole.addAgent(newAgent);
+ }
+
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/NewItem.java b/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/NewItem.java
new file mode 100755
index 0000000..4988700
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/NewItem.java
@@ -0,0 +1,145 @@
+package com.c2kernel.lifecycle.instance.predefined.entitycreation;
+
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import com.c2kernel.collection.MembershipException;
+import com.c2kernel.common.CannotManageException;
+import com.c2kernel.common.ObjectAlreadyExistsException;
+import com.c2kernel.common.ObjectCannotBeUpdated;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.TraceableEntity;
+import com.c2kernel.lifecycle.CompositeActivityDef;
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.persistency.ClusterStorageException;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.property.PropertyArrayList;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.LocalObjectLoader;
+import com.c2kernel.utils.Logger;
+
+/**
+ * Complete Structure for new item
+ *
+ * @version $Revision: 1.8 $ $Date: 2006/03/03 13:52:21 $
+ */
+public class NewItem {
+
+ public String name;
+
+ /**
+ * The initial Domain Path to be created for this Item.
+ */
+ public String initialPath;
+
+ /**
+ * The name of the Composite Activity Definition to be
+ * instantiated for the workflow of this Item
+ */
+ public String workflow;
+
+ /**
+ * New Properties for the item
+ */
+ public ArrayList propertyList;
+
+ /**
+ * Field _aggregationList
+ */
+ public ArrayList aggregationList;
+
+ /**
+ * Field _dependencyList
+ */
+ public ArrayList dependencyList;
+
+
+ public NewItem() {
+ super();
+ propertyList = new ArrayList();
+ aggregationList = new ArrayList();
+ dependencyList = new ArrayList();
+ }
+
+ public NewItem(String name, String initialPath, String wf) {
+ this();
+ this.name = name;
+ this.initialPath = initialPath;
+ this.workflow = wf;
+ }
+
+ public void setProperty(String name, String value) {
+ for (Iterator iter = propertyList.iterator(); iter.hasNext();) {
+ Property prop = (Property) iter.next();
+ if (prop.name.equals(name)) {
+ prop.value = value;
+ return;
+ }
+ }
+ propertyList.add(new Property(name, value));
+ }
+
+ protected void create(int agentId) throws ObjectCannotBeUpdated, ObjectNotFoundException, CannotManageException, ObjectAlreadyExistsException {
+ DomainPath domPath = new DomainPath(new DomainPath(initialPath), name);
+ if (domPath.exists())
+ throw new ObjectAlreadyExistsException(domPath+" already exists!", "");
+
+ // create item
+ EntityPath entPath = Gateway.getLDAPLookup().getNextKeyManager().generateNextEntityKey();
+ TraceableEntity newItem = (TraceableEntity)Gateway.getCorbaServer().createEntity(entPath);
+ Gateway.getLDAPLookup().add(entPath);
+
+ // assemble properties
+ PropertyArrayList propList = new PropertyArrayList();
+ propList.list.add(new com.c2kernel.property.Property("Name", name));
+ for (Iterator iter = propertyList.iterator(); iter.hasNext();) {
+ Property element = (Property) iter.next();
+ propList.list.add(new com.c2kernel.property.Property(element.name, element.value));
+ }
+ // init the new item
+ try {
+
+ // find workflow def
+ CompositeActivityDef compact = (CompositeActivityDef)LocalObjectLoader.getActDef(workflow, "last");
+
+ newItem.initialise(
+ agentId,
+ CastorXMLUtility.marshall(propList),
+ CastorXMLUtility.marshall(compact.instantiate()));
+ } catch (Exception ex) {
+ Logger.error("Error initialising new item");
+ Logger.error(ex);
+ throw new CannotManageException("Problem initialising new item. See server log.", "");
+ }
+
+ // create collections
+
+ for (Iterator iter = dependencyList.iterator(); iter.hasNext();) {
+ Dependency element = (Dependency) iter.next();
+ try {
+ Gateway.getStorage().put(entPath.getSysKey(), element.create(), null);
+ } catch (ClusterStorageException ex) {
+ Logger.error(ex);
+ throw new CannotManageException("Could not create Dependency "+element.name, "");
+ } catch (MembershipException ex) {
+ Logger.error(ex);
+ throw new CannotManageException("A specified member is not of the correct type in "+element.name, "");
+ }
+ }
+
+ for (Iterator iter = aggregationList.iterator(); iter.hasNext();) {
+ Aggregation element = (Aggregation) iter.next();
+ try {
+ Gateway.getStorage().put(entPath.getSysKey(), element.create(), null);
+ } catch (ClusterStorageException ex) {
+ Logger.error(ex);
+ throw new CannotManageException("Could not create Aggregation "+element.name, "");
+ }
+ }
+ // register domain path
+ domPath.setEntity(entPath);
+ Gateway.getLDAPLookup().add(domPath);
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/Property.java b/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/Property.java
new file mode 100755
index 0000000..d99a3e3
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/predefined/entitycreation/Property.java
@@ -0,0 +1,26 @@
+package com.c2kernel.lifecycle.instance.predefined.entitycreation;
+/**
+ * New Properties for the item
+ *
+ * @version $Revision: 1.1 $ $Date: 2005/04/28 13:48:26 $
+ */
+public class Property implements java.io.Serializable {
+
+ public String name;
+ public String value;
+
+
+ //----------------/
+ //- Constructors -/
+ //----------------/
+
+ public Property() {
+ super();
+ }
+
+ public Property(String name, String value) {
+ super();
+ this.name = name;
+ this.value = value;
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/stateMachine/StateMachine.java b/source/com/c2kernel/lifecycle/instance/stateMachine/StateMachine.java
new file mode 100755
index 0000000..da7419c
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/stateMachine/StateMachine.java
@@ -0,0 +1,142 @@
+
+package com.c2kernel.lifecycle.instance.stateMachine;
+
+import java.io.Serializable;
+
+import com.c2kernel.lifecycle.instance.Activity;
+import com.c2kernel.utils.Logger;
+
+/**
+ * @version $Revision: 1.30 $ $Date: 2004/06/04 09:39:19 $
+ * @author $Author: sgaspard $
+ */
+/** this class represents the link between 2 successive activities */
+public class StateMachine implements Serializable
+{
+ public int state = 0;
+ private Activity activity;
+
+ public static final String SKIPPABLE = "Skippable";
+ public static final String REPEATABLE = "Repeatable";
+ public static final String IGNORABLE = "Ignorable";
+ public static final String AUTOSTART = "Autostart";
+
+
+ /**
+ * Method StateMachine.
+ * @param act
+ */
+ public StateMachine(Activity act)
+ {
+ activity = act;
+ }
+
+ /** row : States from (WAITING,RESERVED,STARTED,SUSPENDED,FINISHED,RWAITING,RRESERVED,RSTARTED,RSUSPENDED)
+ * collumn : transition (RESERVE,START,SKIP,DONE,COMPLETE,SUSPEND,REASIGN,RESUME,REPEAT,IGNORE,PROCEED)
+ * cell : State that is reached (-1 if transition not allowed)
+ */
+ private int[][] getCurrentMachine()
+ {
+ int [][] returnArray =
+ { /*RESERVE, START, SKIP, DONE,COMPLETE,SUSPEND,REASIGN,RESUME, REPEAT, IGNORE, PROCEED*/
+ /*0 WAITING*/ { 1,getActive()?2:-1,getSkippable()?4:-1,getActive()?4:-1, -1, -1, -1, -1, -1, -1, -1},/*0 WAITING*/
+ /*1 RESERVED*/ { -1,getActive()?2:-1,getSkippable()?4:-1,getActive()?4:-1, -1, -1, -1, -1, -1, 0, -1},/*1 RESERVED*/
+ /*2 STARTED*/ { -1, -1, -1, -1, 4, 3, -1, -1, -1,getIgnorable()?0:-1, -1},/*2 STARTED*/
+ /*3 SUSPENDED*/ { -1, -1, -1, -1, -1, -1, 2, 2, -1,getIgnorable()?0:-1, -1},/*3 SUSPENDED*/
+ /*4 FINISHED*/ { -1, -1, -1, -1, -1, -1, -1, -1,getRepeatable()?!getAutoStart()?5:7:-1, -1,getActive()?4:-1},/*4 FINISHED*/
+ /*5 RWAITING*/ { 6,getActive()?7:-1,getSkippable()?4:-1,getActive()?4:-1, -1, -1, -1, -1, -1, -1, -1},/*5 RWAITING*/
+ /*6 RRESERVED*/ { -1,getActive()?7:-1,getSkippable()?4:-1,getActive()?4:-1, -1, -1, -1, -1, -1, -1, -1},/*6 RRESERVED*/
+ /*7 RSTARTED*/ { -1, -1, -1, -1, 4, 8, -1, -1, -1,getIgnorable()?5:-1, -1},/*7 RSTARTED*/
+ /*8 RSUSPENDED*/ { -1, -1, -1, -1, -1, -1, 8, 7, -1, -1, -1} /*8 RSUSPENDED*/
+ };
+ return returnArray;
+ }
+
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public StateMachine()
+ {
+ }
+
+ /**
+ * Method getCurrentState.
+ * @return String
+ */
+ public int getCurrentState()
+ {
+ return state;
+ }
+
+ /**
+ * Method possibleTransition.
+ * @return String[]
+ */
+ public int[] possibleTransition()
+ {
+ int[] trans = new int[9];
+ int cmpt = 0;
+ for (int i=0; i< getCurrentMachine()[state].length;i++)
+ if (getCurrentMachine()[state][i]!=-1) trans[cmpt++]=i;
+
+ int [] result = new int[cmpt];
+ for (int i=0;i<cmpt;i++) result[i] = trans[i];
+ return result;
+ }
+
+ /**
+ * Method traverse.
+ * @param transition
+ * @return boolean
+ */
+ public boolean traverse(int transition)
+ {
+ int newState = getCurrentMachine()[state][transition];
+ if (newState > -1) {
+ state=newState;
+ return true;
+ }
+ Logger.msg("StateMachine.traverse() - Illegal transition "+Transitions.getTransitionName(transition)+" from "+States.getStateName(state));
+ return false;
+ }
+ public int simulate(int transition)
+ {
+ return getCurrentMachine()[state][transition];
+ }
+ /**
+ * Returns the ignorable.
+ * @return boolean
+ */
+ public boolean getIgnorable()
+ {
+ return ((Boolean)activity.getProperties().get(IGNORABLE)).booleanValue();
+ }
+
+ /**
+ * Returns the repeatable.
+ * @return boolean
+ */
+ public boolean getRepeatable()
+ {
+ return ((Boolean)activity.getProperties().get(REPEATABLE)).booleanValue();
+ }
+
+ /**
+ * Returns the skippable.
+ * @return boolean
+ */
+ public boolean getSkippable()
+ {
+ return ((Boolean)activity.getProperties().get(SKIPPABLE)).booleanValue();
+ }
+
+ public boolean getAutoStart()
+ {
+ return ((Boolean)activity.getProperties().get(AUTOSTART)).booleanValue();
+ }
+ public boolean getActive()
+ {
+ return activity.getActive();
+ }
+
+}
diff --git a/source/com/c2kernel/lifecycle/instance/stateMachine/States.java b/source/com/c2kernel/lifecycle/instance/stateMachine/States.java
new file mode 100755
index 0000000..638a7b0
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/stateMachine/States.java
@@ -0,0 +1,40 @@
+package com.c2kernel.lifecycle.instance.stateMachine;
+
+
+/**
+ * @author XSeb74
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class States
+{
+ public final static int WAITING = 0;
+ public final static int RESERVED = 1;
+ public final static int STARTED = 2;
+ public final static int SUSPENDED = 3;
+ public final static int FINISHED = 4;
+ public final static int RWAITING = 5;
+ public final static int RRESERVED = 6;
+ public final static int RSTARTED = 7;
+ public final static int RSUSPENDED = 8;
+
+ //everything less that this constant is NOT a repeating state
+ public final static int REPEATSTATESTART = 5;
+
+ public static final String[] states = { "Waiting", "Reserved", "Started", "Suspended", "Finished", "Waiting(R)", "Reserved(R)", "Started(R)", "Suspended(R)" };
+
+ public static String getStateName(int state)
+ {
+ try
+ {
+ return states[state];
+ }
+ catch (ArrayIndexOutOfBoundsException ex)
+ {
+ return "Invalid State: " + state;
+ }
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/instance/stateMachine/Transitions.java b/source/com/c2kernel/lifecycle/instance/stateMachine/Transitions.java
new file mode 100755
index 0000000..6597686
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/instance/stateMachine/Transitions.java
@@ -0,0 +1,41 @@
+package com.c2kernel.lifecycle.instance.stateMachine;
+
+import com.c2kernel.utils.Language;
+
+/**
+ * @author XSeb74
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class Transitions
+{
+ public final static int RESERVE = 0;
+ public final static int START = 1;
+ public final static int SKIP = 2;
+ public final static int DONE = 3;
+ public final static int COMPLETE = 4;
+ public final static int SUSPEND = 5;
+ public final static int REASSIGN = 6;
+ public final static int RESUME = 7;
+ public final static int REPEAT = 8;
+ public final static int IGNORE = 9;
+ public final static int PROCEED = 10;
+ public final static int ACTIVATION = 11;
+
+ private static String[] transitions = { "reserve", "start", "skip", "done", "complete", "suspend", "reassign", "resume", "repeat","ignore","proceed","activation" };
+
+ public static String getTransitionName(int trans)
+ {
+ try
+ {
+ return Language.translate(transitions[trans]);
+ }
+ catch (ArrayIndexOutOfBoundsException ex)
+ {
+ return "Invalid Transition: " + trans;
+ }
+ }
+}
diff --git a/source/com/c2kernel/lifecycle/routingHelpers/ViewpointDataHelper.java b/source/com/c2kernel/lifecycle/routingHelpers/ViewpointDataHelper.java
new file mode 100755
index 0000000..754bd8f
--- /dev/null
+++ b/source/com/c2kernel/lifecycle/routingHelpers/ViewpointDataHelper.java
@@ -0,0 +1,79 @@
+package com.c2kernel.lifecycle.routingHelpers;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.persistency.outcome.Outcome;
+import com.c2kernel.persistency.outcome.Viewpoint;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.XmlElementParser;
+
+/**
+ * @author XSeb74
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class ViewpointDataHelper
+{
+ static Object[] errArr = { "" };
+ /**
+ * Method get.
+ * @param value
+ * @return String[]
+ * @throws Exception
+ */
+ /**@param value : EntityPath:ActivityPath:XPathInOutcome*/
+ public static Object [] get(String value) throws Exception
+ {
+ //Syntax of search : <EntityPath>/<ViewpointPath>:<XPathinOutcome>
+ String entityPath;
+ String viewpoint;
+ String xpath;
+ Object[] retArr;
+
+ // find syskey, viewname, xpath
+ int firstSlash = value.indexOf("/");
+ if (firstSlash > 0) {
+ entityPath = value.substring(0, firstSlash);
+ int startXPath = value.indexOf(":");
+ if (startXPath==-1) {
+ viewpoint = value.substring(firstSlash + 1);
+ xpath = null;
+ } else {
+ viewpoint = value.substring(firstSlash + 1, startXPath);
+ xpath = value.substring(startXPath+1);
+ }
+ }
+ else return errArr;
+
+ // find entity
+ EntityPath sourcePath;
+ try
+ {
+ sourcePath = new EntityPath(Integer.parseInt(entityPath));
+ } catch (Exception e) {
+ sourcePath = new EntityPath(entityPath);
+ }
+
+ try {
+ // load viewpoint
+ ItemProxy dataSource = (ItemProxy)Gateway.getProxyManager().getProxy(sourcePath);
+ Viewpoint view = (Viewpoint)dataSource.getObject(ClusterStorage.VIEWPOINT + "/" + viewpoint);
+ Outcome outcome = view.getOutcome();
+ if (xpath == null) {
+ retArr = new Object[1];
+ retArr[0] = outcome;
+ }
+ else
+ retArr = XmlElementParser.parse(outcome.getData(), xpath);
+ return retArr;
+
+ } catch (ObjectNotFoundException e) {
+ return errArr;
+ }
+ }
+}
diff --git a/source/com/c2kernel/lookup/AgentPath.java b/source/com/c2kernel/lookup/AgentPath.java
new file mode 100755
index 0000000..01c764f
--- /dev/null
+++ b/source/com/c2kernel/lookup/AgentPath.java
@@ -0,0 +1,152 @@
+/**************************************************************************
+ * EntityPath.java
+ *
+ * $Revision: 1.12 $
+ * $Date: 2005/10/13 08:15:00 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.lookup;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import org.apache.xerces.impl.dv.util.Base64;
+
+import com.c2kernel.common.ObjectCannotBeUpdated;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.process.Gateway;
+import com.novell.ldap.LDAPAttribute;
+import com.novell.ldap.LDAPAttributeSet;
+import com.novell.ldap.LDAPEntry;
+
+
+/**
+* Extends Path to enforce SystemKey structure and support int form
+*
+* @version $Revision: 1.12 $ $Date: 2005/10/13 08:15:00 $
+* @author $Author: abranson $
+**/
+public class AgentPath extends EntityPath
+{
+
+ private String mAgentName=null;
+ private String mPassword=null;
+
+ public AgentPath(int syskey, String agentName)
+ throws InvalidAgentPathException,InvalidEntityPathException
+ {
+ super(syskey);
+ if (agentName!=null && agentName.length()>0)
+ setAgentName(agentName);
+ else
+ throw new InvalidAgentPathException();
+ }
+
+ public AgentPath(int syskey)
+ throws InvalidEntityPathException
+ {
+ super(syskey);
+ }
+
+ public AgentPath(EntityPath entity) {
+ super();
+ try {
+ setSysKey(entity.getSysKey());
+ } catch (InvalidEntityPathException ex) {
+ //won't happen as the entity path was valid
+ }
+ }
+
+ public void setAgentName(String agentID)
+ {
+ mAgentName = agentID;
+ }
+
+ public String getAgentName()
+ {
+ if (mAgentName==null)
+ {
+ try {
+ LDAPEntry agentEntry = LDAPLookupUtils.getEntry(Gateway.getLDAPLookup().getConnection(), this.getDN() + mLocalPath);
+ mAgentName = LDAPLookupUtils.getFirstAttributeValue(agentEntry,"uid");
+ } catch (ObjectNotFoundException e) {
+ mAgentName = "";
+ }
+ }
+ return mAgentName;
+ }
+
+ public RolePath[] getRoles()
+ {
+ return Gateway.getLDAPLookup().getRoleManager().getRoles(this);
+ }
+
+ public boolean hasRole(RolePath role) {
+ return Gateway.getLDAPLookup().getRoleManager().hasRole(this, role);
+ }
+
+ public boolean hasRole(String role) {
+ try {
+ return hasRole(Gateway.getLDAPLookup().getRoleManager().getRolePath(role));
+ } catch (ObjectNotFoundException ex) {
+ return false;
+ }
+ }
+
+ public void setPassword(String passwd)
+ {
+ mPassword = passwd;
+ }
+
+ public String getPassword()
+ {
+ return mPassword;
+ }
+
+ public String dump() {
+ return super.dump()+
+ "\n agentID="+
+ mAgentName;
+ }
+
+ static String generateUserPassword(String pass, String algo) throws NoSuchAlgorithmException {
+ MessageDigest sha = MessageDigest.getInstance(algo);
+ sha.reset();
+ sha.update(pass.getBytes());
+ byte hash[] = sha.digest();
+ StringBuffer digest = new StringBuffer("{").append(algo).append("}");
+ digest.append(Base64.encode(hash));
+ return digest.toString();
+ }
+
+ public LDAPAttributeSet createAttributeSet() throws ObjectCannotBeUpdated
+ {
+ LDAPAttributeSet attrs = new LDAPAttributeSet();
+ attrs.add(new LDAPAttribute("objectclass","cristalagent"));
+ attrs.add(new LDAPAttribute("intsyskey",Integer.toString(mSysKey)));
+ attrs.add(new LDAPAttribute("cn", getPath()[getPath().length-1]));
+ if (mIOR != null)
+ attrs.add(new LDAPAttribute("ior", Gateway.getORB().object_to_string(mIOR)));
+
+ if (mAgentName!=null && mAgentName.length()>0)
+ attrs.add(new LDAPAttribute("uid",mAgentName));
+ else
+ throw new ObjectCannotBeUpdated("Cannot create agent. No userId specified", "");
+
+ if (mPassword!=null && mPassword.length()>0)
+ try {
+ attrs.add(new LDAPAttribute("userPassword",generateUserPassword(mPassword, "SHA")));
+ } catch (NoSuchAlgorithmException ex) {
+ throw new ObjectCannotBeUpdated("Cryptographic libraries for password hashing not found.", "");
+ }
+ else
+ throw new ObjectCannotBeUpdated("Cannot create agent. No password given", "");
+
+ return attrs;
+ }
+
+}
+
diff --git a/source/com/c2kernel/lookup/DomainPath.java b/source/com/c2kernel/lookup/DomainPath.java
new file mode 100755
index 0000000..ad314ee
--- /dev/null
+++ b/source/com/c2kernel/lookup/DomainPath.java
@@ -0,0 +1,153 @@
+/**************************************************************************
+ * DomainPath.java
+ *
+ * $Revision: 1.22 $
+ * $Date: 2005/10/13 08:15:00 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.lookup;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Logger;
+import com.novell.ldap.LDAPAttribute;
+import com.novell.ldap.LDAPAttributeSet;
+
+
+/**
+* @version $Revision: 1.22 $ $Date: 2005/10/13 08:15:00 $
+* @author $Author: abranson $
+**/
+public class DomainPath extends Path
+{
+ private EntityPath target = null;
+ protected static String mTypeRoot;
+
+/* Very simple extension to Path. Only copies constructors and defines root */
+
+ public DomainPath()
+ {
+ super(Path.UNKNOWN);
+ }
+
+ public DomainPath(short type)
+ {
+ super();
+ mType = type;
+ }
+
+ public DomainPath(String[] path)
+ {
+ super(path, Path.UNKNOWN);
+ }
+
+ public DomainPath(String path)
+ {
+ super(path, Path.UNKNOWN);
+ }
+
+ public DomainPath(String path, EntityPath entity) throws InvalidEntityPathException
+ {
+ super(path, Path.UNKNOWN);
+ setEntity(entity);
+ }
+
+ public DomainPath(DomainPath parent, String child) {
+ super(parent, child);
+ }
+
+ /* the root of domain paths is /domain
+ * clearly
+ */
+ public String getRoot() {
+ return "domain";
+ }
+
+ public DomainPath getParent() {
+ if (mPath.length == 0)
+ return null;
+
+ String[] parentPath = new String[mPath.length-1];
+ System.arraycopy(mPath, 0, parentPath, 0, parentPath.length);
+ return new DomainPath(parentPath);
+ }
+
+ public void setEntity(EntityPath newTarget) {
+ if (newTarget == null) { // clear
+ target = null;
+ mType = Path.CONTEXT;
+ return;
+ }
+
+ target = newTarget;
+ mType = Path.ENTITY;
+ }
+
+ public EntityPath getEntity() throws ObjectNotFoundException {
+ if (mType == UNKNOWN) { // must decide
+ checkType();
+ }
+
+ if (target == null)
+ throw new ObjectNotFoundException("Path is a context", "");
+ return target;
+ }
+
+ public short getType() {
+ if (mType == UNKNOWN) { // must decide
+ checkType();
+ }
+ return mType;
+ }
+
+ public void checkType() {
+ try {
+ setEntity(Gateway.getLDAPLookup().resolvePath(this));
+ } catch (InvalidEntityPathException ex) {
+ Logger.error(ex);
+ mType = CONTEXT;
+ } catch (ObjectNotFoundException ex) {
+ mType = CONTEXT;
+ }
+
+ }
+
+ /**
+ * Retrieves the domkey of the path
+ * @return the last path component;
+ */
+ public String getName() {
+ return mPath[mPath.length-1];
+ }
+
+ public int getSysKey() {
+ if (mType == UNKNOWN) { // must decide
+ checkType();
+ }
+
+ if (mType == ENTITY) {
+ return target.getSysKey();
+ }
+ else return INVALID;
+ }
+
+ public LDAPAttributeSet createAttributeSet() {
+ LDAPAttributeSet attrs = new LDAPAttributeSet();
+ attrs.add(new LDAPAttribute("cn",getName()));
+ if (getType() == ENTITY) {
+ String objectclass_values[] = { "alias", "aliasObject" };
+ attrs.add(new LDAPAttribute("objectclass",objectclass_values));
+ attrs.add(new LDAPAttribute("aliasedObjectName",target.getFullDN()));
+ }
+
+ else
+ {
+ attrs.add(new LDAPAttribute("objectclass","cristalcontext"));
+ }
+ return attrs;
+ }
+}
+
diff --git a/source/com/c2kernel/lookup/EntityPath.java b/source/com/c2kernel/lookup/EntityPath.java
new file mode 100755
index 0000000..079f171
--- /dev/null
+++ b/source/com/c2kernel/lookup/EntityPath.java
@@ -0,0 +1,172 @@
+/**************************************************************************
+ * EntityPath.java
+ *
+ * $Revision: 1.14 $
+ * $Date: 2006/03/03 13:52:21 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.lookup;
+
+import java.util.ArrayList;
+
+import com.c2kernel.common.ObjectCannotBeUpdated;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.process.Gateway;
+import com.novell.ldap.LDAPAttribute;
+import com.novell.ldap.LDAPAttributeSet;
+
+
+/**
+* Extends Path to enforce SystemKey structure and support int form
+*
+* @version $Revision: 1.14 $ $Date: 2006/03/03 13:52:21 $
+* @author $Author: abranson $
+**/
+public class EntityPath extends Path
+{
+ // no of components in a syskey
+ public static final int elementNo = 3;
+ // no of digits in a syskey component
+ public static final int elementLen = 3;
+ // maximum possible int syskey
+ public static final int maxSysKey = (int)Math.pow(10, elementNo*elementLen)-1;
+ protected static String mTypeRoot;
+ /*
+ * From syskey int
+ * Note no EntityPath constructors allow setting of CONTEXT or ENTITY:
+ * The object decides that for itself from the number of components
+ */
+
+ public EntityPath(int syskey) throws InvalidEntityPathException {
+ super();
+ setSysKey(syskey);
+ }
+
+ /*
+ */
+ public EntityPath()
+ {
+ super();
+ }
+
+
+ /*
+ */
+ public EntityPath(String[] path) throws InvalidEntityPathException
+ {
+ super(path, Path.CONTEXT); // dummy - it will get replaced in checkSysPath()
+ checkSysPath();
+ }
+
+ /*
+ */
+ public EntityPath(String path) throws InvalidEntityPathException
+ {
+ super(path, Path.CONTEXT);
+ checkSysPath();
+ }
+
+ /*
+ */
+ public EntityPath(EntityPath parent, String child) throws InvalidEntityPathException {
+ super(parent, child);
+ checkSysPath();
+ }
+
+ // EntityPaths root in /entity
+ public String getRoot() {
+ return "entity";
+ }
+
+ public EntityPath getEntity() throws ObjectNotFoundException {
+ return this;
+ }
+
+ public byte[] getOID() {
+ if (mSysKey == Path.INVALID) return null;
+ return String.valueOf(mSysKey).getBytes();
+ }
+
+ /*************************************************************************/
+
+ /** Returns int form of syskey (if possible)
+ */
+ public int getSysKey() {
+ if (mSysKey == Path.INVALID && mType == Path.ENTITY)
+ try {
+ if (mPath.length != elementNo)
+ throw new InvalidEntityPathException("Incorrect number of components for a system key");
+ mSysKey = 0;
+ for (int i=0; i<mPath.length;i++) {
+ String keypart = mPath[i];
+ if (keypart.length()!=elementLen+1)
+ throw new InvalidEntityPathException("Component '"+keypart+"' is not the correct size for a system key");
+ for(int j=1; j<elementLen+1; j++) // skip the 'd' prefix
+ {
+ char c = keypart.charAt(j);
+ if((c >= '0') && (c <='9'))
+ mSysKey = mSysKey*10 + c - '0';
+ else
+ throw new InvalidEntityPathException("Component '"+keypart+"' contained a non-numeric char (excluding first char 'd').");
+
+ }
+ }
+ } catch (InvalidEntityPathException ex) {
+ mSysKey = Path.INVALID;
+ }
+ return mSysKey;
+ }
+
+ /** Sets path from int syskey
+ */
+ public void setSysKey(int sysKey) throws InvalidEntityPathException
+ {
+ if (sysKey < 0 || sysKey > maxSysKey)
+ throw new InvalidEntityPathException("System key "+sysKey+" out of range");
+ String stringPath = Integer.toString(sysKey);
+ ArrayList newKey = new ArrayList();
+ for (int i=0; i<elementNo; i++) {
+ StringBuffer nextComponent = new StringBuffer("d");
+ int start = stringPath.length()-elementLen;
+ if (start < 0) {
+ nextComponent.append("000000".substring(0,Math.abs(start))).append(stringPath);
+ stringPath = "";
+ }
+ else {
+ nextComponent.append(stringPath.substring(start));
+ stringPath = stringPath.substring(0, start);
+ }
+ newKey.add(0, nextComponent.toString());
+ }
+
+ mPath = (String[])(newKey.toArray(mPath));
+ mSysKey = sysKey;
+ mStringPath = null;
+ mDN = null;
+ mType = Path.ENTITY;
+ checkSysPath();
+ }
+
+ public void checkSysPath() throws InvalidEntityPathException {
+ if (mPath.length > elementNo)
+ throw new InvalidEntityPathException("EntityPath cannot have more than "+elementNo+" components: "+toString());
+ if (mPath.length == elementNo)
+ mType = Path.ENTITY;
+ else
+ mType = Path.CONTEXT;
+ }
+
+ public LDAPAttributeSet createAttributeSet() throws ObjectCannotBeUpdated {
+ LDAPAttributeSet attrs = new LDAPAttributeSet();
+ attrs.add(new LDAPAttribute("objectclass","cristalentity"));
+ attrs.add(new LDAPAttribute("intsyskey",Integer.toString(mSysKey)));
+ attrs.add(new LDAPAttribute("cn", getPath()[getPath().length-1]));
+ if (mIOR != null)
+ attrs.add(new LDAPAttribute("ior", Gateway.getORB().object_to_string(mIOR)));
+ return attrs;
+ }
+}
+
diff --git a/source/com/c2kernel/lookup/InvalidAgentPathException.java b/source/com/c2kernel/lookup/InvalidAgentPathException.java
new file mode 100755
index 0000000..be4d952
--- /dev/null
+++ b/source/com/c2kernel/lookup/InvalidAgentPathException.java
@@ -0,0 +1,13 @@
+package com.c2kernel.lookup;
+
+public class InvalidAgentPathException extends InvalidEntityPathException {
+
+ public InvalidAgentPathException() {
+ super();
+ }
+
+ public InvalidAgentPathException(String msg) {
+ super(msg);
+ }
+
+}
diff --git a/source/com/c2kernel/lookup/InvalidEntityPathException.java b/source/com/c2kernel/lookup/InvalidEntityPathException.java
new file mode 100755
index 0000000..27c754d
--- /dev/null
+++ b/source/com/c2kernel/lookup/InvalidEntityPathException.java
@@ -0,0 +1,13 @@
+package com.c2kernel.lookup;
+
+public class InvalidEntityPathException extends Exception {
+
+ public InvalidEntityPathException() {
+ super();
+ }
+
+ public InvalidEntityPathException(String msg) {
+ super(msg);
+ }
+
+}
diff --git a/source/com/c2kernel/lookup/LDAPLookup.java b/source/com/c2kernel/lookup/LDAPLookup.java
new file mode 100755
index 0000000..04d99f0
--- /dev/null
+++ b/source/com/c2kernel/lookup/LDAPLookup.java
@@ -0,0 +1,461 @@
+/*
+ * Directory Lookup Service *
+ * author: Florida Estrella
+*/
+
+package com.c2kernel.lookup;
+
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+
+import com.c2kernel.common.ObjectAlreadyExistsException;
+import com.c2kernel.common.ObjectCannotBeUpdated;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.TraceableEntity;
+import com.c2kernel.entity.agent.ActiveEntity;
+import com.c2kernel.entity.proxy.EntityProxyManager;
+import com.c2kernel.entity.proxy.ProxyMessage;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.Resource;
+import com.novell.ldap.*;
+
+/**
+ * The LDAPLookup object, statically accessible through the Gateway, manages
+ * the LDAP connection for the cristal process. It provides:
+ * <ul>
+ * <li>Authentication - returning an AgentProxy object if a user has logged in
+ * <li>System key generation - through the NextKeyManager
+ * <li>Agent and Role lookup/modification - through the RoleManager
+ * <li>
+ * @version $Revision: 1.113 $ $Date: 2006/03/03 13:52:21 $
+ * @author $Author: abranson $
+ */
+
+public class LDAPLookup
+
+{
+ private LDAPConnection mLDAPConn;
+ private LDAPProperties mLDAPProps;
+ private NextKeyManager mNextKeyManager;
+ private LDAPPropertyManager mPropManager;
+ private LDAPRoleManager mRoleManager;
+
+
+
+ /**
+ * Creates a new LDAPLookup manager with the properties supplied.
+ * This should be only done by the Gateway during initialisation.
+ *
+ * @param props The LDAP properties object that extracts LDAP connection properties from the global c2kprops
+ */
+ public LDAPLookup(LDAPProperties props) throws LDAPException
+ {
+ Logger.msg(8,"LDAPLookup - initialising.");
+
+ mLDAPProps = props;
+
+ mLDAPConn = createConnection(mLDAPProps);
+
+ Path.mGlobalPath=props.mGlobalPath;
+ Path.mRootPath=props.mRootPath;
+ Path.mLocalPath=props.mLocalPath;
+
+ EntityPath.mTypeRoot = "cn=entity,"+props.mLocalPath;
+ DomainPath.mTypeRoot = "cn=domain,"+props.mLocalPath;
+
+ mNextKeyManager = new NextKeyManager(this, "cn=last,"+EntityPath.mTypeRoot);
+ Logger.debug("LDAP.useOldProps="+Gateway.getProperty("LDAP.useOldProps", "false"));
+ if (Gateway.getProperty("LDAP.useOldProps", "false").equals("true")) {
+ Logger.debug("Using Kernel 2.1 LDAP Property Format");
+ mPropManager = new LegacyLDAPPropertyManager(this);
+ }
+ else {
+ Logger.debug("Using Kernel 2.2 LDAP Property Format");
+ mPropManager = new LDAPPropertyManager(this);
+ }
+ mRoleManager = new LDAPRoleManager(this, "cn=agent,"+DomainPath.mTypeRoot, EntityPath.mTypeRoot);
+
+ }
+
+ /**
+ * Utility method to connect to an LDAP server
+ * @param lp LDAP properties to connect with
+ * @return a novell LDAPConnection object
+ * @throws LDAPException when the connection was unsuccessful
+ */
+ public static LDAPConnection createConnection(LDAPProperties lp) throws LDAPException {
+ LDAPConnection ld = new LDAPConnection();
+
+ Logger.msg(3, "LDAPLookup - connecting to " + lp.mHost);
+ ld.connect(lp.mHost, Integer.valueOf(lp.mPort).intValue());
+
+ Logger.msg(3, "LDAPLookup - authenticating user:" + lp.mUser);
+ ld.bind( LDAPConnection.LDAP_V3, lp.mUser,
+ String.valueOf(lp.mPassword).getBytes());
+
+ Logger.msg(3, "LDAPLookup - authentication successful");
+ LDAPSearchConstraints searchCons = new LDAPSearchConstraints();
+ searchCons.setMaxResults(0);
+ ld.setConstraints(searchCons);
+
+ return ld;
+ }
+
+ /**
+ * Gets the entity key generator, used to get a unique system key for new entities.
+ * @return the global NextKeyManager
+ */
+ public NextKeyManager getNextKeyManager()
+ {
+ return mNextKeyManager;
+ }
+
+ /**
+ * Gets the property manager, that is used to read and write cristal properties to the LDAP store.
+ * @return Returns the global LDAPPropertyManager.
+ */
+ public LDAPPropertyManager getPropManager() {
+ return mPropManager;
+ }
+ /**
+ * Gets the role manager, that is used to add and remove roles and agents.
+ * @return Returns the mRoleManager.
+ */
+ public LDAPRoleManager getRoleManager() {
+ return mRoleManager;
+ }
+
+ /**
+ * Returns the current LDAP connection, and attempts to reconnect if it has been closed.
+ * @return
+ */
+ protected LDAPConnection getConnection()
+ {
+ if (!mLDAPConn.isConnected()) {
+ Logger.warning("LDAPLookup - lost connection to LDAP server. Attempting to reconnect.");
+ try {
+ mLDAPConn = createConnection(mLDAPProps);
+ } catch (LDAPException ex) { }
+ }
+ return mLDAPConn;
+ }
+
+ /**
+ * Disconnects the connection with the LDAP server during shutdown
+ */
+ public void disconnect() {
+ Logger.msg(1, "LDAP Lookup: Shutting down LDAP connection.");
+ if (mLDAPConn != null) {
+ try {
+ mLDAPConn.disconnect();
+ } catch (LDAPException e) {
+ Logger.error(e);
+ }
+ mLDAPConn = null;
+ }
+ }
+
+ /**
+ * Attempts to resolve the CORBA object for a Path, either directly or through an alias.
+ * @param path the path to resolve
+ * @return the CORBA object
+ * @throws ObjectNotFoundException When the path does not exist
+ */
+ public org.omg.CORBA.Object getIOR(Path path)
+ throws ObjectNotFoundException
+ {
+ return resolveObject(path.getFullDN());
+ }
+
+ /**
+ * Attempts to resolve the CORBA object from the IOR attribute of a DN, either directly or through an alias
+ * @param dn The String dn
+ * @throws ObjectNotFoundException when the dn or aliased dn does not exist
+ */
+ private org.omg.CORBA.Object resolveObject(String dn)
+ throws ObjectNotFoundException
+ {
+ Logger.msg(8,"LDAPLookup.resolveObject("+dn+")");
+ LDAPEntry anEntry = LDAPLookupUtils.getEntry(getConnection(),dn,LDAPSearchConstraints.DEREF_NEVER);
+ if (anEntry != null)
+ {
+ String iorString;
+ try {
+ iorString = LDAPLookupUtils.getFirstAttributeValue(anEntry, "ior");
+ org.omg.CORBA.Object ior=Gateway.getORB().string_to_object(iorString);
+ if (ior!=null)
+ return ior;
+ else
+ throw new ObjectNotFoundException("LDAPLookup.resolveObject() - " + dn + " has no IOR", "");
+ } catch (ObjectNotFoundException ex) {
+ return resolveObject(LDAPLookupUtils.getFirstAttributeValue(anEntry,"aliasedObjectName"));
+ }
+ }
+ else
+ throw new ObjectNotFoundException("LDAPLookup.resolveObject() LDAP node " + dn + " is not in LDAP or has no IOR.", "");
+ }
+
+ /**
+ *
+ * @param domPath
+ * @return
+ * @throws InvalidEntityPathException
+ * @throws ObjectNotFoundException
+ */
+ protected EntityPath resolvePath(DomainPath domPath)
+ throws InvalidEntityPathException, ObjectNotFoundException {
+ EntityPath referencedPath = null;
+ LDAPEntry domEntry = LDAPLookupUtils.getEntry(getConnection(), domPath
+ .getFullDN(), LDAPSearchConstraints.DEREF_ALWAYS);
+ String entityKey = LDAPLookupUtils.getFirstAttributeValue(domEntry,
+ "intsyskey");
+ Logger.msg(7, "DomainPath " + domPath + " is a reference to "
+ + entityKey);
+ String objClass = LDAPLookupUtils.getFirstAttributeValue(domEntry,
+ "objectClass");
+ if (objClass.equals("cristalagent"))
+ referencedPath = new AgentPath(Integer.parseInt(entityKey));
+ else
+ referencedPath = new EntityPath(Integer.parseInt(entityKey));
+
+ return referencedPath;
+ }
+
+
+ public LDAPEntry add(Path path)
+ throws ObjectCannotBeUpdated, ObjectAlreadyExistsException
+ {
+ String root = path.getRoot();
+ try {
+ checkLDAPContext(path);
+ LDAPAttributeSet attrSet = path.createAttributeSet();
+ LDAPEntry newEntry = new LDAPEntry(path.getFullDN(),attrSet);
+ LDAPLookupUtils.addEntry(getConnection(),newEntry);
+ if (path instanceof DomainPath)
+ EntityProxyManager.sendProxyEvent(new ProxyMessage(ProxyMessage.NA, path.toString(), ProxyMessage.ADDED));
+ return newEntry;
+ } catch (LDAPException ex) {
+ if (ex.getResultCode() == LDAPException.ENTRY_ALREADY_EXISTS)
+ throw new ObjectAlreadyExistsException(ex.getLDAPErrorMessage(), "");
+ else
+ throw new ObjectCannotBeUpdated(ex.getLDAPErrorMessage(), "");
+ }
+ }
+
+ //deletes a node
+ //throws LDAPexception if node cannot be deleted (eg node is not a leaf)
+ public void delete(Path path) throws ObjectCannotBeUpdated
+ {
+ try {
+ LDAPLookupUtils.delete(getConnection(),path.getDN()+Path.mLocalPath);
+ } catch (LDAPException ex) {
+ throw new ObjectCannotBeUpdated(ex.getLDAPErrorMessage(), "");
+ }
+ if (path instanceof DomainPath) {
+ EntityProxyManager.sendProxyEvent(new ProxyMessage(ProxyMessage.NA, path.toString(), ProxyMessage.DELETED));
+ }
+ }
+
+ //change specs, add boolean alias leaf context
+ protected void checkLDAPContext(Path path)
+ throws LDAPException
+ {
+ String dn = path.getFullDN();
+ if (!LDAPLookupUtils.exists(getConnection(),dn))
+ {
+ String listDN[] = path.getPath();
+ String name = "cn="+ path.getRoot() + "," + Path.mLocalPath;
+ int i=0;
+ while (i<listDN.length-1)
+ {
+ name= "cn="+listDN[i]+","+name;
+ if (!LDAPLookupUtils.exists(getConnection(),name))
+ {
+ try
+ {
+ //create cristalcontext
+ Logger.msg(8,"LDAPLookup::addLDAPContext() context added " + name);
+ LDAPLookupUtils.createCristalContext(getConnection(), name);
+ }
+ catch (Exception ex)
+ {
+ Logger.error("LDAPLookup::addContext() " + ex);
+ }
+ }
+ i++;
+ }
+ }
+ }
+ public void createBootTree()
+ {
+ Logger.msg(8,"Initializing LDAP Boot tree");
+
+ //create org
+ LDAPLookupUtils.createOrganizationContext(getConnection(), Path.mGlobalPath);
+ //create root
+ LDAPLookupUtils.createCristalContext(getConnection(), Path.mRootPath);
+ //create local
+ LDAPLookupUtils.createCristalContext(getConnection(), Path.mLocalPath);
+ }
+
+ public void install() throws LDAPException
+ {
+ createBootTree();
+ initTree( Resource.getTextResource("boot/LDAPboot.txt"));
+ }
+
+ public void initTree(String bootFile)
+ {
+ Logger.msg(8,"Verifying Cristal LDAP roots");
+ StringTokenizer strTokenizer = new StringTokenizer(bootFile, "\n\r");
+ while (strTokenizer.hasMoreTokens())
+ {
+ String line = strTokenizer.nextToken();
+ Logger.msg(8,"Checking " + line+Path.mLocalPath);
+ LDAPLookupUtils.createCristalContext(getConnection(), line+Path.mLocalPath);
+ }
+
+ }
+
+ //typically search for cn=barcode
+ public Enumeration search(Path start, String filter)
+ {
+ Logger.msg(8,"LDAPLookup::search() From " + start.getDN() + " for cn=" + filter );
+ return search(start.getFullDN(),"cn="+LDAPLookupUtils.escapeSearchFilter(filter));
+ }
+
+ protected Enumeration search(String startDN, int scope, String filter, LDAPSearchConstraints searchCons)
+ {
+ Logger.msg(8,"Searching for "+filter+" in "+startDN);
+ searchCons.setMaxResults(0);
+ String[] attr = { LDAPConnection.ALL_USER_ATTRS };
+ try
+ {
+ LDAPSearchResults res = getConnection().search(LDAPLookupUtils.escapeDN(startDN),scope,
+ filter,attr,false,searchCons);
+ return new LDAPPathSet(res);
+ }
+ catch (LDAPException ex)
+ {
+ Logger.error("LDAPException::LDAPLookup::search() " + ex.toString());
+ return new LDAPPathSet();
+ }
+ }
+ //typically search for (any filter combination)
+ public Enumeration search(String startDN,String filter)
+ {
+ LDAPSearchConstraints searchCons = new LDAPSearchConstraints();
+ searchCons.setBatchSize(0);
+ searchCons.setDereference(LDAPSearchConstraints.DEREF_NEVER);
+ return search(startDN,LDAPConnection.SCOPE_SUB,filter,searchCons);
+ }
+
+ public Enumeration searchEntities(Path start) {
+ LDAPSearchConstraints searchCons = new LDAPSearchConstraints();
+ searchCons.setBatchSize(0);
+ searchCons.setDereference(LDAPSearchConstraints.DEREF_SEARCHING);
+ return search(start.getFullDN(), LDAPConnection.SCOPE_SUB, "objectClass=cristalentity", searchCons);
+ }
+
+ public Enumeration searchAliases(DomainPath start) {
+ LDAPSearchConstraints searchCons = new LDAPSearchConstraints();
+ searchCons.setBatchSize(0);
+ searchCons.setDereference(LDAPSearchConstraints.DEREF_NEVER);
+ return search(start.getFullDN(), LDAPConnection.SCOPE_SUB, "objectClass=aliasObject", searchCons);
+ }
+
+ public boolean exists(Path path) {
+ return LDAPLookupUtils.exists(getConnection(), path.getFullDN());
+ }
+
+ public Class getEntityClass(Path path) throws ObjectNotFoundException {
+ String[] attr = { LDAPConnection.ALL_USER_ATTRS };
+ try {
+ LDAPEntry anEntry=getConnection().read(path.getDN()+Path.mLocalPath,attr);
+ String type = LDAPLookupUtils.getFirstAttributeValue(anEntry, "objectClass");
+ if (type.equals("cristalentity"))
+ return TraceableEntity.class;
+ else if (type.equals("cristalagent"))
+ return ActiveEntity.class;
+ else
+ throw new ObjectNotFoundException("Not an entity", "");
+
+ } catch (LDAPException ex) {
+ if (ex.getResultCode() == LDAPException.NO_SUCH_OBJECT)
+ throw new ObjectNotFoundException("Entity does not exist", "");
+ Logger.error(ex);
+ throw new ObjectNotFoundException("Error getting entity class", "");
+ }
+ }
+
+ /** converts an LDAPentry to a Path object
+ * Note that the search producing the entry should have retrieved the attrs
+ * 'ior' and 'uniquemember'
+ * @throws ObjectNotFoundException
+ * @throws ObjectNotFoundException
+ */
+ protected Path nodeToPath(LDAPEntry entry) throws InvalidEntityPathException, ObjectNotFoundException
+ {
+ String dn = entry.getDN();
+
+ // extract syskey
+ int entityKey = -1;
+ try {
+ String entityKeyStr = LDAPLookupUtils.getFirstAttributeValue(entry,"intsyskey");
+ entityKey = Integer.parseInt(entityKeyStr);
+ } catch (Exception e) { }
+
+ // extract IOR
+ org.omg.CORBA.Object ior = null;
+ try {
+ String stringIOR = LDAPLookupUtils.getFirstAttributeValue(entry,"ior");
+ ior = Gateway.getORB().string_to_object(stringIOR);
+ } catch (ObjectNotFoundException e2) { }
+
+ /* Find the right path class */
+ Path thisPath;
+ if (LDAPLookupUtils.existsAttributeValue(entry,"objectclass","cristalagent"))
+ { //cristalagent
+ String agentID = LDAPLookupUtils.getFirstAttributeValue(entry,"uid");
+ thisPath = new AgentPath(entityKey, agentID);
+ }
+
+ else if (LDAPLookupUtils.existsAttributeValue(entry,"objectclass","cristalrole"))
+ { //cristalrole
+ thisPath = new RolePath(LDAPDN.explodeDN(dn,true)[0],
+ LDAPLookupUtils.getFirstAttributeValue(entry, "jobList").equals("TRUE"));
+ }
+ else if (LDAPLookupUtils.existsAttributeValue(entry,"objectclass","aliasObject") ||
+ (LDAPLookupUtils.existsAttributeValue(entry,"objectclass","cristalcontext") && dn.endsWith(DomainPath.mTypeRoot)))
+ {
+ DomainPath domainPath = new DomainPath();
+ domainPath.setDN(dn);
+ thisPath = domainPath;
+ }
+ else if (LDAPLookupUtils.existsAttributeValue(entry,"objectclass","cristalentity") ||
+ (LDAPLookupUtils.existsAttributeValue(entry,"objectclass","cristalcontext") && dn.endsWith(EntityPath.mTypeRoot)))
+ {
+ if(dn.endsWith(EntityPath.mTypeRoot)) {
+ EntityPath entityPath;
+ if (entityKey != -1)
+ entityPath = new EntityPath(entityKey);
+ else {
+ entityPath = new EntityPath();
+ entityPath.setDN(dn);
+ }
+ thisPath = entityPath;
+ }
+ else
+ throw new ObjectNotFoundException("Entity found outside entity tree");
+ }
+ else
+ {
+ throw new ObjectNotFoundException("Unrecognised LDAP entry. Not a cristal entry");
+ }
+
+ //set IOR if we have one
+ if (ior!=null) thisPath.setIOR(ior);
+ return thisPath;
+ }
+}
diff --git a/source/com/c2kernel/lookup/LDAPLookupUtils.java b/source/com/c2kernel/lookup/LDAPLookupUtils.java
new file mode 100755
index 0000000..6516374
--- /dev/null
+++ b/source/com/c2kernel/lookup/LDAPLookupUtils.java
@@ -0,0 +1,317 @@
+/*
+ * Lookup helper class.
+ */
+
+package com.c2kernel.lookup;
+
+//import netscape.ldap.*;
+//import netscape.ldap.util.*;
+import com.c2kernel.common.ObjectAlreadyExistsException;
+import com.c2kernel.common.ObjectCannotBeUpdated;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.utils.Logger;
+import com.novell.ldap.LDAPAttribute;
+import com.novell.ldap.LDAPAttributeSet;
+import com.novell.ldap.LDAPConnection;
+import com.novell.ldap.LDAPDN;
+import com.novell.ldap.LDAPEntry;
+import com.novell.ldap.LDAPException;
+import com.novell.ldap.LDAPModification;
+import com.novell.ldap.LDAPSearchConstraints;
+import com.novell.ldap.LDAPSearchResults;
+
+/**
+ * @version $Revision: 1.74 $ $Date: 2006/03/03 13:52:21 $
+ * @author $Author: abranson $
+ */
+
+final public class LDAPLookupUtils
+{
+ static public LDAPEntry getEntry(LDAPConnection ld, String dn,int dereference)
+ throws ObjectNotFoundException
+ {
+ try {
+ LDAPSearchConstraints searchCons = new LDAPSearchConstraints();
+ searchCons.setBatchSize(0);
+ searchCons.setDereference(dereference);
+ LDAPEntry thisEntry = ld.read(dn,searchCons);
+ if (thisEntry != null) return thisEntry;
+ } catch (LDAPException ex) {
+ throw new ObjectNotFoundException("LDAP Exception: "+ex.getMessage(), "");
+ }
+ throw new ObjectNotFoundException(dn+" does not exist", "");
+
+ }
+
+ //Given a DN, return an LDAP Entry
+ static public LDAPEntry getEntry(LDAPConnection ld, String dn)
+ throws ObjectNotFoundException
+ {
+ return getEntry(ld, dn, LDAPSearchConstraints.DEREF_NEVER);
+ }
+
+ static public String getFirstAttributeValue(LDAPEntry anEntry, String attribute) throws ObjectNotFoundException
+ {
+ LDAPAttribute attr = anEntry.getAttribute(attribute);
+ if (attr==null)
+ throw new ObjectNotFoundException("No attributes named '"+attribute+"'", "");
+ return (String)attr.getStringValues().nextElement();
+ }
+
+ static public String[] getAllAttributeValues(LDAPEntry anEntry, String attribute) throws ObjectNotFoundException
+ {
+ LDAPAttribute attr = anEntry.getAttribute(attribute);
+ if (attr!=null)
+ return attr.getStringValueArray();
+
+ throw new ObjectNotFoundException("No attributes named '"+attribute+"'", "");
+
+ }
+
+ static public boolean existsAttributeValue(LDAPEntry anEntry, String attribute, String value)
+ {
+ LDAPAttribute attr = anEntry.getAttribute(attribute);
+ if (attr!=null)
+ {
+ String[] attrValues = new String[attr.size()];
+ attrValues = attr.getStringValueArray();
+ for (int i=0;i<attr.size();i++)
+ if (attrValues[i].equalsIgnoreCase(value))
+ return true;
+ }
+ return false;
+ }
+ static public boolean hasOneAttributeValue(LDAPEntry anEntry, String attribute) throws ObjectNotFoundException
+ {
+ int j =0;
+ LDAPAttribute attr = anEntry.getAttribute(attribute);
+ if (attr==null)
+ throw new ObjectNotFoundException("No attributes named '"+attribute+"'", "");
+ j=attr.size();
+ return j==1;
+ }
+
+ //this is for a single-valued attribute
+ static public void setAttributeValue(LDAPConnection ld, LDAPEntry anEntry, String attribute, String newValue)
+ throws ObjectNotFoundException, ObjectCannotBeUpdated
+ {
+ try {
+ if (!hasOneAttributeValue(anEntry, attribute))
+ throw new ObjectCannotBeUpdated("Attribute "+attribute + " of entry " + anEntry.getDN()+" has more than one value", "");
+ } catch (ObjectNotFoundException ex) {
+ addAttributeValue(ld, anEntry, attribute, newValue);
+ }
+ try
+ {
+ ld.modify(anEntry.getDN(),new LDAPModification(LDAPModification.REPLACE,new LDAPAttribute(attribute,newValue)));
+ }
+ catch (LDAPException ex)
+ {
+ Logger.error(ex);
+ throw new ObjectCannotBeUpdated("Attribute " + attribute + " of entry " + anEntry.getDN() + " could not be modified", "");
+ }
+ }
+
+
+ //this is for a multi-valued attribute eg uniqueMember
+ static public void addAttributeValue(LDAPConnection ld, LDAPEntry anEntry, String attribute, String value)
+ throws ObjectCannotBeUpdated
+ {
+ try
+ {
+ ld.modify(anEntry.getDN(),new LDAPModification(LDAPModification.ADD, new LDAPAttribute(attribute,value)));
+ }
+ catch (LDAPException ex)
+ {
+ Logger.error(ex);
+ throw new ObjectCannotBeUpdated("Attribute " + attribute + " of entry " + anEntry.getDN() + " could not be added.", "");
+ }
+ }
+
+ //this is for a multi-valued attribute eg uniqueMember
+ static public void removeAttributeValue(LDAPConnection ld, LDAPEntry anEntry, String attribute, String value)
+ throws ObjectCannotBeUpdated
+ {
+ try
+ {
+ ld.modify(anEntry.getDN(),new LDAPModification(LDAPModification.DELETE,new LDAPAttribute(attribute,value)));
+ }
+ catch (LDAPException ex)
+ {
+ Logger.error(ex);
+ throw new ObjectCannotBeUpdated("Attribute " + attribute + " of entry " + anEntry.getDN() + " could not be deleted", "");
+ }
+ }
+
+ static public boolean exists(LDAPConnection ld, String name)
+ {
+ try {
+ String[] attr = { LDAPConnection.NO_ATTRS };
+ LDAPEntry anEntry=ld.read(name,attr);
+ if (anEntry!=null)
+ return true;
+ } catch (LDAPException ex)
+ {
+ Logger.debug(9, "LDAPLookupUtils.exists("+name+": "+ex.getMessage());
+ return false;
+ }
+ return false;
+ }
+
+ static public void addEntry(LDAPConnection ld,LDAPEntry myEntry)
+ throws ObjectAlreadyExistsException, LDAPException
+ {
+ try
+ {
+ ld.add( myEntry );
+ }
+ catch( LDAPException ex ) {
+ if (ex.getResultCode() == LDAPException.ENTRY_ALREADY_EXISTS)
+ throw new ObjectAlreadyExistsException("Entry already present." + myEntry.getDN(), "");
+ throw ex;
+ }
+ }
+
+ static public boolean hasChildren(LDAPConnection ld, String dn, String filter)
+ {
+ String[] attr = { LDAPConnection.NO_ATTRS };
+ LDAPSearchConstraints searchCons = new LDAPSearchConstraints();
+ searchCons.setBatchSize(0);
+ searchCons.setDereference(LDAPSearchConstraints.DEREF_NEVER);
+
+ try
+ {
+ LDAPSearchResults res = ld.search(dn,LDAPConnection.SCOPE_ONE,filter,attr,false,searchCons);
+ if (res.hasMore())
+ return true;
+ }
+ catch (LDAPException ex)
+ {
+ Logger.error(ex);
+ }
+ return false;
+ }
+
+ //returns list of dns
+ static public String[] getChildrenDNs(LDAPConnection ld, String dn, String filter)
+ {
+ String[] result = null;
+ String[] attr = { LDAPConnection.NO_ATTRS };
+ LDAPSearchConstraints searchCons = new LDAPSearchConstraints();
+ searchCons.setBatchSize(0);
+ searchCons.setDereference(LDAPSearchConstraints.DEREF_NEVER);
+
+ try
+ {
+ LDAPSearchResults res = ld.search(dn,LDAPConnection.SCOPE_ONE,filter,attr,false,searchCons);
+ result = new String[res.getCount()];
+ int i=0;
+ while (res.hasMore())
+ {
+ LDAPEntry findEntry=res.next();
+ if (findEntry!=null)
+ {
+ result[i++] = new String(findEntry.getDN());
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.error(ex);
+ }
+ return result;
+ }
+
+ static public void delete(LDAPConnection ld, String dn)
+ throws LDAPException
+ {
+ try
+ {
+ Logger.msg(7, "LDAPLookupUtils.delete() - "+dn);
+ ld.delete(dn);
+ }
+ catch (LDAPException ex)
+ {
+ Logger.error("LDAPLookupUtils.remove() - Cannot remove "+dn+": " + ex.getMessage());
+ throw ex;
+ }
+ }
+
+ //param dn is the DN of the name
+ //param name is the name of the node (also the RDN)
+ //example: cn=lab27,o=cern.ch lab27
+ //example: cn=product, cn=domain, cn=lab27, cn= cristal2, o=cern.ch product
+ static public void createCristalContext(LDAPConnection ld, String dn)
+ {
+ if (LDAPLookupUtils.exists(ld,dn))
+ return;
+ try
+ {
+ String name = LDAPDN.explodeDN(dn,true)[0];
+ LDAPAttributeSet attrs = new LDAPAttributeSet();
+ attrs.add(new LDAPAttribute("cn",name));
+ String objectclass_values[] = new String[1];
+ objectclass_values[0] = "cristalcontext";
+ if (name.equals("last"))
+ attrs.add(new LDAPAttribute("intsyskey", "0"));
+
+ attrs.add(new LDAPAttribute("objectclass",objectclass_values));
+
+ LDAPLookupUtils.addEntry(ld,new LDAPEntry(dn,attrs));
+ }
+ catch (Exception ex)
+ {
+ Logger.error("LDAPLookupUtils.createCristalContext() " + ex.toString());
+ }
+ }
+
+ static public void createOrganizationContext(LDAPConnection ld, String dn)
+ {
+ if (LDAPLookupUtils.exists(ld,dn))
+ return;
+
+ try
+ {
+ String name = LDAPDN.explodeDN(dn,true)[0];
+ LDAPAttributeSet attrs = new LDAPAttributeSet();
+ attrs.add(new LDAPAttribute("objectclass","top"));
+ attrs.add(new LDAPAttribute("objectclass","organization"));
+ attrs.add(new LDAPAttribute("o",name));
+ LDAPLookupUtils.addEntry(ld,new LDAPEntry(dn,attrs));
+ }
+ catch (Exception ex)
+ {
+ Logger.msg(ex.toString());
+ }
+ }
+ public static String escapeDN (String name) {
+ //From RFC 2253 and the / character for JNDI
+ final char[] META_CHARS = {'+', '"', '<', '>', ';', '/'};
+ String escapedStr = new String(name);
+
+ //Backslash is both a Java and an LDAP escape character, so escape it first
+ escapedStr = escapedStr.replaceAll("\\\\","\\\\");
+
+ //Positional characters - see RFC 2253
+ escapedStr = escapedStr.replaceAll("^#","\\\\#");
+ escapedStr = escapedStr.replaceAll("^ | $","\\\\ ");
+
+ for (int i=0;i < META_CHARS.length;i++) {
+ escapedStr = escapedStr.replaceAll("\\"+META_CHARS[i],"\\\\" + META_CHARS[i]);
+ }
+ Logger.msg(6, "LDAP DN "+name+" escaped to "+escapedStr);
+ return escapedStr;
+ }
+
+ public static String escapeSearchFilter (String filter) {
+ //From RFC 2254
+ String escapedStr = new String(filter);
+
+ escapedStr = escapedStr.replaceAll("\\\\","\\\\5c");
+ //escapedStr = escapedStr.replaceAll("\\*","\\\\2a"); // we need stars for searching
+ escapedStr = escapedStr.replaceAll("\\(","\\\\28");
+ escapedStr = escapedStr.replaceAll("\\)","\\\\29");
+ Logger.msg(6, "LDAP Search Filter "+filter+" escaped to "+escapedStr);
+ return escapedStr;
+ }
+}
diff --git a/source/com/c2kernel/lookup/LDAPPathSet.java b/source/com/c2kernel/lookup/LDAPPathSet.java
new file mode 100755
index 0000000..9c68c5c
--- /dev/null
+++ b/source/com/c2kernel/lookup/LDAPPathSet.java
@@ -0,0 +1,70 @@
+package com.c2kernel.lookup;
+
+import java.util.Enumeration;
+
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Logger;
+import com.novell.ldap.LDAPEntry;
+import com.novell.ldap.LDAPException;
+import com.novell.ldap.LDAPSearchResults;
+
+/**************************************************************************
+ *
+ * $Revision: 1.6 $
+ * $Date: 2005/12/01 14:23:14 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+
+
+public class LDAPPathSet implements Enumeration {
+ LDAPSearchResults results;
+ LDAPEntry nextEntry;
+
+ public LDAPPathSet() { // empty
+ results = null;
+ }
+
+ public LDAPPathSet(LDAPSearchResults results) {
+ this.results = results;
+ }
+
+ public boolean hasMoreElements() {
+ if (results == null) return false;
+ if (nextEntry != null) return true;
+ if (results.hasMore())
+ try {
+ nextEntry = results.next();
+ return true;
+ } catch (LDAPException ex) {
+ if (ex.getResultCode()!=32) {// no results
+ Logger.error(ex);
+ Logger.error("Error loading LDAP result set: "+ex.getMessage());
+ }
+ }
+ return false;
+ }
+
+ public Object nextElement() {
+ if (results == null) return null;
+ try {
+ if (nextEntry == null)
+ nextEntry = results.next();
+ Path nextPath = Gateway.getLDAPLookup().nodeToPath(nextEntry);
+ nextEntry = null;
+ return nextPath;
+ } catch (Exception ex) {
+ Logger.error("Error loading next path");
+ Logger.error(ex);
+ nextEntry = null;
+ if (hasMoreElements()) {
+ Logger.error("Skipping to next entry");
+ return nextElement();
+ }
+ else
+ return null;
+ }
+ }
+}
diff --git a/source/com/c2kernel/lookup/LDAPProperties.java b/source/com/c2kernel/lookup/LDAPProperties.java
new file mode 100755
index 0000000..e884a54
--- /dev/null
+++ b/source/com/c2kernel/lookup/LDAPProperties.java
@@ -0,0 +1,38 @@
+/*
+ * Directory Lookup Service
+*/
+
+package com.c2kernel.lookup;
+
+import com.c2kernel.process.Gateway;
+
+/**
+ * @version $Revision: 1.16 $ $Date: 2005/10/12 12:51:54 $
+ * @author $Author: abranson $
+ */
+public class LDAPProperties
+{
+ public String mGlobalPath = null; //o=cern.ch
+ public String mRootPath = null; //cn=cristal2
+ public String mLocalPath = null; //cn=lab27
+ public String mPort = null;
+ public String mHost = null;
+ public String mUser = null;
+ public String mPassword = null;
+
+ public LDAPProperties()
+ {
+ mGlobalPath = Gateway.getProperty( "LDAP.GlobalPath" );
+ mRootPath = Gateway.getProperty( "LDAP.RootPath" );
+ mLocalPath = Gateway.getProperty( "LDAP.LocalPath" );
+ mPort = Gateway.getProperty( "LDAP.port" );
+ mHost = Gateway.getProperty( "LDAP.host" );
+ mUser = Gateway.getProperty( "LDAP.user" );
+ mPassword = Gateway.getProperty( "LDAP.password" );
+
+ mRootPath += "," + mGlobalPath;
+ mLocalPath += "," + mRootPath;
+
+ }
+}
+
diff --git a/source/com/c2kernel/lookup/LDAPPropertyManager.java b/source/com/c2kernel/lookup/LDAPPropertyManager.java
new file mode 100755
index 0000000..4e1883e
--- /dev/null
+++ b/source/com/c2kernel/lookup/LDAPPropertyManager.java
@@ -0,0 +1,118 @@
+package com.c2kernel.lookup;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+import com.c2kernel.common.ObjectCannotBeUpdated;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.property.Property;
+import com.c2kernel.utils.Logger;
+import com.novell.ldap.LDAPAttribute;
+import com.novell.ldap.LDAPEntry;
+
+/**************************************************************************
+ *
+ * $Revision: 1.3 $
+ * $Date: 2006/03/03 13:52:21 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class LDAPPropertyManager {
+ /**
+ *
+ */
+ protected LDAPLookup ldap;
+
+ public LDAPPropertyManager(LDAPLookup ldap) {
+ super();
+ this.ldap = ldap;
+ }
+
+ /**
+ * @param thisEntity - EntityPath of the subject entity
+ * @return
+ * @throws ObjectNotFoundException
+ */
+ public boolean hasProperties(EntityPath thisEntity) throws ObjectNotFoundException {
+ LDAPEntry entityEntry = LDAPLookupUtils.getEntry(ldap.getConnection(), thisEntity.getFullDN());
+ return entityEntry.getAttribute("cristalprop") != null;
+ }
+
+ /**
+ * @param thisEntity - EntityPath of the subject entity
+ * @return array of Property
+ * @throws ObjectNotFoundException
+ */
+ public String[] getPropertyNames(EntityPath thisEntity) throws ObjectNotFoundException {
+ LDAPEntry entityEntry = LDAPLookupUtils.getEntry(ldap.getConnection(), thisEntity.getFullDN());
+ ArrayList propbag = new ArrayList();
+ LDAPAttribute props = entityEntry.getAttribute("cristalprop");
+ for (Enumeration e = props.getStringValues(); e.hasMoreElements();) {
+ String thisProp = (String)e.nextElement();
+ propbag.add(thisProp.substring(0, thisProp.indexOf(':')));
+ }
+
+ String[] retArr = new String[props.size()];
+ return (String[])propbag.toArray(retArr);
+ }
+
+ /**
+ * @param thisEntity - EntityPath of the subject entity
+ * @param propName - the name of the property to retrieve
+ * @return String the property value
+ * @throws ObjectNotFoundException
+ */
+ public String getPropertyValue(EntityPath thisEntity, String name) throws ObjectNotFoundException {
+ LDAPEntry entityEntry = LDAPLookupUtils.getEntry(ldap.getConnection(), thisEntity.getFullDN());
+ return getPropertyAttr(entityEntry, name);
+ }
+
+ /**
+ * @param thisEntity - EntityPath of the subject entity
+ * @param name - the property name to delete
+ * @throws ObjectNotFoundException
+ * @throws ObjectCannotBeUpdated
+ */
+ public void deleteProperty(EntityPath thisEntity, String name) throws ObjectNotFoundException, ObjectCannotBeUpdated {
+ LDAPEntry entityEntry = LDAPLookupUtils.getEntry(ldap.getConnection(), thisEntity.getFullDN());
+ String propVal = getPropertyAttr(entityEntry, name);
+ Logger.msg(6, "LDAPLookupUtils.deleteProperty("+name+") - Deleting property");
+ LDAPLookupUtils.removeAttributeValue(ldap.getConnection(), entityEntry, "cristalprop", name+":"+propVal);
+ }
+
+ /**
+ * @param thisEntity - EntityPath of the subject entity
+ * @param prop - the property to store
+ * @throws ObjectNotFoundException
+ * @throws ObjectCannotBeUpdated
+ */
+ public void setProperty(EntityPath thisEntity, Property prop) throws ObjectNotFoundException, ObjectCannotBeUpdated {
+ LDAPEntry entityEntry = LDAPLookupUtils.getEntry(ldap.getConnection(), thisEntity.getFullDN());
+ try {
+ String propVal = getPropertyAttr(entityEntry, prop.getName());
+ Logger.msg(6, "LDAPLookupUtils.setProperty("+prop.getName()+") - Removing old value '"+propVal+"'");
+ LDAPLookupUtils.removeAttributeValue(ldap.getConnection(), entityEntry, "cristalprop", prop.getName()+":"+propVal);
+ } catch (ObjectNotFoundException ex) {
+ Logger.msg(6, "LDAPLookupUtils.setProperty("+prop.getName()+") - creating new property.");
+ }
+ Logger.msg(6, "LDAPLookupUtils.setProperty("+prop.getName()+") - setting to '"+prop.getValue()+"'");
+ LDAPLookupUtils.addAttributeValue(ldap.getConnection(), entityEntry, "cristalprop", prop.getName()+":"+prop.getValue());
+ }
+
+ private String getPropertyAttr(LDAPEntry myEntry, String propName) throws ObjectNotFoundException {
+ // delete existing props
+ LDAPAttribute props = myEntry.getAttribute("cristalprop");
+ if (props == null)
+ throw new ObjectNotFoundException("Property "+propName+" does not exist", "");
+ String propPrefix = propName+":";
+ for (Enumeration e = props.getStringValues(); e.hasMoreElements();) {
+ String val = (String)e.nextElement();
+ if (val.toLowerCase().startsWith(propPrefix.toLowerCase()))
+ return val.substring(propPrefix.length());
+ }
+ throw new ObjectNotFoundException("Property "+propName+" does not exist", "");
+ }
+
+}
diff --git a/source/com/c2kernel/lookup/LDAPRoleManager.java b/source/com/c2kernel/lookup/LDAPRoleManager.java
new file mode 100755
index 0000000..a9b6b23
--- /dev/null
+++ b/source/com/c2kernel/lookup/LDAPRoleManager.java
@@ -0,0 +1,199 @@
+package com.c2kernel.lookup;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+import com.c2kernel.common.ObjectAlreadyExistsException;
+import com.c2kernel.common.ObjectCannotBeUpdated;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.utils.Logger;
+import com.novell.ldap.*;
+
+/**************************************************************************
+ *
+ * $Revision: 1.1 $
+ * $Date: 2005/04/26 06:48:12 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+// public static final String codeRevision = "$Revision: 1.1 $ $Date: 2005/04/26 06:48:12 $ $Author: abranson $";
+public class LDAPRoleManager {
+
+ /**
+ *
+ */
+ LDAPLookup mLdap;
+ private String mRolePath;
+ private String mEntityPath;
+
+ public LDAPRoleManager(LDAPLookup ldap, String rolePath, String entityPath) {
+ super();
+ this.mLdap = ldap;
+ this.mRolePath = rolePath;
+ this.mEntityPath = entityPath;
+ }
+
+ //NOTE: A role must have at LEAST 1 userDN, cannot be empty...
+ //Creates a cristalRole
+ //CristalRole is-a specialized CristalContext which contains multi-valued uniqueMember attribute pointing to cristalagents
+ public RolePath createRole(String roleName, boolean jobList)
+ throws ObjectAlreadyExistsException, ObjectCannotBeUpdated
+ {
+
+ // create the role
+ RolePath rolePath = new RolePath(roleName, jobList);
+ String roleDN = rolePath.getFullDN();
+ LDAPEntry roleNode;
+ try
+ {
+ roleNode = LDAPLookupUtils.getEntry(mLdap.getConnection(), rolePath.getFullDN());
+ throw new ObjectAlreadyExistsException();
+ } catch (ObjectNotFoundException ex) { }
+
+ //create CristalRole if it does not exist
+ roleNode = new LDAPEntry(roleDN, rolePath.createAttributeSet());
+ try {
+ LDAPLookupUtils.addEntry(mLdap.getConnection(),roleNode);
+ } catch (LDAPException e) {
+ throw new ObjectCannotBeUpdated(e.getLDAPErrorMessage(), "");
+ }
+ return rolePath;
+
+
+ }
+ public void deleteRole(RolePath role) throws ObjectNotFoundException, ObjectCannotBeUpdated {
+ try {
+ LDAPLookupUtils.delete(mLdap.getConnection(), role.getFullDN());
+ } catch (LDAPException ex) {
+ throw new ObjectCannotBeUpdated("Could not remove role");
+ }
+ }
+
+ protected void addRole(AgentPath agent, RolePath role)
+ throws ObjectCannotBeUpdated, ObjectNotFoundException
+ {
+ LDAPEntry roleEntry = LDAPLookupUtils.getEntry(mLdap.getConnection(), role.getFullDN());
+ //add memberDN to uniqueMember if it is not yet a member
+ if (!LDAPLookupUtils.existsAttributeValue(roleEntry, "uniqueMember", agent.getFullDN()))
+ LDAPLookupUtils.addAttributeValue(mLdap.getConnection(), roleEntry, "uniqueMember", agent.getFullDN());
+ else
+ throw new ObjectCannotBeUpdated("Agent " + agent.getAgentName() + " already has role " + role.getName());
+ }
+
+ protected void removeRole(AgentPath agent, RolePath role)
+ throws ObjectCannotBeUpdated, ObjectNotFoundException
+ {
+ LDAPEntry roleEntry = LDAPLookupUtils.getEntry(mLdap.getConnection(), role.getFullDN());
+ if (LDAPLookupUtils.existsAttributeValue(roleEntry, "uniqueMember", agent.getFullDN()))
+ LDAPLookupUtils.removeAttributeValue(mLdap.getConnection(), roleEntry, "uniqueMember", agent.getFullDN());
+ else
+ throw new ObjectCannotBeUpdated("Agent did not have that role");
+ }
+
+ protected boolean hasRole(AgentPath agent, RolePath role) {
+ String filter = "(&(objectclass=cristalrole)(uniqueMember="+agent.getFullDN()+")(cn="+role.getName()+"))";
+ LDAPSearchConstraints searchCons = new LDAPSearchConstraints();
+ searchCons.setBatchSize(0);
+ searchCons.setDereference(LDAPSearchConstraints.DEREF_NEVER );
+ Enumeration roles = mLdap.search(mRolePath,LDAPConnection.SCOPE_SUB,filter,searchCons);
+ return roles.hasMoreElements();
+ }
+
+ protected AgentPath[] getAgents(RolePath role)
+ throws ObjectNotFoundException
+ {
+ //get the roleDN entry, and its uniqueMember entry pointing to
+ LDAPEntry roleEntry;
+ try {
+ roleEntry = LDAPLookupUtils.getEntry(mLdap.getConnection(), role.getFullDN());
+ } catch (ObjectNotFoundException e) {
+ throw new ObjectNotFoundException("Role does not exist", "");
+ }
+
+ String[] res = LDAPLookupUtils.getAllAttributeValues(roleEntry,"uniqueMember");
+ ArrayList agents = new ArrayList();
+ for (int i=0; i<res.length; i++)
+ {
+ String userDN = res[i];
+ try {
+ LDAPEntry userEntry = LDAPLookupUtils.getEntry(mLdap.getConnection(), userDN);
+ AgentPath path = (AgentPath)mLdap.nodeToPath(userEntry);
+ agents.add(path);
+ } catch (ObjectNotFoundException ex) {
+ Logger.error("Agent "+res[i]+" does not exist");
+ } catch (InvalidEntityPathException ex) {
+ Logger.error("Agent "+res[i]+" is not a valid entity");
+ }
+ }
+ AgentPath[] usersList = new AgentPath[0];
+ usersList = (AgentPath[])agents.toArray(usersList);
+ return usersList;
+ }
+
+ //returns the role/s of a user
+ protected RolePath[] getRoles(AgentPath agentPath)
+ {
+ //search the mDomainPath tree uniqueMember=userDN
+ //filter = objectclass=cristalrole AND uniqueMember=userDN
+ String filter = "(&(objectclass=cristalrole)(uniqueMember="+agentPath.getFullDN()+"))";
+ LDAPSearchConstraints searchCons = new LDAPSearchConstraints();
+ searchCons.setBatchSize(0);
+ searchCons.setDereference(LDAPSearchConstraints.DEREF_NEVER );
+ Enumeration roles = mLdap.search(mRolePath,LDAPConnection.SCOPE_SUB,filter,searchCons);
+ ArrayList roleList = new ArrayList();
+
+ while(roles.hasMoreElements())
+ {
+ RolePath path = (RolePath) roles.nextElement();
+ roleList.add(path);
+ }
+ RolePath[] roleArr = new RolePath[roleList.size()];
+ roleArr = (RolePath[])roleList.toArray(roleArr);
+ return roleArr;
+ }
+
+ /**
+ * Utility for looking up a login name
+ *
+ * @param ld
+ * @param agentName
+ * @param baseDN
+ * @return
+ * @throws ObjectNotFoundException
+ */
+ public AgentPath getAgentPath(String agentName) throws ObjectNotFoundException
+ {
+ //search to get the userDN equivalent of the userID
+ LDAPSearchConstraints searchCons = new LDAPSearchConstraints();
+ searchCons.setBatchSize(0);
+ searchCons.setDereference(LDAPSearchConstraints.DEREF_NEVER );
+ String filter = "(&(objectclass=cristalagent)(uid="+agentName+"))";
+ Enumeration res = mLdap.search(mEntityPath,LDAPConnection.SCOPE_SUB,filter,searchCons);
+ if (!res.hasMoreElements())
+ throw new ObjectNotFoundException("Agent not found");
+ Path result = (Path)res.nextElement();
+ if (result instanceof AgentPath)
+ return (AgentPath)result;
+ else
+ throw new ObjectNotFoundException("Entry was not an Agent");
+ }
+
+ public RolePath getRolePath(String roleName) throws ObjectNotFoundException
+ {
+ LDAPSearchConstraints searchCons = new LDAPSearchConstraints();
+ searchCons.setBatchSize(0);
+ searchCons.setDereference(LDAPSearchConstraints.DEREF_NEVER );
+ String filter = "(&(objectclass=cristalrole)(cn="+roleName+"))";
+ Enumeration res = mLdap.search(mRolePath,LDAPConnection.SCOPE_SUB,filter,searchCons);
+ if (!res.hasMoreElements())
+ throw new ObjectNotFoundException("Role not found");
+ Path result = (Path)res.nextElement();
+ if (result instanceof RolePath)
+ return (RolePath)result;
+ else
+ throw new ObjectNotFoundException("Entry was not a Role");
+ }
+
+}
diff --git a/source/com/c2kernel/lookup/LegacyLDAPPropertyManager.java b/source/com/c2kernel/lookup/LegacyLDAPPropertyManager.java
new file mode 100755
index 0000000..62653fb
--- /dev/null
+++ b/source/com/c2kernel/lookup/LegacyLDAPPropertyManager.java
@@ -0,0 +1,70 @@
+package com.c2kernel.lookup;
+
+import com.c2kernel.common.ObjectCannotBeUpdated;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.property.Property;
+import com.c2kernel.utils.Logger;
+import com.novell.ldap.LDAPAttribute;
+import com.novell.ldap.LDAPAttributeSet;
+import com.novell.ldap.LDAPDN;
+import com.novell.ldap.LDAPEntry;
+import com.novell.ldap.LDAPException;
+
+public class LegacyLDAPPropertyManager extends LDAPPropertyManager {
+
+ public LegacyLDAPPropertyManager(LDAPLookup ldap) {
+ super(ldap);
+ }
+
+ public void deleteProperty(EntityPath thisEntity, String name) throws ObjectNotFoundException, ObjectCannotBeUpdated {
+ try {
+ LDAPLookupUtils.delete(ldap.getConnection(), "cn="+name+","+thisEntity.getFullDN());
+ } catch (LDAPException ex) {
+ Logger.error("Error deleting prop "+name+" from "+thisEntity.getSysKey());
+ Logger.error(ex);
+ }
+ }
+
+ public String[] getPropertyNames(EntityPath thisEntity) throws ObjectNotFoundException {
+ String props[]= LDAPLookupUtils.getChildrenDNs(ldap.getConnection(), thisEntity.getFullDN(), "objectclass=cristalproperty");
+ String names[] = new String[props.length];
+ for (int i=0; i<props.length;i++)
+ names[i] = new String(LDAPDN.explodeDN(props[i],true)[0]);
+ return names;
+ }
+
+ public String getPropertyValue(EntityPath thisEntity, String name) throws ObjectNotFoundException {
+ LDAPEntry anEntry = LDAPLookupUtils.getEntry(ldap.getConnection(),"cn="+name+","+thisEntity.getFullDN());
+ if (anEntry==null)
+ throw new ObjectNotFoundException("LDAPLookup: Property "+name+" not found in "+thisEntity.getSysKey(), "");
+ return LDAPLookupUtils.getFirstAttributeValue(anEntry,"propval");
+ }
+
+ public boolean hasProperties(EntityPath thisEntity) throws ObjectNotFoundException {
+ return LDAPLookupUtils.hasChildren(ldap.getConnection(), thisEntity.getFullDN(), "objectclass=cristalproperty" );
+ }
+
+ public void setProperty(EntityPath thisEntity, Property prop) throws ObjectNotFoundException, ObjectCannotBeUpdated {
+ try {
+ LDAPEntry anEntry = LDAPLookupUtils.getEntry(ldap.getConnection(),"cn="+prop.getName()+","+thisEntity.getFullDN());
+ String currentVal = LDAPLookupUtils.getFirstAttributeValue(anEntry,"propval");
+ if (currentVal == null || !currentVal.equals(prop.getValue()) )
+ //change the propvalue if the prop.getValue() is not the same value in LDAP
+ LDAPLookupUtils.setAttributeValue(ldap.getConnection(), anEntry,"propval",prop.getValue());
+
+ } catch (ObjectNotFoundException ex) {
+ LDAPAttributeSet attrSet = new LDAPAttributeSet();
+ attrSet.add(new LDAPAttribute("objectclass","cristalproperty"));
+ attrSet.add(new LDAPAttribute("cn",prop.getName()));
+ if (prop.getValue()!=null && prop.getValue().length()!=0)
+ attrSet.add(new LDAPAttribute("propval",prop.getValue()));
+ LDAPEntry newEntry = new LDAPEntry("cn="+prop.getName()+","+thisEntity.getFullDN(),attrSet);
+ try {
+ LDAPLookupUtils.addEntry(ldap.getConnection(),newEntry);
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new ObjectCannotBeUpdated(e.getMessage(), "");
+ }
+ }
+ }
+}
diff --git a/source/com/c2kernel/lookup/NextKeyManager.java b/source/com/c2kernel/lookup/NextKeyManager.java
new file mode 100755
index 0000000..04581c0
--- /dev/null
+++ b/source/com/c2kernel/lookup/NextKeyManager.java
@@ -0,0 +1,72 @@
+package com.c2kernel.lookup;
+
+import com.c2kernel.common.ObjectCannotBeUpdated;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.novell.ldap.LDAPEntry;
+
+/**************************************************************************
+ *
+ * $Revision: 1.2 $
+ * $Date: 2005/04/27 13:47:24 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+// public static final String codeRevision = "$Revision: 1.2 $ $Date: 2005/04/27 13:47:24 $ $Author: abranson $";
+public class NextKeyManager {
+
+ LDAPLookup ldap;
+ String lastKeyPath;
+
+ public NextKeyManager(LDAPLookup ldap, String lastKeyPath) {
+ super();
+ this.ldap = ldap;
+ this.lastKeyPath = lastKeyPath;
+ }
+
+ public synchronized EntityPath generateNextEntityKey()
+ throws ObjectCannotBeUpdated, ObjectNotFoundException
+ {
+ LDAPEntry lastKeyEntry = LDAPLookupUtils.getEntry(ldap.getConnection(),lastKeyPath);
+ EntityPath lastKey = getLastEntityPath();
+
+ try {
+ lastKey.setSysKey(lastKey.getSysKey()+1);
+ } catch (InvalidEntityPathException ex) {
+ throw new ObjectCannotBeUpdated("Invalid syskey "+(lastKey.getSysKey()+1)+". Maybe centre is full.");
+ }
+ //set the last key
+ writeLastEntityKey(lastKey.getSysKey());
+
+ return lastKey;
+ }
+
+ public synchronized AgentPath generateNextAgentKey()
+ throws ObjectCannotBeUpdated, ObjectNotFoundException {
+ EntityPath newEntity = generateNextEntityKey();
+ return new AgentPath(newEntity);
+ }
+
+ public void writeLastEntityKey(int sysKey) throws ObjectCannotBeUpdated, ObjectNotFoundException {
+ LDAPEntry lastKeyEntry = LDAPLookupUtils.getEntry(ldap.getConnection(),lastKeyPath);
+ LDAPLookupUtils.setAttributeValue(ldap.getConnection(), lastKeyEntry,"intsyskey",Integer.toString(sysKey));
+ }
+
+ public EntityPath getLastEntityPath() throws ObjectNotFoundException
+ {
+ LDAPEntry lastKeyEntry = LDAPLookupUtils.getEntry(ldap.getConnection(),lastKeyPath);
+ String lastKey = LDAPLookupUtils.getFirstAttributeValue(lastKeyEntry,"intsyskey");
+ try {
+ int sysKey = Integer.parseInt(lastKey);
+ EntityPath sysPath = new EntityPath(sysKey);
+ return sysPath;
+ } catch (InvalidEntityPathException ex) {
+ throw new ObjectNotFoundException("Invalid syskey. Maybe centre is full.");
+ } catch (NumberFormatException ex) {
+ throw new ObjectNotFoundException("Invalid syskey in lastkey.");
+ }
+
+ }
+
+}
diff --git a/source/com/c2kernel/lookup/Path.java b/source/com/c2kernel/lookup/Path.java
new file mode 100755
index 0000000..b189910
--- /dev/null
+++ b/source/com/c2kernel/lookup/Path.java
@@ -0,0 +1,301 @@
+/**************************************************************************
+ * Path.java
+ *
+ * $Revision: 1.27 $
+ * $Date: 2006/01/17 07:49:58 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.lookup;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+
+import com.c2kernel.common.ObjectCannotBeUpdated;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.process.Gateway;
+import com.novell.ldap.LDAPAttributeSet;
+import com.novell.ldap.LDAPConnection;
+import com.novell.ldap.LDAPSearchConstraints;
+
+
+/**
+* @version $Revision: 1.27 $ $Date: 2006/01/17 07:49:58 $
+* @author $Author: abranson $
+**/
+public abstract class Path implements Serializable
+{
+ public static final String delim = "/";
+
+ // types
+ public static final short UNKNOWN = 0;
+ public static final short CONTEXT = 1;
+ public static final short ENTITY = 2;
+
+ // invalid int key
+ public static final int INVALID = -1;
+
+ protected String[] mPath = new String[0];
+
+ // slash delimited path
+ protected String mStringPath = null;
+ // entity or context
+ protected short mType = CONTEXT;
+ // LDAP dn
+ protected String mDN = null;
+ // int syskey (only valid for entity SystemPaths)
+ protected int mSysKey = INVALID;
+
+ // ior is stored in here when it is resolved
+ protected org.omg.CORBA.Object mIOR = null;
+ //
+ // needed for unusual subclass constructors
+
+ protected static String mGlobalPath; //cern.ch
+ protected static String mRootPath; //cristal2
+ protected static String mLocalPath; //lab27
+
+ public Path() {
+ }
+
+ /*
+ * Creates an empty path
+ */
+ public Path(short type)
+ {
+ mType = type;
+ }
+
+ /*
+ * Creates a path with an arraylist of the path (big endian)
+ */
+ public Path(String[] path, short type) {
+ setPath(path);
+ mType = type;
+ }
+
+ /*
+ * Creates a path from a slash separated string (big endian)
+ */
+ public Path(String path, short type) {
+ setPath(path);
+ mType = type;
+ }
+
+ /*
+ * Create a path by appending a child string to an existing path
+ */
+ public Path(Path parent, String child, short type) {
+ String[] oldPath = parent.getPath();
+ mPath = new String[oldPath.length+1];
+ for (int i=0; i<oldPath.length; i++)
+ mPath[i] = oldPath[i];
+ mPath[oldPath.length] = child;
+ mType = type;
+ }
+
+ /*
+ * Create a path by appending a child and inheriting the type
+ */
+ public Path(Path parent, String child) {
+ this(parent, child, UNKNOWN);
+ }
+ /*************************************************************************/
+
+ // Setters
+
+ /* string array path e.g. { "Product", "Crystal", "Barrel", "2L", "331013013348" }
+ * system/domain node ABSENT
+ */
+ public void setPath(String[] path)
+ {
+ mStringPath = null;
+ mDN = null;
+ mPath = (String[])path.clone();
+ mSysKey = INVALID;
+ }
+
+ /* string path e.g. /system/d000/d000/d001
+ * system/domain node PRESENT
+ */
+ public void setPath(String path)
+ {
+ ArrayList newPath = new ArrayList();
+ StringTokenizer tok = new StringTokenizer(path, delim);
+ if (tok.hasMoreTokens()) {
+ String first = tok.nextToken();
+ if (!first.equals(getRoot()))
+ newPath.add(first);
+ while (tok.hasMoreTokens())
+ newPath.add(tok.nextToken());
+ }
+
+ mPath = (String[])(newPath.toArray(mPath));
+ mStringPath = null;
+ mDN = null;
+ mSysKey = INVALID;
+ }
+
+ // lookup sets the IOR
+ public void setIOR(org.omg.CORBA.Object IOR) {
+ mIOR = IOR;
+ if (IOR == null) mType = Path.CONTEXT;
+ else mType = Path.ENTITY;
+ }
+
+ /* clone another path object
+ */
+ public void setPath(Path path)
+ {
+ mStringPath = null;
+ mDN = null;
+ mPath = (String[])(path.getPath().clone());
+ mSysKey = INVALID;
+ }
+
+ /* LDAP dn e.g. cn=6L,cn=Barrel,cn=Crystal,cn=Product,cn=domain,
+ * system/domain node PRESENT
+ * trailing comma
+ */
+ public void setDN(String dn)
+ {
+ // strip off root path components
+ String root = "cn="+getRoot()+",";
+ if (dn.endsWith(mLocalPath))
+ dn = dn.substring(0, dn.lastIndexOf(mLocalPath));
+
+ if (dn.endsWith(root))
+ dn = dn.substring(0, dn.lastIndexOf(root));
+
+ ArrayList newPath = new ArrayList();
+ StringTokenizer tok = new StringTokenizer(dn, ",");
+ while (tok.hasMoreTokens()) {
+ String nextPath = tok.nextToken();
+ if (nextPath.indexOf("cn=") == 0)
+ newPath.add(0, nextPath.substring(3));
+ else
+ break;
+ }
+ mPath = (String[])(newPath.toArray(mPath));
+ mSysKey = INVALID;
+ mStringPath = null;
+ mDN = dn+root;
+ }
+
+ /*************************************************************************/
+
+ /*
+ * Getter Methods
+ */
+
+ // root is defined as 'domain', 'entity' or 'system' in subclasses
+ public abstract String getRoot();
+
+ public String[] getPath()
+ {
+ return mPath;
+ }
+
+ public String getString()
+ {
+ if (mStringPath == null) {
+ StringBuffer stringPathBuffer = new StringBuffer("/").append(getRoot());
+ for (int i=0; i<mPath.length; i++)
+ stringPathBuffer.append(delim).append(mPath[i]);
+ mStringPath = stringPathBuffer.toString();
+ }
+ return mStringPath;
+ }
+
+ public String getDN() {
+ if (mDN == null) {
+ StringBuffer dnBuffer = new StringBuffer();
+ for (int i=mPath.length-1; i>=0; i--)
+ dnBuffer.append("cn=").append(mPath[i]).append(",");
+ dnBuffer.append("cn="+getRoot()+",");
+ mDN = dnBuffer.toString();
+ }
+ return mDN;
+ }
+
+ public String getFullDN() {
+ return getDN()+mLocalPath;
+ }
+
+ public boolean exists() {
+ return Gateway.getLDAPLookup().exists(this);
+ }
+
+ /** Queries the lookup for the IOR
+ */
+
+ public org.omg.CORBA.Object getIOR() {
+ org.omg.CORBA.Object newIOR = null;
+ if (mIOR==null) { // if not cached try to resolve
+ LDAPLookup myLookup = Gateway.getLDAPLookup();
+ try {
+ newIOR = myLookup.getIOR(this);
+ } catch (ObjectNotFoundException ex) {
+ newIOR = null;
+ }
+ setIOR(newIOR);
+ }
+ return mIOR;
+ }
+
+ public String toString() {
+ return getString();
+ }
+
+ public short getType() {
+ return mType;
+ }
+
+ public int getSysKey() {
+ return mSysKey;
+ }
+
+ public Enumeration getChildren() {
+ String filter = "objectclass=*";
+ LDAPSearchConstraints searchCons = new LDAPSearchConstraints();
+ searchCons.setBatchSize(10);
+ searchCons.setDereference(LDAPSearchConstraints.DEREF_FINDING );
+ return Gateway.getLDAPLookup().search(getFullDN(), LDAPConnection.SCOPE_ONE,filter,searchCons);
+ }
+
+ public Path find(String name) throws ObjectNotFoundException {
+ Enumeration e = Gateway.getLDAPLookup().search(this, name);
+ if (e.hasMoreElements()) {
+ Path thisPath =(Path)e.nextElement();
+ if (e.hasMoreElements())
+ throw new ObjectNotFoundException("More than one match for "+name, "");
+ return thisPath;
+ }
+ throw new ObjectNotFoundException("No match for "+name, "");
+ }
+
+ public abstract EntityPath getEntity() throws ObjectNotFoundException;
+
+ public abstract LDAPAttributeSet createAttributeSet() throws ObjectCannotBeUpdated;
+
+ public boolean equals( Object path )
+ {
+ return toString().equals(path.toString());
+ }
+
+ public int hashCode() {
+ return toString().hashCode();
+ }
+
+ public String dump() {
+ StringBuffer comp = new StringBuffer("Components: { ");
+ for (int i=0; i<mPath.length; i++)
+ comp.append("'").append(mPath[i]).append("' ");
+ return "Path - dump(): "+comp.toString()+"}\n dn="+getDN()+"\n string="+toString()+"\n int="+getSysKey()+"\n type="+mType;
+ }
+}
+
diff --git a/source/com/c2kernel/lookup/RolePath.java b/source/com/c2kernel/lookup/RolePath.java
new file mode 100755
index 0000000..df26eae
--- /dev/null
+++ b/source/com/c2kernel/lookup/RolePath.java
@@ -0,0 +1,117 @@
+/**************************************************************************
+ * DomainPath.java
+ *
+ * $Revision: 1.7 $
+ * $Date: 2005/04/26 06:48:12 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.lookup;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import com.c2kernel.common.ObjectCannotBeUpdated;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Logger;
+import com.novell.ldap.LDAPAttribute;
+import com.novell.ldap.LDAPAttributeSet;
+
+
+
+/**
+* @version $Revision: 1.7 $ $Date: 2005/04/26 06:48:12 $
+* @author $Author: abranson $
+**/
+public class RolePath extends DomainPath
+{
+ /**
+ *
+ */
+
+ private boolean hasJobList = false;
+
+ public RolePath(String roleName) {
+ super(new DomainPath("agent"), roleName);
+ }
+
+ public RolePath(String roleName, boolean jobList) {
+ this(roleName);
+ hasJobList = jobList;
+ }
+
+ /**
+ * @return Returns the hasJobList.
+ */
+ public boolean hasJobList() {
+ return hasJobList;
+ }
+ /**
+ * @param hasJobList The hasJobList to set.
+ */
+ public void setHasJobList(boolean hasJobList) {
+ this.hasJobList = hasJobList;
+ }
+
+
+ public void checkType() {
+ mType = CONTEXT;
+ }
+
+ public Enumeration getChildren() {
+ AgentPath[] agents = getAgentsWithRole();
+ Vector children = new Vector(agents.length);
+ for (int i = 0; i < agents.length; i++)
+ children.add(i, agents[i]);
+ return children.elements();
+ }
+
+ public AgentPath[] getAgentsWithRole() {
+ try {
+ return Gateway.getLDAPLookup().getRoleManager().getAgents(this);
+ } catch (ObjectNotFoundException ex) {
+ Logger.error("Cannot retrieve agent list. Role "+getName()+" does not exist in LDAP");
+ return new AgentPath[0];
+ }
+ }
+
+ public void addAgent(AgentPath agent) throws ObjectCannotBeUpdated, ObjectNotFoundException {
+ Gateway.getLDAPLookup().getRoleManager().addRole(agent, this);
+ }
+
+ public void removeAgent(AgentPath agent) throws ObjectCannotBeUpdated, ObjectNotFoundException {
+ Gateway.getLDAPLookup().getRoleManager().removeRole(agent, this);
+ }
+
+ public String dump() {
+ StringBuffer comp = new StringBuffer("Components: { ");
+ for (int i=0; i<mPath.length; i++)
+ comp.append("'").append(mPath[i]).append("' ");
+
+ return "Path - dump(): "+
+ comp.toString()+
+ "}\n dn="+
+ getDN()+
+ "\n string="+
+ toString()+
+ "\n type="+
+ mType+
+ "\n name="+
+ getName()+
+ "\n ";
+ }
+
+ public LDAPAttributeSet createAttributeSet()
+ {
+ LDAPAttributeSet attrs = new LDAPAttributeSet();
+ attrs.add(new LDAPAttribute("objectclass","cristalrole"));
+ String jobListString = hasJobList?"TRUE":"FALSE";
+ attrs.add(new LDAPAttribute("jobList",jobListString));
+ attrs.add(new LDAPAttribute("cn", getName()));
+ return attrs;
+ }
+}
+
diff --git a/source/com/c2kernel/persistency/ClusterStorage.java b/source/com/c2kernel/persistency/ClusterStorage.java
new file mode 100755
index 0000000..f0d28a4
--- /dev/null
+++ b/source/com/c2kernel/persistency/ClusterStorage.java
@@ -0,0 +1,104 @@
+
+package com.c2kernel.persistency;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.persistency.outcome.Outcome;
+import com.c2kernel.persistency.outcome.Viewpoint;
+import com.c2kernel.utils.Logger;
+
+/** Interface for persistency managers of entities.
+ A Cluster is defined as a path under the item
+ Each ClusterStorage must support get() and getClusterContents() for clusters they return READ and READWRITE from queryClusterSupport
+ and put() and delete() for clusters they return WRITE and READWRITE from queryClusterSupport().
+ Unsupported operations should throw a ClusterStorageException.
+ If a cluster does not exist, get should return null, and delete should return
+ @version $Revision: 1.22 $ $Date: 2006/02/01 13:27:47 $
+ @author $Author: abranson $
+*/
+public abstract class ClusterStorage {
+
+ public static final short NONE = 0;
+ public static final short READ = 1;
+ public static final short WRITE = 2;
+ public static final short READWRITE = 3;
+
+ // Cluster types
+ public static final String ROOT = "";
+ public static final String PROPERTY = "Property";
+ public static final String COLLECTION = "Collection";
+ public static final String LIFECYCLE = "LifeCycle";
+ public static final String OUTCOME = "Outcome";
+ public static final String HISTORY = "AuditTrail";
+ public static final String VIEWPOINT = "ViewPoint";
+ public static final String JOB = "Job";
+
+ // connection maintenance
+ public abstract void open()
+ throws ClusterStorageException;
+ public abstract void close()
+ throws ClusterStorageException;
+
+ // introspection
+ public abstract short queryClusterSupport(String clusterType);
+ public abstract String getName();
+ // for addressing queries
+ public abstract String getId();
+
+
+ /** Quickly gets the first string of the slashed path */
+ public static String getClusterType(String path) {
+ try {
+ if (path == null || path.length() == 0) return ClusterStorage.ROOT;
+ int start = path.charAt(0) == '/' ? 1 : 0;
+ int end = path.indexOf('/', start + 1);
+ if (end == -1) end = path.length();
+ return path.substring(start, end);
+ } catch (Exception ex) {
+ Logger.error(ex);
+ return ClusterStorage.ROOT;
+ }
+ }
+
+ public static String getPath(C2KLocalObject obj) {
+ String root = obj.getClusterType();
+ if (root == null) return null; // no storage allowed
+ if (obj instanceof Outcome) {
+ Outcome oc = (Outcome)obj;
+ return root+"/"+oc.getSchemaType()+"/"+oc.getSchemaVersion()+"/"+oc.getName();
+ }
+ else if (obj instanceof Viewpoint) {
+ Viewpoint vp = (Viewpoint)obj;
+ return root+"/"+vp.getSchemaName()+"/"+vp.getName();
+ }
+ else
+ return root+"/"+obj.getName();
+ }
+
+ /* object manipulation */
+
+ // retrieve object by path
+ public abstract C2KLocalObject get(Integer sysKey, String path)
+ throws ClusterStorageException;
+ // store object by path
+ public abstract void put(Integer sysKey, C2KLocalObject obj)
+ throws ClusterStorageException;
+ // delete cluster
+ public abstract void delete(Integer sysKey, String path)
+ throws ClusterStorageException;
+
+ // db specific queries
+ public Object query(Object query)
+ throws ClusterStorageException {
+ throw new ClusterStorageException("Query not supported on this storage");
+ }
+
+ public String queryToXML(String query, boolean genericFormat)
+ throws ClusterStorageException {
+ throw new ClusterStorageException("Query not supported on this storage");
+ }
+
+
+ // directory listing
+ public abstract String[] getClusterContents(Integer sysKey, String path)
+ throws ClusterStorageException;
+
+}
diff --git a/source/com/c2kernel/persistency/ClusterStorageException.java b/source/com/c2kernel/persistency/ClusterStorageException.java
new file mode 100755
index 0000000..b51982c
--- /dev/null
+++ b/source/com/c2kernel/persistency/ClusterStorageException.java
@@ -0,0 +1,17 @@
+package com.c2kernel.persistency;
+
+/**
+ *
+ * @version $Revision: 1.2 $ $Date: 2003/07/14 07:57:06 $
+ * @author $Author: abranson $
+ */
+
+public class ClusterStorageException extends Exception {
+ public ClusterStorageException() {
+ super();
+ }
+ public ClusterStorageException(String s) {
+ super(s);
+ }
+
+}
diff --git a/source/com/c2kernel/persistency/ClusterStorageManager.java b/source/com/c2kernel/persistency/ClusterStorageManager.java
new file mode 100755
index 0000000..5309f33
--- /dev/null
+++ b/source/com/c2kernel/persistency/ClusterStorageManager.java
@@ -0,0 +1,369 @@
+package com.c2kernel.persistency;
+
+import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.entity.proxy.EntityProxyManager;
+import com.c2kernel.entity.proxy.ProxyMessage;
+import com.c2kernel.persistency.outcome.Outcome;
+import com.c2kernel.persistency.outcome.Viewpoint;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.SoftCache;
+
+/**
+ * instantiates ClusterStorages listed in properties file All read/write requests to storage pass through this object, which
+ * can query the capabilities of each declared storage, and channel requests accordingly. Transaction based.
+ *
+ * * @version $Revision: 1.62 $ $Date: 2006/02/01 13:27:46 $
+ * @author $Author: abranson $
+ */
+public class ClusterStorageManager {
+ HashMap allStores = new HashMap();
+ String[] clusterPriority;
+ HashMap clusterWriters = new HashMap();
+ HashMap clusterReaders = new HashMap();
+ // we don't need a soft cache for the top level cache - the proxies and entities clear that when reaped
+ HashMap memoryCache = new HashMap();
+ boolean ready = false;
+
+ /**
+ * Initialises all ClusterStorage handlers listed by class name in the property "ClusterStorages"
+ * This property is usually process specific, and so should be in the server/client.conf and not the connect file.
+ */
+ public ClusterStorageManager() throws ClusterStorageException {
+ String allClusters = Gateway.getProperty("ClusterStorage");
+ if (allClusters == null || allClusters.equals("")) {
+ Logger.warning("ClusterStorageManager.init() - no ClusterStorages defined. No persistency!");
+ return;
+ }
+ StringTokenizer tok = new StringTokenizer(allClusters, ",");
+ clusterPriority = new String[tok.countTokens()];
+ int clusterNo = 0;
+ ArrayList rootStores = new ArrayList();
+ while (tok.hasMoreTokens()) {
+ ClusterStorage newStorage = null;
+ String newStorageClass = tok.nextToken();
+ try {
+ try {
+ newStorage = (ClusterStorage)(Class.forName(newStorageClass).newInstance());
+ } catch (ClassNotFoundException ex2) {
+ newStorage = (ClusterStorage)(Class.forName("com.c2kernel.persistency."+newStorageClass).newInstance());
+ }
+ newStorage.open();
+ Logger.msg(5, "ClusterStorageManager.init() - Cluster storage " + newStorageClass +
+ " initialised successfully.");
+ allStores.put(newStorage.getId(), newStorage);
+ rootStores.add(newStorage);
+ clusterPriority[clusterNo++] = newStorage.getId();
+
+ } catch (ClusterStorageException ex) {
+ Logger.error(ex);
+ throw new ClusterStorageException("ClusterStorageManager.init() - Error initialising storage handler " + newStorageClass +
+ ": " + ex.getMessage());
+ } catch (ClassNotFoundException ex) {
+ throw new ClusterStorageException("ClusterStorageManager.init() - The cluster storage handler class " + newStorageClass +
+ " could not be found.");
+ } catch (InstantiationException ex) {
+ throw new ClusterStorageException("ClusterStorageManager.init() - The cluster storage handler class " + newStorageClass +
+ " could not be instantiated.");
+ } catch (IllegalAccessException ex) {
+ throw new ClusterStorageException("ClusterStorageManager.init() - The cluster storage handler class " + newStorageClass +
+ " was not allowed to be instantiated.");
+ }
+ }
+ clusterReaders.put(ClusterStorage.ROOT, rootStores); // all storages are queried for clusters at the root level
+ ready = true;
+ }
+
+ public void close() {
+ for (Iterator iter = allStores.values().iterator(); iter.hasNext();) {
+ ClusterStorage thisStorage = (ClusterStorage)iter.next();
+ try {
+ thisStorage.close();
+ } catch (ClusterStorageException ex) {
+ Logger.error(ex);
+ }
+ }
+ ready = false;
+ }
+
+ /**
+ * Returns the loaded storage that declare that they can handle writing or reading the specified cluster name (e.g.
+ * Collection, Property) Must specify if the request is a read or a write.
+ */
+ private ArrayList findStorages(String clusterType, boolean forWrite) {
+
+ if (!ready) {
+ Logger.error("ClusterStorageManager.findStorages() - called before init!");
+ return null;
+ }
+
+ // choose the right cache for readers or writers
+ HashMap cache;
+ if (forWrite)
+ cache = clusterWriters;
+ else
+ cache = clusterReaders;
+
+ // check to see if we've been asked to do this before
+ if (cache.containsKey(clusterType))
+ return (ArrayList)cache.get(clusterType);
+
+ // not done yet, we'll have to query them all
+ Logger.msg(7, "ClusterStorageManager.findStorages() - finding storage for "+clusterType+" forWrite:"+forWrite);
+ ArrayList useableStorages = new ArrayList();
+ for (int i = 0; i < clusterPriority.length; i++) {
+ ClusterStorage thisStorage = (ClusterStorage)allStores.get(clusterPriority[i]);
+ short requiredSupport = forWrite ? ClusterStorage.WRITE : ClusterStorage.READ;
+ if ((thisStorage.queryClusterSupport(clusterType) & requiredSupport) == requiredSupport) {
+ Logger.msg(7, "ClusterStorageManager.findStorages() - Got "+thisStorage.getName());
+ useableStorages.add(thisStorage);
+ }
+ }
+ cache.put(clusterType, useableStorages);
+ return useableStorages;
+ }
+
+ /**
+ * Retrieves the ids of the next level of a cluster
+ * Does not look in any currently open transactions.
+ */
+ public String[] getClusterContents(Integer sysKey, String path) throws ClusterStorageException {
+ //String[] retArr = new String[0];
+ ArrayList contents = new ArrayList();
+ // get all readers
+ String type = ClusterStorage.getClusterType(path);
+ Logger.msg(8, "ClusterStorageManager.getClusterContents() - Finding contents of "+path);
+ ArrayList readers = findStorages(ClusterStorage.getClusterType(path), false);
+ // try each in turn until we get a result
+ for (Iterator i = readers.iterator(); i.hasNext();) {
+ ClusterStorage thisReader = (ClusterStorage)i.next();
+ try {
+ String[] thisArr = thisReader.getClusterContents(sysKey, path);
+ if (thisArr != null) {
+ for (int j = 0; j < thisArr.length; j++)
+ if (!contents.contains(thisArr[j])) {
+ Logger.msg(9, "ClusterStorageManager.getClusterContents() - "+thisReader.getName()+" reports "+thisArr[j]);
+ contents.add(thisArr[j]);
+ }
+ }
+ } catch (ClusterStorageException e) {
+ Logger.error("ClusterStorageManager.getClusterContents() - reader " + thisReader.getName() +
+ " could not retrieve contents of " + sysKey + "/" + path + ": " + e.getMessage());
+ }
+ }
+
+ String[] retArr = new String[0];
+ retArr = (String[])contents.toArray(retArr);
+ return retArr;
+ }
+
+ /** Internal get method. Retrieves clusters from ClusterStorages & maintains the memory cache */
+ public C2KLocalObject get(Integer sysKeyIntObj, String path) throws ClusterStorageException, ObjectNotFoundException {
+ C2KLocalObject result;
+ // check cache first
+ SoftCache sysKeyMemCache = null;
+ if (memoryCache.containsKey(sysKeyIntObj)) {
+ sysKeyMemCache = (SoftCache)memoryCache.get(sysKeyIntObj);
+ synchronized(sysKeyMemCache) {
+ C2KLocalObject obj = (C2KLocalObject)sysKeyMemCache.get(path);
+ if (obj != null) {
+ Logger.msg(7, "ClusterStorageManager.get() - found "+sysKeyIntObj+"/"+path+" in memcache");
+ return obj;
+ }
+ }
+ }
+
+ // special case - loading viewpoint contents
+ if (path.startsWith(ClusterStorage.VIEWPOINT) &&
+ path.endsWith("/data")) {
+ StringTokenizer tok = new StringTokenizer(path,"/");
+ if (tok.countTokens() == 4) { // to not catch viewpoints called 'data'
+ Outcome data = null;
+ Viewpoint view = (Viewpoint)get(sysKeyIntObj, path.substring(0, path.lastIndexOf("/")));
+ if (view != null)
+ data = view.getOutcome();
+ return data;
+ }
+ }
+
+ // else try each reader in turn until we find it
+ ArrayList readers = findStorages(ClusterStorage.getClusterType(path), false);
+ for (Iterator i = readers.iterator(); i.hasNext(); ) {
+ ClusterStorage thisReader = (ClusterStorage)i.next();
+ try {
+ result = thisReader.get(sysKeyIntObj, path);
+ Logger.msg(7, "ClusterStorageManager.get() - reading "+path+" from "+thisReader.getName() + " for intkey=" + sysKeyIntObj);
+ if (result != null) { // got it!
+ // store it in the cache
+ if (sysKeyMemCache == null) { // create cache if needed
+ sysKeyMemCache = new SoftCache(0);
+ synchronized (memoryCache) {
+ memoryCache.put(sysKeyIntObj, sysKeyMemCache);
+ }
+ }
+ synchronized(sysKeyMemCache) {
+ sysKeyMemCache.put(path, result);
+ }
+ // then return it
+ return result;
+ }
+ } catch (ClusterStorageException e) {
+ Logger.msg(7, "ClusterStorageManager.get() - reader " + thisReader.getName() + " could not retrieve " + sysKeyIntObj +
+ "/" + path + ": " + e.getMessage());
+ }
+ }
+ throw new ObjectNotFoundException("ClusterStorageManager.get() - Path " + path + " not found in " + sysKeyIntObj, "");
+ }
+
+ /** Internal put method. Creates or overwrites a cluster in all writers. Used when committing transactions. */
+ public void put(Integer sysKeyIntObj, C2KLocalObject obj) throws ClusterStorageException {
+ String path = ClusterStorage.getPath(obj);
+ ArrayList writers = findStorages(ClusterStorage.getClusterType(path), true);
+ for (Iterator i = writers.iterator(); i.hasNext(); ) {
+ ClusterStorage thisWriter = (ClusterStorage)i.next();
+ try {
+ Logger.msg(7, "ClusterStorageManager.put() - writing "+path+" to "+thisWriter.getName());
+ thisWriter.put(sysKeyIntObj, obj);
+ } catch (ClusterStorageException e) {
+ Logger.error("ClusterStorageManager.put() - writer " + thisWriter.getName() + " could not store " +
+ sysKeyIntObj + "/" + path + ": " + e.getMessage());
+ throw e;
+ }
+ }
+ // put in mem cache if that worked
+ SoftCache sysKeyMemCache;
+ if (memoryCache.containsKey(sysKeyIntObj))
+ sysKeyMemCache = (SoftCache)memoryCache.get(sysKeyIntObj);
+ else {
+ sysKeyMemCache = new SoftCache();
+ synchronized (memoryCache) {
+ memoryCache.put(sysKeyIntObj, sysKeyMemCache);
+ }
+ }
+
+ synchronized(sysKeyMemCache) {
+ sysKeyMemCache.put(path, obj);
+ }
+
+ if (Logger.doLog(9)) dumpCacheContents(9);
+
+ // transmit proxy event
+ EntityProxyManager.sendProxyEvent( new ProxyMessage(sysKeyIntObj.intValue(), path, ProxyMessage.ADDED));
+ }
+
+ /** Deletes a cluster from all writers */
+ public void remove(Integer sysKeyIntObj, String path) throws ClusterStorageException {
+ ArrayList writers = findStorages(ClusterStorage.getClusterType(path), true);
+ for (Iterator i = writers.iterator(); i.hasNext(); ) {
+ ClusterStorage thisWriter = (ClusterStorage)i.next();
+ try {
+ Logger.msg(7, "ClusterStorageManager.delete() - removing "+path+" from "+thisWriter.getName());
+ thisWriter.delete(sysKeyIntObj, path);
+ } catch (ClusterStorageException e) {
+ Logger.error("ClusterStorageManager.delete() - writer " + thisWriter.getName() + " could not delete " + sysKeyIntObj +
+ "/" + path + ": " + e.getMessage());
+ throw e;
+ }
+ }
+
+ if (memoryCache.containsKey(sysKeyIntObj)) {
+ SoftCache sysKeyMemCache = (SoftCache)memoryCache.get(sysKeyIntObj);
+ synchronized (sysKeyMemCache) {
+ sysKeyMemCache.remove(path);
+ }
+ }
+
+
+ // transmit proxy event
+ EntityProxyManager.sendProxyEvent( new ProxyMessage(sysKeyIntObj.intValue(), path, ProxyMessage.DELETED));
+ }
+
+ public void clearCache(Integer sysKeyIntObj, String path) {
+ Logger.msg(7, "CSM.clearCache() - removing "+sysKeyIntObj+"/"+path);
+
+ if (memoryCache.containsKey(sysKeyIntObj)) {
+ SoftCache sysKeyMemCache = (SoftCache)memoryCache.get(sysKeyIntObj);
+ synchronized(sysKeyMemCache) {
+ for (Iterator iter = sysKeyMemCache.keySet().iterator(); iter.hasNext();) {
+ String thisPath = (String)iter.next();
+ if (thisPath.startsWith(path)) {
+ Logger.msg(7, "CSM.clearCache() - removing "+sysKeyIntObj+"/"+thisPath);
+ iter.remove();
+ }
+ }
+ }
+ }
+ }
+
+ public void clearCache(Integer sysKeyIntObj) {
+
+ Logger.msg(5, "CSM.clearCache() - removing entire cache of "+sysKeyIntObj);
+
+ if (memoryCache.containsKey(sysKeyIntObj)) {
+ synchronized (memoryCache) {
+ if (Logger.doLog(6)) {
+ SoftCache sysKeyMemCache = (SoftCache)memoryCache.get(sysKeyIntObj);
+ int size = sysKeyMemCache.size();
+ Logger.msg(6, "CSM.clearCache() - "+size+" objects to remove.");
+ }
+ memoryCache.remove(sysKeyIntObj);
+ }
+ }
+ else
+ Logger.msg(6, "CSM.clearCache() - No objects cached");
+ }
+
+ public void clearCache() {
+ synchronized (memoryCache) {
+ memoryCache.clear();
+ }
+ Logger.msg(5, "CSM.clearCache() - cleared entire cache, "+memoryCache.size()+" entities.");
+ }
+
+ public void dumpCacheContents(int logLevel) {
+ if (!Logger.doLog(logLevel)) return;
+ synchronized(memoryCache) {
+ for (Iterator iter = memoryCache.keySet().iterator(); iter.hasNext();) {
+ Integer sysKey = (Integer) iter.next();
+ Logger.msg(logLevel, "Cached Objects of Entity "+sysKey);
+ SoftCache sysKeyMemCache = (SoftCache)memoryCache.get(sysKey);
+ try {
+ synchronized(sysKeyMemCache) {
+ for (Iterator iterator = sysKeyMemCache.keySet().iterator();iterator.hasNext();) {
+ String path = (String) iterator.next();
+ try {
+ Logger.msg(logLevel, " Path "+path+": "+sysKeyMemCache.get(path).getClass().getName());
+ } catch (NullPointerException e) {
+ Logger.msg(logLevel, " Path "+path+": reaped");
+ }
+ }
+ }
+ } catch (ConcurrentModificationException ex) {
+ Logger.msg(logLevel, "Cache modified - aborting");
+ }
+ }
+ Logger.msg(logLevel, "Total number of cached entities: "+memoryCache.size());
+ }
+ }
+
+ public Object query(String id, Object query) throws ClusterStorageException {
+ ClusterStorage requiredStorage = (ClusterStorage)allStores.get(id);
+ if (requiredStorage == null)
+ throw new ClusterStorageException("Storage "+id+" not found.");
+ return requiredStorage.query(query);
+ }
+
+ public String queryToXML(String id, String query, boolean genericFormat) throws ClusterStorageException {
+ ClusterStorage requiredStorage = (ClusterStorage)allStores.get(id);
+ if (requiredStorage == null)
+ throw new ClusterStorageException("Storage "+id+" not found.");
+ return requiredStorage.queryToXML(query, genericFormat);
+ }
+}
diff --git a/source/com/c2kernel/persistency/LDAPClientReader.java b/source/com/c2kernel/persistency/LDAPClientReader.java
new file mode 100755
index 0000000..c40658e
--- /dev/null
+++ b/source/com/c2kernel/persistency/LDAPClientReader.java
@@ -0,0 +1,39 @@
+package com.c2kernel.persistency;
+
+import com.c2kernel.entity.C2KLocalObject;
+
+/** Allows clients to directly load properties and collections from the LDAP
+* so no CORBA calls need to be made during normal browsing
+*/
+
+public class LDAPClientReader extends LDAPClusterStorage {
+ // return all readwrite support as readonly
+ public short queryClusterSupport(String clusterType) {
+ return (short)(super.queryClusterSupport(clusterType) & READ);
+ }
+
+
+ /**
+ * @see com.c2kernel.persistency.ClusterStorage#delete(Integer, String)
+ */
+ public void delete(Integer sysKey, String path)
+ throws ClusterStorageException {
+ throw new ClusterStorageException("Writing not supported in ClientReader");
+ }
+
+ /**
+ * @see com.c2kernel.persistency.ClusterStorage#getName()
+ */
+ public String getName() {
+ return "LDAP Client Cluster Reader";
+ }
+
+ /**
+ * @see com.c2kernel.persistency.ClusterStorage#put(Integer, String, C2KLocalObject)
+ */
+ public void put(Integer sysKey, String path, C2KLocalObject obj)
+ throws ClusterStorageException {
+ throw new ClusterStorageException("Writing not supported in ClientReader");
+ }
+
+}
diff --git a/source/com/c2kernel/persistency/LDAPClusterStorage.java b/source/com/c2kernel/persistency/LDAPClusterStorage.java
new file mode 100755
index 0000000..8e159e0
--- /dev/null
+++ b/source/com/c2kernel/persistency/LDAPClusterStorage.java
@@ -0,0 +1,163 @@
+package com.c2kernel.persistency;
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.lookup.InvalidEntityPathException;
+import com.c2kernel.lookup.LDAPPropertyManager;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.property.Property;
+import com.c2kernel.utils.Logger;
+
+public class LDAPClusterStorage extends ClusterStorage {
+ LDAPPropertyManager ldapStore;
+
+ public void open() throws ClusterStorageException {
+ ldapStore = Gateway.getLDAPLookup().getPropManager();
+
+ }
+
+ public void close() throws ClusterStorageException {
+ }
+
+ // introspection
+ public short queryClusterSupport(String clusterType) {
+ if (clusterType.equals(PROPERTY))
+ return READWRITE;
+ else
+ return NONE;
+ }
+
+ public String getName() {
+ return "LDAP Cluster Storage";
+ }
+
+ public String getId() {
+ return "LDAP";
+ }
+
+ // retrieve object by path
+ public C2KLocalObject get(Integer sysKey, String path) throws ClusterStorageException {
+ Logger.msg(6, "LDAPClusterStorage.get() - "+sysKey+"/"+path);
+ StringTokenizer tok = new StringTokenizer(path, "/");
+ int pathLength = tok.countTokens();
+ if (pathLength != 2)
+ throw new ClusterStorageException("Path length was invalid: "+path);
+ String type = tok.nextToken();
+
+ EntityPath thisEntity;
+ try {
+ thisEntity = new EntityPath(sysKey.intValue());
+ } catch (InvalidEntityPathException e) {
+ throw new ClusterStorageException("Invalid Syskey:"+sysKey);
+ }
+
+ String objName = tok.nextToken();
+ C2KLocalObject newObj;
+
+ if (type.equals(PROPERTY)) {
+ try {
+ String value = ldapStore.getPropertyValue(thisEntity, objName);
+ Property newProperty = new Property();
+ newProperty.setName(objName);
+ newProperty.setValue(value);
+ newObj = newProperty;
+ } catch (ObjectNotFoundException ex) {
+ throw new ClusterStorageException("Property "+objName+" not found in "+sysKey);
+ }
+
+ }
+ else
+ throw new ClusterStorageException("Cluster type "+type+" not supported.");
+
+ return newObj;
+ }
+ // store object by path
+ public void put(Integer sysKey, C2KLocalObject obj) throws ClusterStorageException {
+ Logger.msg(6, "LDAPClusterStorage.put() - "+sysKey+"/"+ClusterStorage.getPath(obj));
+
+ String type = obj.getClusterType();
+
+ EntityPath thisEntity;
+ try {
+ thisEntity = new EntityPath(sysKey.intValue());
+ } catch (InvalidEntityPathException e) {
+ throw new ClusterStorageException("Invalid Syskey:"+sysKey);
+ }
+
+ if (type.equals(PROPERTY)) {
+ try {
+ ldapStore.setProperty(thisEntity, (Property)obj);
+ } catch (Exception e1) {
+ Logger.error(e1);
+ throw new ClusterStorageException("LDAPClusterStorage - could not write property");
+ }
+ }
+ else
+ throw new ClusterStorageException("Cluster type "+type+" not supported.");
+
+ }
+ // delete cluster
+ public void delete(Integer sysKey, String path) throws ClusterStorageException {
+ StringTokenizer tok = new StringTokenizer(path, "/");
+ int pathLength = tok.countTokens();
+ if (pathLength != 2)
+ throw new ClusterStorageException("Path length was invalid: "+path);
+ String type = tok.nextToken();
+
+ EntityPath thisEntity;
+ try {
+ thisEntity = new EntityPath(sysKey.intValue());
+ } catch (InvalidEntityPathException e) {
+ throw new ClusterStorageException("Invalid Syskey:"+sysKey);
+ }
+
+ if (type.equals(PROPERTY)) {
+ try {
+ ldapStore.deleteProperty(thisEntity, tok.nextToken());
+ } catch (Exception e1) {
+ Logger.error(e1);
+ throw new ClusterStorageException("LDAPClusterStorage - could not delete property");
+ }
+ }
+ else
+ throw new ClusterStorageException("Cluster type "+type+" not supported.");
+
+ }
+
+ /* navigation */
+
+ // directory listing
+ public String[] getClusterContents(Integer sysKey, String path) throws ClusterStorageException {
+ Logger.msg(6, "LDAPClusterStorage.getClusterContents() - "+sysKey+"/"+path);
+ StringTokenizer tok = new StringTokenizer(path, "/");
+ int pathLength = tok.countTokens();
+ if (pathLength > 1)
+ return new String[0];
+
+ String type = getClusterType(path);
+ try
+ {
+ EntityPath thisEntity = new EntityPath(sysKey.intValue());
+ if (type.equals(PROPERTY))
+ return ldapStore.getPropertyNames(thisEntity);
+ else
+ if (type.equals("")) { // root query
+ String[] allClusters = new String[0];
+ ArrayList clusterList = new ArrayList();
+ if (ldapStore.hasProperties(thisEntity))
+ clusterList.add(PROPERTY);
+ allClusters = (String[])clusterList.toArray(allClusters);
+ return allClusters;
+ }
+ else
+ throw new ClusterStorageException("Cluster type "+type+" not supported.");
+ } catch (InvalidEntityPathException e) {
+ throw new ClusterStorageException("Invalid Syskey:"+sysKey);
+ } catch (ObjectNotFoundException e) {
+ throw new ClusterStorageException("Entity "+sysKey+" does not exist");
+ }
+ }
+}
diff --git a/source/com/c2kernel/persistency/ProxyLoader.java b/source/com/c2kernel/persistency/ProxyLoader.java
new file mode 100755
index 0000000..d20fb2d
--- /dev/null
+++ b/source/com/c2kernel/persistency/ProxyLoader.java
@@ -0,0 +1,124 @@
+package com.c2kernel.persistency;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+
+import com.c2kernel.entity.AgentHelper;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.entity.ItemHelper;
+import com.c2kernel.entity.ManageableEntity;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.lookup.LDAPLookup;
+import com.c2kernel.persistency.outcome.Outcome;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.Logger;
+
+/** Used by proxies to load clusters by queryData from the Entity.
+* Last client storage - only used if not cached elsewhere
+*/
+
+public class ProxyLoader extends ClusterStorage {
+ HashMap entities = new HashMap();
+ LDAPLookup lookup;
+
+ public void open() throws ClusterStorageException {
+ lookup = Gateway.getLDAPLookup();
+ }
+
+ public void close() throws ClusterStorageException {
+ }
+ // introspection
+ public short queryClusterSupport(String clusterType) {
+ return READ;
+ }
+
+ public String getName() {
+ return "Proxy Cluster Loader";
+ }
+
+ public String getId() {
+ return "CORBA";
+ }
+
+ // retrieve object by path
+ public C2KLocalObject get(Integer sysKey, String path) throws ClusterStorageException {
+ try {
+ ManageableEntity thisEntity = getIOR(sysKey);
+ String type = getClusterType(path);
+
+ // fetch the xml from the item
+ String queryData = thisEntity.queryData(path);
+
+ if (queryData != null) {
+ if (type.equals(OUTCOME))
+ return new Outcome(path, queryData);
+ else
+ return (C2KLocalObject)CastorXMLUtility.unmarshall(queryData);
+ }
+ } catch (Exception e) {
+ //Logger.error(e);
+ throw new ClusterStorageException(e.getMessage());
+ }
+ return null;
+ }
+
+ // store object by path
+ public void put(Integer sysKey, C2KLocalObject obj) throws ClusterStorageException {
+ // not supported
+ throw new ClusterStorageException("Cannot write to items through the ProxyLoader");
+ }
+ // delete cluster
+ public void delete(Integer sysKey, String path) throws ClusterStorageException {
+ // not supported
+ throw new ClusterStorageException("Cannot write to items through the ProxyLoader");
+ }
+
+ /* navigation */
+
+ // directory listing
+ public String[] getClusterContents(Integer sysKey, String path) throws ClusterStorageException {
+ try {
+ ManageableEntity thisEntity = getIOR(sysKey);
+ String contents = thisEntity.queryData(path+"/all");
+ StringTokenizer tok = new StringTokenizer(contents, ",");
+ String[] result = new String[tok.countTokens()];
+ for (int i=0; i<result.length; i++)
+ result[i] = tok.nextToken();
+
+ return result;
+ } catch (Exception e) {
+ throw new ClusterStorageException(e.getMessage());
+ }
+ }
+
+ private ManageableEntity getIOR(Integer sysKey) throws ClusterStorageException {
+ if (entities.containsKey(sysKey)) {
+ // check the cache
+ Logger.msg(7, "ProxyLoader.getIOR() - "+sysKey+" cached.");
+ return (ManageableEntity)entities.get(sysKey);
+ }
+
+ try {
+ Logger.msg(7, "ProxyLoader.getIOR() - Resolving "+sysKey+".");
+
+ org.omg.CORBA.Object ior = lookup.getIOR(new EntityPath(sysKey.intValue()));
+
+ ManageableEntity thisEntity = null;
+ try {
+ thisEntity = ItemHelper.narrow(ior);
+ } catch (org.omg.CORBA.BAD_PARAM ex) {
+ try {
+ thisEntity = AgentHelper.narrow(ior);
+ } catch (org.omg.CORBA.BAD_PARAM ex2) {
+ throw new ClusterStorageException ("Could not narrow "+sysKey+" as a known Entity type");
+ }
+ }
+
+ Logger.msg(7, "ProxyLoader.getIOR() - Found "+sysKey+".");
+ entities.put(sysKey, thisEntity);
+ return thisEntity;
+ } catch (Exception e) {
+ throw new ClusterStorageException("Error narrowing "+sysKey+": "+e.getMessage());
+ }
+ }
+}
diff --git a/source/com/c2kernel/persistency/RemoteMap.java b/source/com/c2kernel/persistency/RemoteMap.java
new file mode 100755
index 0000000..ca9cbc4
--- /dev/null
+++ b/source/com/c2kernel/persistency/RemoteMap.java
@@ -0,0 +1,404 @@
+package com.c2kernel.persistency;
+
+import java.util.AbstractSet;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.entity.proxy.*;
+import com.c2kernel.entity.proxy.EntityProxyObserver;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Logger;
+
+/**
+ * Maps a storage cluster onto a java.util.Map
+ *
+ * @author Andrew Branson
+ * $Revision: 1.22 $
+ * $Date: 2006/03/03 13:52:21 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ */
+public class RemoteMap implements C2KLocalObject, Map {
+
+ protected static final boolean KEYS = false;
+ protected static final boolean VALUES = true;
+
+ private int mID=-1;
+ private String mName;
+ protected int mSysKey;
+ private String mPath = "";
+ protected String[] keys = null;
+ Object keyLock = new Object();
+ protected C2KLocalObject[] values = null;
+ TransactionManager storage;
+ EntityProxyObserver listener;
+ EntityProxy source;
+ Object mLocker; // if this remote map will participate in a transaction
+
+ public RemoteMap(int sysKey, String path, Object locker) {
+ mSysKey = sysKey;
+ mLocker = locker;
+
+ // split the path into path/name
+ int lastSlash = path.lastIndexOf("/");
+ mName = path.substring(lastSlash+1);
+ if (lastSlash>0) mPath = path.substring(0,lastSlash);
+
+ // see if the name is also a suitable id
+ try {
+ mID = Integer.parseInt(mName);
+ } catch (NumberFormatException e) {}
+ storage = Gateway.getStorage();
+
+ listener = new EntityProxyObserver() {
+ public void add(C2KLocalObject obj) {
+ synchronized (keyLock) {
+ if (keys == null) return;
+ boolean found = false;
+ for (int i=0; i<keys.length; i++) {
+ if (keys[i].equals(obj.getName())) { //replaced
+ values[i] = obj;
+ found = true;
+ break;
+ }
+ }
+
+ if (found == false) { // new
+ String[] newKeys = new String[keys.length+1];
+ C2KLocalObject[] newValues = new C2KLocalObject[keys.length+1];
+ System.arraycopy(keys, 0, newKeys, 0, keys.length);
+ if (values!=null) System.arraycopy(values, 0, newValues, 0, keys.length);
+ newKeys[newKeys.length-1] = obj.getName();
+ newValues[newValues.length-1] = obj;
+ keys = newKeys;
+ values = newValues;
+ }
+ }
+ }
+
+ public void remove(String id) {
+ synchronized (keyLock) {
+ if (keys == null) return;
+ boolean found = false;
+ for (int i=0; i<keys.length; i++) {
+ if (keys[i].equals(id)) { //replaced
+ String[] newKeys = new String[keys.length-1];
+ C2KLocalObject[] newValues = new C2KLocalObject[keys.length-1];
+ int pos = 0;
+ for (int j=0; j<keys.length;j++) {
+ if (i!=j) {
+ newKeys[pos] = keys[j];
+ newValues[pos++] = values[j];
+ }
+ }
+ keys = newKeys;
+ values = newValues;
+ break;
+ }
+ }
+ }
+ }
+ };
+
+ try {
+ source = Gateway.getProxyManager().getProxy(new EntityPath(sysKey));
+ source.subscribe(listener, path, false);
+ } catch (Exception ex) {
+ Logger.error("Error subscribing to remote map. Changes will not be received");
+ Logger.error(ex);
+ }
+ }
+
+ protected void loadKeys() throws ClusterStorageException {
+ synchronized(keyLock) {
+ keys = storage.getClusterContents(mSysKey, mPath+mName);
+ values = new C2KLocalObject[keys.length];
+ }
+ }
+
+ protected String[] getKeys() {
+ try {
+ if (keys == null) loadKeys();
+ } catch (ClusterStorageException e) {
+ Logger.error(e);
+ keys = new String[0];
+ }
+ return keys;
+ }
+
+ public synchronized int getLastId() {
+
+ synchronized (this) {
+ int lastID = -1;
+
+ String[] allIds = getKeys();
+
+ for (int i = 0; i < allIds.length; i++) {
+ try {
+ int thisID = Integer.parseInt(allIds[i]);
+ if (thisID > lastID) lastID = thisID;
+ } catch (NumberFormatException e) {
+ Logger.warning("RemoteMap.getLastID() - Cluster contained invalid id: "+allIds[i]);
+ }
+ }
+ Logger.msg(7, "RemoteMap.getLastID() - last id in "+mPath+mName+" of "+mSysKey+" is "+lastID);
+ return lastID;
+ }
+ }
+
+
+ // c2kLocalObject methods
+ public void setID(int id) { mID = id; }
+
+ public int getID() { return mID; }
+
+ public void setName(String name) { mName = name; }
+
+ public String getName() { return mName; }
+
+ /**
+ * Cannot be stored
+ */
+ public String getClusterType() {
+ return null;
+ }
+ /**
+ * @see java.util.Map#clear()
+ */
+ public synchronized void clear() {
+ keys = null;
+ }
+
+
+
+ /**
+ * @see java.util.Map#containsKey(Object)
+ */
+ public synchronized boolean containsKey(Object key) {
+ getKeys();
+ for (int i = 0; i < keys.length; i++) {
+ if (key.equals(keys[i]))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * This must retrieve all the values until a match is made.
+ * Very expensive, but if you must, you must.
+ * @see java.util.Map#containsValue(Object)
+ */
+ public synchronized boolean containsValue(Object value) {
+ getKeys();
+ synchronized(keyLock) {
+ if (values == null) values = new C2KLocalObject[keys.length];
+ for (int i = 0; i < keys.length; i++) {
+ try {
+ if (values[i] == null) values[i] = storage.get(mSysKey, mPath+mName+"/"+keys[i], mLocker);
+ if (value.equals(values[i])) return true;
+ } catch (ClusterStorageException ex) {
+ Logger.error(ex);
+ } catch (ObjectNotFoundException e) {
+ Logger.error(e);
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @see java.util.Map#entrySet()
+ */
+ public synchronized Set entrySet() {
+ return new RemoteMap.RemoteSet(this, KEYS);
+ }
+
+ /**
+ * @see java.util.Map#get(Object)
+ */
+ public synchronized Object get(Object key) {
+ getKeys();
+ synchronized(keyLock) {
+ if (values == null) values = new C2KLocalObject[keys.length];
+ try {
+ for (int i = 0; i < keys.length; i++) {
+ if (key.equals(keys[i])) {
+ if (values[i] == null)
+ values[i] = storage.get(mSysKey, mPath+mName+"/"+keys[i], mLocker);
+ return values[i];
+ }
+ }
+ } catch (ClusterStorageException e) {
+ Logger.error(e);
+ } catch (ObjectNotFoundException e) {
+ Logger.error(e);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @see java.util.Map#isEmpty()
+ */
+ public synchronized boolean isEmpty() {
+ return getKeys().length==0;
+ }
+
+ /**
+ * @see java.util.Map#keySet()
+ */
+ public synchronized Set keySet() {
+ return new RemoteMap.RemoteSet(this, KEYS);
+ }
+
+ /**
+ * Inserts the given object into the storage
+ * the key is ignored - it can be fetched from the value.
+ * @see java.util.Map#put(Object, Object)
+ */
+ public synchronized Object put(Object key, Object value) {
+ try {
+ C2KLocalObject newValue = (C2KLocalObject)value;
+ synchronized(keyLock) {
+ storage.put(mSysKey, newValue, mLocker);
+ keys = null; values = null;
+ }
+ } catch (ClusterStorageException e) {
+ Logger.error(e);
+ return null;
+ } catch (ClassCastException e) {
+ Logger.error("RemoteMap.put() - value was not a localobject, it was a "+value.getClass().getName());
+ return null;
+ }
+ return value;
+ }
+
+ /**
+ * @see java.util.Map#putAll(Map)
+ */
+ public synchronized void putAll(Map t) {
+ for (Iterator iter = t.keySet().iterator(); iter.hasNext();) {
+ Object key = iter.next();
+ put(key, t.get(key));
+ }
+ }
+
+ /**
+ * @see java.util.Map#remove(Object)
+ */
+ public synchronized Object remove(Object key) {
+ try {
+ synchronized(keyLock) {
+ storage.remove(mSysKey, mPath+mName+"/"+key, mLocker);
+ keys = null; values = null;
+ }
+ } catch (ClusterStorageException e) {
+ Logger.error(e);
+ }
+ return null;
+ }
+
+ /**
+ * @see java.util.Map#size()
+ */
+ public synchronized int size() {
+ return getKeys().length;
+ }
+
+ /**
+ * @see java.util.Map#values()
+ */
+ public synchronized Collection values() {
+ return new RemoteMap.RemoteSet(this, VALUES);
+ }
+
+ /**
+ * Basic implementation of Set and Collection to bridge to the Iterator
+ * Disallows all writes.
+ */
+
+ private class RemoteSet extends AbstractSet {
+ RemoteMap mParent;
+ boolean mMode;
+
+ public RemoteSet(RemoteMap parent, boolean mode) {
+ mParent = parent;
+ mMode = mode;
+ }
+
+ // no modifications allowed
+ public boolean add(Object o) {
+ throw new UnsupportedOperationException();
+ }
+ public boolean addAll(Collection c) {
+ throw new UnsupportedOperationException();
+ }
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+ public boolean remove(Object o) {
+ throw new UnsupportedOperationException();
+ }
+ public boolean removeAll(Collection c) {
+ throw new UnsupportedOperationException();
+ }
+ public boolean retainAll(Collection c) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Iterator iterator() {
+ return new RemoteIterator(mParent, mMode);
+ }
+
+ public int size() {
+ return mParent.size();
+ }
+
+ }
+ /**
+ * Iterator view on RemoteMap data. Doesn't preload anything.
+ * REVISIT: Will go strange if the RemoteMap is modified. Detect this and throw ConcurrentMod ex
+ */
+ private class RemoteIterator implements Iterator {
+ RemoteMap mParent;
+ boolean mMode;
+ String[] keyArr;
+ int pos;
+
+ public RemoteIterator(RemoteMap parent, boolean mode) {
+ mParent = parent;
+ mMode = mode;
+ keyArr = mParent.getKeys();
+ }
+
+ public boolean hasNext() {
+ return (pos<keyArr.length);
+ }
+
+ public Object next() {
+ if (pos == keyArr.length)
+ throw new NoSuchElementException();
+
+ if (mMode == KEYS)
+ return keyArr[pos++];
+ else
+ return mParent.get(keyArr[pos++]);
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ }
+
+
+
+
+}
diff --git a/source/com/c2kernel/persistency/TransactionManager.java b/source/com/c2kernel/persistency/TransactionManager.java
new file mode 100755
index 0000000..252c758
--- /dev/null
+++ b/source/com/c2kernel/persistency/TransactionManager.java
@@ -0,0 +1,334 @@
+package com.c2kernel.persistency;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.entity.agent.JobList;
+import com.c2kernel.events.History;
+import com.c2kernel.lookup.InvalidEntityPathException;
+import com.c2kernel.utils.Logger;
+
+public class TransactionManager {
+
+ HashMap locks;
+ HashMap pendingTransactions;
+ ClusterStorageManager storage;
+
+ public TransactionManager() throws ClusterStorageException {
+ storage = new ClusterStorageManager();
+ locks = new HashMap();
+ pendingTransactions = new HashMap();
+ }
+
+ public boolean hasPendingTransactions()
+ {
+ return pendingTransactions.size() > 0;
+ }
+
+ public ClusterStorageManager getDb() {
+ return storage;
+ }
+
+ public void close() {
+ if (pendingTransactions.size() != 0) {
+ Logger.error("There were pending transactions on shutdown. All changes were lost.");
+ dumpPendingTransactions(0);
+ }
+ Logger.msg("Transaction Manager: Closing storages");
+ storage.close();
+ }
+
+ public String[] getClusterContents(int sysKey, String path) throws ClusterStorageException {
+ if (path.startsWith("/") && path.length() > 1) path = path.substring(1);
+ return storage.getClusterContents(new Integer(sysKey), path);
+ }
+
+ /**
+ * Public get method. Required a 'locker' object for a transaction key.
+ * Checks the transaction table first to see if the caller has uncommitted changes
+ */
+ public C2KLocalObject get(int sysKey, String path, Object locker)
+ throws ClusterStorageException,
+ ObjectNotFoundException {
+ if (path.startsWith("/") && path.length() > 1) path = path.substring(1);
+
+ // deal out top level remote maps
+ if (path.indexOf('/') == -1) {
+ try {
+ if (path.equals(ClusterStorage.HISTORY))
+ return new History(sysKey, locker);
+ if (path.equals(ClusterStorage.JOB))
+ return new JobList(sysKey, locker);
+ } catch (InvalidEntityPathException ex) {
+ throw new ObjectNotFoundException("Invalid key");
+ }
+ }
+
+ Integer sysKeyIntObj = new Integer(sysKey);
+ // check to see if the locker has been modifying this cluster
+ synchronized(locks) {
+ if (locks.containsKey(sysKeyIntObj) && locks.get(sysKeyIntObj).equals(locker)) {
+ ArrayList lockerTransaction = (ArrayList)pendingTransactions.get(locker);
+ for (Iterator i = lockerTransaction.iterator(); i.hasNext(); ) {
+ TransactionEntry thisEntry = (TransactionEntry)i.next();
+ if (sysKey == thisEntry.sysKey.intValue() && path.equals(thisEntry.getPath())) {
+ if (thisEntry.obj == null)
+ throw new ClusterStorageException("ClusterStorageManager.get() - Cluster " + path + " has been deleted in " + sysKey +
+ " but not yet committed");
+ return thisEntry.obj;
+ }
+ }
+ }
+ }
+ return storage.get(sysKeyIntObj, path);
+ }
+
+ /**
+ * Public put method. Manages the transaction table keyed by the object 'locker'.
+ * If this object is null, transaction support is bypassed (so long as no lock exists on that object).
+ */
+ public void put(int sysKey, C2KLocalObject obj, Object locker) throws ClusterStorageException {
+ Integer sysKeyIntObj = new Integer(sysKey);
+ ArrayList lockerTransaction;
+ String path = ClusterStorage.getPath(obj);
+
+ synchronized(locks) {
+ // look to see if this object is already locked
+ if (locks.containsKey(sysKeyIntObj)) {
+ // if it's this locker, get the transaction list
+ Object thisLocker = locks.get(sysKeyIntObj);
+ if (thisLocker.equals(locker)) // retrieve the transaction list
+ lockerTransaction = (ArrayList)pendingTransactions.get(locker);
+ else // locked by someone else
+ throw new ClusterStorageException("ClusterStorageManager.get() - Access denied: Object " + sysKeyIntObj +
+ " has been locked for writing by " + thisLocker);
+ }
+ else { // either we are the locker, or there is no locker
+ if (locker == null) { // non-locking put/delete
+ storage.put(sysKeyIntObj, obj);
+ return;
+ }
+ else {// initialise the transaction
+ locks.put(sysKeyIntObj, locker);
+ lockerTransaction = new ArrayList();
+ pendingTransactions.put(locker, lockerTransaction);
+ }
+ }
+
+ // create the new entry in the transaction table
+ TransactionEntry newEntry = new TransactionEntry(sysKeyIntObj, path, obj);
+ /* equals() in TransactionEntry only compares sysKey and path, so we can use
+ * contains() in ArrayList to looks for preexisting entries for this cluster
+ * and overwrite them.
+ */
+ if (lockerTransaction.contains(newEntry))
+ lockerTransaction.remove(newEntry);
+ lockerTransaction.add(newEntry);
+ }
+ }
+
+ /** Public delete method. Uses the put method, with null as the object value.
+ */
+ public void remove(int sysKey, String path, Object locker) throws ClusterStorageException {
+ Integer sysKeyIntObj = new Integer(sysKey);
+ ArrayList lockerTransaction;
+ synchronized(locks) {
+ // look to see if this object is already locked
+ if (locks.containsKey(sysKeyIntObj)) {
+ // if it's this locker, get the transaction list
+ Object thisLocker = locks.get(sysKeyIntObj);
+ if (thisLocker.equals(locker)) // retrieve the transaction list
+ lockerTransaction = (ArrayList)pendingTransactions.get(locker);
+ else // locked by someone else
+ throw new ClusterStorageException("ClusterStorageManager.get() - Access denied: Object " + sysKeyIntObj +
+ " has been locked for writing by " + thisLocker);
+ }
+ else { // either we are the locker, or there is no locker
+ if (locker == null) { // non-locking put/delete
+ storage.remove(sysKeyIntObj, path);
+ return;
+ }
+ else {// initialise the transaction
+ locks.put(sysKeyIntObj, locker);
+ lockerTransaction = new ArrayList();
+ pendingTransactions.put(locker, lockerTransaction);
+ }
+ }
+
+ // create the new entry in the transaction table
+ TransactionEntry newEntry = new TransactionEntry(sysKeyIntObj, path, null);
+ /* equals() in TransactionEntry only compares sysKey and path, so we can use
+ * contains() in ArrayList to looks for preexisting entries for this cluster
+ * and overwrite them.
+ */
+ if (lockerTransaction.contains(newEntry))
+ lockerTransaction.remove(newEntry);
+ lockerTransaction.add(newEntry);
+ }
+ }
+
+ /**
+ * Removes all child objects from the given path
+ *
+ * @param sysKey - entity to delete from
+ * @param path - root path to delete
+ * @param locker - locking object
+ *
+ * @throws ClusterStorageException - when deleting fails
+ */
+ public void removeCluster(int sysKey, String path, Object locker) throws ClusterStorageException {
+
+ String[] children = getClusterContents(sysKey, path);
+ for (int i = 0; i < children.length; i++)
+ removeCluster(sysKey, path+(path.length()>0?"/":"")+children[i], locker);
+ if (children.length==0 && path.indexOf("/") > -1)
+ remove(sysKey, path, locker);
+
+ }
+ /**
+ * Writes all pending changes to the backends.
+ */
+ public void commit(Object locker) {
+ synchronized(locks) {
+ ArrayList lockerTransactions = (ArrayList)pendingTransactions.get(locker);
+ HashMap exceptions = new HashMap();
+ // quit if no transactions are present;
+ if (lockerTransactions == null) return;
+ for (Iterator i = lockerTransactions.iterator();i.hasNext();) {
+ TransactionEntry thisEntry = (TransactionEntry)i.next();
+ try {
+ if (thisEntry.obj == null)
+ storage.remove(thisEntry.sysKey, thisEntry.path);
+ else
+ storage.put(thisEntry.sysKey, thisEntry.obj);
+ locks.remove(thisEntry.sysKey);
+ } catch (Exception e) {
+ exceptions.put(thisEntry, e);
+ }
+ }
+ pendingTransactions.remove(locker);
+ if (exceptions.size() > 0) { // oh dear
+ Logger.error("TransactionManager.commit() - Problems during transaction commit of locker "+locker.toString()+". Database may be in an inconsistent state.");
+ for (Iterator iter = exceptions.keySet().iterator(); iter.hasNext();) {
+ TransactionEntry entry = (TransactionEntry) iter.next();
+ Exception ex = (Exception)exceptions.get(entry);
+ Logger.msg(entry.toString());
+ Logger.error(ex);
+ }
+ dumpPendingTransactions(0);
+ Logger.die("Database failure");
+ }
+
+ }
+ }
+
+ /**
+ * Rolls back all changes sent in the name of 'locker' and unlocks the sysKeys
+ */
+ public void abort(Object locker) {
+ synchronized(locks) {
+ if (locks.containsValue(locker)) {
+ for (Iterator i=locks.keySet().iterator(); i.hasNext();) {
+ Integer thisKey = (Integer)i.next();
+ if (locks.get(thisKey).equals(locker))
+ locks.remove(thisKey);
+ }
+ }
+ pendingTransactions.remove(locker);
+ }
+ }
+
+ public void clearCache(int sysKey, String path) {
+ if (sysKey == -1)
+ storage.clearCache();
+ else if (path == null)
+ storage.clearCache(new Integer(sysKey));
+ else
+ storage.clearCache(new Integer(sysKey), path);
+
+ }
+
+ public void dumpPendingTransactions(int logLevel) {
+ Logger.msg(logLevel, "================");
+ Logger.msg(logLevel, "Transaction dump");
+ Logger.msg(logLevel, "Locked Items:");
+ if (locks.size() == 0)
+ Logger.msg(logLevel, " None");
+ else
+ for (Iterator iter = locks.keySet().iterator(); iter.hasNext();) {
+ Integer thisKey = (Integer)iter.next();
+ Object locker = locks.get(thisKey);
+ Logger.msg(logLevel, " "+thisKey+" locked by "+locker);
+ }
+
+ Logger.msg(logLevel, "Open transactions:");
+ if (pendingTransactions.size() == 0)
+ Logger.msg(logLevel, " None");
+ else
+ for (Iterator iter = pendingTransactions.keySet().iterator(); iter.hasNext();) {
+ Object thisLocker = iter.next();
+ Logger.msg(logLevel, " Transaction owner:"+thisLocker);
+ ArrayList entries = (ArrayList)pendingTransactions.get(thisLocker);
+ for (Iterator iterator = entries.iterator(); iterator.hasNext();) {
+ TransactionEntry thisEntry = (TransactionEntry) iterator.next();
+ Logger.msg(logLevel, " "+thisEntry.toString());
+ }
+ }
+ }
+
+ /** Used in the transaction table to store details of a put until commit
+ */
+ class TransactionEntry {
+ public Integer sysKey;
+ public String path;
+ public C2KLocalObject obj;
+ public TransactionEntry(Integer sysKey, String path, C2KLocalObject obj) {
+ this.sysKey = sysKey;
+ this.path = path;
+ this.obj = obj;
+ }
+
+ public String getPath() {
+ return ClusterStorage.getPath(obj);
+ }
+
+ public String toString() {
+ StringBuffer report = new StringBuffer();
+ if (obj == null)
+ report.append("Delete");
+ else
+ report.append("Put "+obj.getClass().getName());
+ report.append(" at ").append(path).append(" in ").append(sysKey);
+ return report.toString();
+
+ }
+ /**
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ return sysKey.hashCode()*getPath().hashCode();
+ }
+
+ /**
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object other) {
+ if (other instanceof TransactionEntry)
+ return hashCode() == ((TransactionEntry)other).hashCode();
+ return false;
+ }
+
+ }
+
+ public Object query(String id, Object query) throws ClusterStorageException {
+ return storage.query(id, query);
+ }
+
+ public String queryToXML(String id, String query, boolean genericFormat) throws ClusterStorageException {
+ return storage.queryToXML(id, query, genericFormat);
+ }
+
+}
diff --git a/source/com/c2kernel/persistency/XMLClusterStorage.java b/source/com/c2kernel/persistency/XMLClusterStorage.java
new file mode 100755
index 0000000..6e3cd72
--- /dev/null
+++ b/source/com/c2kernel/persistency/XMLClusterStorage.java
@@ -0,0 +1,145 @@
+package com.c2kernel.persistency;
+import java.io.File;
+import java.util.ArrayList;
+
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.lookup.InvalidEntityPathException;
+import com.c2kernel.persistency.outcome.Outcome;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.FileStringUtility;
+import com.c2kernel.utils.Logger;
+
+public class XMLClusterStorage extends ClusterStorage {
+ String rootDir=null;
+
+ public XMLClusterStorage() {
+ }
+
+ public void open() throws ClusterStorageException {
+ String rootProp = Gateway.getProperty("XMLStorage.root");
+ if (rootProp == null)
+ throw new ClusterStorageException("XMLClusterStorage.open() - Root path not given in config file.");
+
+ rootDir = new File(rootProp).getAbsolutePath();
+
+ if( !FileStringUtility.checkDir( rootDir ) ) {
+ Logger.error("XMLClusterStorage.open() - Path " + rootDir + "' does not exist. Attempting to create.");
+ boolean success = FileStringUtility.createNewDir(rootDir);
+ if (!success) throw new ClusterStorageException("XMLClusterStorage.open() - Could not create dir "+ rootDir +". Cannot continue.");
+ }
+ }
+
+ public void close() {
+ rootDir = null;
+ }
+
+ // introspection
+ public short queryClusterSupport(String clusterType) {
+ return ClusterStorage.READWRITE;
+ }
+
+ public String getName() {
+ return "XML File Cluster Storage";
+ }
+
+ public String getId() {
+ return "XML";
+ }
+
+ /* object manipulation */
+
+ // retrieve object by path
+ public C2KLocalObject get(Integer sysKey, String path) throws ClusterStorageException {
+ try {
+ String type = ClusterStorage.getClusterType(path);
+ String filePath = getFilePath(sysKey, path)+".xml";
+ String objString = FileStringUtility.file2String(filePath);
+ if (objString.length() == 0) return null;
+
+ if (type.equals("Outcome"))
+ return new Outcome(path, objString);
+ else
+ return (C2KLocalObject)CastorXMLUtility.unmarshall(objString);
+
+ } catch (Exception e) {
+ Logger.msg(3,"XMLClusterStorage.get() - The path "+path+" from "+sysKey+" does not exist.: "+e.getMessage());
+ }
+ return null;
+ }
+
+ // store object by path
+ public void put(Integer sysKey, C2KLocalObject obj) throws ClusterStorageException {
+ try {
+ String filePath = getFilePath(sysKey, getPath(obj)+".xml");
+ Logger.msg(7, "Writing "+filePath);
+ String data = CastorXMLUtility.marshall(obj);
+
+ String dir = filePath.substring(0, filePath.lastIndexOf('/'));
+ if( !FileStringUtility.checkDir( dir ) ) {
+ boolean success = FileStringUtility.createNewDir(dir);
+ if (!success) throw new ClusterStorageException("XMLClusterStorage.put() - Could not create dir "+ dir +". Cannot continue.");
+ }
+ FileStringUtility.string2File(filePath, data);
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new ClusterStorageException("XMLClusterStorage.put() - Could not write "+getPath(obj)+" to "+sysKey);
+ }
+ }
+
+ // delete cluster
+ public void delete(Integer sysKey, String path) throws ClusterStorageException {
+ try {
+ String filePath = getFilePath(sysKey, path+".xml");
+ boolean success = FileStringUtility.deleteDir(filePath, true, true);
+ if (success) return;
+ filePath = getFilePath(sysKey, path);
+ success = FileStringUtility.deleteDir(filePath, true, true);
+ if (success) return;
+ } catch(Exception e) { }
+ throw new ClusterStorageException("XMLClusterStorage.delete() - Failure deleting path "+path+" in "+sysKey);
+ }
+
+ /* navigation */
+
+ // directory listing
+ public String[] getClusterContents(Integer sysKey, String path) throws ClusterStorageException {
+ String[] result = new String[0];
+ try {
+ String filePath = getFilePath(sysKey, path);
+ ArrayList paths = FileStringUtility.listDir( filePath, true, false );
+ if (paths == null) return result; // dir doesn't exist yet
+ ArrayList contents = new ArrayList();
+ String previous = null;
+ for (int i=0; i<paths.size(); i++) {
+ String next = (String)paths.get(i);
+
+ // trim off the xml from the end if it's there
+ if (next.endsWith(".xml")) next = next.substring(0, next.length()-4);
+
+ // avoid duplicates (xml and dir)
+ if (next.equals(previous)) continue;
+ previous = next;
+
+ // only keep the last bit of the path
+ if (next.indexOf('/') > -1) next = next.substring(next.lastIndexOf('/')+1);
+ contents.add(next);
+ }
+
+ result = (String[])contents.toArray(result);
+ return result;
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new ClusterStorageException("XMLClusterStorage.getClusterContents() - Could not get contents of "+path+" from "+sysKey+": "+e.getMessage());
+ }
+ }
+
+ protected String getFilePath(Integer sysKey, String path) throws InvalidEntityPathException {
+ EntityPath thisEntity = new EntityPath(sysKey.intValue());
+ if (path.length() == 0 || path.charAt(0) != '/') path = "/"+path;
+ String filePath = rootDir+thisEntity.toString()+path;
+ Logger.msg(8, "XMLClusterStorage.getFilePath() - "+filePath);
+ return filePath;
+ }
+}
diff --git a/source/com/c2kernel/persistency/outcome/Outcome.java b/source/com/c2kernel/persistency/outcome/Outcome.java
new file mode 100755
index 0000000..f919230
--- /dev/null
+++ b/source/com/c2kernel/persistency/outcome/Outcome.java
@@ -0,0 +1,159 @@
+package com.c2kernel.persistency.outcome;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.StringTokenizer;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.xml.serialize.Method;
+import org.apache.xml.serialize.OutputFormat;
+import org.apache.xml.serialize.XMLSerializer;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+
+import com.c2kernel.common.PersistencyException;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.utils.Logger;
+
+public class Outcome implements C2KLocalObject {
+ int mID = -1;
+ String mData;
+ String mSchemaType;
+ int mSchemaVersion;
+ static DocumentBuilder parser;
+
+ static {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setValidating(false);
+ dbf.setNamespaceAware(false);
+ try {
+ parser = dbf.newDocumentBuilder();
+ } catch (ParserConfigurationException e) {
+ Logger.error(e);
+ }
+ }
+
+ //id is the eventID
+ public Outcome(int id, String data, String schemaType, int schemaVersion) {
+ mID = id;
+ mData = data;
+ mSchemaType = schemaType;
+ mSchemaVersion = schemaVersion;
+ }
+
+ public Outcome(String path, String data) throws PersistencyException {
+ // derive all the meta data from the path
+ StringTokenizer tok = new StringTokenizer(path,"/");
+ if (tok.countTokens() != 3 && !(tok.nextToken().equals("Outcome")))
+ throw new PersistencyException("Outcome() - Outcome path must have three components: "+path, null);
+ mSchemaType = tok.nextToken();
+ String verstring = tok.nextToken();
+ String objId = tok.nextToken();
+ try {
+ mSchemaVersion = Integer.parseInt(verstring);
+ } catch (NumberFormatException ex) {
+ throw new PersistencyException("Outcome() - Outcome version was an invalid number: "+verstring, null);
+ }
+ try {
+ mID = Integer.parseInt(objId);
+ } catch (NumberFormatException ex) {
+ mID = -1;
+ }
+ mData = data;
+ }
+
+ public void setID(int ID) {
+ mID = ID;
+ }
+
+ public int getID() {
+ return mID;
+ }
+
+ public void setName(String name) {
+ try {
+ mID = Integer.parseInt(name);
+ } catch (NumberFormatException e) {
+ Logger.error("Invalid id set on Outcome:"+name);
+ }
+ }
+
+ public String getName() {
+ return String.valueOf(mID);
+ }
+
+ public void setData(String data) {
+ mData = data;
+ }
+
+ public void setData(Document data) {
+ mData = serialize(data, false);
+ }
+
+ public String getData() {
+ return mData;
+ }
+
+ public void setSchemaType(String schemaType) {
+ mSchemaType = schemaType;
+ }
+
+ public String getSchemaType() {
+ return mSchemaType;
+ }
+
+ public void setSchemaURL(int schemaVersion) {
+ mSchemaVersion = schemaVersion;
+ }
+
+ public int getSchemaVersion() {
+ return mSchemaVersion;
+ }
+
+ public void setSchemaVersion(int schVer) {
+ mSchemaVersion = schVer;
+ }
+
+ public String getClusterType() {
+ return ClusterStorage.OUTCOME;
+ }
+
+ // special script API methods
+
+ /**
+ * Parses the outcome into a DOM tree
+ * @return a DOM Document
+ */
+ public Document getDOM() {
+ try {
+ synchronized (parser) {
+ return parser.parse(new InputSource(new StringReader(mData)));
+ }
+ } catch (Exception e) {
+ Logger.error(e);
+ return null;
+ }
+ }
+
+ static public String serialize(Document doc, boolean prettyPrint)
+ {
+ String serializedDoc = null;
+ OutputFormat format = new OutputFormat(Method.XML, null, prettyPrint);
+ StringWriter stringOut = new StringWriter();
+ XMLSerializer serial = new XMLSerializer(stringOut, format);
+ try
+ {
+ serial.asDOMSerializer();
+ serial.serialize(doc);
+ }
+ catch (java.io.IOException ex)
+ {
+ Logger.error(ex.toString());
+ }
+ serializedDoc = stringOut.toString();
+ return serializedDoc;
+ }
+}
diff --git a/source/com/c2kernel/persistency/outcome/OutcomeValidator.java b/source/com/c2kernel/persistency/outcome/OutcomeValidator.java
new file mode 100755
index 0000000..1a76322
--- /dev/null
+++ b/source/com/c2kernel/persistency/outcome/OutcomeValidator.java
@@ -0,0 +1,183 @@
+
+package com.c2kernel.persistency.outcome;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import org.apache.xerces.parsers.DOMParser;
+import org.apache.xerces.parsers.IntegratedParserConfiguration;
+import org.apache.xerces.parsers.XMLGrammarPreparser;
+import org.apache.xerces.util.SymbolTable;
+import org.apache.xerces.util.XMLGrammarPoolImpl;
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.grammars.Grammar;
+import org.apache.xerces.xni.grammars.XMLGrammarDescription;
+import org.apache.xerces.xni.parser.XMLErrorHandler;
+import org.apache.xerces.xni.parser.XMLInputSource;
+import org.apache.xerces.xni.parser.XMLParseException;
+import org.apache.xerces.xni.parser.XMLParserConfiguration;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.utils.Logger;
+
+/**************************************************************************
+ *
+ * $Revision: 1.24 $
+ * $Date: 2005/06/09 13:50:10 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+
+public class OutcomeValidator implements ErrorHandler, XMLErrorHandler {
+
+ protected static final String NAMESPACES_FEATURE_ID = "http://xml.org/sax/features/namespaces";
+ /** Validation feature id (http://xml.org/sax/features/validation). */
+ protected static final String VALIDATION_FEATURE_ID = "http://xml.org/sax/features/validation";
+ /** Schema validation feature id (http://apache.org/xml/features/validation/schema). */
+ protected static final String SCHEMA_VALIDATION_FEATURE_ID = "http://apache.org/xml/features/validation/schema";
+ /** Schema full checking feature id (http://apache.org/xml/features/validation/schema-full-checking). */
+ protected static final String SCHEMA_FULL_CHECKING_FEATURE_ID = "http://apache.org/xml/features/validation/schema-full-checking";
+ public static final String GRAMMAR_POOL = "http://apache.org/xml/properties/internal/grammar-pool";
+
+ static SchemaValidator schemaValid = new SchemaValidator();
+
+ Schema schema;
+ protected StringBuffer errors = null;
+ XMLGrammarPoolImpl schemaGrammarPool = new XMLGrammarPoolImpl(1);
+ SymbolTable sym = new SymbolTable();
+
+ public static OutcomeValidator getValidator(Schema schema) throws InvalidDataException {
+ String schemaId = schema.docType+"_"+schema.docVersion;
+
+ if (schemaId.equals("Schema_0"))
+ return schemaValid;
+
+ return new OutcomeValidator(schema);
+ }
+
+ protected OutcomeValidator() {
+ errors = new StringBuffer();
+ }
+
+ public OutcomeValidator(Schema schema) throws InvalidDataException {
+ this.schema = schema;
+
+ if (schema.docType.equals("Schema"))
+ throw new InvalidDataException("Use SchemaValidator to validate schema", "");
+
+ errors = new StringBuffer();
+ Logger.msg(5, "Parsing "+schema.docType+" version "+schema.docVersion+". "+schema.schema.length()+" chars");
+
+ XMLGrammarPreparser preparser = new XMLGrammarPreparser(sym);
+ preparser.registerPreparser(XMLGrammarDescription.XML_SCHEMA, null);
+ preparser.setProperty(GRAMMAR_POOL, schemaGrammarPool);
+
+ preparser.setFeature(NAMESPACES_FEATURE_ID, true);
+ preparser.setFeature(VALIDATION_FEATURE_ID, true);
+ preparser.setFeature(SCHEMA_VALIDATION_FEATURE_ID, true);
+ preparser.setFeature(SCHEMA_FULL_CHECKING_FEATURE_ID, true);
+ preparser.setErrorHandler(this);
+ try {
+ Grammar g = preparser.preparseGrammar(XMLGrammarDescription.XML_SCHEMA, new XMLInputSource(null, null, null, new StringReader(schema.schema), null));
+ } catch (IOException ex) {
+ throw new InvalidDataException("Error parsing schema: "+ex.getMessage(), "");
+ }
+
+ if (errors.length() > 0) {
+ throw new InvalidDataException("Schema error: \n"+errors.toString(), "");
+ }
+
+ }
+
+ public synchronized String validate(Outcome outcome) {
+ if (outcome == null) return "Outcome object was null";
+ Logger.msg(5, "Validating outcome no "+outcome.getID()+" as "+schema.docType+" v"+schema.docVersion);
+ if (outcome.getSchemaType().equals(schema.docType)
+ && outcome.getSchemaVersion() == schema.docVersion) {
+ return validate(outcome.getData());
+ }
+ else
+ return "Outcome type and version did not match schema "+schema.docType;
+ }
+
+ public synchronized String validate(String outcome) {
+ if (outcome == null) return "Outcome String was null";
+ errors = new StringBuffer();
+ try {
+ XMLParserConfiguration parserConfiguration = new IntegratedParserConfiguration(sym, schemaGrammarPool);
+ parserConfiguration.setFeature(NAMESPACES_FEATURE_ID, true);
+ parserConfiguration.setFeature(VALIDATION_FEATURE_ID, true);
+ // now we can still do schema features just in case,
+ // so long as it's our configuraiton......
+ parserConfiguration.setFeature(SCHEMA_VALIDATION_FEATURE_ID, true);
+ parserConfiguration.setFeature(SCHEMA_FULL_CHECKING_FEATURE_ID, true);
+ DOMParser parser = new DOMParser(parserConfiguration);
+ parser.setErrorHandler(this);
+
+ parser.parse(new XMLInputSource(null, null, null, new StringReader(outcome), null));
+ } catch (Exception e) {
+ return e.getMessage();
+ }
+ return errors.toString();
+ }
+
+ private void appendError(String level, Exception ex) {
+ errors.append(level);
+ String message = ex.getMessage();
+ if (message == null || message.length()==0)
+ message = ex.getClass().getName();
+ errors.append(message);
+ errors.append("\n");
+ }
+
+ /**
+ * ErrorHandler for instances
+ */
+ public void error(SAXParseException ex) throws SAXException {
+ appendError("ERROR: ", ex);
+ }
+
+ /**
+ *
+ */
+ public void fatalError(SAXParseException ex) throws SAXException {
+ appendError("FATAL: ", ex);
+ }
+
+ /**
+ *
+ */
+ public void warning(SAXParseException ex) throws SAXException {
+ appendError("WARNING: ", ex);
+ }
+
+ /**
+ * XMLErrorHandler for schema
+ */
+ public void error(String domain, String key, XMLParseException ex)
+ throws XNIException {
+ appendError("ERROR: ", ex);
+ }
+
+ /**
+ *
+ */
+ public void fatalError(String domain, String key, XMLParseException ex)
+ throws XNIException {
+ appendError("FATAL: ", ex);
+ }
+
+ /**
+ *
+ */
+ public void warning(String domain, String key, XMLParseException ex)
+ throws XNIException {
+ appendError("WARNING: ", ex);
+ }
+
+}
diff --git a/source/com/c2kernel/persistency/outcome/Schema.java b/source/com/c2kernel/persistency/outcome/Schema.java
new file mode 100755
index 0000000..9514ebe
--- /dev/null
+++ b/source/com/c2kernel/persistency/outcome/Schema.java
@@ -0,0 +1,18 @@
+package com.c2kernel.persistency.outcome;
+
+/**
+ * @author Andrew Branson
+ *
+ * $Revision: 1.3 $
+ * $Date: 2006/09/14 14:13:26 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ */
+
+public class Schema {
+ public String docType;
+ public int docVersion;
+ public boolean breakApart;
+ public String schema;
+ }
diff --git a/source/com/c2kernel/persistency/outcome/SchemaValidator.java b/source/com/c2kernel/persistency/outcome/SchemaValidator.java
new file mode 100755
index 0000000..f2dfa0b
--- /dev/null
+++ b/source/com/c2kernel/persistency/outcome/SchemaValidator.java
@@ -0,0 +1,54 @@
+package com.c2kernel.persistency.outcome;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import org.exolab.castor.xml.schema.reader.SchemaReader;
+import org.xml.sax.InputSource;
+
+
+/**************************************************************************
+ *
+ * $Revision: 1.2 $
+ * $Date: 2005/04/26 06:48:13 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+
+
+public class SchemaValidator extends OutcomeValidator {
+
+ org.exolab.castor.xml.schema.Schema castorSchema;
+ /**
+ *
+ */
+
+ public SchemaValidator() {
+
+ }
+
+ public org.exolab.castor.xml.schema.Schema getSOM() {
+ return castorSchema;
+ }
+
+ /**
+ *
+ */
+
+ public synchronized String validate(String outcome) {
+ errors = new StringBuffer();
+ try {
+ InputSource schemaSource = new InputSource(new StringReader(outcome));
+ SchemaReader mySchemaReader = new SchemaReader(schemaSource);
+ mySchemaReader.setErrorHandler(this);
+ mySchemaReader.setValidation(true);
+ castorSchema = mySchemaReader.read();
+ } catch (IOException e) {
+ errors.append(e.getMessage());
+ }
+ return errors.toString();
+ }
+
+}
diff --git a/source/com/c2kernel/persistency/outcome/Viewpoint.java b/source/com/c2kernel/persistency/outcome/Viewpoint.java
new file mode 100755
index 0000000..7fc2aa5
--- /dev/null
+++ b/source/com/c2kernel/persistency/outcome/Viewpoint.java
@@ -0,0 +1,176 @@
+package com.c2kernel.persistency.outcome;
+
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.events.Event;
+import com.c2kernel.lookup.Path;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.persistency.ClusterStorageException;
+import com.c2kernel.process.Gateway;
+
+/**
+ * @author Andrew Branson
+ *
+ * $Revision: 1.10 $
+ * $Date: 2005/10/05 07:39:36 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ */
+
+// public static final String codeRevision =
+// "$Revision: 1.10 $ $Date: 2005/10/05 07:39:36 $ $Author: abranson $";
+public class Viewpoint implements C2KLocalObject {
+
+ int ID = -1; // not really used in this
+
+ // db fields
+ int sysKey;
+ String schemaName;
+ String name;
+ int schemaVersion;
+ int eventId;
+ public static final int NONE = -1;
+
+ public Viewpoint() {
+ eventId = NONE;
+ sysKey = Path.INVALID;
+ schemaVersion = NONE;
+ schemaName = null;
+ name = null;
+ }
+
+ public Viewpoint(int sysKey, String schemaName, String name, int schemaVersion, int eventId) {
+ this.sysKey = sysKey;
+ this.schemaName = schemaName;
+ this.name = name;
+ this.schemaVersion = schemaVersion;
+ this.eventId = eventId;
+ }
+
+ public Outcome getOutcome() throws ObjectNotFoundException, ClusterStorageException {
+ if (eventId == NONE) throw new ObjectNotFoundException("No last eventId defined", "");
+ Outcome retVal = (Outcome)Gateway.getStorage().get(sysKey, ClusterStorage.OUTCOME+"/"+schemaName+"/"+schemaVersion+"/"+eventId, null);
+ return retVal;
+ }
+
+ public String getClusterType() {
+ return ClusterStorage.VIEWPOINT;
+ }
+
+
+ /**
+ * Returns the eventId.
+ * @return int
+ */
+ public int getEventId() {
+ return eventId;
+ }
+
+ /**
+ * Returns the iD.
+ * @return int
+ */
+ public int getID() {
+ return ID;
+ }
+
+ /**
+ * Returns the name.
+ * @return String
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the schemaName.
+ * @return String
+ */
+ public String getSchemaName() {
+ return schemaName;
+ }
+
+ /**
+ * Returns the schemaVersion.
+ * @return int
+ */
+ public int getSchemaVersion() {
+ return schemaVersion;
+ }
+
+ /**
+ * Returns the sysKey.
+ * @return int
+ */
+ public int getSysKey() {
+ return sysKey;
+ }
+
+ /**
+ * Sets the eventId.
+ * @param eventId The eventId to set
+ */
+ public void setEventId(int eventId) {
+ this.eventId = eventId;
+ }
+
+ /**
+ * Sets the iD.
+ * @param iD The iD to set
+ */
+ public void setID(int iD) {
+ ID = iD;
+ }
+
+ /**
+ * Sets the name.
+ * @param name The name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Sets the schemaName.
+ * @param schemaName The schemaName to set
+ */
+ public void setSchemaName(String schemaName) {
+ this.schemaName = schemaName;
+ }
+
+ /**
+ * Sets the schemaVersion.
+ * @param schemaVersion The schemaVersion to set
+ */
+ public void setSchemaVersion(int schemaVersion) {
+ this.schemaVersion = schemaVersion;
+ }
+
+ /**
+ * Sets the sysKey.
+ * @param sysKey The sysKey to set
+ */
+ public void setSysKey(int sysKey) {
+ this.sysKey = sysKey;
+ }
+
+ /**
+ * Method getEvent.
+ * @return GDataRecord
+ */
+ public Event getEvent()
+ throws InvalidDataException, ClusterStorageException, ObjectNotFoundException
+ {
+ if (eventId == NONE)
+ throw new InvalidDataException("No last eventId defined", "");
+
+ return (Event)Gateway.getStorage().get(sysKey, ClusterStorage.HISTORY+"/"+eventId, null);
+ }
+
+ public String toString() {
+ return name;
+ }
+
+}
diff --git a/source/com/c2kernel/process/AbstractMain.java b/source/com/c2kernel/process/AbstractMain.java
new file mode 100755
index 0000000..97af4f8
--- /dev/null
+++ b/source/com/c2kernel/process/AbstractMain.java
@@ -0,0 +1,205 @@
+/**************************************************************************
+ * AbstractMain
+ *
+ * $Revision: 1.67 $
+ * $Date: 2004/10/25 15:27:35 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.process;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+
+import com.c2kernel.utils.FileStringUtility;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.Resource;
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2004/10/25 15:27:35 $
+ * @version $Revision: 1.67 $
+ **************************************************************************/
+abstract public class AbstractMain
+{
+ public static boolean runningAsWrapper = false;
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ static protected void usage()
+ {
+ System.out.println();
+ System.out.println("USAGE: com.c2kernel.process.AbstractMain \n" +
+ " -config <server/client config file> \n" +
+ " [-connect <LC connect file> ] (or LocalCentre in conf)\n" +
+ " [-resURL c2kernel/resources] (or KernelResourceURL in conf)\n" +
+ " [-domResURL domain/resources] (or DomainResourceURL in conf)\n" +
+ " [-h] [-help] \n" +
+ " [-logLevel 0-19] \n" +
+ " [-logFile <path to log file>]");
+ Logger.die("Initialisation error");
+ }
+
+ /**************************************************************************
+ * reading and setting the standard c2k input paramaters
+ **************************************************************************/
+ static public java.util.Properties readC2KArgs( String[] args )
+ {
+ int i = 0;
+ String configPath = null;
+ String connectPath = null;
+ java.util.Properties c2kProps = null;
+ int logLevel = 0;
+ PrintStream logStream = System.out;
+ String centreId = null;
+
+ try
+ {
+ if( args != null )
+ {
+ while( i < args.length )
+ {
+ if( args[i].equals("-h") || args[i].equals("-help") )
+ {
+ usage();
+ }
+ else if(args[i].equals("-config"))
+ {
+ if( (i+1) >= args.length )
+ {
+ System.out.println("AbstractMain::readC2KArgs() - argument expected " +
+ "for -config");
+ usage();
+ }
+ System.out.println("Config file: "+args[i+1]);
+ configPath = args[++i];
+
+ }
+ else if(args[i].equals("-connect"))
+ {
+ if( (i+1) < args.length ) // batch file will have no arg if no cmd line arg
+ {
+ connectPath = args[++i];
+ }
+ }
+ else if(args[i].equals("-logLevel"))
+ {
+ if( (i+1) >= args.length )
+ {
+ System.out.println("AbstractMain::readC2KArgs() - argument expected " +
+ "for -logLevel");
+ usage();
+ }
+ logLevel = Integer.parseInt(args[++i]);
+ }
+ else if(args[i].equals("-logFile"))
+ {
+ if( (i+1) >= args.length )
+ {
+ System.out.println("AbstractMain::readC2KArgs() - argument expected " +
+ "for -logFile");
+ usage();
+ }
+ logStream = new PrintStream(new FileOutputStream(args[++i], true));
+ }
+ else if(args[i].equals("-resURL"))
+ {
+ String resString = args[++i];
+ System.out.println("AbstractMain::readC2KArgs() - Resource location:" +
+ resString);
+ Resource.setKernelBaseURL(resString);
+ }
+ else if(args[i].equals("-domResURL"))
+ {
+ String resString = args[++i];
+ System.out.println("AbstractMain::readC2KArgs() - Domain resource location:" +
+ resString);
+ Resource.setDomainBaseURL(resString);
+ }
+ i++;
+ }
+
+ // Set up log stream
+ Logger.addLogStream(logStream, logLevel);
+
+ if (configPath == null) {
+ System.out.println("No config file specified");
+ usage();
+ }
+
+ // Load config & connect files into c2kprops
+ c2kProps = FileStringUtility.loadConfigFile( configPath );
+
+ if (connectPath == null) {
+ // see if LC is listed in the config
+ Logger.msg(6, "No connect file specified in arguments. Looking in config.");
+ centreId = c2kProps.getProperty("LocalCentre");
+ if (centreId!= null) connectPath = "connect/"+centreId+".clc";
+ }
+
+ if (connectPath != null) {
+ Logger.msg(6, "Connect file: "+connectPath);
+ if (centreId == null) {
+ String connectFileName = new File(connectPath).getName();
+ centreId = connectFileName.substring(0, connectFileName.lastIndexOf(".clc"));
+ c2kProps.setProperty("LocalCentre", centreId);
+ }
+ FileStringUtility.appendConfigFile( c2kProps, connectPath);
+ }
+ else {
+ System.out.println("No connect file specified in args nor config file. Cannot continue.");
+ usage();
+ }
+ }
+ else
+ {
+ System.out.println("AbstractMain::readC2KArgs() - no arguments!");
+ usage();
+ }
+ }
+ catch( Exception ex )
+ {
+ System.out.println("Main::readC2KArgs() - bad arguments! ");
+ ex.printStackTrace();
+ usage();
+ }
+
+ Logger.msg(7, "AbstractMain::standardSetUp() - readC2KArgs() DONE.");
+
+ return c2kProps;
+ }
+
+ /**************************************************************************
+ * Required for most of the client & server application
+ *
+ * reads arguments
+ * initialises C2K properties
+ * initialises ORB
+ * initialises VirtualTreeManager
+ * initialises EventValueFactory + ProxyEventValueFactory
+ * initialises
+ **************************************************************************/
+ static protected void standardSetUp(String[] args)
+ throws Exception
+ {
+ //Reads the C2Kernel arguments, and inits the Gateway with them
+ Gateway.init(readC2KArgs(args));
+
+ }
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ static protected void standardTearDown()
+ throws Exception
+ {
+ Gateway.close();
+ Logger.msg(5, "AbstractMain::standardTearDown() - DONE.");
+ }
+
+}
diff --git a/source/com/c2kernel/process/Bootstrap.java b/source/com/c2kernel/process/Bootstrap.java
new file mode 100755
index 0000000..61ce46f
--- /dev/null
+++ b/source/com/c2kernel/process/Bootstrap.java
@@ -0,0 +1,356 @@
+package com.c2kernel.process;
+
+import java.net.InetAddress;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.TraceableEntity;
+import com.c2kernel.entity.agent.ActiveEntity;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.events.Event;
+import com.c2kernel.events.History;
+import com.c2kernel.lifecycle.CompositeActivityDef;
+import com.c2kernel.lifecycle.instance.CompositeActivity;
+import com.c2kernel.lifecycle.instance.Workflow;
+import com.c2kernel.lifecycle.instance.predefined.PredefinedStepContainer;
+import com.c2kernel.lifecycle.instance.predefined.ServerPredefinedStepContainer;
+import com.c2kernel.lifecycle.instance.predefined.entitycreation.NewItem;
+import com.c2kernel.lifecycle.instance.stateMachine.States;
+import com.c2kernel.lifecycle.instance.stateMachine.Transitions;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.lookup.LDAPLookup;
+import com.c2kernel.lookup.RolePath;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.persistency.outcome.Outcome;
+import com.c2kernel.persistency.outcome.Viewpoint;
+import com.c2kernel.property.Property;
+import com.c2kernel.property.PropertyArrayList;
+import com.c2kernel.property.PropertyDescription;
+import com.c2kernel.property.PropertyDescriptionList;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.FileStringUtility;
+import com.c2kernel.utils.LocalObjectLoader;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.Resource;
+
+/**
+ * @version $Revision: 1.25 $ $Date: 2006/01/10 09:48:32 $
+ * @author $Author: abranson $
+ */
+
+public class Bootstrap
+{
+ static HashMap bootstrapFactoryItems = new HashMap();
+ static DomainPath thisServerPath;
+
+ /**
+ * Run everything without timing-out the service wrapper
+ */
+ public static void run() throws Exception {
+ // check for system agents
+ checkAdminAgents();
+
+ // create the server's mother item
+ createServerItem();
+ new Thread(new Runnable() {
+ public void run() {
+ try {
+ Thread.currentThread().setName("Bootstrapper");
+
+ // make sure all of the boot items are up-to-date
+ verifyBootDataItems();
+
+ // verify the server item's wf
+ initServerItemWf();
+
+ // create the factories etc.
+ createBootstrapFactoryItems();
+ Logger.msg("Bootstrap.run() - Bootstrapping complete");
+ } catch (Exception e) {
+ Logger.error(e);
+ Logger.die("Exception performing bootstrap. Check that everything is OK.");
+ }
+ }
+ }).start();
+ }
+
+ /**************************************************************************
+ * Checks all kernel descriptions, stored in resources
+ **************************************************************************/
+ public static void verifyBootDataItems() throws Exception {
+ String bootItems;
+ Logger.msg(1, "Verifying kernel boot items");
+ bootItems = FileStringUtility.url2String(Resource.getKernelResourceURL("boot/allbootitems.txt"));
+ verifyBootDataItems(bootItems, true);
+ if (Resource.getDomainBaseURL() == null)
+ Logger.msg(1, "No Domain base URL. Skipping domain boot check.");
+ else {
+ try {
+ Logger.msg(1, "Verifying domain boot items");
+ bootItems = FileStringUtility.url2String(Resource.getDomainResourceURL("boot/allbootitems.txt"));
+ verifyBootDataItems(bootItems, false);
+ } catch (Exception ex) {
+ Logger.error(ex);
+ Logger.msg("No domain boot items found.");
+ return;
+ }
+ Logger.msg(1, "Verifying domain agents");
+
+ try {
+ bootItems = FileStringUtility.url2String(Resource.getDomainResourceURL("boot/domainagents.txt"));
+ verifyDomainAgents(bootItems);
+ } catch (Exception ex) {
+ Logger.error(ex);
+ Logger.msg("No domain agents found.");
+ return;
+ }
+ }
+
+ Logger.msg(1, "Boot data items complete");
+
+ }
+
+ private static void verifyDomainAgents(String agentFile) throws Exception {
+ StringTokenizer str = new StringTokenizer(agentFile, "\n\r");
+ while (str.hasMoreTokens()) {
+ String thisItem = str.nextToken();
+ StringTokenizer agent = new StringTokenizer(thisItem, ",");
+ checkAgent(agent.nextToken(), agent.nextToken(), agent.nextToken(), agent.nextToken().equalsIgnoreCase("true"));
+ }
+ }
+
+ private static void verifyBootDataItems(String bootList, boolean isKernel) {
+ StringTokenizer str = new StringTokenizer(bootList, "\n\r");
+ while (str.hasMoreTokens()) {
+ String thisItem = str.nextToken();
+ int delim = thisItem.indexOf('/');
+ String itemType = thisItem.substring(0,delim);
+ String itemName = thisItem.substring(delim+1);
+ try {
+ String data = Resource.getTextResource("boot/"+thisItem+".xml");
+ if (data == null)
+ Logger.die("No data found for "+getDataType(itemType)+" "+itemName);
+ if (itemType.equals("factory")) {
+ bootstrapFactoryItems.put(itemName, data);
+ continue;
+ }
+
+ Logger.msg(1, "Bootstrap.verifyBootItems() - Verifying data of "+getDataType(itemType)+" "+itemName);
+ Enumeration en = Gateway.getLDAPLookup().search(getTypeRoot(itemType), itemName);
+ ItemProxy thisProxy;
+
+ if (!en.hasMoreElements()) {
+ Logger.msg("Bootstrap.verifyBootItems() - "+getDataType(itemType)+" "+itemName+" not found. Creating new.");
+ thisProxy = createBootstrapDataItem(itemType, itemName, isKernel);
+ }
+ else {
+ DomainPath path = (DomainPath)en.nextElement();
+ thisProxy = (ItemProxy)Gateway.getProxyManager().getProxy(path);
+ try {
+ Viewpoint currentData = (Viewpoint)thisProxy.getObject(ClusterStorage.VIEWPOINT+"/"+getDataType(itemType)+"/last");
+ String oldData = currentData.getOutcome().getData();
+ if (data.equals(oldData)) {
+ Logger.msg(5, "Bootstrap.verifyBootItems() - Data identical, no update required");
+
+ continue;
+ }
+ } catch (ObjectNotFoundException ex) {
+ Logger.error("Bootstrap.verifyBootItems() - Item exists but no data found! Attempting to insert new.");
+ }
+ }
+ // data was missing or doesn't match
+ Logger.msg("Bootstrap.verifyBootItems() - Writing new data to "+getDataType(itemType)+" "+itemName);
+ History hist = (History)thisProxy.getObject(ClusterStorage.HISTORY);
+ Event newEvent = hist.addEvent("system", "Admin", Transitions.DONE, "Import", "Import", "Import", States.FINISHED);
+ Outcome newOutcome = new Outcome(newEvent.getID(), data, getDataType(itemType), 0);
+ Viewpoint newLastView = new Viewpoint(thisProxy.getSystemKey(), getDataType(itemType), "last", 0, newEvent.getID());
+ Viewpoint newZeroView = new Viewpoint(thisProxy.getSystemKey(), getDataType(itemType), "0", 0, newEvent.getID());
+ Gateway.getStorage().put(thisProxy.getSystemKey(), newOutcome, thisProxy);
+ Gateway.getStorage().put(thisProxy.getSystemKey(), newLastView, thisProxy);
+ Gateway.getStorage().put(thisProxy.getSystemKey(), newZeroView, thisProxy);
+ Gateway.getStorage().commit(thisProxy);
+ } catch (Exception e) {
+ Logger.error(e);
+ Logger.die("Error importing bootstrap items. Unsafe to continue.");
+ }
+ }
+ }
+
+ /**
+ * @param itemType
+ * @param itemName
+ * @param data
+ */
+ private static ItemProxy createBootstrapDataItem(String itemType, String itemName, boolean isKernel) throws Exception {
+ // create props
+ PropertyDescriptionList pdList = (PropertyDescriptionList)CastorXMLUtility.unmarshall(Resource.getTextResource("boot/property/"+itemType+"Prop.xml"));
+ PropertyArrayList props = new PropertyArrayList();
+ for (int i = 0; i < pdList.list.size(); i++) {
+ PropertyDescription pd = (PropertyDescription) pdList.list.get(i);
+ String propName = pd.getName();
+ String propVal = propName.equals("Name")?itemName:pd.getDefaultValue();
+ props.list.add(new Property(propName, propVal));
+ }
+
+ EntityPath entityPath = Gateway.getLDAPLookup().getNextKeyManager().generateNextEntityKey();
+ TraceableEntity newItem = (TraceableEntity)Gateway.getCorbaServer().createEntity(entityPath);
+ Gateway.getLDAPLookup().add(entityPath);
+ newItem.initialise(
+ 1,
+ CastorXMLUtility.marshall(props),
+ CastorXMLUtility.marshall(new CompositeActivity()));
+ DomainPath newDomPath = new DomainPath(getTypeRoot(itemType).toString()+"/system/"+(isKernel?"kernel":"domain")+"/"+itemName);
+ newDomPath.setEntity(entityPath);
+ Gateway.getLDAPLookup().add(newDomPath);
+ return (ItemProxy)Gateway.getProxyManager().getProxy(entityPath);
+ }
+
+ public static DomainPath getTypeRoot(String type) throws Exception {
+ if (type.equals("CA") || type.equals("EA"))
+ return new DomainPath("/desc/ActivityDesc/");
+ if (type.equals("SC"))
+ return new DomainPath("/desc/Script/");
+ if (type.equals("OD"))
+ return new DomainPath("/desc/OutcomeDesc/");
+ throw new Exception("Unknown bootstrap item type: "+type);
+ }
+
+ private static String getDataType(String type) throws Exception {
+ if (type.equals("CA"))
+ return "CompositeActivityDef";
+ if (type.equals("EA"))
+ return "ElementaryActivityDef";
+ if (type.equals("OD"))
+ return "Schema";
+ if (type.equals("SC"))
+ return "Script";
+ throw new Exception("Unknown bootstrap item type: "+type);
+
+ }
+
+ /**************************************************************************
+ * Checks for the existence of the admin users so you can use Cristal
+ **************************************************************************/
+ private static void checkAgent(String name, String pass, String role, boolean joblist) throws Exception {
+ Logger.msg(1, "Bootstrap.checkAgent() - Checking for existence of '"+name+"' user.");
+ LDAPLookup lookup = Gateway.getLDAPLookup();
+ try {
+ AgentPath agentPath = lookup.getRoleManager().getAgentPath(name);
+ Logger.msg(3, "Bootstrap.checkAgent() - User '"+name+"' found.");
+ return;
+ } catch (ObjectNotFoundException ex) { }
+ Logger.msg("Bootstrap.checkAgent() - User '"+name+"' not found. Creating.");
+
+ RolePath rolePath;
+ try {
+ rolePath = lookup.getRoleManager().getRolePath(role);
+ } catch (ObjectNotFoundException ex) {
+ rolePath = lookup.getRoleManager().createRole(role, joblist);
+ }
+
+ try {
+ EntityPath entityPath = lookup.getNextKeyManager().generateNextEntityKey();
+ AgentPath agentPath = new AgentPath(entityPath.getSysKey(), name);
+ agentPath.setPassword(pass);
+ ActiveEntity adminAgent = (ActiveEntity)Gateway.getCorbaServer().createEntity(agentPath);
+ Gateway.getLDAPLookup().add(agentPath);
+
+ // assign admin role
+ Logger.msg("Bootstrap.checkAgent() - Assigning role '"+role+"'");
+ rolePath.addAgent(agentPath);
+ Gateway.getStorage().put(agentPath.getSysKey(), new Property("Name", name), null);
+ Gateway.getStorage().put(agentPath.getSysKey(), new Property("Type", "Agent"), null);
+ Logger.msg("Bootstrap.checkAgent() - Done");
+ } catch (Exception ex) {
+ Logger.error("Unable to create "+name+" user.");
+ throw ex;
+ }
+ }
+
+ /**
+ *
+ */
+ public static void checkAdminAgents() throws Exception {
+ // check for administrative user
+ String adminPassword = Gateway.getProperty("AdminPassword", "admin12345");
+
+ checkAgent("admin", adminPassword, "Admin", false);
+
+ // check for import user
+ checkAgent("system", adminPassword, "Admin", false);
+
+ // check for local usercode user
+ checkAgent(InetAddress.getLocalHost().getHostName(), "uc", "UserCode", true);
+ }
+
+ public static void createServerItem() throws Exception {
+ String serverName = Gateway.getProperty("ItemServer.name");
+ thisServerPath = new DomainPath("/servers/"+serverName);
+ EntityPath serverEntity;
+ try {
+ serverEntity = thisServerPath.getEntity();
+ } catch (ObjectNotFoundException ex) {
+ Logger.msg("Creating server item "+thisServerPath);
+ serverEntity = Gateway.getLDAPLookup().getNextKeyManager().generateNextEntityKey();
+ TraceableEntity newItem = (TraceableEntity)Gateway.getCorbaServer().createEntity(serverEntity);
+ Gateway.getLDAPLookup().add(serverEntity);
+ thisServerPath.setEntity(serverEntity);
+ Gateway.getLDAPLookup().add(thisServerPath);
+ }
+ Gateway.getStorage().put(serverEntity.getSysKey(), new Property("Name", serverName), null);
+ Gateway.getStorage().put(serverEntity.getSysKey(), new Property("Type", "Server"), null);
+ if (Gateway.getProperty("ItemServer.Proxy.port") != null)
+ Gateway.getStorage().put(serverEntity.getSysKey(),
+ new Property("ProxyPort", Gateway.getProperty("ItemServer.Proxy.port")), null);
+ if (Gateway.getProperty("ItemServer.Console.port") != null)
+ Gateway.getStorage().put(serverEntity.getSysKey(),
+ new Property("ConsolePort", Gateway.getProperty("ItemServer.Console.port")), null);
+ Gateway.getProxyManager().connectToProxyServer(Gateway.getProperty("ItemServer.name"), Integer.parseInt(Gateway.getProperty("ItemServer.Proxy.port")));
+
+ }
+
+ public static void initServerItemWf() throws Exception {
+ CompositeActivityDef serverWfCa = (CompositeActivityDef)LocalObjectLoader.getActDef("ServerItemWorkflow", "last");
+ Workflow wf = new Workflow((CompositeActivity)serverWfCa.instantiate());
+ PredefinedStepContainer predef = (PredefinedStepContainer)wf.search("workflow/predefined");
+ wf.getChildGraphModel().removeVertex(predef);
+ wf.addChild(new ServerPredefinedStepContainer(), predef.getCentrePoint());
+ wf.initialise(thisServerPath.getSysKey(), Gateway.getLDAPLookup().getRoleManager().getAgentPath("system"));
+ Gateway.getStorage().put(thisServerPath.getSysKey(), wf, null);
+ // add this proxy server in case it was just registered, or the port has changed
+ }
+
+ public static void createBootstrapFactoryItems() throws Exception {
+ Logger.msg(1, "Verifying local object factories");
+ for (Iterator iter = bootstrapFactoryItems.keySet().iterator(); iter.hasNext();) {
+ String itemName = (String) iter.next();
+ String itemXML = (String)bootstrapFactoryItems.get(itemName);
+ Logger.msg(2, "Verifying "+itemName);
+ NewItem item = (NewItem)CastorXMLUtility.unmarshall(itemXML);
+ DomainPath factPath = new DomainPath(new DomainPath(item.initialPath), item.name);
+ if (factPath.exists()) continue;
+ ItemProxy serverEntity = (ItemProxy)Gateway.getProxyManager().getProxy(thisServerPath);
+ serverEntity.requestAction(
+ Gateway.getLDAPLookup().getRoleManager().getAgentPath("system").getSysKey(),
+ "workflow/predefined/CreateNewItem",
+ Transitions.DONE,
+ itemXML);
+ Logger.msg("Bootstrap.createBootstrapFactoryItems() - Created factory item: "+itemName);
+ ItemProxy factProxy = (ItemProxy)Gateway.getProxyManager().getProxy(factPath);
+ String propDesc = Resource.getTextResource("boot/property/"+itemName+"Prop.xml");
+ History hist = (History)factProxy.getObject(ClusterStorage.HISTORY);
+ Event newEvent = hist.addEvent("system", "Admin", Transitions.DONE, "Import", "Import", "Import", States.FINISHED);
+ Outcome newOutcome = new Outcome(newEvent.getID(), propDesc, "PropertyDescription", 0);
+ Viewpoint newLastView = new Viewpoint(factProxy.getSystemKey(), "PropertyDescription", "last", 0, newEvent.getID());
+ Gateway.getStorage().put(factProxy.getSystemKey(), newOutcome, factProxy);
+ Gateway.getStorage().put(factProxy.getSystemKey(), newLastView, factProxy);
+ Gateway.getStorage().commit(factProxy);
+ }
+ }
+
+}
diff --git a/source/com/c2kernel/process/Gateway.java b/source/com/c2kernel/process/Gateway.java
new file mode 100755
index 0000000..fcec1c4
--- /dev/null
+++ b/source/com/c2kernel/process/Gateway.java
@@ -0,0 +1,414 @@
+package com.c2kernel.process;
+
+/**
+ * @version $Revision: 1.17 $ $Date: 2005/10/12 12:51:54 $
+ * @author $Author: abranson $
+ */
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Properties;
+
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.CorbaServer;
+import com.c2kernel.entity.proxy.AgentProxy;
+import com.c2kernel.entity.proxy.EntityProxyManager;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.lookup.LDAPLookup;
+import com.c2kernel.lookup.LDAPProperties;
+import com.c2kernel.persistency.ClusterStorageException;
+import com.c2kernel.persistency.TransactionManager;
+import com.c2kernel.utils.*;
+import com.c2kernel.utils.server.SimpleTCPIPServer;
+
+
+/**************************************************************************
+ * The Gateway is the central object of a CRISTAL process. It initializes,
+ * maintains and shuts down every other subsystem in both the client and the
+ * server.
+ *
+ * Child objects:
+ * <ul>
+ * <li>LDAPLookup - Provides access to the CRISTAL directory. Find or
+ * search for Items or Agents.
+ * <li>EntityProxyManager - Gives a local proxy object for Entities found
+ * in LDAP. Execute activities in Items, query or subscribe to Entity data.
+ * <li>TransactionManager - Access to the configured CRISTAL databases
+ * <li>CorbaServer - Manages the memory pool of active Entities
+ * <li>mORB - the Orbacus CORBA ORB
+ * </ul>
+ *
+ * @author $Author: abranson $ $Date: 2005/10/12 12:51:54 $
+ * @version $Revision: 1.17 $
+ **************************************************************************/
+
+public class Gateway
+{
+ static private Properties mC2KProps;
+ static private org.omg.CORBA.ORB mORB;
+ static private LDAPLookup mLDAPLookup;
+ static private TransactionManager mStorage;
+ static private EntityProxyManager mProxyManager;
+ static private CorbaServer mCorbaServer;
+ static private SimpleTCPIPServer mHTTPServer;
+
+
+ private Gateway() { }
+
+ /**
+ * Initialises the Gateway and all of the client objects it holds, with
+ * the exception of the LDAPLookup, which is initialised during connect()
+ *
+ * @param props - java.util.Properties containing all application properties.
+ * If null, the java system properties are used
+ * @throws InvalidDataException - invalid properties caused a failure in initialisation
+ */
+ static public void init(Properties props) throws InvalidDataException {
+ // if supplied props are null, use system props
+ if (props == null) props = System.getProperties();
+
+ // set resource URLs from config
+ String resURL = props.getProperty("KernelResourceURL");
+ if (resURL != null && resURL.length()>0)
+ Resource.setKernelBaseURL(resURL);
+
+ resURL = props.getProperty("DomainResourceURL");
+ if (resURL != null && resURL.length()>0)
+ Resource.setDomainBaseURL(resURL);
+
+ // Start with default props from kernel jar
+ try {
+ mC2KProps = FileStringUtility.loadConfigFile( Resource.getKernelResourceURL("textFiles/defaultConf.properties").toString());
+ } catch (MalformedURLException ex) {
+ Logger.die("Default properties not found. Probable cause is missing resources");
+ }
+
+ // Overwrite with supplied props
+ for (Enumeration e = props.propertyNames(); e.hasMoreElements();) {
+ String propName = (String)e.nextElement();
+ mC2KProps.put(propName, props.get(propName));
+ }
+
+ // dump properties
+ dumpC2KProps(7);
+
+ // report version info
+ Logger.msg("Domain version: "+Resource.getDomainVersion());
+ Logger.msg("Kernel version: "+Resource.getKernelVersion());
+
+ // load kernel and domain mapfiles
+ try {
+ CastorXMLUtility.loadMapsFrom(Resource.getKernelResourceURL("mapFiles/"));
+ if (Resource.getDomainBaseURL()!=null)
+ CastorXMLUtility.loadMapsFrom(Resource.getDomainResourceURL("mapFiles/"));
+ } catch (MalformedURLException e1) {
+ throw new InvalidDataException("Invalid Resource Location", "");
+ }
+
+ //Initialise language file
+ String languageFile = getProperty("language.file");
+ if (languageFile != null && languageFile.length() > 0) {
+ Language.isTranlated=true;
+ Language.mTableOfTranslation = FileStringUtility.loadLanguageFile(languageFile);
+ }
+
+ try {
+ Resource.setImportURL(new URL("file:"+getProperty("Import.dir")));
+ } catch (MalformedURLException e) {
+ Logger.error("Import directory not set. "+getProperty("Import.dir"));
+ }
+ }
+
+ /**
+ * Makes this process capable of creating and managing server entities. Runs the
+ * bootstrap to create the root LDAP contexts, initialises the CORBA server and
+ * time-out manager.
+ *
+ * @throws InvalidDataException - error initialising
+ */
+ static public void startServer() throws InvalidDataException {
+ try {
+ // check top level LDAP contexts
+ mLDAPLookup.install();
+
+ // start entity proxy server
+ EntityProxyManager.initServer();
+
+ // Init ORB - set various config to sys properties
+ java.util.Properties sysProps = System.getProperties();
+ String serverName = getProperty("ItemServer.name");
+ if (serverName != null)
+ sysProps.put("ORBHost", serverName);
+ String serverPort = getProperty("ItemServer.iiop", "1500");
+ sysProps.put("ORBPort", serverPort);
+ sysProps.put("com.sun.CORBA.POA.ORBServerId", "1");
+ sysProps.put("com.sun.CORBA.POA.ORBPersistentServerPort", serverPort);
+
+ //Standard initialisation of the ORB
+ mORB = org.omg.CORBA.ORB.init(new String[0], sysProps);
+
+ Logger.msg("Gateway.init() - ORB initialised. ORB is " + mORB.getClass().getName() );
+
+ // start corba server components
+ mCorbaServer = new CorbaServer();
+
+ // start checking bootstrap items
+ Bootstrap.run();
+
+ } catch (Exception ex) {
+ Logger.error(ex);
+ Logger.die("Exception starting server components. Shutting down.");
+ }
+
+ // start the http server
+ try {
+ int httpPort = Integer.parseInt(Gateway.getProperty("ItemServer.HTTP.port"));
+ Logger.msg(2, "Starting HTTP Server on port "+httpPort);
+ mHTTPServer = new SimpleTCPIPServer(httpPort, ItemHTTPBridge.class, 5);
+ mHTTPServer.startListening();
+ } catch (NumberFormatException ex) {
+ Logger.msg(3, "Invalid or no HTTP port defined. HTTP server not available.");
+ }
+
+ System.out.println("Server '"+Gateway.getCentreId()+"' initialised.");
+ }
+
+ /**
+ * Connects to the LDAP server in an administrative context - using the admin username and
+ * password given in the LDAP.user and LDAP.password props of the kernel properties.
+ *
+ * @throws InvalidDataException - bad params
+ * @throws ClusterStorageException - error starting storages
+ */
+ static public void connect()
+ throws InvalidDataException,
+ ClusterStorageException
+ {
+ LDAPProperties ldapProps = new LDAPProperties();
+
+ if( ldapProps.mHost != null && ldapProps.mPort != null &&
+ ldapProps.mUser != null && ldapProps.mPassword != null )
+ {
+ try
+ {
+ mLDAPLookup = new LDAPLookup(ldapProps);
+ }
+ catch (Exception ex)
+ {
+ Logger.error(ex);
+ throw new InvalidDataException("Cannot authenticate. Name and/or password invalid.", "");
+ }
+ }
+ else
+ {
+ Logger.error("LDAP not configured properly.");
+ throw new InvalidDataException("Cannot authenticate. Name and/or password invalid.", "");
+ }
+
+ setup();
+ }
+
+ /**
+ * Authenticates a user and returns and AgentProxy on them without overriding the system LDAP context.
+ * Useful for handling multiple users in one context e.g. on a web server
+ *
+ * @param agentName - username
+ * @param agentPassword - password
+ * @return AgentProxy on that user
+ * @throws InvalidDataException
+ * @throws ObjectNotFoundException
+ */
+ static public AgentProxy login(String agentName, String agentPassword) throws InvalidDataException, ObjectNotFoundException {
+ LDAPProperties ldapProps = new LDAPProperties();
+ AgentPath agentPath;
+ try {
+ agentPath = mLDAPLookup.getRoleManager().getAgentPath(agentName);
+ } catch (Exception ex) {
+ Logger.error(ex);
+ throw new ObjectNotFoundException("Could not resolve agent", "");
+ }
+ String agentDN = agentPath.getFullDN();
+ ldapProps.mUser = agentDN;
+ ldapProps.mPassword = agentPassword;
+
+ try {
+ LDAPLookup.createConnection(ldapProps);
+ return (AgentProxy)getProxyManager().getProxy(mLDAPLookup.getRoleManager().getAgentPath(agentName));
+ } catch (Exception ex) {
+ Logger.error(ex);
+ throw new InvalidDataException("Could not log in", "");
+ }
+ }
+
+
+ /**
+ * Logs into the LDAP server with the given username and password, and initialises the lookup.
+ *
+ * @param agentName - username
+ * @param agentPassword - password
+ * @return an AgentProxy on the requested user
+ * @throws InvalidDataException
+ */
+ static public AgentProxy connect(String agentName, String agentPassword)
+ throws InvalidDataException
+ {
+
+ LDAPProperties ldapProps = new LDAPProperties();
+ if (ldapProps.mHost!=null && ldapProps.mPort!= null && ldapProps.mLocalPath!=null )
+ {
+ try {
+ ldapProps.mUser = "";
+ ldapProps.mPassword = "";
+ mLDAPLookup = new LDAPLookup(ldapProps);
+ String agentDN = mLDAPLookup.getRoleManager().getAgentPath(agentName).getFullDN();
+
+ //found agentDN, try to log in with it
+ ldapProps.mUser = agentDN;
+ ldapProps.mPassword = agentPassword;
+ mLDAPLookup = new LDAPLookup(ldapProps);
+
+ // find agent proxy
+ AgentPath agentPath = mLDAPLookup.getRoleManager().getAgentPath(agentName);
+
+ if (agentPath!=null)
+ {
+ setup();
+ return (AgentProxy) mProxyManager.getProxy(agentPath);
+ }
+ else
+ {
+ throw new InvalidDataException("The agentDN " +agentDN+ " is invalid.", "");
+ }
+ } catch (ClusterStorageException e) {
+ Logger.error(e);
+ throw new InvalidDataException(Language.translate("Error initialising storage")+Language.translate(". See log."), "");
+ } catch (ObjectNotFoundException e) {
+ Logger.error(e);
+ throw new InvalidDataException(Language.translate("Invalid username/password"), "");
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new InvalidDataException(Language.translate("Could not log in")+": "+Language.translate(e.getMessage()), "");
+ }
+
+ }
+ else
+ {
+ throw new InvalidDataException("Cannot log in. Some connection properties are not set.", "");
+ }
+
+ }
+
+ /**
+ * Initializes the storage and proxy manager, called during connect.
+ *
+ * @throws InvalidDataException
+ * @throws ClusterStorageException
+ */
+ static private void setup()
+ throws InvalidDataException,
+ ClusterStorageException
+ {
+
+ // Init storages
+ mStorage = new TransactionManager();
+ mProxyManager = new EntityProxyManager();
+
+ }
+
+ /**
+ * Shuts down all kernel api objects
+ */
+ public static void close()
+ {
+ // shut down servers if running
+ if (mCorbaServer != null)
+ mCorbaServer.close();
+ mCorbaServer = null;
+ if (mHTTPServer != null)
+ mHTTPServer.stopListening();
+ mHTTPServer = null;
+
+ // disconnect from storages
+ if (mStorage != null)
+ mStorage.close();
+ mStorage = null;
+
+ // disconnect from ldap
+ if (mLDAPLookup != null)
+ mLDAPLookup.disconnect();
+ mLDAPLookup = null;
+
+ // shut down proxy manager
+ if (mProxyManager != null)
+ mProxyManager.shutdown();
+ mProxyManager = null;
+ EntityProxyManager.shutdownServer();
+
+ // close log consoles
+ Logger.closeConsole();
+
+ // finally, destroy the ORB
+ getORB().destroy();
+ }
+
+ static public org.omg.CORBA.ORB getORB()
+ {
+ if (mORB == null)
+ mORB = org.omg.CORBA.ORB.init(new String[0], null);
+ return mORB;
+ }
+
+ static public LDAPLookup getLDAPLookup()
+ {
+ return mLDAPLookup;
+ }
+
+ static public CorbaServer getCorbaServer()
+ {
+ return mCorbaServer;
+ }
+
+ static public TransactionManager getStorage()
+ {
+ return mStorage;
+ }
+
+ static public EntityProxyManager getProxyManager()
+ {
+ return mProxyManager;
+ }
+
+ static public String getCentreId() {
+ return getProperty("LocalCentre");
+ }
+
+ static public String getProperty(String propName) {
+ return getProperty(propName, null);
+ }
+
+ static public String getProperty(String propName, String defaultValue) {
+ if (mC2KProps == null) return defaultValue;
+ return mC2KProps.getProperty(propName, defaultValue);
+ }
+
+ static public void setProperty(String propName, String propValue) {
+ if (mC2KProps == null) return;
+ mC2KProps.put(propName, propValue);
+ }
+
+ static public Enumeration propertyNames() {
+ return mC2KProps.propertyNames();
+ }
+
+ static public void dumpC2KProps(int logLevel) {
+ if (!Logger.doLog(logLevel)) return;
+ Logger.msg(logLevel, "C2K Properties:");
+ for (Enumeration e = propertyNames(); e.hasMoreElements();) {
+ String name = (String) e.nextElement();
+ Logger.msg(" "+name+": "+getProperty(name));
+ }
+ }
+}
+
diff --git a/source/com/c2kernel/process/ItemHTTPBridge.java b/source/com/c2kernel/process/ItemHTTPBridge.java
new file mode 100755
index 0000000..8ef2e58
--- /dev/null
+++ b/source/com/c2kernel/process/ItemHTTPBridge.java
@@ -0,0 +1,52 @@
+package com.c2kernel.process;
+
+import java.util.StringTokenizer;
+
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.server.HTTPRequestHandler;
+
+/* QueryData over HTTP Socket Handler
+ * Processes an HTTP request consisting of /<path to item>/<path to kernel object>
+ * and returns that kernel object as XML
+ * Currently supports GET requests.
+ * REVISIT: POST calls Item.request()
+ */
+
+public class ItemHTTPBridge extends HTTPRequestHandler {
+
+ public ItemHTTPBridge() { }
+
+ public String getName() {
+ return "Item HTTP Server";
+ }
+
+ public String processRequest() {
+ System.out.println("ItemHTTPBridge::ProcessRequest()");
+ StringTokenizer tok = new StringTokenizer(resource, "?");
+ String itemPath = tok.nextToken();
+ String query = tok.nextToken();
+ int sysKey = -1;
+ //Path path = Gateway.getLDAPLookup().;
+ if (method.equals("GET")) {
+ try {
+ DomainPath domPath = new DomainPath(itemPath);
+ EntityPath entityPath = domPath.getEntity();
+
+ if (sysKey > -1) {
+ C2KLocalObject response = Gateway.getStorage().get(sysKey, query, null);
+ return CastorXMLUtility.marshall(response);
+ }
+ else
+ return error("404 Not Found", "The entity "+sysKey+" you requested was not found.");
+ }
+ catch (Exception e) {
+ return error("400 Bad Request", "Usage: GET &lt;path to item&gt;?&lt;path to kernel object&gt;<br>"+e.getClass().getName());
+ }
+ }
+ return(super.processRequest());
+ }
+
+}
diff --git a/source/com/c2kernel/process/StandardClient.java b/source/com/c2kernel/process/StandardClient.java
new file mode 100755
index 0000000..00cebe6
--- /dev/null
+++ b/source/com/c2kernel/process/StandardClient.java
@@ -0,0 +1,16 @@
+/**************************************************************************
+ * StandardClient
+ *
+ * $Revision: 1.7 $
+ * $Date: 2003/04/25 16:17:12 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.process;
+
+abstract public class StandardClient extends AbstractMain
+{
+
+}
diff --git a/source/com/c2kernel/process/StandardServer.java b/source/com/c2kernel/process/StandardServer.java
new file mode 100755
index 0000000..2c9bcaf
--- /dev/null
+++ b/source/com/c2kernel/process/StandardServer.java
@@ -0,0 +1,125 @@
+/**************************************************************************
+ * StandardServer
+ *
+ * $Revision: 1.47 $
+ * $Date: 2005/04/28 13:49:43 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.process;
+
+import org.tanukisoftware.wrapper.WrapperListener;
+import org.tanukisoftware.wrapper.WrapperManager;
+
+import com.c2kernel.utils.Logger;
+
+/**************************************************************************
+ * Base class for all servers i.e. c2k processes that serve Entities
+ *
+ * @author $Author: abranson $ $Date: 2005/04/28 13:49:43 $
+ * @version $Revision: 1.47 $
+ **************************************************************************/
+public class StandardServer extends AbstractMain implements WrapperListener
+{
+ protected static StandardServer server;
+
+
+ /**************************************************************************
+ * C2KRootPOA suitable for Factory objects
+ **************************************************************************/
+
+
+
+
+
+ /**************************************************************************
+ * void StandardInitalisation( String[] )
+ *
+ * Set-up calls to ORB, POA and Factorys, both optional and required.
+ **************************************************************************/
+ protected void standardInitialisation( String[] args )
+ throws Exception
+ {
+ // read args and init Gateway
+ standardSetUp(args);
+
+ // connect to LDAP as root
+ Gateway.connect();
+
+ //start console
+ Logger.initConsole("ItemServer");
+
+ //initialize the server objects
+ Gateway.startServer();
+
+ Logger.msg(5, "StandardServer::standardInitialisation - complete.");
+
+ }
+
+
+ /**************************************************************************
+ * Sets up and runs and item server
+ **************************************************************************/
+ public Integer start(String[] args)
+ {
+ try
+ {
+ //initialise everything
+ standardInitialisation( args );
+ }
+ catch( Exception ex )
+ {
+ Logger.error(ex);
+ Logger.die("Startup failed");
+ }
+ return null;
+ }
+
+ public static void main(String[] args) {
+ server = new StandardServer();
+ AbstractMain.runningAsWrapper = true;
+ WrapperManager.start( server, args );
+ }
+
+ /**
+ *
+ */
+ public void controlEvent(int event) {
+ if (WrapperManager.isControlledByNativeWrapper()) {
+ // The Wrapper will take care of this event
+ } else {
+ // We are not being controlled by the Wrapper, so
+ // handle the event ourselves.
+ if ((event == WrapperManager.WRAPPER_CTRL_C_EVENT) ||
+ (event == WrapperManager.WRAPPER_CTRL_CLOSE_EVENT) ||
+ (event == WrapperManager.WRAPPER_CTRL_SHUTDOWN_EVENT)){
+ WrapperManager.stop(0);
+ }
+ }
+
+ }
+
+ /**************************************************************************
+ * Closes all listeners, quits the VM.
+ * This method should be called to kill the server process
+ * e.g. from the NT service wrapper
+ **************************************************************************/
+ public int stop(int arg0) {
+ try
+ {
+ // close gateway
+ standardTearDown();
+ }
+ catch( Exception ex )
+ {
+ Logger.error(ex);
+ return 1;
+ }
+
+ Logger.msg("StandardServer::shutdown - complete. ");
+ return 0;
+ }
+
+}
diff --git a/source/com/c2kernel/process/UserCodeProcess.java b/source/com/c2kernel/process/UserCodeProcess.java
new file mode 100755
index 0000000..7eff37b
--- /dev/null
+++ b/source/com/c2kernel/process/UserCodeProcess.java
@@ -0,0 +1,229 @@
+package com.c2kernel.process;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.InvalidTransitionException;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.entity.agent.Job;
+import com.c2kernel.entity.proxy.AgentProxy;
+import com.c2kernel.entity.proxy.EntityProxyObserver;
+import com.c2kernel.entity.proxy.MemberControl;
+import com.c2kernel.lifecycle.instance.stateMachine.Transitions;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.utils.Logger;
+
+/**************************************************************************
+ *
+ * $Revision: 1.31 $
+ * $Date: 2004/10/21 08:02:19 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+public class UserCodeProcess extends StandardClient implements EntityProxyObserver, Runnable {
+ protected AgentProxy agent;
+ static boolean active = true;
+ ArrayList ignoredPaths = new ArrayList();
+ HashMap jobs;
+
+ public UserCodeProcess(String agentName, String agentPass) {
+ // login - try for a while in case server hasn't imported our user yet
+ for (int i=1;i<6;i++) {
+ try {
+ Logger.msg("Login attempt "+i+" of 5");
+ agent = Gateway.connect(agentName, agentPass);
+ break;
+ } catch (InvalidDataException ex) {
+ Logger.error("Could not log in.");
+ Logger.error(ex);
+ try {
+ Thread.sleep(5000);
+ } catch (InterruptedException ex2) { }
+ }
+ }
+ System.out.println(getDesc()+" initialised for " + agentName);
+ }
+
+ public void run() {
+ Thread.currentThread().setName("Usercode Process");
+ jobs = new HashMap();
+ // subscribe to job list
+ agent.subscribe(this, ClusterStorage.JOB, true);
+ while (active) {
+ Job thisJob = null;
+ synchronized (jobs) {
+ if (jobs.size() > 0) {
+ thisJob = getJob(jobs, Transitions.COMPLETE);
+ if (thisJob == null)
+ thisJob = getJob(jobs, Transitions.START);
+ if (thisJob == null)
+ thisJob = getJob(jobs, Transitions.SUSPEND);
+ if (thisJob == null)
+ thisJob = getJob(jobs, Transitions.RESUME);
+
+ if (thisJob == null) {
+ Logger.error("No supported jobs, but joblist is not empty! Discarding remaining jobs");
+ jobs.clear();
+ }
+ else
+ jobs.remove(ClusterStorage.getPath(thisJob));
+ }
+ }
+
+ if (thisJob != null) {
+ String jobKey = thisJob.getItemSysKey()+":"+thisJob.getStepPath();
+ try {
+ if (thisJob.getPossibleTransition()==Transitions.START) {
+ Logger.msg(5, "Testing start conditions");
+ boolean start = assessStartConditions(thisJob);
+ if (start) {
+ Logger.msg(5, "Attempting to start");
+ agent.execute(thisJob);
+ }
+ else {
+ Logger.msg(5, "Start conditions failed "+thisJob.getStepName()+" in "+thisJob.getItemSysKey());
+ }
+ }
+ else if (thisJob.getPossibleTransition()==Transitions.COMPLETE) {
+ Logger.msg(5, "Executing logic");
+ runUCLogic(thisJob);
+ if (ignoredPaths.contains(jobKey))
+ ignoredPaths.remove(jobKey);
+ }
+ else if (thisJob.getPossibleTransition()==Transitions.SUSPEND) {
+ if (ignoredPaths.contains(jobKey))
+ agent.execute(thisJob);
+ }
+ else if (thisJob.getPossibleTransition()==Transitions.RESUME) {
+ if (!ignoredPaths.contains(jobKey))
+ agent.execute(thisJob);
+ }
+ } catch (InvalidTransitionException ex) {
+ // must have already been done by someone else - ignore
+ } catch (Throwable ex) {
+ Logger.error("Error executing "+Transitions.getTransitionName(thisJob.getPossibleTransition())+" job:");
+ Logger.error(ex);
+ ignoredPaths.add(jobKey);
+ }
+ }
+ try {
+ synchronized (jobs) {
+ if (jobs.size() == 0) {
+ Logger.msg("Sleeping");
+ while (active && jobs.size() == 0)
+ jobs.wait(2000);
+ }
+ }
+ } catch (InterruptedException ex) { }
+ }
+
+ // shut down
+ try
+ {
+ standardTearDown();
+ }
+ catch( Exception ex )
+ {
+ Logger.error(ex);
+ }
+ }
+
+ private Job getJob(HashMap jobs, int transition) {
+ for (Iterator list = jobs.values().iterator();list.hasNext();) {
+ Job thisJob = (Job)list.next();
+ if (thisJob.getPossibleTransition() == transition) {
+ Logger.msg(1,"=================================================================");
+ Logger.msg(1, "Got "+Transitions.getTransitionName(transition)+" job for "+thisJob.getStepName()+" in "+thisJob.getItemSysKey());
+ return thisJob;
+ }
+ }
+ return null;
+ }
+
+ public boolean assessStartConditions(Job job) {
+ // default implementation - has no start conditions.
+ return true;
+ }
+
+ public void runUCLogic(Job job) throws Exception {
+ // default implementation - the agent will execute any scripts defined when we execute
+ agent.execute(job);
+ }
+
+
+ /**
+ * Receives job from the AgentProxy. Reactivates thread if sleeping.
+ */
+ public void add(C2KLocalObject contents) {
+ if (contents instanceof MemberControl) {
+ MemberControl ctrl = (MemberControl)contents;
+ Logger.msg(5,ctrl.toString());
+ }
+ else
+ synchronized(jobs) {
+ Logger.msg(7, "Adding "+ClusterStorage.getPath(contents));
+ jobs.put(ClusterStorage.getPath(contents), contents);
+ jobs.notify();
+ }
+
+ }
+
+ /**
+ * Removes job removal notification from the AgentProxy.
+ */
+ public void remove(String id) {
+ synchronized(jobs) {
+ Logger.msg(7, "Deleting "+id);
+ jobs.remove(id);
+ }
+ }
+
+ public static UserCodeProcess getInstance() throws UnknownHostException {
+ return new UserCodeProcess(InetAddress.getLocalHost().getHostName(), "uc");
+ }
+
+ static public void main(String[] args)
+ {
+ int status = 0;
+
+ try
+ {
+ standardSetUp(args);
+ UserCodeProcess proc = getInstance();
+ new Thread(proc).start();
+ Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
+ public void run() {
+ shutdown();
+ }
+ }));
+ }
+ catch( Exception ex )
+ {
+ Logger.error(ex);
+
+ try
+ {
+ standardTearDown();
+ }
+ catch(Exception ex1)
+ {
+ Logger.error(ex1);
+ }
+ status = 1;
+ System.exit(status);
+ }
+ }
+
+ public String getDesc() {
+ return("Usercode Process");
+ }
+
+ public static void shutdown() {
+ active = false;
+ }
+}
diff --git a/source/com/c2kernel/property/Property.java b/source/com/c2kernel/property/Property.java
new file mode 100755
index 0000000..2374c1b
--- /dev/null
+++ b/source/com/c2kernel/property/Property.java
@@ -0,0 +1,82 @@
+/**************************************************************************
+ *
+ * $Revision: 1.3 $
+ * $Date: 2003/10/03 12:31:28 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.property;
+
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.persistency.ClusterStorage;
+
+
+public class Property implements C2KLocalObject
+{
+ private String mName;
+ private String mValue;
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public Property()
+ {
+ setName( "" );
+ setValue( "" );
+ }
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public Property( String name, String value )
+ {
+ setName( name );
+ setValue( value );
+ }
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public void setName(String name)
+ {
+ mName = name;
+ }
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public String getName()
+ {
+ return mName;
+ }
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public void setValue( String value )
+ {
+ mValue = value;
+ }
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public String getValue()
+ {
+ return mValue;
+ }
+ /**
+ * @see com.c2kernel.entity.C2KLocalObject#getClusterType()
+ */
+ public String getClusterType() {
+ return ClusterStorage.PROPERTY;
+ }
+
+}
diff --git a/source/com/c2kernel/property/PropertyArrayList.java b/source/com/c2kernel/property/PropertyArrayList.java
new file mode 100755
index 0000000..71fc9b7
--- /dev/null
+++ b/source/com/c2kernel/property/PropertyArrayList.java
@@ -0,0 +1,29 @@
+/**************************************************************************
+ *
+ * $Revision: 1.2 $
+ * $Date: 2003/06/20 11:44:30 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.property;
+
+import java.util.ArrayList;
+
+import com.c2kernel.utils.CastorArrayList;
+
+public class PropertyArrayList extends CastorArrayList
+{
+ public PropertyArrayList()
+ {
+ super();
+ }
+
+ public PropertyArrayList(ArrayList aList)
+ {
+ super(aList);
+ }
+
+
+}
diff --git a/source/com/c2kernel/property/PropertyDescription.java b/source/com/c2kernel/property/PropertyDescription.java
new file mode 100755
index 0000000..dbbd6b9
--- /dev/null
+++ b/source/com/c2kernel/property/PropertyDescription.java
@@ -0,0 +1,77 @@
+/**************************************************************************
+ *
+ * $Revision: 1.5 $
+ * $Date: 2003/05/16 11:36:47 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.property;
+
+public class PropertyDescription
+{
+ private String mName=null;
+ private String mDefaultValue=null;
+ private boolean mIsClassIdentifier=false;
+ private boolean mIsMutable=false;
+
+
+ public PropertyDescription()
+ {
+ }
+
+ public PropertyDescription(String name, String defaultValue, boolean isClassIdentifier, boolean isMutable )
+ {
+ setName(name);
+ setDefaultValue(defaultValue);
+ setIsClassIdentifier(isClassIdentifier);
+ setIsMutable(isMutable);
+ }
+
+ public void setName(String name)
+ {
+ mName = name;
+ }
+
+ public void setIsClassIdentifier(boolean classId)
+ {
+ mIsClassIdentifier = classId;
+ }
+
+ public void setDefaultValue(String defaultValue)
+ {
+ mDefaultValue = defaultValue;
+ }
+
+ public void setIsMutable(boolean mutable)
+ {
+ mIsMutable = mutable;
+ }
+
+ public String getName()
+ {
+ return mName;
+ }
+
+ public boolean getIsClassIdentifier()
+ {
+ return mIsClassIdentifier;
+ }
+
+ public String getDefaultValue()
+ {
+ return mDefaultValue;
+ }
+
+ public boolean getIsMutable()
+ {
+ return mIsMutable;
+ }
+
+ public Property getProperty()
+ {
+ return new Property(mName,mDefaultValue);
+ }
+
+}
diff --git a/source/com/c2kernel/property/PropertyDescriptionList.java b/source/com/c2kernel/property/PropertyDescriptionList.java
new file mode 100755
index 0000000..596aa52
--- /dev/null
+++ b/source/com/c2kernel/property/PropertyDescriptionList.java
@@ -0,0 +1,53 @@
+/**************************************************************************
+ *
+ * $Revision: 1.3 $
+ * $Date: 2003/07/18 12:43:53 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.property;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import com.c2kernel.utils.CastorArrayList;
+
+public class PropertyDescriptionList extends CastorArrayList
+{
+ public PropertyDescriptionList()
+ {
+ super();
+ }
+
+ public PropertyDescriptionList(ArrayList aList)
+ {
+ super(aList);
+ }
+
+ public String getClassProps() {
+ StringBuffer props = new StringBuffer();
+ for (Iterator iter = list.iterator(); iter.hasNext();) {
+ PropertyDescription element = (PropertyDescription)iter.next();
+ if (element.getIsClassIdentifier()) {
+ if (props.length()>0)
+ props.append(",");
+ props.append(element.getName());
+ }
+ }
+ return props.toString();
+ }
+
+ public boolean setDefaultValue(String name, String value) {
+ for (Iterator iter = list.iterator(); iter.hasNext();) {
+ PropertyDescription element = (PropertyDescription)iter.next();
+ if (element.getName().equals(name)) {
+ element.setDefaultValue(value);
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/source/com/c2kernel/property/PropertyUtility.java b/source/com/c2kernel/property/PropertyUtility.java
new file mode 100755
index 0000000..9c65598
--- /dev/null
+++ b/source/com/c2kernel/property/PropertyUtility.java
@@ -0,0 +1,87 @@
+/**************************************************************************
+ *
+ * $Revision: 1.4 $
+ * $Date: 2004/10/21 08:02:26 $
+ *
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+package com.c2kernel.property;
+
+import java.util.ArrayList;
+
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.persistency.outcome.Outcome;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.CastorHashMap;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.Logger;
+
+
+public class PropertyUtility
+{
+ static public String getValue(ArrayList pdlist, String name)
+ {
+ Object[] values = pdlist.toArray();
+ for (int i=0;i<values.length;i++)
+ {
+ PropertyDescription pd = (PropertyDescription) values[i];
+ if ( name.equalsIgnoreCase(pd.getName()) )
+ return pd.getDefaultValue();
+ }
+ return null;
+ }
+
+ static public String getNames(ArrayList pdlist)
+ {
+ Object[] values = pdlist.toArray();
+ StringBuffer names = new StringBuffer();
+ for (int i=0;i<values.length;i++)
+ names.append( ((PropertyDescription)values[i]).getDefaultValue()).append(" ");
+ return names.toString();
+ }
+
+ static public String getClassIdNames(ArrayList pdlist)
+ {
+ Object[] values = pdlist.toArray();
+ StringBuffer names = new StringBuffer();
+ for (int i=0;i<values.length;i++)
+ {
+ PropertyDescription pd = ((PropertyDescription)values[i]);
+ if (pd.getIsClassIdentifier())
+ names.append(pd.getName());
+ if (i<values.length-1 && i!=0)
+ names.append(",");
+ }
+ return names.toString();
+ }
+
+
+ static public PropertyDescriptionList getPropertyDescriptionOutcome(int entityKey)
+ {
+ try
+ {
+ Outcome outc = (Outcome) Gateway.getStorage().get(entityKey, ClusterStorage.VIEWPOINT+"/PropertyDescription/last/data", null);
+ return (PropertyDescriptionList)CastorXMLUtility.unmarshall(outc.getData());
+ }
+ catch (Exception ex)
+ {
+ Logger.error(ex);
+ return null;
+ }
+ }
+
+ static public CastorHashMap createProperty(PropertyDescriptionList pdList)
+ {
+ CastorHashMap props = new CastorHashMap();
+ for (int i=0; i< pdList.list.size();i++)
+ {
+ PropertyDescription pd = (PropertyDescription) pdList.list.get(i);
+ if (pd.getIsClassIdentifier())
+ props.put(pd.getName(),pd.getDefaultValue());
+ }
+ return props;
+ }
+
+}
diff --git a/source/com/c2kernel/scripting/ErrorInfo.java b/source/com/c2kernel/scripting/ErrorInfo.java
new file mode 100755
index 0000000..2714b93
--- /dev/null
+++ b/source/com/c2kernel/scripting/ErrorInfo.java
@@ -0,0 +1,43 @@
+package com.c2kernel.scripting;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**************************************************************************
+ *
+ * $Revision: 1.2 $
+ * $Date: 2003/06/06 11:37:45 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+public class ErrorInfo {
+ ArrayList msg;
+ boolean fatal = false;
+
+ public ErrorInfo() {
+ super();
+ msg = new ArrayList();
+ }
+
+ public void addError(String error) {
+ msg.add(error);
+ }
+
+ public String getErrors() {
+ StringBuffer err = new StringBuffer();
+ for (Iterator iter = msg.iterator(); iter.hasNext();) {
+ String element = (String)iter.next();
+ err.append(element+"\n");
+ }
+ return err.toString();
+ }
+
+ public void setFatal() {
+ fatal=true;
+ }
+
+ public boolean getFatal() {
+ return fatal;
+ }
+}
diff --git a/source/com/c2kernel/scripting/Parameter.java b/source/com/c2kernel/scripting/Parameter.java
new file mode 100755
index 0000000..c51c9d4
--- /dev/null
+++ b/source/com/c2kernel/scripting/Parameter.java
@@ -0,0 +1,47 @@
+package com.c2kernel.scripting;
+
+
+/**************************************************************************
+* Place holder for the Parameter details to be passed to the script.
+**************************************************************************/
+public class Parameter {
+
+ private String name;
+ private Class type;
+ private boolean initialised=false;
+
+ public Parameter(String name) {
+ this.name = name;
+ }
+
+ public void setName(String n)
+ {
+ name=n;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setType(Class t)
+ {
+ type=t;
+ }
+
+ public Class getType()
+ {
+ return type;
+ }
+
+ public void setInitialised(boolean state)
+ {
+ initialised=state;
+ }
+
+ public boolean getInitialised()
+ {
+ return initialised;
+ }
+
+}
diff --git a/source/com/c2kernel/scripting/ParameterException.java b/source/com/c2kernel/scripting/ParameterException.java
new file mode 100755
index 0000000..b191908
--- /dev/null
+++ b/source/com/c2kernel/scripting/ParameterException.java
@@ -0,0 +1,20 @@
+package com.c2kernel.scripting;
+
+public class ParameterException extends ScriptingEngineException {
+
+ /**
+ * Creates new <code>ParameterException</code> without detail message.
+ */
+ public ParameterException() {
+ }
+
+ /**
+ * Constructs an <code>ParameterException</code> with the specified detail message.
+ * @param msg the detail message.
+ */
+ public ParameterException(String msg) {
+ super(msg);
+ }
+}
+
+
diff --git a/source/com/c2kernel/scripting/Script.java b/source/com/c2kernel/scripting/Script.java
new file mode 100755
index 0000000..7b1c6db
--- /dev/null
+++ b/source/com/c2kernel/scripting/Script.java
@@ -0,0 +1,438 @@
+package com.c2kernel.scripting;
+
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.xml.sax.InputSource;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.agent.Job;
+import com.c2kernel.entity.proxy.AgentProxy;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.utils.LocalObjectLoader;
+import com.c2kernel.utils.Logger;
+import com.ibm.bsf.BSFException;
+import com.ibm.bsf.BSFManager;
+
+/**************************************************************************
+ *
+ * $Revision: 1.25 $
+ * $Date: 2005/10/05 07:39:37 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+public class Script
+{
+ Class mOutputClass;
+ String mOutputName;
+ String mScript = "";
+ String mName;
+ String mVersion;
+ String mLang;
+ HashMap mInputParams = new HashMap();
+ HashMap mAllInputParams = new HashMap();
+ ArrayList mIncludes = new ArrayList();
+ BSFManager scriptManager;
+
+ /**
+ * Loads script xml and parses it for script source, parameters and output specifications.
+ * First tries to load the script from resource path /scriptFiles/scriptName_scriptVersion.xml
+ * If not found tries to find item at /desc/ScriptDesc/scriptName and load Viewpoint scriptVersion from it.
+ *
+ * For the specification of script xml, see the Script schema from resources.
+ *
+ * @param scriptName - name of the script
+ * @param scriptVersion - named version of the script (must be numbered viewpoint)
+ * @throws ScriptParsingException - when script not found (ScriptLoadingException) or xml is invalid (ScriptParsingException)
+ */
+ public Script(String scriptName, int scriptVersion) throws ScriptingEngineException
+ {
+ this(scriptName, scriptVersion, new BSFManager());
+ }
+
+ public Script(String scriptName, int scriptVersion, BSFManager scriptManager) throws ScriptingEngineException
+ {
+ mName = scriptName;
+ mVersion = String.valueOf(scriptVersion);
+ if (scriptName.equals("")) return;
+ setScriptEnv(scriptManager);
+ setScript(mName, mVersion);
+ }
+
+ /**
+ * Creates a script executor for the supplied expression, bypassing the xml parsing bit
+ * Output class is forced to an object.
+ */
+ public Script(String lang, String expr, BSFManager scriptManager) throws ScriptingEngineException
+ {
+ setScriptEnv(scriptManager);
+ mName = "<expr>";
+ mLang = lang;
+ mVersion = "";
+ mOutputClass = Object.class;
+ mScript = expr;
+ }
+
+ public Script(String lang, String expr) throws ScriptingEngineException
+ {
+ this(lang, expr, new BSFManager());
+ }
+
+ public Script(ItemProxy object, AgentProxy subject, Job job) throws ScriptingEngineException
+ {
+ this(job.getActPropString("ScriptName"), job.getActPropString("ScriptVersion") == null ? -1 : Integer.parseInt(job.getActPropString("ScriptVersion")));
+ // set enviroment - this needs to be well documented for script developers
+ addInputParam("item", "com.c2kernel.entity.proxy.ItemProxy");
+ setInputParamValue("item", object);
+
+ addInputParam("agent", "com.c2kernel.entity.proxy.AgentProxy");
+ setInputParamValue("agent", subject);
+
+ addInputParam("job", "com.c2kernel.entity.agent.Job");
+ setInputParamValue("job", job);
+
+ setOutput("errors", "com.c2kernel.scripting.ErrorInfo");
+ }
+
+ public void setScript(String scriptName, String scriptVersion) throws ScriptingEngineException
+ {
+ try
+ {
+ mName = scriptName;
+ mVersion = scriptVersion;
+ parseScriptXML(LocalObjectLoader.getScript(scriptName, scriptVersion));
+ }
+ catch (ObjectNotFoundException e)
+ {
+ throw new ScriptingEngineException("Script "+scriptName+" not found");
+ }
+ }
+
+ public void setScriptEnv(BSFManager manager) {
+ this.scriptManager = manager;
+ }
+
+ /**
+ * Extracts script data from script xml.
+ *
+ * @param scriptXML
+ * @throws ScriptParsingException - when script is invalid
+ */
+ private void parseScriptXML(String scriptXML) throws ScriptParsingException, ParameterException
+ {
+ Document scriptDoc = null;
+
+ // get the DOM document from the XML
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ try
+ {
+ DocumentBuilder domBuilder = factory.newDocumentBuilder();
+ scriptDoc = domBuilder.parse(new InputSource(new StringReader(scriptXML)));
+ }
+ catch (Exception ex)
+ {
+ throw new ScriptParsingException("Error parsing Script XML : " + ex.toString());
+ }
+
+ Element root = scriptDoc.getDocumentElement();
+ NodeList scriptNodes = root.getChildNodes();
+ for (int i = 0; i < scriptNodes.getLength(); i++)
+ {
+ Element currentParam;
+ String paramName;
+
+ try
+ {
+ currentParam = (Element) scriptNodes.item(i);
+ }
+ catch (ClassCastException ex)
+ {
+ // not an element, skip
+ continue;
+ }
+ paramName = currentParam.getTagName();
+ Logger.msg(9, "Script.parseScriptXML() - Found element " + paramName);
+
+ // Process script parameters
+
+ // New input parameter
+ if (paramName.equals("param"))
+ {
+ if (!(currentParam.hasAttribute("name") && currentParam.hasAttribute("type")))
+ throw new ScriptParsingException("Script Input Param incomplete, must have name and type");
+ addInputParam(currentParam.getAttribute("name"), currentParam.getAttribute("type"));
+ }
+
+ //load output type
+ else if (paramName.equals("output"))
+ {
+ if (!currentParam.hasAttribute("type"))
+ throw new ScriptParsingException("Script Output declaration incomplete, must have type");
+ setOutput(currentParam.getAttribute("name"), currentParam.getAttribute("type"));
+ }
+
+ //load any included scripts
+ else if (paramName.equals("include"))
+ {
+ if (!(currentParam.hasAttribute("name") && currentParam.hasAttribute("version")))
+ throw new ScriptParsingException("Script include declaration incomplete, must have name and version");
+ String includeName = currentParam.getAttribute("name");
+ String includeVersion = currentParam.getAttribute("version");
+ try {
+ Script includedScript = new Script(includeName, Integer.parseInt(includeVersion), scriptManager);
+ mIncludes.add(includedScript);
+ for (Iterator iter = includedScript.getInputParams().values().iterator(); iter.hasNext();) {
+ Parameter includeParam = (Parameter) iter.next();
+ addIncludedInputParam(includeParam.getName(), includeParam.getType());
+ }
+ } catch (NumberFormatException e) {
+ throw new ScriptParsingException("Invalid version in imported script "+includeName+"_"+includeVersion);
+ } catch (ScriptingEngineException e) {
+ throw new ScriptParsingException("Error parsing imported script "+includeName+"_"+includeVersion+": "+e.getMessage());
+ }
+
+
+ }
+ //load Script
+ else if (paramName.equals("script"))
+ {
+ if (!currentParam.hasAttribute("language"))
+ throw new ScriptParsingException("Script data incomplete, must have language");
+ Logger.msg(6, "Script.parseScriptXML() - Script Language: " + currentParam.getAttribute("language"));
+ mLang = currentParam.getAttribute("language");
+
+ // get script source
+ NodeList scriptChildNodes = currentParam.getChildNodes();
+ if (scriptChildNodes.getLength() != 1)
+ throw new ScriptParsingException("More than one child element found under script tag. Script characters may need escaping - suggest convert to CDATA section");
+ if (scriptChildNodes.item(0) instanceof Text)
+ mScript = ((Text) scriptChildNodes.item(0)).getData();
+ else
+ throw new ScriptParsingException("Child element of script tag was not text");
+ Logger.msg(6, "Script.parseScriptXML() - script:" + mScript);
+ }
+ }
+ }
+
+ protected void addInputParam(String name, String type) throws ParameterException
+ {
+ Parameter inputParam = new Parameter(name);
+
+ try
+ {
+ inputParam.setType(Class.forName(type));
+ }
+ catch (ClassNotFoundException ex)
+ {
+ throw new ParameterException("Input parameter " + inputParam.getName() + " specifies class " + type + " which was not found.");
+ }
+
+ Logger.msg(6, "ScriptExecutor.parseScriptXML() - declared parameter " + name + " (" + type + ")");
+ //add parameter to hashtable
+ mInputParams.put(inputParam.getName(), inputParam);
+ mAllInputParams.put(inputParam.getName(), inputParam);
+
+ }
+
+ protected void addIncludedInputParam(String name, Class type) throws ParameterException
+ {
+ // check if we already have it
+ if (mAllInputParams.containsKey(name)) {
+ Parameter existingParam = (Parameter)mAllInputParams.get(name);
+ // check the types match
+ if (existingParam.getType() == type)
+ return; // matches
+ else // error
+ throw new ParameterException("Parameter conflict. Parameter'"+name+"' is declared as "
+ +existingParam.getType().getName()+" is declared in another script as "+type.getName());
+ }
+
+ Parameter inputParam = new Parameter(name);
+ inputParam.setType(type);
+
+ //add parameter to hashtable
+ mAllInputParams.put(inputParam.getName(), inputParam);
+
+ }
+
+
+ protected void setOutput(String name, String type) throws ScriptParsingException
+ {
+ mOutputName = name;
+
+ // set name to null if empty
+ if (mOutputName != null && mOutputName.equals(""))
+ mOutputName = null;
+
+ try
+ {
+ Logger.msg(6, "Script.setOutput() - Output: " + name + " (" + type + ")");
+ mOutputClass = Class.forName(type);
+ }
+ catch (ClassNotFoundException ex)
+ {
+ throw new ScriptParsingException("Output class "+type+" not found");
+ }
+
+ // set up the output object if named
+ // we declare this now so imported scripts using the same object will not overwrite each other during execution
+ if (mOutputName!=null)
+ try
+ {
+ Logger.msg(8, "Script.setOutput() - Initialising output bean '" + mOutputName + "'");
+ Object emptyObject = mOutputClass.newInstance();
+ scriptManager.declareBean(mOutputName, emptyObject, mOutputClass);
+ }
+ catch (Exception ex)
+ {
+ Logger.error(ex);
+ throw new ScriptParsingException("Error initialising output bean: "+ex.getMessage());
+ }
+
+ }
+
+ /**
+ * Gets all declared parameters
+ * @return HashMap of String (name), com.c2kernel.scripting.Parameter (param)
+ * @see com.c2kernel.scripting.Parameter
+ */
+ public HashMap getInputParams()
+ {
+ return mInputParams;
+ }
+
+ /**
+ * Gets all declared parameters, including those of imported scripts
+ * @return HashMap of String (name), com.c2kernel.scripting.Parameter (param)
+ * @see com.c2kernel.scripting.Parameter
+ */
+ public HashMap getAllInputParams()
+ {
+ return mAllInputParams;
+ }
+
+ /**
+ * Submits an input parameter to the script. Must be declared by name and type in the script XML.
+ *
+ * @param name - input parameter name from the script xml
+ * @param value - object to use for this parameter
+ * @throws ParameterException - name not found or wrong type
+ */
+ public void setInputParamValue(String name, Object value) throws ParameterException
+ {
+ Parameter param = (Parameter) mInputParams.get(name);
+
+ if (!mAllInputParams.containsKey(name))
+ throw new ParameterException("Parameter " + name + " not found in parameter list");
+
+ if (param != null) { // param is in this script
+ if (value.getClass() != param.getType())
+ throw new ParameterException(
+ "Parameter " + name + " is wrong type \n" + "Required: " + param.getType().toString() + "\n" + "Supplied: " + value.getClass().toString());
+ try {
+ scriptManager.declareBean(name, value, param.getType());
+ Logger.msg(7, "Script.setInputParamValue() - " + name + ": " + value.toString());
+ param.setInitialised(true);
+ } catch (BSFException ex) {
+ throw new ParameterException("Error initialising parameter '"+name+"' - "+ex.getMessage());
+ }
+ }
+
+ // pass param down to child scripts
+ for (Iterator iter = mIncludes.iterator(); iter.hasNext();) {
+ Script importScript = (Script) iter.next();
+ importScript.setInputParamValue(name, value);
+ }
+ }
+
+ /**
+ * Executes the script with the submitted parameters. All declared input parametes should have been set first.
+ *
+ * @return The return value depends on the way the output type was declared in the script xml.
+ * <ul><li>If there was no output class declared then null is returned
+ * <li>If a class was declared, but not named, then the object returned by the script is checked
+ * to be of that type, then returned.
+ * <li>If the output value was named and typed, then an object of that class is created and
+ * passed to the script as an input parameter. The script should set this before it returns.
+ * </ul>
+ * @throws ScriptingEngineException - input parameters weren't set, there was an error executing the script, or the output was invalid
+ */
+ public Object execute() throws ScriptingEngineException
+ {
+ Object returnValue = null;
+ Object outputValue = null;
+
+ // check input params
+ StringBuffer missingParams = new StringBuffer();
+ for (Iterator iter = mInputParams.values().iterator(); iter.hasNext();)
+ {
+ Parameter thisParam = (Parameter) iter.next();
+ if (!thisParam.getInitialised())
+ missingParams.append(thisParam.getName()).append("\n");
+ }
+ // croak if any missing
+ if (missingParams.length() > 0)
+ throw new ScriptingEngineException("Execution aborted, the following declared parameters were not set: \n" + missingParams.toString());
+
+ // execute the child scripts
+ for (Iterator iter = mIncludes.iterator(); iter.hasNext();) {
+ Script importScript = (Script) iter.next();
+ importScript.execute();
+ }
+
+
+ // run the script
+ try
+ {
+ Logger.msg(7, "Script.execute() - Executing script");
+ scriptManager.setDebug(Logger.doLog(8));
+ returnValue = scriptManager.eval(mLang, mName, 0, 0, mScript);
+ Logger.msg(8, "Script.execute() - script returned \"" + returnValue + "\"");
+ if (mOutputName != null)
+ {
+ // retrieve the value from the registered output bean
+ outputValue = scriptManager.lookupBean(mOutputName);
+ Logger.msg(8, "Script.execute() - output bean value: \"" + outputValue + "\"");
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new ScriptingEngineException("Error executing script: " + ex.getMessage());
+ }
+
+ // if no output class specified, return null
+ if (mOutputClass == null)
+ return null;
+
+ // if output name not specified, then check the return value against the output class
+ if (mOutputName == null && returnValue != null && !(mOutputClass.isInstance(returnValue)))
+ throw new ScriptingEngineException(
+ "Script return value was not null or instance of " + mOutputClass.getName() + ", it was " + returnValue.getClass().getName());
+
+ // return the output, or the return value if output name isn't defined
+ if (mOutputName != null)
+ return outputValue;
+ else
+ return returnValue;
+ }
+
+ /**
+ * Resets the scripting enviroment, clearing all state and parameters for another execution.
+ */
+ public void reset()
+ {
+ for (Iterator iter = mInputParams.values().iterator(); iter.hasNext();)
+ ((Parameter) iter.next()).setInitialised(false);
+ scriptManager = new BSFManager();
+ }
+}
diff --git a/source/com/c2kernel/scripting/ScriptConsole.java b/source/com/c2kernel/scripting/ScriptConsole.java
new file mode 100755
index 0000000..c144ef7
--- /dev/null
+++ b/source/com/c2kernel/scripting/ScriptConsole.java
@@ -0,0 +1,234 @@
+package com.c2kernel.scripting;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.InterruptedIOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintStream;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+
+import org.omg.CORBA.ORB;
+import org.tanukisoftware.wrapper.WrapperManager;
+
+import com.c2kernel.entity.proxy.AgentProxy;
+import com.c2kernel.entity.proxy.EntityProxyManager;
+import com.c2kernel.lookup.LDAPLookup;
+import com.c2kernel.persistency.TransactionManager;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.Resource;
+import com.c2kernel.utils.server.SocketHandler;
+import com.ibm.bsf.BSFEngine;
+import com.ibm.bsf.BSFException;
+import com.ibm.bsf.BSFManager;
+
+/**************************************************************************
+ *
+ * $Revision: 1.16 $
+ * $Date: 2005/08/31 07:20:40 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+
+
+public class ScriptConsole implements SocketHandler {
+ BufferedReader input;
+ PrintStream output;
+ Socket socket = null;
+ BSFManager manager;
+ BSFEngine context;
+ static ArrayList securityHosts = new ArrayList();
+ public static final short NONE = 0;
+ public static final short ALLOW = 1;
+ public static final short DENY = 2;
+ static short securityMode;
+
+ static {
+ securityMode = ALLOW;
+ String hosts = Gateway.getProperty("ItemServer.Console.allow");
+ if (hosts == null || hosts.equals("")) {
+ securityMode = DENY;
+ hosts = Gateway.getProperty("ItemServer.Console.deny");
+ }
+ if (hosts == null || hosts.equals("")) { // by default only allow localhost
+ securityMode = ALLOW;
+ securityHosts.add("127.0.0.1");
+ }
+ else {
+ StringTokenizer tok = new StringTokenizer(hosts, ",");
+ while(tok.hasMoreTokens()) {
+ try {
+ securityHosts.add(InetAddress.getByName(tok.nextToken()).getHostAddress());
+ } catch (UnknownHostException ex) {
+ Logger.error("Host not found "+ex.getMessage());
+ }
+ }
+ }
+ }
+ public ScriptConsole() {
+ }
+
+ public String getName() {
+ return "Script Console";
+ }
+
+ public boolean isBusy() {
+ return (socket != null);
+ }
+
+ public void setSocket(Socket newSocket) {
+ try {
+ input = new BufferedReader(new InputStreamReader(newSocket.getInputStream()));
+ OutputStreamWriter ansi = new OutputStreamWriter(newSocket.getOutputStream(), "US-ASCII");
+ output = new PrintStream(newSocket.getOutputStream());
+ newSocket.setSoTimeout(0);
+ socket = newSocket;
+ } catch (IOException ex) {
+ try {
+ newSocket.close();
+ } catch (IOException ex2) {
+ }
+ socket = null;
+ return;
+ }
+ }
+
+ public void shutdown() {
+ Socket closingSocket = socket;
+ socket = null;
+ if (closingSocket == null)
+ return;
+ try {
+ Logger.removeLogStream(output);
+ closingSocket.shutdownInput();
+ closingSocket.shutdownOutput();
+ closingSocket.close();
+ Logger.msg("Script console to "+closingSocket.getInetAddress()+" closed");
+ } catch (IOException e) {
+ Logger.error("Script Console to " + closingSocket.getInetAddress() + " - Error closing.");
+ Logger.error(e);
+ }
+ }
+
+
+ public void run() {
+ // check permission
+ boolean allowed = true;
+ if (securityMode!=NONE) {
+ if (securityHosts.contains(socket.getInetAddress().getHostAddress())) {
+ if (securityMode==DENY)
+ allowed = false;
+ }
+ else if (securityMode==ALLOW)
+ allowed = false;
+ }
+
+ if (!allowed) {
+ Logger.error("Host "+socket.getInetAddress()+" access denied");
+ output.println("Host "+socket.getInetAddress()+" access denied");
+ shutdown();
+ return;
+ }
+
+ // get system objects
+ try {
+ Logger.addLogStream(output, 0);
+ try {
+ manager = new BSFManager();
+ manager.declareBean("storage", Gateway.getStorage(), TransactionManager.class);
+ manager.declareBean("db", Gateway.getStorage().getDb(), TransactionManager.class);
+ manager.declareBean("proxy", Gateway.getProxyManager(), EntityProxyManager.class);
+ manager.declareBean("lookup", Gateway.getLDAPLookup(), LDAPLookup.class);
+ manager.declareBean("orb", Gateway.getORB(), ORB.class);
+ try {
+ manager.declareBean("system", Gateway.getProxyManager().getProxy(
+ Gateway.getLDAPLookup().getRoleManager().getAgentPath("system")), AgentProxy.class);
+ } catch (Exception ex) {
+ output.println("System agent unavailable");
+ }
+ context = manager.loadScriptingEngine("javascript");
+ } catch (BSFException ex) {
+ output.println("Error initialising environment objects");
+ output.flush();
+ shutdown();
+ }
+ StringBuffer commandBuffer = new StringBuffer();
+ while (socket != null) {
+
+ output.println();
+ output.print('>');
+
+ String command = null;
+ boolean gotCommand = false;
+ while (!gotCommand) {
+ try {
+ command = input.readLine();
+ gotCommand = true;
+ } catch (InterruptedIOException ex) {
+ }
+ }
+ if (command == null) // disconnected
+ shutdown();
+ else {
+ if (command.equals("exit")) {
+ shutdown();
+ continue;
+ }
+ else if(command.startsWith("log")) {
+ try {
+ int newLogLevel = Integer.parseInt(command.substring(4));
+ Logger.removeLogStream(output);
+ Logger.addLogStream(output, newLogLevel);
+ Logger.msg("Log level for "+socket.getInetAddress()+" set to "+newLogLevel);
+ continue;
+ } catch (NumberFormatException ex) { }
+ }
+ else if(command.equals("help")) {
+ output.println(Resource.getTextResource("textFiles/consoleHelp.txt"));
+ continue;
+ }
+ else if(command.equals("version")) {
+ output.println("Domain version: "+Resource.getDomainVersion());
+ output.println("Kernel version: "+Resource.getKernelVersion());
+ continue;
+ }
+ try {
+ if (command.endsWith("\\")) {
+ commandBuffer.append(command.substring(0,command.length()-1));
+ continue;
+ }
+ commandBuffer.append(command);
+ command = commandBuffer.toString();
+ commandBuffer = new StringBuffer();
+ Logger.msg("Console command from "+socket.getInetAddress()+": "+command);
+
+ // process control
+ if (command.equals("shutdown")) {
+ WrapperManager.stop(0);
+ }
+ else {
+ Object response = context.eval("Command", 0, 0, command);
+ if (response instanceof org.mozilla.javascript.Undefined)
+ output.println("Ok");
+ else
+ output.println(response);
+ }
+ } catch (Throwable ex) {
+ ex.printStackTrace(output);
+ }
+ output.flush();
+ }
+ }
+ } catch (IOException ex) {
+ Logger.error("IO Exception reading from script console socket");
+ shutdown();
+ }
+ }
+ }
diff --git a/source/com/c2kernel/scripting/ScriptLoadingException.java b/source/com/c2kernel/scripting/ScriptLoadingException.java
new file mode 100755
index 0000000..16f9ab5
--- /dev/null
+++ b/source/com/c2kernel/scripting/ScriptLoadingException.java
@@ -0,0 +1,24 @@
+package com.c2kernel.scripting;
+
+/**************************************************************************
+ *
+ * $Revision: 1.1 $
+ * $Date: 2003/04/06 12:32:51 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+public class ScriptLoadingException extends ScriptingEngineException {
+ /**
+ *
+ */
+ public ScriptLoadingException() {
+ super();
+ }
+ /**
+ *
+ */
+ public ScriptLoadingException(String msg) {
+ super(msg);
+ }
+}
diff --git a/source/com/c2kernel/scripting/ScriptParsingException.java b/source/com/c2kernel/scripting/ScriptParsingException.java
new file mode 100755
index 0000000..939372b
--- /dev/null
+++ b/source/com/c2kernel/scripting/ScriptParsingException.java
@@ -0,0 +1,21 @@
+package com.c2kernel.scripting;
+
+public class ScriptParsingException extends ScriptingEngineException {
+
+ /**
+ * Creates new <code>ScriptParsingException</code> without detail message.
+ */
+ public ScriptParsingException() {
+ }
+
+
+ /**
+ * Constructs an <code>ScriptParsingException</code> with the specified detail message.
+ * @param msg the detail message.
+ */
+ public ScriptParsingException(String msg) {
+ super(msg);
+ }
+}
+
+
diff --git a/source/com/c2kernel/scripting/ScriptingEngineException.java b/source/com/c2kernel/scripting/ScriptingEngineException.java
new file mode 100755
index 0000000..2c8128c
--- /dev/null
+++ b/source/com/c2kernel/scripting/ScriptingEngineException.java
@@ -0,0 +1,20 @@
+package com.c2kernel.scripting;
+
+public class ScriptingEngineException extends java.lang.Exception {
+
+ /**
+ * Creates new <code>sciptingEngineException</code> without detail message.
+ */
+ public ScriptingEngineException() {
+ }
+
+ /**
+ * Constructs an <code>sciptingEngineException</code> with the specified detail message.
+ * @param msg the detail message.
+ */
+ public ScriptingEngineException(String msg) {
+ super(msg);
+ }
+}
+
+
diff --git a/source/com/c2kernel/utils/ActDefCache.java b/source/com/c2kernel/utils/ActDefCache.java
new file mode 100755
index 0000000..bfd5cdb
--- /dev/null
+++ b/source/com/c2kernel/utils/ActDefCache.java
@@ -0,0 +1,91 @@
+/**
+ *
+ */
+package com.c2kernel.utils;
+
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.entity.proxy.EntityProxyObserver;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.lifecycle.ActivityDef;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.persistency.ClusterStorageException;
+import com.c2kernel.persistency.outcome.Viewpoint;
+
+public class ActDefCache {
+
+ SoftCache actCache = new SoftCache();
+
+ public ActivityDef get(String actName, String actVersion) throws ObjectNotFoundException, InvalidDataException {
+ ActivityDef thisActDef;
+ synchronized(actCache) {
+ ActCacheEntry thisActDefEntry = ((ActCacheEntry)actCache.get(actName+"_"+actVersion));
+ if (thisActDefEntry == null) {
+ Logger.msg(6, actName+" v"+actVersion+" not found in cache. Retrieving.");
+ ItemProxy actDefItem = LocalObjectLoader.loadLocalObjectDef("/desc/ActivityDesc/", actName);
+ String actType = actDefItem.getProperty("Complexity");
+ Viewpoint actView = (Viewpoint)actDefItem.getObject(ClusterStorage.VIEWPOINT + "/" + actType + "ActivityDef/" + actVersion);
+ String marshalledAct;
+ try {
+ marshalledAct = actView.getOutcome().getData();
+ } catch (ClusterStorageException ex) {
+ Logger.error(ex);
+ throw new ObjectNotFoundException("Problem loading "+actName+" v"+actVersion+": "+ex.getMessage(), "");
+ }
+ try {
+ thisActDef = (ActivityDef)CastorXMLUtility.unmarshall(marshalledAct);
+ } catch (Exception ex) {
+ Logger.error(ex);
+ throw new InvalidDataException("Could not unmarshall '"+actName+"' v"+actVersion+": "+ex.getMessage(), "");
+ }
+ thisActDef.setName(actName);
+ thisActDef.setVersion(actVersion);
+ actCache.put(actName+"_"+actVersion, new ActCacheEntry(thisActDef, actDefItem, this));
+ }
+ else {
+ Logger.msg(6, actName+" v"+actVersion+" found in cache.");
+ thisActDef = thisActDefEntry.actDef;
+ }
+ }
+ return thisActDef;
+ }
+
+ public void removeAct(String id) {
+ synchronized(actCache) {
+ if (actCache.keySet().contains(id)) {
+ Logger.msg(7, "ActDefCache: Removing activity def "+id+" from cache");
+ actCache.remove(id);
+ }
+ }
+ }
+
+ public class ActCacheEntry implements EntityProxyObserver {
+ public String id;
+ public ItemProxy actProxy;
+ public ActivityDef actDef;
+ public ActDefCache parent;
+ public ActCacheEntry(ActivityDef actDef, ItemProxy actProxy, ActDefCache parent) {
+ this.id = actDef.getName()+"_"+actDef.getVersion();
+ this.actDef = actDef;
+ this.parent = parent;
+ this.actProxy = actProxy;
+ actProxy.subscribe(this, ClusterStorage.VIEWPOINT, false);
+ }
+ public void finalize() {
+ parent.removeAct(id);
+ actProxy.unsubscribe(this);
+ }
+ public void add(C2KLocalObject contents) {
+ parent.removeAct(id);
+ }
+
+ public void remove(String id) {
+ parent.removeAct(id);
+ }
+
+ public String toString() {
+ return "ActDef cache entry: "+id;
+ }
+ }
+} \ No newline at end of file
diff --git a/source/com/c2kernel/utils/CastorArrayList.java b/source/com/c2kernel/utils/CastorArrayList.java
new file mode 100755
index 0000000..10ff948
--- /dev/null
+++ b/source/com/c2kernel/utils/CastorArrayList.java
@@ -0,0 +1,30 @@
+package com.c2kernel.utils;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+
+/**************************************************************************
+ * Wrapper for a root element to an ArrayList. Castor Marshalls arraylists
+ * as multiple elements, so this class is needed to provide a root element
+ * to stop it crashing.
+ *
+ * $Revision: 1.4 $
+ * $Date: 2004/01/22 11:17:42 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+//
+abstract public class CastorArrayList implements Serializable{
+ public ArrayList list = new ArrayList();
+
+ public CastorArrayList() {
+ super();
+ list = new ArrayList();
+ }
+
+ public CastorArrayList(ArrayList list) {
+ this();
+ this.list = list;
+ }
+}
diff --git a/source/com/c2kernel/utils/CastorHashMap.java b/source/com/c2kernel/utils/CastorHashMap.java
new file mode 100755
index 0000000..fec2044
--- /dev/null
+++ b/source/com/c2kernel/utils/CastorHashMap.java
@@ -0,0 +1,54 @@
+package com.c2kernel.utils;
+
+import java.util.HashMap;
+import java.util.Iterator;
+
+
+// This subclass of hashtable can be marshalled
+// and unmarshalled with Castor
+public class CastorHashMap extends HashMap
+{
+ public CastorHashMap()
+ {
+ clear();
+ }
+
+ public KeyValuePair[] getKeyValuePairs()
+ {
+ int numKeys = size();
+
+ KeyValuePair[] keyValuePairs = new KeyValuePair[numKeys];
+ Iterator keyIter = keySet().iterator();
+ int i = 0;
+
+ for(i=0; i<numKeys; i++)
+ if (keyIter.hasNext())
+ {
+ String tmp = (String)keyIter.next();
+ keyValuePairs[i] = new KeyValuePair(tmp,get(tmp));
+ }
+
+ return keyValuePairs;
+ }
+
+
+ public void setKeyValuePairs(KeyValuePair[] keyValuePairs)
+ {
+ int i = 0;
+
+ // Clears this hashtable so that it contains no keys
+ clear();
+
+ // Put each key value pair into this hashtable
+ for(i=0; i<keyValuePairs.length; i++)
+ {
+ setKeyValuePair(keyValuePairs[i]);
+ }
+ }
+
+ public void setKeyValuePair(KeyValuePair keyValuePair)
+ {
+ put(keyValuePair.getKey(), keyValuePair.getValue());
+ }
+
+}
diff --git a/source/com/c2kernel/utils/CastorXMLUtility.java b/source/com/c2kernel/utils/CastorXMLUtility.java
new file mode 100755
index 0000000..3f23d53
--- /dev/null
+++ b/source/com/c2kernel/utils/CastorXMLUtility.java
@@ -0,0 +1,126 @@
+package com.c2kernel.utils;
+
+//Java
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.net.URL;
+import java.util.HashSet;
+import java.util.StringTokenizer;
+
+import org.exolab.castor.mapping.Mapping;
+import org.exolab.castor.mapping.MappingException;
+import org.exolab.castor.xml.MarshalException;
+import org.exolab.castor.xml.Marshaller;
+import org.exolab.castor.xml.Unmarshaller;
+import org.exolab.castor.xml.ValidationException;
+
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.persistency.outcome.Outcome;
+
+
+/**************************************************************************
+ * Loads all mapfiles, and wraps marshalling/unmarshalling
+ *
+ * @author $Author: abranson $ $Date: 2004/10/20 14:10:21 $
+ * @version $Revision: 1.12 $
+ **************************************************************************/
+public class CastorXMLUtility
+{
+ private static Mapping mMapping = new Mapping();
+ private static HashSet mMappingKeys = new HashSet();
+
+ /**
+ * Looks for a file called 'index.xml' at the given URL, and loads every file
+ * listed in there by relative path
+ *
+ * @param mapURL - map root
+ */
+ static public void loadMapsFrom(URL mapURL) throws InvalidDataException {
+ // load index.xml
+ Logger.msg(3, "Loading maps from "+mapURL);
+ String index;
+ try {
+ index = FileStringUtility.url2String( new URL(mapURL, "index.xml") );
+ } catch (Exception e) {
+ Logger.warning("Could not load map index from "+mapURL.toString());
+ return;
+ }
+
+ StringTokenizer sTokenizer = new StringTokenizer(index);
+ while( sTokenizer.hasMoreTokens() ) {
+ String thisMap = sTokenizer.nextToken();
+ try {
+ addMapping( new URL(mapURL, thisMap));
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new InvalidDataException("Error loading map '"+thisMap+"'", "");
+ }
+ }
+ Logger.msg("Loaded all maps from "+mapURL.toString());
+ }
+
+ /**************************************************************************
+ * Updates a mapping referenced by the mapID.
+ * The same mapping cannot be loaded many times as it generates an exception.
+ * That is the reason for this method as it maintains the HashSet of MappingKeys.
+ **************************************************************************/
+ static public void addMapping( URL mapID )
+ throws IOException,
+ MappingException,
+ MarshalException,
+ ValidationException
+ {
+
+ if( !mMappingKeys.contains(mapID) )
+ {
+ Logger.msg(7, "Added mapping file:"+mapID);
+
+ mMapping.loadMapping( mapID );
+ mMappingKeys.add( mapID );
+ }
+ else
+ {
+ Logger.msg("Map file already loaded:"+mapID);
+ }
+ }
+
+ /**************************************************************************
+ * Marshalls a mapped object to string. The mapping must be loaded before.
+ * See updateMapping().
+ **************************************************************************/
+ static public String marshall( Object obj )
+ throws IOException,
+ MappingException,
+ MarshalException,
+ ValidationException
+ {
+ if (obj == null) return "<NULL/>";
+ if (obj instanceof Outcome)
+ return ((Outcome)obj).getData();
+ StringWriter sWriter = new StringWriter();
+ Marshaller marshaller = new Marshaller( sWriter );
+
+ marshaller.setMapping( mMapping );
+ marshaller.setMarshalAsDocument( false );
+ marshaller.marshal( obj );
+
+ return sWriter.toString();
+ }
+
+ /**************************************************************************
+ * Unmarshalls a mapped object from string. The mapping must be loaded before.
+ * See updateMapping().
+ **************************************************************************/
+ static public Object unmarshall( String data )
+ throws IOException,
+ MappingException,
+ MarshalException,
+ ValidationException
+ {
+ StringReader sReader = new StringReader( data );
+ Unmarshaller unmarshaller = new Unmarshaller( mMapping );
+ if (data.equals("<NULL/>")) return null;
+ return unmarshaller.unmarshal( sReader );
+ }
+}
diff --git a/source/com/c2kernel/utils/DateUtility.java b/source/com/c2kernel/utils/DateUtility.java
new file mode 100755
index 0000000..6e3b569
--- /dev/null
+++ b/source/com/c2kernel/utils/DateUtility.java
@@ -0,0 +1,118 @@
+package com.c2kernel.utils;
+import com.c2kernel.common.GTimeStamp;
+/**
+ * @version $Revision: 1.8 $ $Date: 2005/05/10 15:14:55 $
+ * @author $Author: abranson $
+ */
+public class DateUtility
+{
+ public static GTimeStamp setToNow(GTimeStamp date)
+ {
+ java.util.Calendar now = java.util.Calendar.getInstance();
+ date.mYear = now.get(java.util.Calendar.YEAR);
+ date.mMonth = now.get(java.util.Calendar.MONTH) + 1;
+ date.mDay = now.get(java.util.Calendar.DAY_OF_MONTH);
+ date.mHour = now.get(java.util.Calendar.HOUR_OF_DAY);
+ date.mMinute = now.get(java.util.Calendar.MINUTE);
+ date.mSecond = now.get(java.util.Calendar.SECOND);
+ date.mTimeOffset = now.get(java.util.Calendar.ZONE_OFFSET);
+ return date;
+ }
+
+ public static String getSQLFormat(GTimeStamp timeStamp)
+ {
+ StringBuffer time = new StringBuffer().append(timeStamp.mYear).append("-");
+ if (timeStamp.mMonth < 10)
+ time.append("0");
+ time.append(timeStamp.mMonth).append("-");
+ if (timeStamp.mDay < 10)
+ time.append("0");
+ time.append(timeStamp.mDay).append(" ");
+ if (timeStamp.mHour < 10)
+ time.append("0");
+ time.append(timeStamp.mHour).append(":");
+ if (timeStamp.mMinute < 10)
+ time.append("0");
+ time.append(timeStamp.mMinute).append(":");
+ if (timeStamp.mSecond < 10)
+ time.append("0");
+ time.append(timeStamp.mSecond);
+ return time.toString();
+ }
+
+ public static int getNbDayInYear(GTimeStamp date)
+ {
+ int centuary = date.mYear / 100;
+ int cdivby4 = centuary / 4;
+ int ydivby4 = date.mYear / 4;
+ if (centuary * 100 - date.mYear == 0)
+ {
+ if (centuary == cdivby4 * 4)
+ return 366;
+ else
+ return 365;
+ }
+ else if (date.mYear == ydivby4 * 4)
+ return 366;
+ else
+ return 365;
+ }
+ public static int getNbDayInMonth(GTimeStamp date)
+ {
+ switch (date.mMonth)
+ {
+ case 2 :
+ if (getNbDayInYear(date) == 365)
+ return 28;
+ else
+ return 29;
+ case 4 :
+ return 30;
+ case 6 :
+ return 30;
+ case 9 :
+ return 30;
+ case 11 :
+ return 30;
+ default :
+ return 31;
+ }
+ }
+
+ public static long diff(GTimeStamp date1, GTimeStamp date2)
+ {
+ GTimeStamp tmp = new GTimeStamp(date1.mYear, date1.mMonth, date1.mDay, date1.mHour, date1.mMinute, date1.mSecond, date1.mTimeOffset);
+ while (tmp.mYear - date2.mYear < 0)
+ {
+ while (tmp.mMonth < 13)
+ {
+ tmp.mDay = tmp.mDay - getNbDayInMonth(tmp);
+ tmp.mMonth++;
+ }
+ tmp.mMonth = 1;
+ tmp.mYear++;
+ }
+ while (tmp.mYear - date2.mYear > 0)
+ {
+ while (tmp.mMonth > 1)
+ {
+ tmp.mMonth--;
+ tmp.mDay = tmp.mDay + getNbDayInMonth(tmp);
+ }
+ tmp.mMonth = 12;
+ tmp.mDay = tmp.mDay + getNbDayInMonth(tmp);
+ tmp.mYear--;
+ }
+ while (tmp.mMonth - date2.mMonth < 0)
+ {
+ tmp.mDay = tmp.mDay - getNbDayInMonth(tmp);
+ tmp.mMonth++;
+ }
+ while (tmp.mMonth - date2.mMonth > 0)
+ {
+ tmp.mMonth--;
+ tmp.mDay = tmp.mDay + getNbDayInMonth(tmp);
+ }
+ return (((tmp.mDay - date2.mDay) * 24 + tmp.mHour - date2.mHour) * 60 + tmp.mMinute - date2.mMinute) * 60 + tmp.mSecond - date2.mSecond;
+ }
+}
diff --git a/source/com/c2kernel/utils/Dom4JElementParser.java b/source/com/c2kernel/utils/Dom4JElementParser.java
new file mode 100755
index 0000000..a4d5bbe
--- /dev/null
+++ b/source/com/c2kernel/utils/Dom4JElementParser.java
@@ -0,0 +1,38 @@
+package com.c2kernel.utils;
+
+import java.io.StringReader;
+import java.util.Iterator;
+import java.util.List;
+
+import org.dom4j.Attribute;
+import org.dom4j.Document;
+import org.dom4j.Element;
+import org.dom4j.io.SAXReader;
+
+public class Dom4JElementParser
+{
+ public static String[] parse(String data, String xpath)
+ {
+ try
+ {
+ SAXReader reader = new SAXReader();
+
+ Document d = reader.read(new StringReader(data));
+ List list = d.selectNodes( xpath );
+ String[] returnArray = new String[list.size()];
+ int i=0;
+ for ( Iterator iter = list.iterator(); iter.hasNext();i++ )
+ {
+ Object object = iter.next();
+ if (object instanceof Element) returnArray[i]=((Element)object).getText();
+ else if (object instanceof Attribute) returnArray[i]=((Attribute)object).getText();
+ }
+ return returnArray;
+ }
+ catch (Exception e)
+ {
+ Logger.error(e);
+ return new String[0];
+ }
+ }
+}
diff --git a/source/com/c2kernel/utils/FileStringUtility.java b/source/com/c2kernel/utils/FileStringUtility.java
new file mode 100755
index 0000000..948341a
--- /dev/null
+++ b/source/com/c2kernel/utils/FileStringUtility.java
@@ -0,0 +1,424 @@
+package com.c2kernel.utils;
+
+//Java
+import java.io.*;
+import java.lang.reflect.Array;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2004/10/20 14:10:21 $
+ * @version $Revision: 1.31 $
+ **************************************************************************/
+public class FileStringUtility
+{
+ /**************************************************************************
+ * Reads a file and converts it to String
+ **************************************************************************/
+ static public String file2String(File file) throws FileNotFoundException, IOException
+ {
+ FileInputStream fis = new FileInputStream(file);
+ byte[] bArray = (byte[]) Array.newInstance(byte.class, (int) file.length());
+ Logger.msg(8, "FileStringUtility.file2String() - Reading file '" + file.getAbsolutePath()+"'");
+
+ fis.read(bArray, 0, (int) file.length());
+ fis.close();
+
+ Logger.msg(9, "FileStringUtility.file2String() - file '" + file.getAbsolutePath() + "' read.");
+
+ return new String(bArray);
+ }
+
+ /**************************************************************************
+ * Reads a file and converts it to String
+ **************************************************************************/
+ static public String file2String(String fileName) throws FileNotFoundException, IOException
+ {
+ return file2String(new File(fileName));
+ }
+
+ /**************************************************************************
+ * Reads a file and converts it to String
+ **************************************************************************/
+ static public String url2String(java.net.URL location) throws IOException
+ {
+ String resource = "";
+
+ BufferedInputStream file = new BufferedInputStream(location.openStream());
+ byte[] buffer = new byte[file.available()];
+
+ if (file.read(buffer) > 0)
+ resource = new String(buffer);
+
+ file.close();
+
+ return resource;
+ }
+
+ /**************************************************************************
+ * Reads a file and converts each line to String[]
+ **************************************************************************/
+ static public String[] file2StringArray(File file) throws FileNotFoundException, IOException
+ {
+ FileReader fr = new FileReader(file);
+ BufferedReader buf = new BufferedReader(fr);
+ Vector lines = new Vector();
+ String thisLine = null;
+ while ((thisLine = buf.readLine()) != null)
+ lines.addElement(thisLine);
+ String[] lineArray = new String[lines.size()];
+ for (int i = 0; i < lines.size(); i++)
+ lineArray[i] = (String) lines.get(i);
+ return lineArray;
+ }
+
+ /**************************************************************************
+ * Reads a file and converts it to String[]
+ **************************************************************************/
+ static public String[] file2StringArray(String fileName) throws FileNotFoundException, IOException
+ {
+ return file2StringArray(new File(fileName));
+ }
+
+ /**************************************************************************
+ * Saves a string to a text file
+ **************************************************************************/
+ static public void string2File(File file, String data) throws FileNotFoundException, IOException
+ {
+ FileWriter thisFile = new FileWriter(file);
+ BufferedWriter thisFileBuffer = new BufferedWriter(thisFile);
+
+ Logger.msg(9, "FileStringUtility.string2File() - writing file '" + file.getAbsolutePath()+"'");
+
+ thisFileBuffer.write(data);
+ thisFileBuffer.close();
+
+ Logger.msg(9, "FileStringUtility.string2File() - file '" + file.getAbsolutePath() + "' complete.");
+ }
+
+ /**************************************************************************
+ * Saves a string to a text file
+ **************************************************************************/
+ static public void string2File(String fileName, String data) throws FileNotFoundException, IOException
+ {
+ string2File(new File(fileName), data);
+ }
+
+ /**************************************************************************
+ * checks for existing directory
+ **************************************************************************/
+ static public boolean checkDir(String dirPath)
+ {
+ File dir = new File(dirPath);
+
+ if (dir.isFile())
+ {
+ Logger.error("FileStringUtility.checkDir() - '" + dir.getAbsolutePath() + "' is a file.");
+ return false;
+ }
+ else if (!dir.exists())
+ {
+ Logger.msg(9, "FileStringUtility.checkDir() - directory '" + dir.getAbsolutePath() + "' does not exist.");
+ return false;
+ }
+
+ return true;
+ }
+
+ /**************************************************************************
+ * creating a new directory
+ **************************************************************************/
+ static public boolean createNewDir(String dirPath)
+ {
+ File dir = new File(dirPath);
+
+ if (dir.isFile())
+ {
+ Logger.error("FileStringUtility.createNewDir() - '" + dir.getAbsolutePath() + "' is a file.");
+ return false;
+ }
+ else if (dir.exists())
+ {
+ Logger.msg(8, "FileStringUtility.createNewDir() - '" + dir.getAbsolutePath() + "' already exists.");
+ return false;
+ }
+ else
+ {
+ if (!dir.mkdirs())
+ {
+ Logger.error("FileStringUtility - Could not create new directory '" + dir.getAbsolutePath() + "'");
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**************************************************************************
+ * deleting a existing directory
+ **************************************************************************/
+ static public boolean deleteDir(String dirPath)
+ {
+ File dir = new File(dirPath);
+
+ if (!checkDir(dirPath))
+ {
+ Logger.msg(8, "FileStringUtility.deleteDir() - directory '" + dir.getAbsolutePath() + "' does not exist.");
+ return false;
+ }
+
+ if (!dir.delete())
+ {
+ //prints the possible reason
+ if (dir.list().length != 0)
+ {
+ Logger.error("FileStringUtility.deleteDir() - cannot delete non-empty directory '" + dir.getAbsolutePath() + "'");
+ }
+ else
+ {
+ Logger.error("FileStringUtility.deleteDir() - directory '" + dir.getAbsolutePath() + "' could not be deleted.");
+ }
+ return false;
+ }
+
+ return true;
+ }
+
+ /**************************************************************************
+ * deleting a existing directory with its structure
+ *
+ * @param dirPath the directory which should be deleted
+ * @param force if true forces to delete the entry (ie. the dirPath) even if
+ * it is a file
+ * @param recursive if true deletes the complete directory structure
+ **************************************************************************/
+ static public boolean deleteDir(String dirPath, boolean force, boolean recursive)
+ {
+ File dir = new File(dirPath);
+ File files[];
+
+ if (!dir.exists())
+ {
+ Logger.error("FileStringUtility.deleteDir() - directory '" + dir.getAbsolutePath() + "' does not exist.");
+ return false;
+ }
+
+ if (dir.isFile())
+ {
+
+ if (force)
+ { //delete the entry even if it is a file
+ dir.delete();
+ return true;
+ }
+ else
+ {
+ Logger.error("FileStringUtility.deleteDir() - '" + dir.getAbsolutePath() + "' was a file.");
+ return false;
+ }
+ }
+
+ if (recursive)
+ {
+ files = dir.listFiles();
+
+ for (int i = 0; i < files.length; i++)
+ deleteDir(files[i].getAbsolutePath(), true, true);
+ }
+
+ return deleteDir(dirPath);
+ }
+
+ /**************************************************************************
+ * List all file names in the directory recursively, relative to the
+ * starting directory.
+ *
+ * @param dirPath starting directory
+ * @param recursive goes into the subdirectories
+ **************************************************************************/
+ static public ArrayList listDir(String dirPath, boolean withDirs, boolean recursive)
+ {
+ ArrayList fileNames = new ArrayList();
+ File dir = new File(dirPath);
+ File files[];
+ String fileName;
+
+ if (!checkDir(dirPath))
+ {
+ Logger.msg(8, "FileStringUtility.listDir() - directory '" + dir.getAbsolutePath() + "' does not exist.");
+ return null;
+ }
+
+ files = dir.listFiles();
+
+ for (int i = 0; i < files.length; i++)
+ {
+ fileName = files[i].getName();
+
+ if (files[i].isFile())
+ {
+ fileNames.add(dirPath + "/" + fileName);
+ }
+ else
+ {
+ if (recursive)
+ fileNames.addAll(listDir(dirPath + "/" + fileName, withDirs, recursive));
+
+ if (withDirs)
+ fileNames.add(dirPath + "/" + fileName);
+ }
+ }
+
+ return fileNames;
+ }
+
+ /**************************************************************************
+ * Open a URL or File as an InputStream
+ **************************************************************************/
+ static public InputStream openTextStream(String source)
+ {
+ java.io.InputStream in = null;
+ java.net.URL url = null;
+
+ // Try to open URL connection first
+ try
+ {
+ try
+ {
+ url = new URL(source);
+ in = url.openStream();
+ }
+ catch (MalformedURLException e)
+ {
+ // Try to open plain file, if `configFile' is not a
+ // URL specification
+ in = new FileInputStream(source);
+ }
+ }
+ catch (java.io.IOException ex)
+ {
+ Logger.error("FileStringUtility.openTextStream() - could not load text stream:" + source);
+ }
+ return in;
+ }
+
+ /**************************************************************************
+ * Load the contents of the configuration file
+ **************************************************************************/
+ static public java.util.Properties loadConfigFile(String configFile)
+ {
+ java.io.BufferedInputStream bin = null;
+ java.io.InputStream in = openTextStream(configFile);
+ java.util.Properties props = new java.util.Properties();
+
+ if (in != null)
+ {
+ try
+ {
+ bin = new java.io.BufferedInputStream(in);
+ props.load(bin);
+ in.close();
+ }
+ catch (IOException ex)
+ {
+ Logger.error("FileStringUtility.loadConfigFile() - could not load configuration file '" + configFile+"'");
+ }
+ }
+ return props;
+ }
+
+ /**************************************************************************
+ * Load the contents of the language file
+ * *************************************************************************/
+ static public Hashtable loadLanguageFile(String configFile)
+ {
+ try
+ {
+ String language = FileStringUtility.file2String(configFile);
+ Hashtable props = new Hashtable();
+ StringTokenizer tok = new StringTokenizer(language, "\n");
+ while (tok.hasMoreTokens())
+ {
+ String t = tok.nextToken();
+ int sep = t.indexOf("=");
+ if (sep >0)props.put(t.substring(0,sep),t.substring(sep+1));
+ }
+ return props;
+ }
+ catch (Exception e)
+ {
+ Logger.error("FileStringUtility.loadLanguageFile() - could not load language file '" + configFile+"'");
+ Logger.error(e);
+ return new Hashtable();
+ }
+
+ }
+
+ /**************************************************************************
+ * Load the contents of the configuration file
+ **************************************************************************/
+ static public void appendConfigFile(java.util.Properties props, String configFile)
+ {
+ java.io.BufferedInputStream bin = null;
+ java.io.InputStream in = openTextStream(configFile);
+
+ if (in != null)
+ {
+ try
+ {
+ bin = new java.io.BufferedInputStream(in);
+ props.load(bin);
+ in.close();
+ }
+ catch (java.io.IOException ex)
+ {
+ Logger.error("FileStringUtility.appendConfigFile() - could not append configuration file '" + configFile+"'");
+ }
+ }
+ }
+ public static String convert(String init)
+ {
+ if (init==null) return null;
+ return init
+ .replace('\'', '_')
+ .replace('\\', '_')
+ .replace('/', '_')
+ .replace('\"', '_')
+ .replace(':', '_')
+ .replace('*', '_')
+ .replace('?', '_')
+ .replace('<', '_')
+ .replace('>', '_')
+ .replace('|', '_')
+ .replace('(', '[')
+ .replace(')', ']')
+ .replace(',','_'); }
+ public static String replaceall(String src,String from,String to)
+ {
+ StringBuffer tmp=new StringBuffer(src);
+ int length = from.length();
+ int index = tmp.toString().indexOf(from);
+ while (index>0)
+ {
+ tmp.replace(index,index+length,to);
+ index = tmp.toString().indexOf(from);
+ }
+ return tmp.toString();
+ }
+ public static String toAlphaNum(String source)
+ {
+ byte[] sourceb = source.getBytes();
+ for (int i=0;i<sourceb.length;i++)
+ {
+ if (sourceb[i]<'0'||(sourceb[i]>'9'&&sourceb[i]<'A')||(sourceb[i]>'Z'&&sourceb[i]<'_')||sourceb[i]>'z')
+ sourceb[i]='_';
+ }
+ return new String(sourceb);
+
+ }
+
+}
diff --git a/source/com/c2kernel/utils/GTimeStampComparator.java b/source/com/c2kernel/utils/GTimeStampComparator.java
new file mode 100755
index 0000000..f57f20d
--- /dev/null
+++ b/source/com/c2kernel/utils/GTimeStampComparator.java
@@ -0,0 +1,26 @@
+package com.c2kernel.utils;
+
+import java.util.Comparator;
+
+import com.c2kernel.common.GTimeStamp;
+
+public class GTimeStampComparator implements Comparator {
+
+ public int compare(Object arg0, Object arg1) {
+ GTimeStamp t0 = (GTimeStamp)arg0;
+ GTimeStamp t1 = (GTimeStamp)arg1;
+
+ int retVal = compareInt(t0.mYear, t1.mYear);
+ if (retVal == 0) retVal = compareInt(t0.mMonth, t1.mMonth);
+ if (retVal == 0) retVal = compareInt(t0.mDay, t1.mDay);
+ if (retVal == 0) retVal = compareInt(t0.mHour-(t0.mTimeOffset/3600), t1.mHour-(t1.mTimeOffset/3600));
+ if (retVal == 0) retVal = compareInt(t0.mMinute, t1.mMinute);
+ if (retVal == 0) retVal = compareInt(t0.mSecond, t1.mSecond);
+
+ return retVal;
+ }
+
+ private int compareInt(int i, int j) {
+ return i-j;
+ }
+}
diff --git a/source/com/c2kernel/utils/KeyValuePair.java b/source/com/c2kernel/utils/KeyValuePair.java
new file mode 100755
index 0000000..149797e
--- /dev/null
+++ b/source/com/c2kernel/utils/KeyValuePair.java
@@ -0,0 +1,77 @@
+package com.c2kernel.utils;
+
+
+public class KeyValuePair
+{
+ private String mKey = null;
+ private Object mValue = null;
+
+ public KeyValuePair() {}
+
+ public KeyValuePair(String key, Object value)
+ {
+ mKey = key;
+ mValue = value;
+ }
+
+ public String getKey() {
+ return mKey;
+ }
+
+ public void setKey(String key) {
+ mKey = key;
+ }
+
+ public Object getValue() {
+ return mValue;
+ }
+
+ public void setValue(Object value) {
+ mValue = value;
+ }
+
+ public String getStringValue() {
+ if (mValue instanceof String)
+ return (String)mValue;
+ else
+ return null;
+ }
+
+ public void setStringValue(String value) {
+ mValue = value;
+ }
+
+ public Integer getIntegerValue() {
+ if (mValue instanceof Integer)
+ return (Integer)mValue;
+ else
+ return null;
+ }
+
+ public void setIntegerValue(Integer value) {
+ mValue = value;
+ }
+
+ public Boolean getBooleanValue() {
+ if (mValue instanceof Boolean)
+ return (Boolean)mValue;
+ else
+ return null;
+ }
+
+ public void setBooleanValue(Boolean value) {
+ mValue = value;
+ }
+
+ public Float getFloatValue() {
+ if (mValue instanceof Float)
+ return (Float)mValue;
+ else
+ return null;
+ }
+
+ public void setFloatValue(Float value) {
+ mValue = value;
+ }
+
+}
diff --git a/source/com/c2kernel/utils/Language.java b/source/com/c2kernel/utils/Language.java
new file mode 100755
index 0000000..ae0947f
--- /dev/null
+++ b/source/com/c2kernel/utils/Language.java
@@ -0,0 +1,66 @@
+package com.c2kernel.utils;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/**************************************************************************
+ *
+ * @author $Author: sgaspard $ $Date: 2004/09/21 13:17:40 $
+ * @version $Revision: 1.9 $
+ **************************************************************************/
+
+public class Language
+{
+ public static Hashtable mTableOfTranslation = new Hashtable();
+ public static Hashtable mTableOfUntranslated = new Hashtable();
+ public static boolean isTranlated=false;
+ private Hashtable tableOfTranslation = new Hashtable();
+
+ public static String translate(String english)
+ {
+ if (!isTranlated) return english;
+ String rep = english;
+ if (rep != null && !rep.equals("")) {
+ String translated = (String) mTableOfTranslation.get(english);
+ if (translated != null) return translated;
+ else
+ {
+ mTableOfUntranslated.put(english,"");
+ try
+ {
+ String s = "";
+ Enumeration e = mTableOfUntranslated.keys();
+ while (e.hasMoreElements()) s =s+"\n"+e.nextElement();
+ FileStringUtility.string2File("untranslated.txt",s);
+ }
+ catch (Exception ex)
+ {
+ Logger.warning("Could not write to preferences file. Preferences have not been updated.");
+ }
+ }
+
+ }
+ return rep;
+ }
+
+ public Language(String filePath)
+ {
+ String languageFile = filePath;
+ if (languageFile == null || languageFile.length() == 0)
+ // no language file defined for this process
+ return;
+ tableOfTranslation = FileStringUtility.loadLanguageFile(languageFile);
+ }
+ public String insTranslate(String english)
+ {
+ String rep = english;
+ if (rep != null && !rep.equals("")) {
+ String translated = (String) tableOfTranslation.get(english);
+ if (translated != null)
+ rep = translated;
+ }
+ return rep;
+ }
+
+
+}
diff --git a/source/com/c2kernel/utils/LocalObjectLoader.java b/source/com/c2kernel/utils/LocalObjectLoader.java
new file mode 100755
index 0000000..620b030
--- /dev/null
+++ b/source/com/c2kernel/utils/LocalObjectLoader.java
@@ -0,0 +1,77 @@
+package com.c2kernel.utils;
+
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.lifecycle.ActivityDef;
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.persistency.ClusterStorageException;
+import com.c2kernel.persistency.outcome.Schema;
+import com.c2kernel.persistency.outcome.Viewpoint;
+import com.c2kernel.process.Gateway;
+
+public class LocalObjectLoader {
+ private static ActDefCache actCache = new ActDefCache();
+
+ static public ItemProxy loadLocalObjectDef(String root, String name)
+ throws ObjectNotFoundException
+ {
+ DomainPath defRoot = new DomainPath(root);
+ DomainPath defPath = (DomainPath)defRoot.find(name);
+ return (ItemProxy)Gateway.getProxyManager().getProxy(defPath);
+ }
+
+ static public String getScript(String scriptName, String scriptVersion) throws ObjectNotFoundException {
+ Logger.msg(5, "Loading script "+scriptName+" v"+scriptVersion);
+ try {
+ ItemProxy script = loadLocalObjectDef("/desc/Script/", scriptName);
+ Viewpoint scriptView = (Viewpoint)script.getObject(ClusterStorage.VIEWPOINT + "/Script/" + scriptVersion);
+ return scriptView.getOutcome().getData();
+ } catch (ClusterStorageException ex) {
+ Logger.error(ex);
+ throw new ObjectNotFoundException("Error loading script " + scriptName + " version " + scriptVersion, "");
+ }
+
+ }
+
+ static public Schema getSchema(String schemaName, int schemaVersion) throws ObjectNotFoundException {
+ Logger.msg(5, "Loading schema "+schemaName+" v"+schemaVersion);
+ Schema thisSchema = new Schema();
+ thisSchema.docType = schemaName;
+ thisSchema.docVersion = schemaVersion;
+
+ // don't bother if this is the Schema schema - for bootstrap esp.
+ if (schemaName.equals("Schema") && schemaVersion == 0) {
+ thisSchema.breakApart = false;
+ thisSchema.schema="";
+ return thisSchema;
+ }
+
+ ItemProxy schema = loadLocalObjectDef("/desc/OutcomeDesc/", schemaName);
+ Viewpoint schemaView = (Viewpoint)schema.getObject(ClusterStorage.VIEWPOINT + "/Schema/" + schemaVersion);
+ try {
+ thisSchema.schema = schemaView.getOutcome().getData();
+ } catch (ClusterStorageException ex) {
+ Logger.error(ex);
+ throw new ObjectNotFoundException("Problem loading schema "+schemaName+" v"+schemaVersion+": "+ex.getMessage(), "");
+ }
+ String breakApart = schema.getProperty("BreakApart");
+ thisSchema.breakApart = breakApart.equals("1");
+
+ return thisSchema;
+ }
+
+ /**
+ * Retrieves a named version of activity def from the database
+ *
+ * @param actName - activity name
+ * @param version - named version (String)
+ * @return ActivityDef
+ * @throws ObjectNotFoundException - When activity or version does not exist
+ */
+ static public ActivityDef getActDef(String actName, String actVersion) throws ObjectNotFoundException, InvalidDataException {
+ Logger.msg(5, "Loading activity def "+actName+" v"+actVersion);
+ return actCache.get(actName, actVersion);
+ }
+}
diff --git a/source/com/c2kernel/utils/Logger.java b/source/com/c2kernel/utils/Logger.java
new file mode 100755
index 0000000..6ac3f7c
--- /dev/null
+++ b/source/com/c2kernel/utils/Logger.java
@@ -0,0 +1,195 @@
+package com.c2kernel.utils;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.sql.Timestamp;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import javax.swing.JOptionPane;
+
+import org.omg.CORBA.UserException;
+import org.tanukisoftware.wrapper.WrapperManager;
+
+import com.c2kernel.process.AbstractMain;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.scripting.ScriptConsole;
+import com.c2kernel.utils.server.SimpleTCPIPServer;
+/**
+ * <pre>- message string should always contain the class name and the method name: Logger.msg(1,"ItemFact::createDir() - LifeCycle DB created"); - use meaningfull abbreviation and also use the dash to separate the 'header' from the message! - each method should start with this 'method signature' debug: Logger.msg(1,"ItemFact::createDir() - path:" + path);
+*</pre>
+ */
+public class Logger
+{
+ /**
+ * logging level 0 (only error & warning) => no logging ; 9 => maximum logging
+ * add ten to output time before each message
+ */
+ private static int mHighestLogLevel = 0;
+ private static HashMap logStreams = new HashMap();
+ static protected SimpleTCPIPServer mConsole = null;
+
+ static private void printMessage(String message, int msgLogLevel)
+ {
+ synchronized(logStreams) {
+ for (Iterator iter = logStreams.keySet().iterator(); iter.hasNext();) {
+ PrintStream element = (PrintStream)iter.next();
+ int logLevel = ((Integer)logStreams.get(element)).intValue();
+ if (logLevel < msgLogLevel || (logLevel > 9 && logLevel - 10 < msgLogLevel))
+ continue;
+ if (logLevel > 9)
+ {
+ Timestamp ts = new Timestamp(System.currentTimeMillis());
+ String sTime = ts.toString();
+ message = sTime + " - " + message;
+ }
+ try {
+ element.println(message);
+ } catch (Exception ex) {
+ iter.remove();
+ }
+ }
+ }
+ }
+
+ static private void printMessage(Throwable ex) {
+ StringWriter msgString = new StringWriter();
+ PrintWriter msg = new PrintWriter(msgString);
+ msg.print(ex instanceof Exception ? "EXCEPTION:" : "JVM ERROR:");
+ ex.printStackTrace(msg);
+ printMessage(msgString.toString(), 0);
+ }
+
+ static public boolean doLog(int logLevel)
+ {
+ return mHighestLogLevel >= logLevel;
+ }
+ /**
+ * Use this only for temporary messages while developing/debugging When the code is stable, change calls to debug to
+ * message/warning/error with an appropriate log level This makes it easier to manage debug calls in the source.
+ *
+ * @param msg -
+ * the string to write to the console, or log file if specified in cmd line
+ */
+ static public void debug(String msg)
+ {
+ msg("DEBUG : " + msg);
+ }
+ static public void debug(int logLevel, String msg)
+ {
+ msg(logLevel, "DEBUG : " + msg);
+ }
+ /**
+ * Use Logger.message to report information that will be useful for debugging a release
+ *
+ * @param level -
+ * log level of this message. If the current log level has been on the cmd line to be less that this number, the log message
+ * will not be displayed
+ * @param msg -
+ * the string to write to the console, or log file if specified in cmd line
+ */
+ static public void msg(int level, String msg)
+ {
+ printMessage(msg, level);
+ }
+ static public void msg(String msg)
+ {
+ printMessage(msg, 0);
+ }
+ static public void error(String msg)
+ {
+ printMessage("ERROR : " + msg, 0);
+ }
+ static public void error(Throwable ex)
+ {
+ printMessage(ex);
+ }
+ static public void warning(String msg)
+ {
+ printMessage("WARNING: " + msg, 0);
+ }
+ static public void die(String msg)
+ {
+ printMessage("FATAL : " + msg, 0);
+ if (AbstractMain.runningAsWrapper)
+ WrapperManager.stop(1);
+ else
+ System.exit(1);
+ }
+ static public void exceptionDialog(Exception ex)
+ {
+ String className = ex.getClass().getName();
+ className = className.substring(className.lastIndexOf('.') + 1);
+ String error = ex.getMessage();
+ if (ex instanceof UserException)
+ error = error.substring(error.indexOf(' ') + 1);
+ JOptionPane.showMessageDialog(null, error, className, JOptionPane.ERROR_MESSAGE);
+ }
+ /**
+ * @param console
+ */
+ public static void addLogStream(PrintStream console, int logLevel) {
+ try {
+ console.println("***********************************************************");
+ console.println(" C2Kernel log started at level "+logLevel+" @"+new Timestamp(System.currentTimeMillis()).toString());
+ console.println("***********************************************************");
+ } catch (Exception ex) {
+ System.out.println("Exception accessing log stream");
+ ex.printStackTrace();
+ }
+
+ synchronized(logStreams) {
+ logStreams.put(console, new Integer(logLevel));
+ if (logLevel > 9) logLevel-=10;
+ if (logLevel > mHighestLogLevel) mHighestLogLevel = logLevel;
+ }
+
+ }
+ /**
+ * @param console
+ */
+ public static void removeLogStream(PrintStream console) {
+ synchronized(logStreams) {
+ Integer logIntObj = (Integer)logStreams.get(console);
+ if (logIntObj == null) return; // not registered
+ int logLevel = (logIntObj).intValue();
+ logStreams.remove(console);
+
+ // recalculate lowest log level
+ if (logLevel == mHighestLogLevel || (logLevel > 9 && logLevel-10 == mHighestLogLevel)) {
+ mHighestLogLevel = -1;
+ for (Iterator iter = logStreams.values().iterator(); iter.hasNext();) {
+ Integer element = (Integer)iter.next();
+ int thisLogLevel = element.intValue()>9?element.intValue()-10:element.intValue();
+ if (thisLogLevel > mHighestLogLevel || mHighestLogLevel == -1)
+ mHighestLogLevel = thisLogLevel;
+ }
+ }
+ }
+ }
+
+ static public void initConsole(String id)
+ {
+ String portString = Gateway.getProperty(id+".Console.port");
+ int port = 0;
+ try {
+ port = Integer.parseInt(portString);
+ } catch (NumberFormatException ex) {
+ Logger.msg("No port defined for "+id+" console. Using any port.");
+ }
+
+ mConsole = new SimpleTCPIPServer(port, ScriptConsole.class, 5);
+ mConsole.startListening();
+ Gateway.setProperty(id+".Console.port", String.valueOf(mConsole.getPort()));
+ }
+
+ static public int getConsolePort() {
+ return mConsole.getPort();
+ }
+
+ static public void closeConsole()
+ {
+ if (mConsole != null)
+ mConsole.stopListening();
+ }
+}
diff --git a/source/com/c2kernel/utils/Resource.java b/source/com/c2kernel/utils/Resource.java
new file mode 100755
index 0000000..7a47625
--- /dev/null
+++ b/source/com/c2kernel/utils/Resource.java
@@ -0,0 +1,187 @@
+package com.c2kernel.utils;
+
+//Java
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Hashtable;
+
+import javax.swing.ImageIcon;
+
+import com.c2kernel.common.ObjectNotFoundException;
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2005/10/05 07:39:36 $
+ * @version $Revision: 1.71 $
+ **************************************************************************/
+public class Resource {
+ static private Hashtable txtCache = new Hashtable();
+ static private Hashtable imgCache = new Hashtable();
+ static private URL baseURL = null;
+ static private URL domainBaseURL = null;
+ static private URL importURL = null;
+ static public ImageIcon nullImg = new ImageIcon(new byte[] { 0 });
+ static {
+ setKernelBaseURL("com/c2kernel/utils/resources/");
+ }
+
+ /*
+ * Kernel Resource URL section
+ */
+ public static void setKernelBaseURL(String newBaseURL) {
+ baseURL = getURLorResURL(newBaseURL);
+ }
+
+ public static void setKernelBaseURL(URL newBaseURL) {
+ baseURL = newBaseURL;
+ }
+
+ public static URL getKernelBaseURL() {
+ return baseURL;
+ }
+
+ static public URL getKernelResourceURL(String resName) throws MalformedURLException {
+ return new URL(baseURL, resName);
+ }
+ /*
+ * Domain Resource URL section
+ */
+
+ public static void setDomainBaseURL(URL newBaseURL) {
+ domainBaseURL = newBaseURL;
+ }
+
+ public static void setDomainBaseURL(String newBaseURL) {
+ domainBaseURL = getURLorResURL(newBaseURL);
+ }
+
+ public static URL getDomainBaseURL() {
+ return domainBaseURL;
+ }
+
+ static public URL getDomainResourceURL(String resName) throws MalformedURLException {
+ return new URL(domainBaseURL, resName);
+ }
+
+ private static URL getURLorResURL(String newURL) {
+ URL result;
+ try {
+ result = new URL(newURL);
+ } catch (java.net.MalformedURLException ex) {
+ //it is assumed that a 'wrong' URL denotes a directory
+ //of files resolvable from the CLASSPATH
+ result = Resource.class.getClassLoader().getResource(newURL);
+ }
+ return result;
+ }
+ /**************************************************************************
+ * Gets any text resource files
+ **************************************************************************/
+ static public String getTextResource(String resName)
+ // throws IOException
+ {
+ Logger.msg(8, "Resource::getTextResource() - Getting resource: " + resName);
+
+ if (txtCache.containsKey(resName)) {
+ return (String)txtCache.get(resName);
+ }
+
+ try {
+
+ String newRes = null;
+ try {
+ newRes = FileStringUtility.url2String(getDomainResourceURL(resName));
+ } catch (Exception ex) { } // no domain base
+
+ if (newRes == null || newRes.length() == 0) { // not found in domain
+ newRes = FileStringUtility.url2String(getKernelResourceURL(resName));
+ }
+ txtCache.put(resName, newRes);
+ return newRes;
+ } catch (Exception e) {
+ return null;
+ }
+ }
+ /**
+ * Gets an image from the resource directories
+ *
+ * @param resName - filename after resources/images
+ * @return
+ */
+ static public ImageIcon getImageResource(String resName) {
+ try {
+ return getImage(resName);
+ } catch (ObjectNotFoundException ex) {
+ Logger.error("Image "+resName+" not found. Using null icon");
+ return nullImg;
+ }
+ }
+
+ static public ImageIcon getImage(String resName) throws ObjectNotFoundException {
+ if (resName == null)
+ return nullImg;
+
+ if (imgCache.containsKey(resName)) {
+ return (ImageIcon)imgCache.get(resName);
+ }
+
+ URL imgLocation = null;
+ ImageIcon newImg = null;
+ // try domain resources first
+ if (domainBaseURL != null) {
+ try {
+ imgLocation = new URL(domainBaseURL + "images/" + resName.toLowerCase());
+ newImg = new ImageIcon(imgLocation);
+ } catch (MalformedURLException e) { }
+ }
+
+ // try kernel resources next
+ if (newImg == null || newImg.getIconHeight() == -1) {
+ try {
+ imgLocation = new URL(baseURL + "images/" + resName.toLowerCase());
+ newImg = new ImageIcon(imgLocation);
+ } catch (MalformedURLException e) { }
+ }
+
+ // else return null image
+ if (newImg == null || newImg.getIconHeight() == -1) {
+ throw new ObjectNotFoundException();
+ }
+
+ else imgCache.put(resName, newImg);
+ Logger.msg(7, "Loaded "+resName+" "+newImg.getIconWidth()+"x"+newImg.getIconHeight());
+ return newImg;
+ }
+
+
+ /**
+ * Retrieves the stored import URL
+ * @return
+ */
+ public static URL getImportURL() {
+ return importURL;
+ }
+
+ /**
+ * @param url
+ */
+ public static void setImportURL(URL url) {
+ importURL = url;
+ }
+ static public String getDomainVersion() {
+ try {
+ return FileStringUtility.url2String(getDomainResourceURL("version.txt"));
+ } catch (Exception ex) {
+ return "Domain application version not found";
+ }
+ }
+
+ static public String getKernelVersion() {
+ try {
+ return FileStringUtility.url2String(getKernelResourceURL("textFiles/version.txt"));
+ } catch (Exception ex) {
+ return "No version info found";
+ }
+
+ }
+}
diff --git a/source/com/c2kernel/utils/SoftCache.java b/source/com/c2kernel/utils/SoftCache.java
new file mode 100755
index 0000000..ce2b390
--- /dev/null
+++ b/source/com/c2kernel/utils/SoftCache.java
@@ -0,0 +1,100 @@
+package com.c2kernel.utils;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.util.*;
+
+/*******************************************************************************
+ * SoftReferences are reaped if not strong references are left and the vm is
+ * running out of memory. Most caches in the kernel use this.
+ *
+ * $Revision: 1.5 $ $Date: 2004/10/29 13:29:09 $
+ ******************************************************************************/
+public class SoftCache extends AbstractMap {
+
+ private final Map hash = new HashMap();
+ private final int minSize;
+ private final LinkedList hardCache = new LinkedList();
+ private final ReferenceQueue queue = new ReferenceQueue();
+
+ public SoftCache() {
+ this(0);
+ }
+
+ public SoftCache(int minSize) {
+ this.minSize = minSize;
+ }
+
+ public Object get(Object key) {
+ Object result = null;
+ SoftReference soft_ref = (SoftReference) hash.get(key);
+ if (soft_ref != null) {
+ result = soft_ref.get();
+ if (result == null)
+ hash.remove(key);
+ else
+ if (minSize > 0) { // add to hard cache so it's not reaped for a while
+ hardCache.addFirst(result);
+ if (hardCache.size() > minSize) // trim last one off
+ hardCache.removeLast();
+ }
+ }
+ return result;
+ }
+
+ public Object put(Object key, Object value) {
+ processQueue();
+ if (minSize > 0) {
+ hardCache.addFirst(value);
+ if (hardCache.size() > minSize)
+ hardCache.removeLast();
+ }
+ return hash.put(key, new SoftValue(value, key, queue));
+ }
+
+ public Object remove(Object key) {
+ processQueue();
+ return hash.remove(key);
+ }
+
+ public void clear() {
+ hardCache.clear();
+ while(queue.poll()!=null);
+ hash.clear();
+ }
+
+ public int size() {
+ processQueue();
+ return hash.size();
+ }
+
+ public Set keySet() {
+ processQueue();
+ return hash.keySet();
+ }
+
+ public Set entrySet() {
+ // Would have to create another Map to do this - too expensive
+ // Throwing runtime expensive is dangerous, but better than nulls
+ throw new UnsupportedOperationException();
+ }
+
+ private static class SoftValue extends SoftReference {
+ private final Object key;
+ private SoftValue(Object k, Object key, ReferenceQueue q) {
+ super(k, q);
+ this.key = key;
+ }
+ }
+
+ /**
+ * Look for values that have been reaped, and remove their keys from the cache
+ */
+ private void processQueue() {
+ SoftValue sv;
+ while ((sv = (SoftValue) queue.poll()) != null) {
+ hash.remove(sv.key);
+ }
+ }
+
+}
diff --git a/source/com/c2kernel/utils/TransientCache.java b/source/com/c2kernel/utils/TransientCache.java
new file mode 100755
index 0000000..b93bbd7
--- /dev/null
+++ b/source/com/c2kernel/utils/TransientCache.java
@@ -0,0 +1,115 @@
+
+package com.c2kernel.utils;
+import java.lang.ref.*;
+import java.util.*;
+/**************************************************************************
+ * TransientCache - Uses transient references to allow unused entries to be
+ * reaped by the java garbage collector.
+ *
+ * $Revision: 1.1 $
+ * $Date: 2004/04/20 09:37:02 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+public abstract class TransientCache extends AbstractMap {
+
+ private Map map = new Hashtable();
+ public synchronized Set entrySet() {
+ Map newMap;
+ Iterator iter;
+ newMap = new Hashtable();
+ iter = map.entrySet().iterator();
+ while (iter.hasNext()) {
+ Map.Entry me = (Map.Entry)iter.next();
+ Reference ref = (Reference)me.getValue();
+ Object o = ref.get();
+ if (o == null) {
+ // Delete cleared reference
+ iter.remove();
+ } else {
+ // Copy out interior object
+ newMap.put(me.getKey(), o);
+ }
+ }
+ // Return set of interior objects
+ return newMap.entrySet();
+ }
+
+ public synchronized Object put(Object key, Object value) {
+ Reference ref = makeReference(value);
+ ref = (Reference)map.put(key, ref);
+ if (ref != null)
+ return (ref.get());
+ return null;
+ }
+
+ public abstract Reference makeReference(Object value);
+
+ public Object remove(Object key) {
+ Iterator i = map.entrySet().iterator();
+ Entry correctEntry = null;
+ if (key == null) {
+ while (correctEntry == null && i.hasNext()) {
+ Entry e = (Entry)i.next();
+ if (e.getKey() == null)
+ correctEntry = e;
+ }
+ } else {
+ while (correctEntry == null && i.hasNext()) {
+ Entry e = (Entry)i.next();
+ if (key.equals(e.getKey()))
+ correctEntry = e;
+ }
+ }
+ Object oldValue = null;
+ if (correctEntry != null) {
+ Reference correctReference = (Reference)correctEntry.getValue();
+ oldValue = correctReference.get();
+ i.remove();
+ }
+ return oldValue;
+ }
+ /**
+ *
+ */
+ public void clear() {
+ map.entrySet().clear();
+ }
+
+ private transient Set keySet = null;
+
+ public Set keySet() {
+ if (keySet == null) {
+ keySet = new AbstractSet() {
+ public Iterator iterator() {
+ return new Iterator() {
+ private Iterator i = map.entrySet().iterator();
+
+ public boolean hasNext() {
+ return i.hasNext();
+ }
+
+ public Object next() {
+ return ((Entry)i.next()).getKey();
+ }
+
+ public void remove() {
+ i.remove();
+ }
+ };
+ }
+
+ public int size() {
+ return TransientCache.this.size();
+ }
+
+ public boolean contains(Object k) {
+ return TransientCache.this.containsKey(k);
+ }
+ };
+ }
+ return keySet;
+ }
+
+}
diff --git a/source/com/c2kernel/utils/XmlElementParser.java b/source/com/c2kernel/utils/XmlElementParser.java
new file mode 100755
index 0000000..f6fef4b
--- /dev/null
+++ b/source/com/c2kernel/utils/XmlElementParser.java
@@ -0,0 +1,115 @@
+package com.c2kernel.utils;
+
+import java.io.StringReader;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+public class XmlElementParser
+{
+ public static String[] parse(String data, String xpath)
+ {
+ try {
+ return Dom4JElementParser.parse(data, xpath);
+ } catch (NoClassDefFoundError ex) {
+ Logger.msg(5, "Using old xpath parser");
+ return parseOld(data, xpath);
+ }
+ }
+
+ public static String[] parseOld(String data, String path)
+ {
+ Vector returnData = new Vector();
+ String[] returnArray = new String[0];
+ try
+ {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ StringReader is = new StringReader(data);
+ Document doc = builder.parse(new InputSource(is));
+ StringTokenizer pathTokens = new StringTokenizer(path, "/");
+ int taille = pathTokens.countTokens();
+ String[] pathElements = new String[taille];
+ int i=taille;
+ while (pathTokens.hasMoreElements())
+ pathElements[--i] = pathTokens.nextToken();
+
+ if (Logger.doLog(6)) {
+ Logger.msg(6, "Path elements:");
+ for (int x=0;x<pathElements.length;x++)
+ Logger.debug(6, pathElements[x]);
+ }
+
+ Logger.msg(6, "Looking for attribute "+pathElements[0]+" in "+pathElements[1]);
+ NodeList nl = doc.getElementsByTagName(pathElements[1]);
+ for (int j = 0; j < nl.getLength(); j++)
+ {
+ Logger.msg(6, "Found one");
+ Element e = (Element)nl.item(j);
+ boolean match=true;
+ Node child=e;
+ for (int k=2;k<taille&&match;k++)
+ {
+ Logger.msg(6, "Checking parent "+pathElements[k]);
+ child = child.getParentNode();
+ if (!child.getNodeName().equals(pathElements[k]))
+ {
+ Logger.msg(6, "No match for "+child.getNodeName());
+ match=false;
+ }
+ else
+ Logger.msg(6, "Match");
+ }
+ if (match&&e.hasAttribute(pathElements[0])) {
+ Logger.msg(6, "Matching Attribute "+pathElements[0]+"="+e.getAttribute(pathElements[0]));
+ returnData.add(e.getAttribute(pathElements[0]));
+ }
+ }
+
+ Logger.msg(6, "Looking for element "+pathElements[0]);
+ nl = doc.getElementsByTagName(pathElements[0]);
+ for (int j = 0; j < nl.getLength(); j++)
+ {
+ Logger.msg(6, "Found one");
+ Element e = (Element)nl.item(j);
+ boolean match=true;
+ Node child=e;
+ for (int k=1;k<taille&&match;k++)
+ {
+ Logger.msg(6, "Checking parent "+pathElements[k]);
+ child = child.getParentNode();
+ if (!child.getNodeName().equals(pathElements[k]))
+ {
+ Logger.msg(6, "No match for "+child.getNodeName());
+ match=false;
+ }
+ else
+ Logger.msg(6, "Match");
+ }
+ if (match)
+ {
+ String s =e.getFirstChild().getNodeValue();
+ Logger.msg(6, "Found Element "+pathElements[0]+"="+s);
+ if (s!=null) returnData.add(s);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ //Logger.error(e);
+ }
+ Logger.msg(3, returnData.size()+" values found for "+path);
+ returnArray=new String[returnData.size()];
+ for (int i=0;i<returnArray.length;i++)
+ returnArray[i] = (String)returnData.get(i);
+ return returnArray;
+ }
+}
diff --git a/source/com/c2kernel/utils/server/HTTPRequestHandler.java b/source/com/c2kernel/utils/server/HTTPRequestHandler.java
new file mode 100755
index 0000000..1cad863
--- /dev/null
+++ b/source/com/c2kernel/utils/server/HTTPRequestHandler.java
@@ -0,0 +1,155 @@
+package com.c2kernel.utils.server;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+
+import com.c2kernel.utils.Logger;
+
+public class HTTPRequestHandler implements SocketHandler {
+
+ protected HashMap headers = new HashMap();
+ protected String method;
+ protected String resource;
+ protected String version;
+ protected String returnMIME;
+ protected String statusCode;
+ protected String postData;
+ protected final static String CRLF = "\r\n";
+ protected BufferedReader request;
+ protected Socket currentSocket = null;
+
+ public HTTPRequestHandler() { }
+
+ public String getName() {
+ return "HTTP Server";
+ }
+
+ public boolean isBusy() {
+ return (currentSocket!=null);
+ }
+
+ public void setSocket(Socket newSocket) {
+ currentSocket = newSocket;
+ }
+
+ public void shutdown() {
+ try {
+ if (currentSocket != null) currentSocket.close();
+ } catch (IOException e) {
+ Logger.error("Error shutting down HTTP connection");
+ }
+ currentSocket = null;
+ }
+
+ public void run() {
+ Thread.currentThread().setName("HTTP Request Handler");
+ try {
+ request = new BufferedReader(new InputStreamReader(currentSocket.getInputStream()));
+ // parse the request
+ boolean firstLine = true;
+ String headerLine;
+ do {
+ headerLine = request.readLine();
+ if (headerLine == null)
+ throw new IOException("Disconnected");
+ if (firstLine) { // request line
+ StringTokenizer params = new StringTokenizer(headerLine);
+ try {
+ method = params.nextToken();
+ resource = params.nextToken();
+ version = params.nextToken();
+ } catch (NoSuchElementException ex1) { } // incomplete request line - doesn't matter
+ firstLine = false;
+ }
+ else { // headers
+ int split = headerLine.indexOf(": ");
+ if (split >= 0)
+ headers.put(
+ headerLine.substring(0, split),
+ headerLine.substring(split+2)
+ );
+ }
+ } while (!headerLine.equals(CRLF) && !headerLine.equals(""));
+
+ String response = null;
+
+ try {
+
+ if (headers.containsKey("Content-length")) { // read POST data
+ StringBuffer postBuffer = new StringBuffer();
+ int received = 0; int length = Integer.parseInt((String)headers.get("Content-length"));
+ try {
+ while (received < length) {
+ String postLine = request.readLine();
+ postBuffer.append(postLine);
+ received+=postLine.length();
+ }
+ } catch (IOException ex) {
+ Logger.error("Error reading post data. "+received+" bytes of "+length+" received. ("+(received*100.0/length)+"%");
+ Logger.error(ex);
+ throw ex;
+ }
+ }
+ // Got the params, generate response
+
+ returnMIME = "text/xml";
+ statusCode = "200 OK";
+
+ response = processRequest();
+ } catch (Exception ex3) {
+ response = error("500 Server Error", ex3.getClass().getName()+"<br>"+ex3.getMessage());
+ }
+ System.out.println(new Date().toString()+" "+currentSocket.getInetAddress()+" "+method+" "+resource+" "+statusCode);
+
+ OutputStream output = currentSocket.getOutputStream();
+
+ statusCode = "HTTP/1.0 "+statusCode+CRLF;
+ output.write(statusCode.getBytes());
+
+ returnMIME = "Content-type: "+returnMIME+CRLF;
+ output.write(returnMIME.getBytes());
+
+ String contentLength = "Content-Length: "+response.length()+CRLF;
+ output.write(contentLength.getBytes());
+
+ // Possible: last mod?
+ // end of headers
+ output.write(CRLF.getBytes());
+
+ // write the content
+ output.write(response.getBytes());
+ request.close();
+ output.close();
+ currentSocket.close();
+ } catch (IOException ex2) {
+ Logger.error(ex2);
+ } // aborted connection probably
+ currentSocket = null;
+ }
+
+ /* This is a dummy method that doesn't support anything.
+ * Override it.
+ */
+
+ public String processRequest() {
+ return error("501 Not Implemented", "The method "+method+" you have requested is not supported by this server.");
+ }
+
+ public String error(String code, String desc) {
+ statusCode = code;
+ returnMIME = "text/html";
+ return ("<HTML>" +
+ "<HEAD><TITLE>"+code+"</TITLE></HEAD>" +
+ "<BODY><h1>"+code+"</h1>" +
+ "<p>"+desc+
+ "<hr><p><small>Cristal Item HTTP server</small></BODY></HTML>");
+ }
+}
+
diff --git a/source/com/c2kernel/utils/server/SimpleTCPIPServer.java b/source/com/c2kernel/utils/server/SimpleTCPIPServer.java
new file mode 100755
index 0000000..12e8ec4
--- /dev/null
+++ b/source/com/c2kernel/utils/server/SimpleTCPIPServer.java
@@ -0,0 +1,112 @@
+package com.c2kernel.utils.server;
+
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+import com.c2kernel.utils.Logger;
+
+
+public class SimpleTCPIPServer implements Runnable
+{
+ int port = 0;
+ int maxConn = 10;
+ Thread listener = null;
+ Class handlerClass = null;
+ ServerSocket serverSocket = null;
+ boolean keepListening = true;
+ ArrayList currentHandlers = new ArrayList();
+ static short noServers = 0;
+
+ public SimpleTCPIPServer(int port, Class handlerClass, int maxConnections)
+ {
+ this.port = port;
+ this.handlerClass = handlerClass;
+ this.maxConn = maxConnections;
+ noServers++;
+ }
+
+ public void startListening()
+ {
+ if(listener != null) return;
+ keepListening = true;
+
+ listener = new Thread(this);
+ listener.start();
+ }
+
+ public void stopListening()
+ {
+ Logger.msg("SimpleTCPIPServer: Closing server for " + handlerClass.getName() +" on port "+ port);
+ keepListening = false;
+ for (Iterator iter = currentHandlers.iterator(); iter.hasNext();) {
+ SocketHandler thisHandler = (SocketHandler)iter.next();
+ thisHandler.shutdown();
+ }
+ }
+
+ public void run()
+ {
+ Thread.currentThread().setName("TCP/IP Server for "+handlerClass.getName());
+ Socket connectionSocket = null;
+ InputStream inputStream = null;
+
+ try {
+ serverSocket = new ServerSocket(port);
+ if (port == 0)
+ port = serverSocket.getLocalPort();
+ Logger.msg("SimpleTCPIPServer: Created server for " + handlerClass.getName()+" on port "+port);
+ serverSocket.setSoTimeout(500);
+ SocketHandler freeHandler = null;
+ while(keepListening) {
+ if (freeHandler == null || freeHandler.isBusy()) {
+ ListIterator i = currentHandlers.listIterator();
+ try {
+ do {
+ freeHandler = (SocketHandler)i.next();
+ } while (freeHandler.isBusy());
+ } catch (NoSuchElementException e) {
+ // create new one
+ if (currentHandlers.size() < maxConn) {
+ freeHandler = (SocketHandler)handlerClass.newInstance();
+ currentHandlers.add(freeHandler);
+ }
+ else { // max handlers are created. wait for a while, then look again
+ Logger.warning("No free handlers left for "+handlerClass.getName()+" on port "+ port + "!");
+ Thread.sleep(2000);
+ continue;
+ }
+ }
+ }
+ try {
+ connectionSocket = serverSocket.accept();
+ if (keepListening) {
+ Logger.msg("SimpleTCPIPServer: Connection to "+freeHandler.getName()+" from "+
+ connectionSocket.getInetAddress());
+ freeHandler.setSocket(connectionSocket);
+ new Thread(freeHandler).start();
+ }
+ } catch (InterruptedIOException ex1) { }// timeout just to check if we've been told to die
+
+ }
+ serverSocket.close();
+ Logger.msg("SimpleTCPIPServer: Server closed for " + handlerClass.getName() +" on port "+ port);
+ } catch(Exception ex) {
+ Logger.error(ex);
+ Logger.error("SimpleTCPIPServer.run(): Fatal Error. Listener for '"+handlerClass.getName()+"' will stop.");
+ listener = null; --noServers;
+ return;
+ }
+ listener = null;
+ Logger.msg("SimpleTCPIPServer - Servers still running: "+--noServers);
+ }
+
+ public int getPort() {
+ return port;
+ }
+}
diff --git a/source/com/c2kernel/utils/server/SocketHandler.java b/source/com/c2kernel/utils/server/SocketHandler.java
new file mode 100755
index 0000000..455a9bd
--- /dev/null
+++ b/source/com/c2kernel/utils/server/SocketHandler.java
@@ -0,0 +1,15 @@
+package com.c2kernel.utils.server;
+
+import java.net.Socket;
+
+public interface SocketHandler extends Runnable {
+
+ public String getName();
+
+ public boolean isBusy();
+
+ public void setSocket(Socket newSocket);
+
+ public void shutdown();
+}
+
diff --git a/source/com/c2kernel/utils/server/UDPListener.java b/source/com/c2kernel/utils/server/UDPListener.java
new file mode 100755
index 0000000..1f02361
--- /dev/null
+++ b/source/com/c2kernel/utils/server/UDPListener.java
@@ -0,0 +1,53 @@
+package com.c2kernel.utils.server;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+
+import com.c2kernel.common.InvalidDataException;
+import com.c2kernel.utils.Logger;
+
+/**************************************************************************
+ *
+ * $Revision: 1.2 $
+ * $Date: 2004/02/06 14:50:43 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public abstract class UDPListener extends Thread {
+
+ private boolean active = true;
+ protected DatagramSocket socket;
+
+ public UDPListener() {
+ super();
+ }
+
+ public void run() {
+ Thread.currentThread().setName("UDP Server");
+ byte[] buffer = new byte[255];
+ DatagramPacket newPacket = new DatagramPacket(buffer, buffer.length);
+ while (active) {
+ try {
+ socket.receive(newPacket);
+ processPacket(newPacket);
+ } catch (InterruptedIOException e) { // ignore timeout
+ } catch (IOException e) {
+ Logger.error("Error receiving proxy packet:");
+ Logger.error(e);
+ } catch (InvalidDataException e) {
+ Logger.error(e);
+ }
+ }
+ socket.close();
+ }
+
+ protected abstract void processPacket(DatagramPacket packet) throws InvalidDataException;
+
+ public void shutdown() {
+ active = false;
+ }
+}
diff --git a/source/idls/c2kernel/CommonExceptions.idl b/source/idls/c2kernel/CommonExceptions.idl
new file mode 100755
index 0000000..9301ad0
--- /dev/null
+++ b/source/idls/c2kernel/CommonExceptions.idl
@@ -0,0 +1,97 @@
+#ifndef __com_CommonExceptions_Idl__
+#define __com_CommonExceptions_Idl__
+
+/*
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ *
+ * @author $Author: abranson $ $Date: 2004/01/21 16:17:18 $
+ * @version $Revision: 1.6 $
+ */
+
+#pragma prefix "c2kernel.com"
+
+module common
+{
+ /**************************************************************************
+ * Thrown by the different Factories
+ **************************************************************************/
+ exception CannotManageException
+ {
+ string mDescription;
+ };
+
+
+
+ /**************************************************************************
+ * The requested Transition in the State Diagram of the Step
+ * cannot be performed.
+ **************************************************************************/
+ exception InvalidTransitionException
+ {
+ string mDescription;
+ };
+
+
+ /**************************************************************************
+ * The action for the requested Transition has got invalid data
+ * Also used in other contexts if the provided data is not valid
+ * (eg. index out of bounds)
+ **************************************************************************/
+ exception InvalidDataException
+ {
+ string mDescription;
+ };
+
+
+ /**************************************************************************
+ * The Agent has no rigths to request the Transition.
+ *
+ *<p><pre> Two major reasons:
+ * 1. The role of the Agent and the Step specifictaion does not much.
+ * 2. The Step is already allocated to an Agent.
+ *</pre>
+ **************************************************************************/
+ exception AccessRightsException
+ {
+ string mDescription;
+ };
+
+
+ /**************************************************************************
+ * The requested object was not found
+ **************************************************************************/
+ exception ObjectNotFoundException
+ {
+ string mDescription;
+ };
+
+
+ /**************************************************************************
+ * Error during storing/retrieving objects
+ **************************************************************************/
+ exception PersistencyException
+ {
+ string mDescription;
+ };
+
+ /**************************************************************************
+ * The object already exists.
+ **************************************************************************/
+ exception ObjectAlreadyExistsException
+ {
+ string mDescription;
+ };
+
+
+ /**************************************************************************
+ * The object cannot be changed.
+ **************************************************************************/
+ exception ObjectCannotBeUpdated
+ {
+ string mDescription;
+ };
+
+}; //end of module common
+
+#endif
diff --git a/source/idls/c2kernel/CommonTypes.idl b/source/idls/c2kernel/CommonTypes.idl
new file mode 100755
index 0000000..93395eb
--- /dev/null
+++ b/source/idls/c2kernel/CommonTypes.idl
@@ -0,0 +1,42 @@
+#ifndef __com_CommonTypes_Idl__
+#define __com_CommonTypes_Idl__
+
+/*
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ *
+ * @author $Author: abranson $ $Date: 2004/01/21 16:17:18 $
+ * @version $Revision: 1.24 $
+ */
+
+#include <CommonExceptions.idl>
+
+#pragma prefix "c2kernel.com"
+
+module common
+{
+
+ /**************************************************************************
+ * Describes the time by year, month, day, hour, minute and second
+ * in Greenwich Mean Time (GMT) so it also describes the timezone by
+ * providing the offset from GMT in seconds.
+ *
+ * @version 1.0
+ * @author kovax
+ **************************************************************************/
+ struct GTimeStamp
+ {
+ long mYear;
+ long mMonth;
+ long mDay;
+ long mHour;
+ long mMinute;
+ long mSecond;
+ long mTimeOffset; //in seconds
+ };
+
+
+
+}; //end of module common
+
+#endif
diff --git a/source/idls/c2kernel/Entity.idl b/source/idls/c2kernel/Entity.idl
new file mode 100755
index 0000000..aa607c7
--- /dev/null
+++ b/source/idls/c2kernel/Entity.idl
@@ -0,0 +1,182 @@
+#ifndef __Entity_Idl__
+#define __Entity_Idl__
+
+/*
+ * Copyright (C) 2001 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ *
+ * @author $Author: abranson $ $Date: 2005/04/26 06:47:48 $
+ * @version $Revision: 1.24 $
+ */
+
+#include <CommonTypes.idl>
+
+#pragma prefix "c2kernel.com"
+
+module entity
+{
+ /**************************************************************************
+ * ManageableEntity is an <i>uniquely identifiable CORBA object</i>.
+ *
+ * - It is persistent or not. This is relevant when the timelife of it
+ * is very short and/or there is no need for recovery from crash.
+ **************************************************************************/
+ abstract interface ManageableEntity
+ {
+
+ /**
+ * <p>System generated unique key of the Entity. It is unique
+ * in the context defined by the domain expert which is to
+ * define the root NamingContext in the Naming Service
+ * (ie. return of orb.resolve_initial_references("NameService") ).
+ * <p>In principle it is equivalent with an OID of an object in a
+ * OODBMS or with an IOR defined on CORBA.
+ **/
+ unsigned long getSystemKey();
+
+
+ /**
+ * The description for operation getData.
+ *
+ * @param xpath A not so dummy argument.
+ * - LifeCycle
+ * - Collection
+ * - History
+ * - Properties
+ * - JobList
+ * - Capabilities
+ *
+ * @return The result string in xml format.
+ *
+ * @exception ObjectNotFoundException 'what' was not found.
+ **/
+ string queryData( in string xpath )
+ raises( common::AccessRightsException,
+ common::ObjectNotFoundException,
+ common::PersistencyException );
+ };
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ interface Agent : ManageableEntity
+ {
+ void initialise( in string agentProps )
+ raises( common::AccessRightsException,
+ common::InvalidDataException,
+ common::PersistencyException );
+ void refreshJobList( in unsigned long sysKey, in string stepPath, in string newJobs );
+ void addRole( in string roleName )
+ raises( common::ObjectNotFoundException,
+ common::CannotManageException );
+ void removeRole( in string roleName )
+ raises( common::ObjectNotFoundException,
+ common::CannotManageException );
+ };
+
+
+ /**************************************************************************
+ * Item is an ManageableEntity which have LifeCycle(s) and can have a
+ * History, Collections and Queries.
+ *
+ * <p><pre>Here is the summary of the different Item configuration:
+ * - It always has one or more LifeCycles.
+ * - It is persistent or not. This is relevant when the Item's LifeCycle
+ * is very short and/or there is no need for recovery from crash.
+ * It is very likely that an Item with no persistency cannot use Queries.
+ * - Item can have only one History. It is possible to have an Item
+ * without History which means it does not support audit trailing.
+ * An Item with no persistency very likely won't need the History.
+ * - Item can have many Collection of the different types (see: {@link CollectionBase}).
+ * In the simple case Item have one Collection for each type but it
+ * also should be able to have many Collections of the same type.
+ * Note that for the later collections have to be named in order to
+ * identify them!
+ * - Item can have a list of named Queries (can be empty list).
+ *
+ * One extreme is to create a non persistent Item which has only
+ * the LifeCycle. This Item can 'only' generate Events in the proper order
+ * and execute special Actions which are implemented by the domain user.
+ * A simple user code could be such an Item!
+ *</pre>
+ *
+ * @author kovax
+ * @version 1.0
+ **************************************************************************/
+
+ interface Item : ManageableEntity
+ {
+ /**
+ *
+ * @param
+ *
+ * @exception ObjectNotFoundException
+ **/
+ void initialise( in unsigned long agentId,
+ in string itemProps,
+ in string workflow )
+ raises( common::AccessRightsException,
+ common::InvalidDataException,
+ common::PersistencyException );
+
+ /**
+ * The Agent reguests one Step in the LifeCycle to perform one Transition.
+ * Item delegetes this request to its LifeCycle object.
+ *
+ * @param agentInfo Complete identification of the Agent. It is used
+ * to check the rigths of the Agent (see:{@link AccessRigthsException})
+ *
+ * @param lifeCycleID
+ *
+ * @param stepPath The id of the Step in the LifeCycle tree
+ *
+ * @param transitionID The id of the Transition
+ *
+ * @param reguestData Domain specific data required to process the
+ * request (eg. conidtions).
+ *
+ * @exception AccessRigthsException The Agent has no rigths
+ * to make the request.
+ * @exception InvalidTransitionException It is impossible to
+ * perform the Transition.
+ * @exception ObjectNotFoundException Step does not exists.
+ **/
+ void requestAction( in unsigned long agentID,
+ in string stepPath,
+ in unsigned long transitionID,
+ in string requestData
+ )
+ raises( common::AccessRightsException,
+ common::InvalidTransitionException,
+ common::ObjectNotFoundException,
+ common::InvalidDataException,
+ common::PersistencyException,
+ common::ObjectAlreadyExistsException );
+
+
+ /**
+ * Queries the LifeCycle for Steps with different conditions. Returns the
+ * xml string containing the Steps matching those conditions.
+ *
+ * @param agentInfo Complete identification of the Agent. It is used
+ * if 'filter' is true.
+ *
+ * @param stateID The ID of the State (eg. Active)
+ *
+ * @param filter false: All the Steps; true: Steps for the Agent only (ID ,role)
+ *
+ * @return The result string in xml format (could be many Steps, or nothing).
+ **/
+ string queryLifeCycle( in unsigned long agentId,
+ in boolean filter )
+ raises( common::AccessRightsException,
+ common::ObjectNotFoundException,
+ common::PersistencyException );
+
+
+ }; //end of Item
+
+}; //end of module entity
+
+#endif //__Entity_Idl__