From 254ee6f47eebfc00462c10756a92066e82cc1a96 Mon Sep 17 00:00:00 2001 From: Andrew Branson Date: Tue, 21 Jun 2011 15:46:02 +0200 Subject: Initial commit --- .classpath | 18 + .project | 17 + bin/UserCode.bat | 6 + bin/ant.bat | 110 +++ bin/conf/client.conf | 3 + bin/conf/server.conf | 4 + bin/env.bat | 5 + bin/itemServer.bat | 7 + bin/itemServer.sh | 15 + bin/lcp.bat | 9 + bin/runGUI.bat | 6 + bin/runOutcomeEditor.bat | 5 + bin/win32/SQLiteSpy.db3 | Bin 0 -> 3072 bytes bin/win32/SQLiteSpy.exe | Bin 0 -> 1657856 bytes bin/win32/Wrapper.dll | Bin 0 -> 65536 bytes bin/win32/clc.reg | Bin 0 -> 2360 bytes bin/win32/iordump.exe | Bin 0 -> 1613824 bytes bin/win32/sqlite3.exe | Bin 0 -> 322630 bytes bin/win32/sqlite_jni.dll | Bin 0 -> 241664 bytes build.xml | 162 ++++ changelog | 139 ++++ connect/dev.clc.example | 29 + javadoc.xml | 8 + lib/bsf.jar | Bin 0 -> 80528 bytes lib/castor-core.jar | Bin 0 -> 55226 bytes lib/castor-xml-schema.jar | Bin 0 -> 347768 bytes lib/castor-xml.jar | Bin 0 -> 749083 bytes lib/commons-logging.jar | Bin 0 -> 38015 bytes lib/dom4j.jar | Bin 0 -> 446847 bytes lib/js.jar | Bin 0 -> 597407 bytes lib/ldap.jar | Bin 0 -> 275642 bytes lib/wrapper.jar | Bin 0 -> 52684 bytes lib/xercesImpl.jar | Bin 0 -> 1207073 bytes lib/xml-apis.jar | Bin 0 -> 195119 bytes resources/boot/CA/CompositeActivityFactory.xml | 108 +++ resources/boot/CA/ElementaryActivityFactory.xml | 108 +++ resources/boot/CA/ManageCompositeActDef.xml | 219 +++++ resources/boot/CA/ManageElementaryActDef.xml | 219 +++++ resources/boot/CA/ManageSchema.xml | 218 +++++ resources/boot/CA/ManageScript.xml | 219 +++++ resources/boot/CA/NoWorkflow.xml | 22 + resources/boot/CA/SchemaFactory.xml | 108 +++ resources/boot/CA/ScriptFactory.xml | 108 +++ resources/boot/CA/ServerItemWorkflow.xml | 217 +++++ resources/boot/EA/AssignNewVersionFromLast.xml | 20 + resources/boot/EA/CreateNewAgent.xml | 19 + resources/boot/EA/CreateNewItem.xml | 19 + resources/boot/EA/CreateNewLocalObjectDef.xml | 19 + resources/boot/EA/EditActivityDef.xml | 19 + resources/boot/EA/EditProperties.xml | 20 + resources/boot/EA/EditSchema.xml | 19 + resources/boot/EA/EditScriptDefinition.xml | 19 + resources/boot/LDAPboot.txt | 4 + resources/boot/OD/CompositeActivityDef.xml | 186 +++++ resources/boot/OD/ElementaryActivityDef.xml | 29 + resources/boot/OD/New.xml | 3 + resources/boot/OD/NewAgent.xml | 20 + resources/boot/OD/NewItem.xml | 73 ++ resources/boot/OD/NewLocalObjectDef.xml | 20 + resources/boot/OD/PredefinedStepOutcome.xml | 13 + resources/boot/OD/PropertyDescription.xml | 36 + resources/boot/OD/Schema.xml | 4 + resources/boot/OD/Script.xml | 38 + .../boot/SC/CreateNewNumberedVersionFromLast.xml | 39 + resources/boot/SC/LocalObjectDefCreator.xml | 57 ++ resources/boot/SC/New.xml | 13 + resources/boot/SC/ServerNewEntity.xml | 20 + resources/boot/allbootitems.txt | 34 + resources/boot/factory/CA.xml | 8 + resources/boot/factory/EA.xml | 8 + resources/boot/factory/OD.xml | 8 + resources/boot/factory/SC.xml | 8 + resources/boot/property/CAProp.xml | 5 + resources/boot/property/EAProp.xml | 5 + resources/boot/property/ODProp.xml | 5 + resources/boot/property/SCProp.xml | 4 + resources/images/Thumbs.db | Bin 0 -> 58368 bytes resources/images/about.png | Bin 0 -> 1906 bytes resources/images/compositeMember.gif | Bin 0 -> 916 bytes resources/images/elementaryMember.gif | Bin 0 -> 872 bytes resources/images/find.png | Bin 0 -> 795 bytes resources/images/folder.png | Bin 0 -> 559 bytes resources/images/graph/autolayout.png | Bin 0 -> 909 bytes resources/images/graph/copy.png | Bin 0 -> 805 bytes resources/images/graph/delete.png | Bin 0 -> 858 bytes resources/images/graph/edge.png | Bin 0 -> 565 bytes resources/images/graph/history.png | Bin 0 -> 991 bytes resources/images/graph/load.png | Bin 0 -> 559 bytes resources/images/graph/newvertex.png | Bin 0 -> 703 bytes resources/images/graph/newvertex_large.png | Bin 0 -> 1221 bytes resources/images/graph/print.png | Bin 0 -> 870 bytes resources/images/graph/resizepad.gif | Bin 0 -> 842 bytes resources/images/graph/save.png | Bin 0 -> 892 bytes resources/images/graph/selection.gif | Bin 0 -> 132 bytes resources/images/graph/start.png | Bin 0 -> 732 bytes resources/images/graph/zoomout.png | Bin 0 -> 927 bytes resources/images/info.png | Bin 0 -> 866 bytes resources/images/leaf.png | Bin 0 -> 626 bytes resources/images/loading.gif | Bin 0 -> 1245 bytes resources/images/next.png | Bin 0 -> 921 bytes resources/images/reload.gif | Bin 0 -> 1005 bytes resources/images/typeicons/agent_16.png | Bin 0 -> 810 bytes resources/images/typeicons/agent_32.png | Bin 0 -> 1803 bytes .../images/typeicons/compositeactivitydesc_16.png | Bin 0 -> 788 bytes .../images/typeicons/compositeactivitydesc_32.png | Bin 0 -> 2102 bytes .../images/typeicons/elementaryactivitydesc_16.png | Bin 0 -> 724 bytes .../images/typeicons/elementaryactivitydesc_32.png | Bin 0 -> 1871 bytes .../images/typeicons/localobjectfactory_16.png | Bin 0 -> 916 bytes .../images/typeicons/localobjectfactory_32.png | Bin 0 -> 2084 bytes resources/images/typeicons/outcome_desc_32.png | Bin 0 -> 1881 bytes resources/images/typeicons/outcomedesc_16.png | Bin 0 -> 840 bytes resources/images/typeicons/outcomedesc_32.png | Bin 0 -> 1881 bytes resources/images/typeicons/script_16.png | Bin 0 -> 894 bytes resources/images/typeicons/script_32.png | Bin 0 -> 2056 bytes resources/images/typeicons/server_16.png | Bin 0 -> 875 bytes resources/images/typeicons/server_32.png | Bin 0 -> 1882 bytes resources/mapFiles/CastorHashMapMap.xml | 41 + resources/mapFiles/CollectionMap.xml | 113 +++ resources/mapFiles/HistoryMap.xml | 43 + resources/mapFiles/JobListMap.xml | 48 ++ resources/mapFiles/KeyValuePairMap.xml | 30 + resources/mapFiles/LifeCycleMap.xml | 121 +++ resources/mapFiles/NewEntityMap.xml | 102 +++ resources/mapFiles/PropertiesMap.xml | 46 ++ resources/mapFiles/TransferMap.xml | 19 + resources/mapFiles/ViewpointMap.xml | 21 + resources/mapFiles/graphModelMap.xml | 126 +++ resources/mapFiles/index.xml | 10 + resources/openldap/README | 5 + resources/openldap/cristal2.schema | 49 ++ resources/openldap/slapd.conf | 20 + resources/textFiles/consoleHelp.txt | 18 + resources/textFiles/defaultConf.properties | 5 + resources/textFiles/license.html | 38 + resources/textFiles/version.txt | 1 + source/com/c2kernel/collection/Aggregation.java | 111 +++ .../collection/AggregationDescription.java | 59 ++ .../c2kernel/collection/AggregationInstance.java | 45 ++ .../com/c2kernel/collection/AggregationMember.java | 154 ++++ source/com/c2kernel/collection/Collection.java | 32 + .../c2kernel/collection/CollectionDescription.java | 14 + .../com/c2kernel/collection/CollectionMember.java | 38 + .../c2kernel/collection/CollectionMemberList.java | 22 + source/com/c2kernel/collection/Dependency.java | 114 +++ .../com/c2kernel/collection/DependencyMember.java | 141 ++++ .../c2kernel/collection/MembershipException.java | 21 + .../collection/Parent2ChildCollection.java | 119 +++ .../com/c2kernel/collection/RelationshipUtils.java | 33 + .../gui/model/AggregationVertexFactory.java | 44 + .../gui/model/AggregationVertexOutlineCreator.java | 43 + .../gui/view/AggregationMemberRenderer.java | 124 +++ .../collection/gui/view/CollectionFrame.java | 41 + .../collection/gui/view/PropertyPanel.java | 36 + .../collection/gui/view/SelectedMemberPanel.java | 150 ++++ source/com/c2kernel/entity/C2KLocalObject.java | 32 + source/com/c2kernel/entity/CorbaServer.java | 191 +++++ source/com/c2kernel/entity/TraceableEntity.java | 335 ++++++++ source/com/c2kernel/entity/TraceableLocator.java | 84 ++ source/com/c2kernel/entity/agent/ActiveEntity.java | 281 +++++++ .../com/c2kernel/entity/agent/ActiveLocator.java | 87 ++ source/com/c2kernel/entity/agent/Job.java | 343 ++++++++ source/com/c2kernel/entity/agent/JobArrayList.java | 30 + source/com/c2kernel/entity/agent/JobList.java | 125 +++ source/com/c2kernel/entity/proxy/AgentProxy.java | 301 +++++++ .../entity/proxy/DomainPathSubscriber.java | 18 + source/com/c2kernel/entity/proxy/EntityProxy.java | 246 ++++++ .../c2kernel/entity/proxy/EntityProxyManager.java | 341 ++++++++ .../c2kernel/entity/proxy/EntityProxyObserver.java | 25 + source/com/c2kernel/entity/proxy/ItemProxy.java | 212 +++++ .../com/c2kernel/entity/proxy/MemberControl.java | 43 + .../c2kernel/entity/proxy/MemberSubscription.java | 121 +++ .../entity/proxy/ProxyClientConnection.java | 179 +++++ source/com/c2kernel/entity/proxy/ProxyMessage.java | 110 +++ .../entity/proxy/ProxyServerConnection.java | 129 +++ .../com/c2kernel/entity/proxy/ProxySubscriber.java | 36 + .../com/c2kernel/entity/transfer/TransferItem.java | 131 +++ .../com/c2kernel/entity/transfer/TransferSet.java | 107 +++ source/com/c2kernel/events/Event.java | 296 +++++++ source/com/c2kernel/events/History.java | 94 +++ .../graph/controller/AutoScrollController.java | 39 + .../graph/controller/DeletionController.java | 89 +++ .../controller/EdgeConstructionController.java | 244 ++++++ .../controller/MultiSelectionDragController.java | 551 +++++++++++++ .../graph/controller/StartVertexController.java | 77 ++ .../controller/VertexConstructionController.java | 45 ++ source/com/c2kernel/graph/event/ClearedEvent.java | 6 + .../com/c2kernel/graph/event/EdgeRemovedEvent.java | 6 + .../c2kernel/graph/event/EdgesChangedEvent.java | 6 + .../graph/event/ElasticBandResizedEvent.java | 6 + .../c2kernel/graph/event/ElasticBandSetEvent.java | 6 + .../graph/event/EntireModelChangedEvent.java | 6 + .../c2kernel/graph/event/ForcedNotifyEvent.java | 6 + .../com/c2kernel/graph/event/GraphModelEvent.java | 7 + .../graph/event/GraphModelResizedEvent.java | 6 + .../graph/event/NewEdgeEndPointChangedEvent.java | 6 + .../graph/event/SelectionChangedEvent.java | 9 + .../c2kernel/graph/event/SelectionMovedEvent.java | 7 + .../graph/event/StartVertexIdChangedEvent.java | 6 + .../com/c2kernel/graph/event/VertexAddedEvent.java | 6 + .../c2kernel/graph/event/VertexCreatedEvent.java | 6 + .../com/c2kernel/graph/event/VertexMovedEvent.java | 6 + .../c2kernel/graph/event/VertexRemovedEvent.java | 6 + .../c2kernel/graph/event/VerticesChangedEvent.java | 6 + .../graph/layout/DefaultGraphLayoutGenerator.java | 116 +++ .../com/c2kernel/graph/layout/IntegerWrapper.java | 13 + source/com/c2kernel/graph/model/DirectedEdge.java | 99 +++ source/com/c2kernel/graph/model/EdgeFactory.java | 14 + source/com/c2kernel/graph/model/ElasticBand.java | 17 + source/com/c2kernel/graph/model/GraphModel.java | 884 +++++++++++++++++++++ .../c2kernel/graph/model/GraphModelCastorData.java | 29 + .../c2kernel/graph/model/GraphModelManager.java | 142 ++++ source/com/c2kernel/graph/model/GraphPoint.java | 18 + source/com/c2kernel/graph/model/Graphable.java | 53 ++ source/com/c2kernel/graph/model/GraphableEdge.java | 71 ++ .../com/c2kernel/graph/model/GraphableVertex.java | 254 ++++++ source/com/c2kernel/graph/model/Selection.java | 35 + .../graph/model/TypeNameAndConstructionInfo.java | 23 + source/com/c2kernel/graph/model/Vertex.java | 308 +++++++ source/com/c2kernel/graph/model/VertexFactory.java | 16 + .../c2kernel/graph/model/VertexOutlineCreator.java | 10 + .../c2kernel/graph/traversal/GraphTraversal.java | 85 ++ .../graph/view/DefaultDirectedEdgeRenderer.java | 75 ++ .../c2kernel/graph/view/DefaultVertexRenderer.java | 59 ++ .../c2kernel/graph/view/DirectedEdgeRenderer.java | 11 + .../c2kernel/graph/view/EditorModeListener.java | 8 + source/com/c2kernel/graph/view/EditorPanel.java | 100 +++ source/com/c2kernel/graph/view/EditorToolBar.java | 336 ++++++++ source/com/c2kernel/graph/view/GraphPanel.java | 274 +++++++ source/com/c2kernel/graph/view/PropertyTable.java | 38 + .../c2kernel/graph/view/PropertyTableModel.java | 125 +++ .../c2kernel/graph/view/SelectedVertexPanel.java | 27 + .../c2kernel/graph/view/VertexPropertyPanel.java | 245 ++++++ source/com/c2kernel/graph/view/VertexRenderer.java | 11 + source/com/c2kernel/gui/Console.java | 269 +++++++ source/com/c2kernel/gui/DomainKeyConsumer.java | 16 + source/com/c2kernel/gui/DomainKeyListener.java | 27 + source/com/c2kernel/gui/DynamicTreeBuilder.java | 176 ++++ source/com/c2kernel/gui/EntityDetails.java | 223 ++++++ source/com/c2kernel/gui/EntityFinder.java | 205 +++++ source/com/c2kernel/gui/EntityTabManager.java | 88 ++ source/com/c2kernel/gui/LoginBox.java | 312 ++++++++ source/com/c2kernel/gui/Main.java | 39 + source/com/c2kernel/gui/MainFrame.java | 306 +++++++ source/com/c2kernel/gui/MenuBuilder.java | 247 ++++++ source/com/c2kernel/gui/TreeBrowser.java | 197 +++++ source/com/c2kernel/gui/data/Node.java | 234 ++++++ source/com/c2kernel/gui/data/NodeAgent.java | 31 + source/com/c2kernel/gui/data/NodeCollection.java | 66 ++ source/com/c2kernel/gui/data/NodeContext.java | 61 ++ source/com/c2kernel/gui/data/NodeEntity.java | 80 ++ source/com/c2kernel/gui/data/NodeItem.java | 110 +++ source/com/c2kernel/gui/data/NodeSubscriber.java | 13 + .../com/c2kernel/gui/tabs/AgentPropertiesPane.java | 50 ++ source/com/c2kernel/gui/tabs/CloseTabIcon.java | 67 ++ source/com/c2kernel/gui/tabs/CollectionPane.java | 100 +++ source/com/c2kernel/gui/tabs/DomainPathAdmin.java | 161 ++++ source/com/c2kernel/gui/tabs/EntityTabPane.java | 182 +++++ source/com/c2kernel/gui/tabs/ExecutionPane.java | 198 +++++ source/com/c2kernel/gui/tabs/HistoryPane.java | 253 ++++++ .../gui/tabs/JTabbedPaneWithCloseIcons.java | 88 ++ source/com/c2kernel/gui/tabs/JobListPane.java | 295 +++++++ source/com/c2kernel/gui/tabs/PropertiesPane.java | 185 +++++ source/com/c2kernel/gui/tabs/ViewpointPane.java | 501 ++++++++++++ source/com/c2kernel/gui/tabs/WorkflowPane.java | 273 +++++++ .../gui/tabs/collection/AggregationView.java | 86 ++ .../tabs/collection/CollectionHistoryWindow.java | 184 +++++ .../gui/tabs/collection/CollectionView.java | 48 ++ .../gui/tabs/collection/DependencyView.java | 33 + .../c2kernel/gui/tabs/execution/ActivityItem.java | 46 ++ .../gui/tabs/execution/ActivityViewer.java | 292 +++++++ .../gui/tabs/execution/DefaultExecutor.java | 33 + .../com/c2kernel/gui/tabs/execution/Executor.java | 21 + .../c2kernel/gui/tabs/execution/RequestButton.java | 33 + .../gui/tabs/outcome/BasicOutcomeEditor.java | 100 +++ .../gui/tabs/outcome/InvalidOutcomeException.java | 11 + .../gui/tabs/outcome/InvalidSchemaException.java | 11 + .../gui/tabs/outcome/OutcomeException.java | 11 + .../c2kernel/gui/tabs/outcome/OutcomeHandler.java | 16 + .../outcome/OutcomeNotInitialisedException.java | 11 + .../gui/tabs/outcome/form/AttributeList.java | 158 ++++ .../gui/tabs/outcome/form/CardinalException.java | 14 + .../c2kernel/gui/tabs/outcome/form/DataRecord.java | 249 ++++++ .../c2kernel/gui/tabs/outcome/form/Dimension.java | 377 +++++++++ .../gui/tabs/outcome/form/DimensionInstance.java | 32 + .../gui/tabs/outcome/form/DimensionTableModel.java | 308 +++++++ .../com/c2kernel/gui/tabs/outcome/form/Field.java | 137 ++++ .../c2kernel/gui/tabs/outcome/form/HelpPane.java | 55 ++ .../tabs/outcome/form/MultiLinePasteAdapter.java | 133 ++++ .../gui/tabs/outcome/form/OutcomeEditor.java | 214 +++++ .../gui/tabs/outcome/form/OutcomePanel.java | 362 +++++++++ .../gui/tabs/outcome/form/OutcomeStructure.java | 283 +++++++ .../gui/tabs/outcome/form/StructuralException.java | 12 + .../tabs/outcome/form/field/ArrayEditField.java | 166 ++++ .../tabs/outcome/form/field/ArrayTableModel.java | 106 +++ .../tabs/outcome/form/field/BooleanEditField.java | 68 ++ .../gui/tabs/outcome/form/field/ComboField.java | 135 ++++ .../tabs/outcome/form/field/DecimalEditField.java | 115 +++ .../tabs/outcome/form/field/FieldConstraints.java | 51 ++ .../tabs/outcome/form/field/ImageEditField.java | 104 +++ .../tabs/outcome/form/field/IntegerEditField.java | 113 +++ .../gui/tabs/outcome/form/field/ListOfValues.java | 31 + .../outcome/form/field/LongStringEditField.java | 38 + .../tabs/outcome/form/field/StringEditField.java | 252 ++++++ source/com/c2kernel/lifecycle/ActivityDef.java | 135 ++++ source/com/c2kernel/lifecycle/ActivitySlotDef.java | 155 ++++ source/com/c2kernel/lifecycle/AndSplitDef.java | 111 +++ .../c2kernel/lifecycle/CompositeActivityDef.java | 225 ++++++ source/com/c2kernel/lifecycle/JoinDef.java | 65 ++ source/com/c2kernel/lifecycle/LoopDef.java | 74 ++ source/com/c2kernel/lifecycle/NextDef.java | 94 +++ source/com/c2kernel/lifecycle/OrSplitDef.java | 23 + source/com/c2kernel/lifecycle/WfCastorHashMap.java | 33 + source/com/c2kernel/lifecycle/WfVertexDef.java | 83 ++ source/com/c2kernel/lifecycle/XOrSplitDef.java | 28 + .../lifecycle/chooser/ActivityChooser.java | 200 +++++ .../lifecycle/chooser/LDAPEntryChooser.java | 70 ++ .../lifecycle/chooser/LDAPFileChooser.java | 119 +++ .../lifecycle/chooser/WorkflowDialogue.java | 20 + .../lifecycle/gui/model/WfDefGraphPanel.java | 58 ++ .../lifecycle/gui/model/WfEdgeDefFactory.java | 29 + .../lifecycle/gui/model/WfVertexDefFactory.java | 93 +++ .../gui/model/WfVertexDefOutlineCreator.java | 50 ++ .../gui/view/ActivitySlotDefRenderer.java | 70 ++ .../gui/view/CompActDefOutcomeHandler.java | 218 +++++ .../gui/view/ElemActDefOutcomeHandler.java | 152 ++++ .../lifecycle/gui/view/SplitJoinDefRenderer.java | 137 ++++ .../gui/view/WfDirectedEdgeDefRenderer.java | 132 +++ .../lifecycle/gui/view/WfVertexDefRenderer.java | 29 + .../com/c2kernel/lifecycle/instance/Activity.java | 689 ++++++++++++++++ .../lifecycle/instance/AdvancementCalculator.java | 228 ++++++ .../com/c2kernel/lifecycle/instance/AndSplit.java | 26 + .../lifecycle/instance/CompositeActivity.java | 448 +++++++++++ .../com/c2kernel/lifecycle/instance/EventList.java | 19 + .../c2kernel/lifecycle/instance/EventStorage.java | 24 + .../com/c2kernel/lifecycle/instance/JobPusher.java | 69 ++ source/com/c2kernel/lifecycle/instance/Join.java | 207 +++++ source/com/c2kernel/lifecycle/instance/Loop.java | 104 +++ source/com/c2kernel/lifecycle/instance/Next.java | 82 ++ .../com/c2kernel/lifecycle/instance/OrSplit.java | 62 ++ .../com/c2kernel/lifecycle/instance/ParserWF.java | 357 +++++++++ source/com/c2kernel/lifecycle/instance/Split.java | 217 +++++ .../com/c2kernel/lifecycle/instance/WfVertex.java | 181 +++++ .../com/c2kernel/lifecycle/instance/Workflow.java | 198 +++++ .../com/c2kernel/lifecycle/instance/XOrSplit.java | 54 ++ .../instance/gui/model/WfEdgeFactory.java | 34 + .../lifecycle/instance/gui/model/WfGraphPanel.java | 58 ++ .../instance/gui/model/WfVertexFactory.java | 88 ++ .../instance/gui/model/WfVertexOutlineCreator.java | 51 ++ .../instance/gui/view/ActivityRenderer.java | 116 +++ .../instance/gui/view/FindActDefPanel.java | 69 ++ .../instance/gui/view/SplitJoinRenderer.java | 141 ++++ .../instance/gui/view/TransitionPanel.java | 184 +++++ .../instance/gui/view/WfDirectedEdgeRenderer.java | 128 +++ .../instance/gui/view/WfVertexRenderer.java | 22 + .../instance/predefined/AddC2KObject.java | 74 ++ .../instance/predefined/AddDomainPath.java | 66 ++ .../predefined/AddStepsFromDescription.java | 55 ++ .../instance/predefined/AssignItemToSlot.java | 116 +++ .../predefined/CreateItemFromDescription.java | 181 +++++ .../lifecycle/instance/predefined/Erase.java | 83 ++ .../lifecycle/instance/predefined/Import.java | 68 ++ .../instance/predefined/PredefinedStep.java | 149 ++++ .../predefined/PredefinedStepContainer.java | 57 ++ .../instance/predefined/RemoveC2KObject.java | 66 ++ .../instance/predefined/RemoveDomainPath.java | 58 ++ .../instance/predefined/ReplaceDomainWorkflow.java | 52 ++ .../predefined/ServerPredefinedStepContainer.java | 40 + .../instance/predefined/WriteProperty.java | 76 ++ .../predefined/entitycreation/Aggregation.java | 26 + .../entitycreation/AggregationMember.java | 21 + .../predefined/entitycreation/CreateNewAgent.java | 46 ++ .../predefined/entitycreation/CreateNewItem.java | 45 ++ .../predefined/entitycreation/Dependency.java | 46 ++ .../entitycreation/DependencyMember.java | 18 + .../predefined/entitycreation/Geometry.java | 29 + .../predefined/entitycreation/NewAgent.java | 65 ++ .../predefined/entitycreation/NewItem.java | 145 ++++ .../predefined/entitycreation/Property.java | 26 + .../instance/stateMachine/StateMachine.java | 142 ++++ .../lifecycle/instance/stateMachine/States.java | 40 + .../instance/stateMachine/Transitions.java | 41 + .../routingHelpers/ViewpointDataHelper.java | 79 ++ source/com/c2kernel/lookup/AgentPath.java | 152 ++++ source/com/c2kernel/lookup/DomainPath.java | 153 ++++ source/com/c2kernel/lookup/EntityPath.java | 172 ++++ .../c2kernel/lookup/InvalidAgentPathException.java | 13 + .../lookup/InvalidEntityPathException.java | 13 + source/com/c2kernel/lookup/LDAPLookup.java | 461 +++++++++++ source/com/c2kernel/lookup/LDAPLookupUtils.java | 317 ++++++++ source/com/c2kernel/lookup/LDAPPathSet.java | 70 ++ source/com/c2kernel/lookup/LDAPProperties.java | 38 + .../com/c2kernel/lookup/LDAPPropertyManager.java | 118 +++ source/com/c2kernel/lookup/LDAPRoleManager.java | 199 +++++ .../c2kernel/lookup/LegacyLDAPPropertyManager.java | 70 ++ source/com/c2kernel/lookup/NextKeyManager.java | 72 ++ source/com/c2kernel/lookup/Path.java | 301 +++++++ source/com/c2kernel/lookup/RolePath.java | 117 +++ .../com/c2kernel/persistency/ClusterStorage.java | 104 +++ .../persistency/ClusterStorageException.java | 17 + .../persistency/ClusterStorageManager.java | 369 +++++++++ .../com/c2kernel/persistency/LDAPClientReader.java | 39 + .../c2kernel/persistency/LDAPClusterStorage.java | 163 ++++ source/com/c2kernel/persistency/ProxyLoader.java | 124 +++ source/com/c2kernel/persistency/RemoteMap.java | 404 ++++++++++ .../c2kernel/persistency/TransactionManager.java | 334 ++++++++ .../c2kernel/persistency/XMLClusterStorage.java | 145 ++++ .../com/c2kernel/persistency/outcome/Outcome.java | 159 ++++ .../persistency/outcome/OutcomeValidator.java | 183 +++++ .../com/c2kernel/persistency/outcome/Schema.java | 18 + .../persistency/outcome/SchemaValidator.java | 54 ++ .../c2kernel/persistency/outcome/Viewpoint.java | 176 ++++ source/com/c2kernel/process/AbstractMain.java | 205 +++++ source/com/c2kernel/process/Bootstrap.java | 356 +++++++++ source/com/c2kernel/process/Gateway.java | 414 ++++++++++ source/com/c2kernel/process/ItemHTTPBridge.java | 52 ++ source/com/c2kernel/process/StandardClient.java | 16 + source/com/c2kernel/process/StandardServer.java | 125 +++ source/com/c2kernel/process/UserCodeProcess.java | 229 ++++++ source/com/c2kernel/property/Property.java | 82 ++ .../com/c2kernel/property/PropertyArrayList.java | 29 + .../com/c2kernel/property/PropertyDescription.java | 77 ++ .../c2kernel/property/PropertyDescriptionList.java | 53 ++ source/com/c2kernel/property/PropertyUtility.java | 87 ++ source/com/c2kernel/scripting/ErrorInfo.java | 43 + source/com/c2kernel/scripting/Parameter.java | 47 ++ .../com/c2kernel/scripting/ParameterException.java | 20 + source/com/c2kernel/scripting/Script.java | 438 ++++++++++ source/com/c2kernel/scripting/ScriptConsole.java | 234 ++++++ .../c2kernel/scripting/ScriptLoadingException.java | 24 + .../c2kernel/scripting/ScriptParsingException.java | 21 + .../scripting/ScriptingEngineException.java | 20 + source/com/c2kernel/utils/ActDefCache.java | 91 +++ source/com/c2kernel/utils/CastorArrayList.java | 30 + source/com/c2kernel/utils/CastorHashMap.java | 54 ++ source/com/c2kernel/utils/CastorXMLUtility.java | 126 +++ source/com/c2kernel/utils/DateUtility.java | 118 +++ source/com/c2kernel/utils/Dom4JElementParser.java | 38 + source/com/c2kernel/utils/FileStringUtility.java | 424 ++++++++++ .../com/c2kernel/utils/GTimeStampComparator.java | 26 + source/com/c2kernel/utils/KeyValuePair.java | 77 ++ source/com/c2kernel/utils/Language.java | 66 ++ source/com/c2kernel/utils/LocalObjectLoader.java | 77 ++ source/com/c2kernel/utils/Logger.java | 195 +++++ source/com/c2kernel/utils/Resource.java | 187 +++++ source/com/c2kernel/utils/SoftCache.java | 100 +++ source/com/c2kernel/utils/TransientCache.java | 115 +++ source/com/c2kernel/utils/XmlElementParser.java | 115 +++ .../c2kernel/utils/server/HTTPRequestHandler.java | 155 ++++ .../c2kernel/utils/server/SimpleTCPIPServer.java | 112 +++ .../com/c2kernel/utils/server/SocketHandler.java | 15 + source/com/c2kernel/utils/server/UDPListener.java | 53 ++ source/idls/c2kernel/CommonExceptions.idl | 97 +++ source/idls/c2kernel/CommonTypes.idl | 42 + source/idls/c2kernel/Entity.idl | 182 +++++ 454 files changed, 40924 insertions(+) create mode 100755 .classpath create mode 100755 .project create mode 100755 bin/UserCode.bat create mode 100755 bin/ant.bat create mode 100755 bin/conf/client.conf create mode 100755 bin/conf/server.conf create mode 100755 bin/env.bat create mode 100755 bin/itemServer.bat create mode 100755 bin/itemServer.sh create mode 100755 bin/lcp.bat create mode 100755 bin/runGUI.bat create mode 100755 bin/runOutcomeEditor.bat create mode 100755 bin/win32/SQLiteSpy.db3 create mode 100755 bin/win32/SQLiteSpy.exe create mode 100755 bin/win32/Wrapper.dll create mode 100755 bin/win32/clc.reg create mode 100755 bin/win32/iordump.exe create mode 100755 bin/win32/sqlite3.exe create mode 100755 bin/win32/sqlite_jni.dll create mode 100755 build.xml create mode 100755 changelog create mode 100755 connect/dev.clc.example create mode 100755 javadoc.xml create mode 100755 lib/bsf.jar create mode 100755 lib/castor-core.jar create mode 100755 lib/castor-xml-schema.jar create mode 100755 lib/castor-xml.jar create mode 100755 lib/commons-logging.jar create mode 100755 lib/dom4j.jar create mode 100755 lib/js.jar create mode 100755 lib/ldap.jar create mode 100755 lib/wrapper.jar create mode 100755 lib/xercesImpl.jar create mode 100755 lib/xml-apis.jar create mode 100755 resources/boot/CA/CompositeActivityFactory.xml create mode 100755 resources/boot/CA/ElementaryActivityFactory.xml create mode 100755 resources/boot/CA/ManageCompositeActDef.xml create mode 100755 resources/boot/CA/ManageElementaryActDef.xml create mode 100755 resources/boot/CA/ManageSchema.xml create mode 100755 resources/boot/CA/ManageScript.xml create mode 100755 resources/boot/CA/NoWorkflow.xml create mode 100755 resources/boot/CA/SchemaFactory.xml create mode 100755 resources/boot/CA/ScriptFactory.xml create mode 100755 resources/boot/CA/ServerItemWorkflow.xml create mode 100755 resources/boot/EA/AssignNewVersionFromLast.xml create mode 100755 resources/boot/EA/CreateNewAgent.xml create mode 100755 resources/boot/EA/CreateNewItem.xml create mode 100755 resources/boot/EA/CreateNewLocalObjectDef.xml create mode 100755 resources/boot/EA/EditActivityDef.xml create mode 100755 resources/boot/EA/EditProperties.xml create mode 100755 resources/boot/EA/EditSchema.xml create mode 100755 resources/boot/EA/EditScriptDefinition.xml create mode 100755 resources/boot/LDAPboot.txt create mode 100755 resources/boot/OD/CompositeActivityDef.xml create mode 100755 resources/boot/OD/ElementaryActivityDef.xml create mode 100755 resources/boot/OD/New.xml create mode 100755 resources/boot/OD/NewAgent.xml create mode 100755 resources/boot/OD/NewItem.xml create mode 100755 resources/boot/OD/NewLocalObjectDef.xml create mode 100755 resources/boot/OD/PredefinedStepOutcome.xml create mode 100755 resources/boot/OD/PropertyDescription.xml create mode 100755 resources/boot/OD/Schema.xml create mode 100755 resources/boot/OD/Script.xml create mode 100755 resources/boot/SC/CreateNewNumberedVersionFromLast.xml create mode 100755 resources/boot/SC/LocalObjectDefCreator.xml create mode 100755 resources/boot/SC/New.xml create mode 100755 resources/boot/SC/ServerNewEntity.xml create mode 100755 resources/boot/allbootitems.txt create mode 100755 resources/boot/factory/CA.xml create mode 100755 resources/boot/factory/EA.xml create mode 100755 resources/boot/factory/OD.xml create mode 100755 resources/boot/factory/SC.xml create mode 100755 resources/boot/property/CAProp.xml create mode 100755 resources/boot/property/EAProp.xml create mode 100755 resources/boot/property/ODProp.xml create mode 100755 resources/boot/property/SCProp.xml create mode 100755 resources/images/Thumbs.db create mode 100755 resources/images/about.png create mode 100755 resources/images/compositeMember.gif create mode 100755 resources/images/elementaryMember.gif create mode 100755 resources/images/find.png create mode 100755 resources/images/folder.png create mode 100755 resources/images/graph/autolayout.png create mode 100755 resources/images/graph/copy.png create mode 100755 resources/images/graph/delete.png create mode 100755 resources/images/graph/edge.png create mode 100755 resources/images/graph/history.png create mode 100755 resources/images/graph/load.png create mode 100755 resources/images/graph/newvertex.png create mode 100755 resources/images/graph/newvertex_large.png create mode 100755 resources/images/graph/print.png create mode 100755 resources/images/graph/resizepad.gif create mode 100755 resources/images/graph/save.png create mode 100755 resources/images/graph/selection.gif create mode 100755 resources/images/graph/start.png create mode 100755 resources/images/graph/zoomout.png create mode 100755 resources/images/info.png create mode 100755 resources/images/leaf.png create mode 100755 resources/images/loading.gif create mode 100755 resources/images/next.png create mode 100755 resources/images/reload.gif create mode 100755 resources/images/typeicons/agent_16.png create mode 100755 resources/images/typeicons/agent_32.png create mode 100755 resources/images/typeicons/compositeactivitydesc_16.png create mode 100755 resources/images/typeicons/compositeactivitydesc_32.png create mode 100755 resources/images/typeicons/elementaryactivitydesc_16.png create mode 100755 resources/images/typeicons/elementaryactivitydesc_32.png create mode 100755 resources/images/typeicons/localobjectfactory_16.png create mode 100755 resources/images/typeicons/localobjectfactory_32.png create mode 100755 resources/images/typeicons/outcome_desc_32.png create mode 100755 resources/images/typeicons/outcomedesc_16.png create mode 100755 resources/images/typeicons/outcomedesc_32.png create mode 100755 resources/images/typeicons/script_16.png create mode 100755 resources/images/typeicons/script_32.png create mode 100755 resources/images/typeicons/server_16.png create mode 100755 resources/images/typeicons/server_32.png create mode 100755 resources/mapFiles/CastorHashMapMap.xml create mode 100755 resources/mapFiles/CollectionMap.xml create mode 100755 resources/mapFiles/HistoryMap.xml create mode 100755 resources/mapFiles/JobListMap.xml create mode 100755 resources/mapFiles/KeyValuePairMap.xml create mode 100755 resources/mapFiles/LifeCycleMap.xml create mode 100755 resources/mapFiles/NewEntityMap.xml create mode 100755 resources/mapFiles/PropertiesMap.xml create mode 100755 resources/mapFiles/TransferMap.xml create mode 100755 resources/mapFiles/ViewpointMap.xml create mode 100755 resources/mapFiles/graphModelMap.xml create mode 100755 resources/mapFiles/index.xml create mode 100755 resources/openldap/README create mode 100755 resources/openldap/cristal2.schema create mode 100755 resources/openldap/slapd.conf create mode 100755 resources/textFiles/consoleHelp.txt create mode 100755 resources/textFiles/defaultConf.properties create mode 100755 resources/textFiles/license.html create mode 100755 resources/textFiles/version.txt create mode 100755 source/com/c2kernel/collection/Aggregation.java create mode 100755 source/com/c2kernel/collection/AggregationDescription.java create mode 100755 source/com/c2kernel/collection/AggregationInstance.java create mode 100755 source/com/c2kernel/collection/AggregationMember.java create mode 100755 source/com/c2kernel/collection/Collection.java create mode 100755 source/com/c2kernel/collection/CollectionDescription.java create mode 100755 source/com/c2kernel/collection/CollectionMember.java create mode 100755 source/com/c2kernel/collection/CollectionMemberList.java create mode 100755 source/com/c2kernel/collection/Dependency.java create mode 100755 source/com/c2kernel/collection/DependencyMember.java create mode 100755 source/com/c2kernel/collection/MembershipException.java create mode 100755 source/com/c2kernel/collection/Parent2ChildCollection.java create mode 100755 source/com/c2kernel/collection/RelationshipUtils.java create mode 100755 source/com/c2kernel/collection/gui/model/AggregationVertexFactory.java create mode 100755 source/com/c2kernel/collection/gui/model/AggregationVertexOutlineCreator.java create mode 100755 source/com/c2kernel/collection/gui/view/AggregationMemberRenderer.java create mode 100755 source/com/c2kernel/collection/gui/view/CollectionFrame.java create mode 100755 source/com/c2kernel/collection/gui/view/PropertyPanel.java create mode 100755 source/com/c2kernel/collection/gui/view/SelectedMemberPanel.java create mode 100755 source/com/c2kernel/entity/C2KLocalObject.java create mode 100755 source/com/c2kernel/entity/CorbaServer.java create mode 100755 source/com/c2kernel/entity/TraceableEntity.java create mode 100755 source/com/c2kernel/entity/TraceableLocator.java create mode 100755 source/com/c2kernel/entity/agent/ActiveEntity.java create mode 100755 source/com/c2kernel/entity/agent/ActiveLocator.java create mode 100755 source/com/c2kernel/entity/agent/Job.java create mode 100755 source/com/c2kernel/entity/agent/JobArrayList.java create mode 100755 source/com/c2kernel/entity/agent/JobList.java create mode 100755 source/com/c2kernel/entity/proxy/AgentProxy.java create mode 100755 source/com/c2kernel/entity/proxy/DomainPathSubscriber.java create mode 100755 source/com/c2kernel/entity/proxy/EntityProxy.java create mode 100755 source/com/c2kernel/entity/proxy/EntityProxyManager.java create mode 100755 source/com/c2kernel/entity/proxy/EntityProxyObserver.java create mode 100755 source/com/c2kernel/entity/proxy/ItemProxy.java create mode 100755 source/com/c2kernel/entity/proxy/MemberControl.java create mode 100755 source/com/c2kernel/entity/proxy/MemberSubscription.java create mode 100755 source/com/c2kernel/entity/proxy/ProxyClientConnection.java create mode 100755 source/com/c2kernel/entity/proxy/ProxyMessage.java create mode 100755 source/com/c2kernel/entity/proxy/ProxyServerConnection.java create mode 100755 source/com/c2kernel/entity/proxy/ProxySubscriber.java create mode 100755 source/com/c2kernel/entity/transfer/TransferItem.java create mode 100755 source/com/c2kernel/entity/transfer/TransferSet.java create mode 100755 source/com/c2kernel/events/Event.java create mode 100755 source/com/c2kernel/events/History.java create mode 100755 source/com/c2kernel/graph/controller/AutoScrollController.java create mode 100755 source/com/c2kernel/graph/controller/DeletionController.java create mode 100755 source/com/c2kernel/graph/controller/EdgeConstructionController.java create mode 100755 source/com/c2kernel/graph/controller/MultiSelectionDragController.java create mode 100755 source/com/c2kernel/graph/controller/StartVertexController.java create mode 100755 source/com/c2kernel/graph/controller/VertexConstructionController.java create mode 100755 source/com/c2kernel/graph/event/ClearedEvent.java create mode 100755 source/com/c2kernel/graph/event/EdgeRemovedEvent.java create mode 100755 source/com/c2kernel/graph/event/EdgesChangedEvent.java create mode 100755 source/com/c2kernel/graph/event/ElasticBandResizedEvent.java create mode 100755 source/com/c2kernel/graph/event/ElasticBandSetEvent.java create mode 100755 source/com/c2kernel/graph/event/EntireModelChangedEvent.java create mode 100755 source/com/c2kernel/graph/event/ForcedNotifyEvent.java create mode 100755 source/com/c2kernel/graph/event/GraphModelEvent.java create mode 100755 source/com/c2kernel/graph/event/GraphModelResizedEvent.java create mode 100755 source/com/c2kernel/graph/event/NewEdgeEndPointChangedEvent.java create mode 100755 source/com/c2kernel/graph/event/SelectionChangedEvent.java create mode 100755 source/com/c2kernel/graph/event/SelectionMovedEvent.java create mode 100755 source/com/c2kernel/graph/event/StartVertexIdChangedEvent.java create mode 100755 source/com/c2kernel/graph/event/VertexAddedEvent.java create mode 100755 source/com/c2kernel/graph/event/VertexCreatedEvent.java create mode 100755 source/com/c2kernel/graph/event/VertexMovedEvent.java create mode 100755 source/com/c2kernel/graph/event/VertexRemovedEvent.java create mode 100755 source/com/c2kernel/graph/event/VerticesChangedEvent.java create mode 100755 source/com/c2kernel/graph/layout/DefaultGraphLayoutGenerator.java create mode 100755 source/com/c2kernel/graph/layout/IntegerWrapper.java create mode 100755 source/com/c2kernel/graph/model/DirectedEdge.java create mode 100755 source/com/c2kernel/graph/model/EdgeFactory.java create mode 100755 source/com/c2kernel/graph/model/ElasticBand.java create mode 100755 source/com/c2kernel/graph/model/GraphModel.java create mode 100755 source/com/c2kernel/graph/model/GraphModelCastorData.java create mode 100755 source/com/c2kernel/graph/model/GraphModelManager.java create mode 100755 source/com/c2kernel/graph/model/GraphPoint.java create mode 100755 source/com/c2kernel/graph/model/Graphable.java create mode 100755 source/com/c2kernel/graph/model/GraphableEdge.java create mode 100755 source/com/c2kernel/graph/model/GraphableVertex.java create mode 100755 source/com/c2kernel/graph/model/Selection.java create mode 100755 source/com/c2kernel/graph/model/TypeNameAndConstructionInfo.java create mode 100755 source/com/c2kernel/graph/model/Vertex.java create mode 100755 source/com/c2kernel/graph/model/VertexFactory.java create mode 100755 source/com/c2kernel/graph/model/VertexOutlineCreator.java create mode 100755 source/com/c2kernel/graph/traversal/GraphTraversal.java create mode 100755 source/com/c2kernel/graph/view/DefaultDirectedEdgeRenderer.java create mode 100755 source/com/c2kernel/graph/view/DefaultVertexRenderer.java create mode 100755 source/com/c2kernel/graph/view/DirectedEdgeRenderer.java create mode 100755 source/com/c2kernel/graph/view/EditorModeListener.java create mode 100755 source/com/c2kernel/graph/view/EditorPanel.java create mode 100755 source/com/c2kernel/graph/view/EditorToolBar.java create mode 100755 source/com/c2kernel/graph/view/GraphPanel.java create mode 100755 source/com/c2kernel/graph/view/PropertyTable.java create mode 100755 source/com/c2kernel/graph/view/PropertyTableModel.java create mode 100755 source/com/c2kernel/graph/view/SelectedVertexPanel.java create mode 100755 source/com/c2kernel/graph/view/VertexPropertyPanel.java create mode 100755 source/com/c2kernel/graph/view/VertexRenderer.java create mode 100755 source/com/c2kernel/gui/Console.java create mode 100755 source/com/c2kernel/gui/DomainKeyConsumer.java create mode 100755 source/com/c2kernel/gui/DomainKeyListener.java create mode 100755 source/com/c2kernel/gui/DynamicTreeBuilder.java create mode 100755 source/com/c2kernel/gui/EntityDetails.java create mode 100755 source/com/c2kernel/gui/EntityFinder.java create mode 100755 source/com/c2kernel/gui/EntityTabManager.java create mode 100755 source/com/c2kernel/gui/LoginBox.java create mode 100755 source/com/c2kernel/gui/Main.java create mode 100755 source/com/c2kernel/gui/MainFrame.java create mode 100755 source/com/c2kernel/gui/MenuBuilder.java create mode 100755 source/com/c2kernel/gui/TreeBrowser.java create mode 100755 source/com/c2kernel/gui/data/Node.java create mode 100755 source/com/c2kernel/gui/data/NodeAgent.java create mode 100755 source/com/c2kernel/gui/data/NodeCollection.java create mode 100755 source/com/c2kernel/gui/data/NodeContext.java create mode 100755 source/com/c2kernel/gui/data/NodeEntity.java create mode 100755 source/com/c2kernel/gui/data/NodeItem.java create mode 100755 source/com/c2kernel/gui/data/NodeSubscriber.java create mode 100755 source/com/c2kernel/gui/tabs/AgentPropertiesPane.java create mode 100755 source/com/c2kernel/gui/tabs/CloseTabIcon.java create mode 100755 source/com/c2kernel/gui/tabs/CollectionPane.java create mode 100755 source/com/c2kernel/gui/tabs/DomainPathAdmin.java create mode 100755 source/com/c2kernel/gui/tabs/EntityTabPane.java create mode 100755 source/com/c2kernel/gui/tabs/ExecutionPane.java create mode 100755 source/com/c2kernel/gui/tabs/HistoryPane.java create mode 100755 source/com/c2kernel/gui/tabs/JTabbedPaneWithCloseIcons.java create mode 100755 source/com/c2kernel/gui/tabs/JobListPane.java create mode 100755 source/com/c2kernel/gui/tabs/PropertiesPane.java create mode 100755 source/com/c2kernel/gui/tabs/ViewpointPane.java create mode 100755 source/com/c2kernel/gui/tabs/WorkflowPane.java create mode 100755 source/com/c2kernel/gui/tabs/collection/AggregationView.java create mode 100755 source/com/c2kernel/gui/tabs/collection/CollectionHistoryWindow.java create mode 100755 source/com/c2kernel/gui/tabs/collection/CollectionView.java create mode 100755 source/com/c2kernel/gui/tabs/collection/DependencyView.java create mode 100755 source/com/c2kernel/gui/tabs/execution/ActivityItem.java create mode 100755 source/com/c2kernel/gui/tabs/execution/ActivityViewer.java create mode 100755 source/com/c2kernel/gui/tabs/execution/DefaultExecutor.java create mode 100755 source/com/c2kernel/gui/tabs/execution/Executor.java create mode 100755 source/com/c2kernel/gui/tabs/execution/RequestButton.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/BasicOutcomeEditor.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/InvalidOutcomeException.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/InvalidSchemaException.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/OutcomeException.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/OutcomeHandler.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/OutcomeNotInitialisedException.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/AttributeList.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/CardinalException.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/DataRecord.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/Dimension.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/DimensionInstance.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/DimensionTableModel.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/Field.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/HelpPane.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/MultiLinePasteAdapter.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/OutcomeEditor.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/OutcomePanel.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/OutcomeStructure.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/StructuralException.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/field/ArrayEditField.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/field/ArrayTableModel.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/field/BooleanEditField.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/field/ComboField.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/field/DecimalEditField.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/field/FieldConstraints.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/field/ImageEditField.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/field/IntegerEditField.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/field/ListOfValues.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/field/LongStringEditField.java create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/field/StringEditField.java create mode 100755 source/com/c2kernel/lifecycle/ActivityDef.java create mode 100755 source/com/c2kernel/lifecycle/ActivitySlotDef.java create mode 100755 source/com/c2kernel/lifecycle/AndSplitDef.java create mode 100755 source/com/c2kernel/lifecycle/CompositeActivityDef.java create mode 100755 source/com/c2kernel/lifecycle/JoinDef.java create mode 100755 source/com/c2kernel/lifecycle/LoopDef.java create mode 100755 source/com/c2kernel/lifecycle/NextDef.java create mode 100755 source/com/c2kernel/lifecycle/OrSplitDef.java create mode 100755 source/com/c2kernel/lifecycle/WfCastorHashMap.java create mode 100755 source/com/c2kernel/lifecycle/WfVertexDef.java create mode 100755 source/com/c2kernel/lifecycle/XOrSplitDef.java create mode 100755 source/com/c2kernel/lifecycle/chooser/ActivityChooser.java create mode 100755 source/com/c2kernel/lifecycle/chooser/LDAPEntryChooser.java create mode 100755 source/com/c2kernel/lifecycle/chooser/LDAPFileChooser.java create mode 100755 source/com/c2kernel/lifecycle/chooser/WorkflowDialogue.java create mode 100755 source/com/c2kernel/lifecycle/gui/model/WfDefGraphPanel.java create mode 100755 source/com/c2kernel/lifecycle/gui/model/WfEdgeDefFactory.java create mode 100755 source/com/c2kernel/lifecycle/gui/model/WfVertexDefFactory.java create mode 100755 source/com/c2kernel/lifecycle/gui/model/WfVertexDefOutlineCreator.java create mode 100755 source/com/c2kernel/lifecycle/gui/view/ActivitySlotDefRenderer.java create mode 100755 source/com/c2kernel/lifecycle/gui/view/CompActDefOutcomeHandler.java create mode 100755 source/com/c2kernel/lifecycle/gui/view/ElemActDefOutcomeHandler.java create mode 100755 source/com/c2kernel/lifecycle/gui/view/SplitJoinDefRenderer.java create mode 100755 source/com/c2kernel/lifecycle/gui/view/WfDirectedEdgeDefRenderer.java create mode 100755 source/com/c2kernel/lifecycle/gui/view/WfVertexDefRenderer.java create mode 100755 source/com/c2kernel/lifecycle/instance/Activity.java create mode 100755 source/com/c2kernel/lifecycle/instance/AdvancementCalculator.java create mode 100755 source/com/c2kernel/lifecycle/instance/AndSplit.java create mode 100755 source/com/c2kernel/lifecycle/instance/CompositeActivity.java create mode 100755 source/com/c2kernel/lifecycle/instance/EventList.java create mode 100755 source/com/c2kernel/lifecycle/instance/EventStorage.java create mode 100755 source/com/c2kernel/lifecycle/instance/JobPusher.java create mode 100755 source/com/c2kernel/lifecycle/instance/Join.java create mode 100755 source/com/c2kernel/lifecycle/instance/Loop.java create mode 100755 source/com/c2kernel/lifecycle/instance/Next.java create mode 100755 source/com/c2kernel/lifecycle/instance/OrSplit.java create mode 100755 source/com/c2kernel/lifecycle/instance/ParserWF.java create mode 100755 source/com/c2kernel/lifecycle/instance/Split.java create mode 100755 source/com/c2kernel/lifecycle/instance/WfVertex.java create mode 100755 source/com/c2kernel/lifecycle/instance/Workflow.java create mode 100755 source/com/c2kernel/lifecycle/instance/XOrSplit.java create mode 100755 source/com/c2kernel/lifecycle/instance/gui/model/WfEdgeFactory.java create mode 100755 source/com/c2kernel/lifecycle/instance/gui/model/WfGraphPanel.java create mode 100755 source/com/c2kernel/lifecycle/instance/gui/model/WfVertexFactory.java create mode 100755 source/com/c2kernel/lifecycle/instance/gui/model/WfVertexOutlineCreator.java create mode 100755 source/com/c2kernel/lifecycle/instance/gui/view/ActivityRenderer.java create mode 100755 source/com/c2kernel/lifecycle/instance/gui/view/FindActDefPanel.java create mode 100755 source/com/c2kernel/lifecycle/instance/gui/view/SplitJoinRenderer.java create mode 100755 source/com/c2kernel/lifecycle/instance/gui/view/TransitionPanel.java create mode 100755 source/com/c2kernel/lifecycle/instance/gui/view/WfDirectedEdgeRenderer.java create mode 100755 source/com/c2kernel/lifecycle/instance/gui/view/WfVertexRenderer.java create mode 100755 source/com/c2kernel/lifecycle/instance/predefined/AddC2KObject.java create mode 100755 source/com/c2kernel/lifecycle/instance/predefined/AddDomainPath.java create mode 100755 source/com/c2kernel/lifecycle/instance/predefined/AddStepsFromDescription.java create mode 100755 source/com/c2kernel/lifecycle/instance/predefined/AssignItemToSlot.java create mode 100755 source/com/c2kernel/lifecycle/instance/predefined/CreateItemFromDescription.java create mode 100755 source/com/c2kernel/lifecycle/instance/predefined/Erase.java create mode 100755 source/com/c2kernel/lifecycle/instance/predefined/Import.java create mode 100755 source/com/c2kernel/lifecycle/instance/predefined/PredefinedStep.java create mode 100755 source/com/c2kernel/lifecycle/instance/predefined/PredefinedStepContainer.java create mode 100755 source/com/c2kernel/lifecycle/instance/predefined/RemoveC2KObject.java create mode 100755 source/com/c2kernel/lifecycle/instance/predefined/RemoveDomainPath.java create mode 100755 source/com/c2kernel/lifecycle/instance/predefined/ReplaceDomainWorkflow.java create mode 100755 source/com/c2kernel/lifecycle/instance/predefined/ServerPredefinedStepContainer.java create mode 100755 source/com/c2kernel/lifecycle/instance/predefined/WriteProperty.java create mode 100755 source/com/c2kernel/lifecycle/instance/predefined/entitycreation/Aggregation.java create mode 100755 source/com/c2kernel/lifecycle/instance/predefined/entitycreation/AggregationMember.java create mode 100755 source/com/c2kernel/lifecycle/instance/predefined/entitycreation/CreateNewAgent.java create mode 100755 source/com/c2kernel/lifecycle/instance/predefined/entitycreation/CreateNewItem.java create mode 100755 source/com/c2kernel/lifecycle/instance/predefined/entitycreation/Dependency.java create mode 100755 source/com/c2kernel/lifecycle/instance/predefined/entitycreation/DependencyMember.java create mode 100755 source/com/c2kernel/lifecycle/instance/predefined/entitycreation/Geometry.java create mode 100755 source/com/c2kernel/lifecycle/instance/predefined/entitycreation/NewAgent.java create mode 100755 source/com/c2kernel/lifecycle/instance/predefined/entitycreation/NewItem.java create mode 100755 source/com/c2kernel/lifecycle/instance/predefined/entitycreation/Property.java create mode 100755 source/com/c2kernel/lifecycle/instance/stateMachine/StateMachine.java create mode 100755 source/com/c2kernel/lifecycle/instance/stateMachine/States.java create mode 100755 source/com/c2kernel/lifecycle/instance/stateMachine/Transitions.java create mode 100755 source/com/c2kernel/lifecycle/routingHelpers/ViewpointDataHelper.java create mode 100755 source/com/c2kernel/lookup/AgentPath.java create mode 100755 source/com/c2kernel/lookup/DomainPath.java create mode 100755 source/com/c2kernel/lookup/EntityPath.java create mode 100755 source/com/c2kernel/lookup/InvalidAgentPathException.java create mode 100755 source/com/c2kernel/lookup/InvalidEntityPathException.java create mode 100755 source/com/c2kernel/lookup/LDAPLookup.java create mode 100755 source/com/c2kernel/lookup/LDAPLookupUtils.java create mode 100755 source/com/c2kernel/lookup/LDAPPathSet.java create mode 100755 source/com/c2kernel/lookup/LDAPProperties.java create mode 100755 source/com/c2kernel/lookup/LDAPPropertyManager.java create mode 100755 source/com/c2kernel/lookup/LDAPRoleManager.java create mode 100755 source/com/c2kernel/lookup/LegacyLDAPPropertyManager.java create mode 100755 source/com/c2kernel/lookup/NextKeyManager.java create mode 100755 source/com/c2kernel/lookup/Path.java create mode 100755 source/com/c2kernel/lookup/RolePath.java create mode 100755 source/com/c2kernel/persistency/ClusterStorage.java create mode 100755 source/com/c2kernel/persistency/ClusterStorageException.java create mode 100755 source/com/c2kernel/persistency/ClusterStorageManager.java create mode 100755 source/com/c2kernel/persistency/LDAPClientReader.java create mode 100755 source/com/c2kernel/persistency/LDAPClusterStorage.java create mode 100755 source/com/c2kernel/persistency/ProxyLoader.java create mode 100755 source/com/c2kernel/persistency/RemoteMap.java create mode 100755 source/com/c2kernel/persistency/TransactionManager.java create mode 100755 source/com/c2kernel/persistency/XMLClusterStorage.java create mode 100755 source/com/c2kernel/persistency/outcome/Outcome.java create mode 100755 source/com/c2kernel/persistency/outcome/OutcomeValidator.java create mode 100755 source/com/c2kernel/persistency/outcome/Schema.java create mode 100755 source/com/c2kernel/persistency/outcome/SchemaValidator.java create mode 100755 source/com/c2kernel/persistency/outcome/Viewpoint.java create mode 100755 source/com/c2kernel/process/AbstractMain.java create mode 100755 source/com/c2kernel/process/Bootstrap.java create mode 100755 source/com/c2kernel/process/Gateway.java create mode 100755 source/com/c2kernel/process/ItemHTTPBridge.java create mode 100755 source/com/c2kernel/process/StandardClient.java create mode 100755 source/com/c2kernel/process/StandardServer.java create mode 100755 source/com/c2kernel/process/UserCodeProcess.java create mode 100755 source/com/c2kernel/property/Property.java create mode 100755 source/com/c2kernel/property/PropertyArrayList.java create mode 100755 source/com/c2kernel/property/PropertyDescription.java create mode 100755 source/com/c2kernel/property/PropertyDescriptionList.java create mode 100755 source/com/c2kernel/property/PropertyUtility.java create mode 100755 source/com/c2kernel/scripting/ErrorInfo.java create mode 100755 source/com/c2kernel/scripting/Parameter.java create mode 100755 source/com/c2kernel/scripting/ParameterException.java create mode 100755 source/com/c2kernel/scripting/Script.java create mode 100755 source/com/c2kernel/scripting/ScriptConsole.java create mode 100755 source/com/c2kernel/scripting/ScriptLoadingException.java create mode 100755 source/com/c2kernel/scripting/ScriptParsingException.java create mode 100755 source/com/c2kernel/scripting/ScriptingEngineException.java create mode 100755 source/com/c2kernel/utils/ActDefCache.java create mode 100755 source/com/c2kernel/utils/CastorArrayList.java create mode 100755 source/com/c2kernel/utils/CastorHashMap.java create mode 100755 source/com/c2kernel/utils/CastorXMLUtility.java create mode 100755 source/com/c2kernel/utils/DateUtility.java create mode 100755 source/com/c2kernel/utils/Dom4JElementParser.java create mode 100755 source/com/c2kernel/utils/FileStringUtility.java create mode 100755 source/com/c2kernel/utils/GTimeStampComparator.java create mode 100755 source/com/c2kernel/utils/KeyValuePair.java create mode 100755 source/com/c2kernel/utils/Language.java create mode 100755 source/com/c2kernel/utils/LocalObjectLoader.java create mode 100755 source/com/c2kernel/utils/Logger.java create mode 100755 source/com/c2kernel/utils/Resource.java create mode 100755 source/com/c2kernel/utils/SoftCache.java create mode 100755 source/com/c2kernel/utils/TransientCache.java create mode 100755 source/com/c2kernel/utils/XmlElementParser.java create mode 100755 source/com/c2kernel/utils/server/HTTPRequestHandler.java create mode 100755 source/com/c2kernel/utils/server/SimpleTCPIPServer.java create mode 100755 source/com/c2kernel/utils/server/SocketHandler.java create mode 100755 source/com/c2kernel/utils/server/UDPListener.java create mode 100755 source/idls/c2kernel/CommonExceptions.idl create mode 100755 source/idls/c2kernel/CommonTypes.idl create mode 100755 source/idls/c2kernel/Entity.idl diff --git a/.classpath b/.classpath new file mode 100755 index 0000000..89543fe --- /dev/null +++ b/.classpath @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/.project b/.project new file mode 100755 index 0000000..342c899 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + cristal-kernel + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + 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 Binary files /dev/null and b/bin/win32/SQLiteSpy.db3 differ diff --git a/bin/win32/SQLiteSpy.exe b/bin/win32/SQLiteSpy.exe new file mode 100755 index 0000000..04cf3c8 Binary files /dev/null and b/bin/win32/SQLiteSpy.exe differ diff --git a/bin/win32/Wrapper.dll b/bin/win32/Wrapper.dll new file mode 100755 index 0000000..38b7807 Binary files /dev/null and b/bin/win32/Wrapper.dll differ diff --git a/bin/win32/clc.reg b/bin/win32/clc.reg new file mode 100755 index 0000000..78bdc72 Binary files /dev/null and b/bin/win32/clc.reg differ diff --git a/bin/win32/iordump.exe b/bin/win32/iordump.exe new file mode 100755 index 0000000..5a9d947 Binary files /dev/null and b/bin/win32/iordump.exe differ diff --git a/bin/win32/sqlite3.exe b/bin/win32/sqlite3.exe new file mode 100755 index 0000000..4387f7b Binary files /dev/null and b/bin/win32/sqlite3.exe differ diff --git a/bin/win32/sqlite_jni.dll b/bin/win32/sqlite_jni.dll new file mode 100755 index 0000000..875c435 Binary files /dev/null and b/bin/win32/sqlite_jni.dll 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 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 @@ + + + + + + + + diff --git a/lib/bsf.jar b/lib/bsf.jar new file mode 100755 index 0000000..619a135 Binary files /dev/null and b/lib/bsf.jar differ diff --git a/lib/castor-core.jar b/lib/castor-core.jar new file mode 100755 index 0000000..03ff0b2 Binary files /dev/null and b/lib/castor-core.jar differ diff --git a/lib/castor-xml-schema.jar b/lib/castor-xml-schema.jar new file mode 100755 index 0000000..9dc9c00 Binary files /dev/null and b/lib/castor-xml-schema.jar differ diff --git a/lib/castor-xml.jar b/lib/castor-xml.jar new file mode 100755 index 0000000..8bf7639 Binary files /dev/null and b/lib/castor-xml.jar differ diff --git a/lib/commons-logging.jar b/lib/commons-logging.jar new file mode 100755 index 0000000..b73a80f Binary files /dev/null and b/lib/commons-logging.jar differ diff --git a/lib/dom4j.jar b/lib/dom4j.jar new file mode 100755 index 0000000..b7b31eb Binary files /dev/null and b/lib/dom4j.jar differ diff --git a/lib/js.jar b/lib/js.jar new file mode 100755 index 0000000..f92e9f9 Binary files /dev/null and b/lib/js.jar differ diff --git a/lib/ldap.jar b/lib/ldap.jar new file mode 100755 index 0000000..3709cb6 Binary files /dev/null and b/lib/ldap.jar differ diff --git a/lib/wrapper.jar b/lib/wrapper.jar new file mode 100755 index 0000000..d4ca1e9 Binary files /dev/null and b/lib/wrapper.jar differ diff --git a/lib/xercesImpl.jar b/lib/xercesImpl.jar new file mode 100755 index 0000000..33990e8 Binary files /dev/null and b/lib/xercesImpl.jar differ diff --git a/lib/xml-apis.jar b/lib/xml-apis.jar new file mode 100755 index 0000000..b338fb6 Binary files /dev/null and b/lib/xml-apis.jar 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 @@ + + + + + + + + + + 9 + + + + + + + + + + + 7 + 12 + + + + + + + + + + + 13 + 7 + 9 + + + + + + + + + + + + + 12 + 13 + + + + + + + CreateNewLocalObjectDef + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CreateNewLocalObjectDef + 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 @@ + + + + + + + + + + 9 + + + + + + + + + + + 7 + 12 + + + + + + + + + + + 13 + 7 + 9 + + + + + + + + + + + + + 12 + 13 + + + + + + + CreateNewLocalObjectDef + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CreateNewLocalObjectDef + 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 @@ + + + + + + + + + + 19 + 20 + 21 + + + + + + + + + + + + + 17 + 20 + 18 + + + + + + + + + + + 16 + 17 + + + + + + + + + + + + 8 + 21 + + + + + + + + + + + 25 + 7 + 8 + + + + + + + + + + + + + 18 + 19 + + + + + + + AssignNewVersionFromLast + + + + + + + + 7 + 16 + 24 + + + + + + + + + + + 24 + 25 + + + + + + + EditActivityDef + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AssignNewVersionFromLast + EditActivityDef + 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 @@ + + + + + + + + + + 19 + 20 + 21 + + + + + + + + + + + + + 17 + 20 + 18 + + + + + + + + + + + 8 + 21 + + + + + + + + + + + 16 + 17 + + + + + + + + + + + + 25 + 7 + 8 + + + + + + + + + + + + + 7 + 16 + 24 + + + + + + + + + + + 18 + 19 + + + + + + + AssignNewVersionFromLast + + + + + + + + 24 + 25 + + + + + + + EditActivityDef + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AssignNewVersionFromLast + EditActivityDef + 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 @@ + + + + + + + + + + 19 + 20 + 21 + + + + + + + + + + + + + 17 + 20 + 18 + + + + + + + + + + + 16 + 17 + + + + + + + + + + + + 8 + 21 + + + + + + + + + + + 6 + 7 + 8 + + + + + + + + + + + + + 18 + 19 + + + + + + + AssignNewVersionFromLast + + + + + + + + 7 + 16 + 5 + + + + + + + + + + + 5 + 6 + + + + + + EditSchema + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AssignNewVersionFromLast + EditSchema + 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 @@ + + + + + + + + + + 24 + 25 + 26 + + + + + + + + + + + + + 21 + 22 + 23 + + + + + + + + + + + + + 18 + 25 + 20 + + + + + + + + + + + 17 + 23 + 19 + + + + + + + + + + + 17 + 18 + + + + + + + + + + + + 19 + 21 + + + + + + EditScriptDefinition + + + + + + + + 20 + 24 + + + + + + + AssignNewVersionFromLast + + + + + + + + 22 + 26 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + EditScriptDefinition + AssignNewVersionFromLast + 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 @@ + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + 9 + + + + + + + + + + + 7 + 12 + + + + + + + + + + + 13 + 7 + 9 + + + + + + + + + + + + + 12 + 13 + + + + + + + CreateNewLocalObjectDef + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CreateNewLocalObjectDef + 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 @@ + + + + + + + + + + 9 + + + + + + + + + + + 7 + 12 + + + + + + + + + + + 13 + 7 + 9 + + + + + + + + + + + + + 12 + 13 + + + + + + + CreateNewLocalObjectDef + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CreateNewLocalObjectDef + 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 @@ + + + + + + + + + + 16 + 17 + + + + + + + + + + + 15 + 16 + 19 + + + + + + + + + + + + + 14 + 17 + 18 + + + + + + + + + + + + + 11 + 19 + 13 + + + + + + + + + + + 10 + 18 + 12 + + + + + + + + + + + 10 + 11 + + + + + + + + + + + + 13 + 15 + + + + + + CreateNewAgent + + + + + + + + 12 + 14 + + + + + + CreateNewItem + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CreateNewAgent + CreateNewItem + 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 @@ + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + 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 @@ + + + + + + Complete Structure for new agent + + + + + + The initial roles that this Agent will hold + + + + + + + + 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 @@ + + + + + + Complete Structure for new item + + + + + + New Properties for the item + + + + + + + + + A new collection with layout + + + + + + + + + The position and size of this member slot on the layout + + + + + + + + + + + + + + + + + + + + + + A new collection without layout + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + Please give a name for your new object. + + + + + If you want to store your object in a subfolder, give the subpath here. + + + + + + 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 @@ + + + + + General holder for predefined step outcomes we can't be bothered to define a proper schema for + + + + + + + + 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 @@ + + + + + Defines the properties that will exist in instances of this description when initially created. + + + + + + + + The name of the new property. + + + + + 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. + + + + + The initial value of the property when it is created. + + + + + Whether or not the property can have its value changed once it has been created. + + + + + + + + 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 @@ + + + + \ 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + 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 @@ + + + + + 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 @@ + + + + + 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 @@ + + + + + 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 @@ + + + + + + + + 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 @@ + + + + + + + + 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 @@ + + + + + + + + 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 @@ + + + + + + + + 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 @@ + + + + + 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 @@ + + + + + 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 @@ + + + + + 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 @@ + + + + diff --git a/resources/images/Thumbs.db b/resources/images/Thumbs.db new file mode 100755 index 0000000..551f7e5 Binary files /dev/null and b/resources/images/Thumbs.db differ diff --git a/resources/images/about.png b/resources/images/about.png new file mode 100755 index 0000000..3f34032 Binary files /dev/null and b/resources/images/about.png differ diff --git a/resources/images/compositeMember.gif b/resources/images/compositeMember.gif new file mode 100755 index 0000000..9e267fc Binary files /dev/null and b/resources/images/compositeMember.gif differ diff --git a/resources/images/elementaryMember.gif b/resources/images/elementaryMember.gif new file mode 100755 index 0000000..9aa677e Binary files /dev/null and b/resources/images/elementaryMember.gif differ diff --git a/resources/images/find.png b/resources/images/find.png new file mode 100755 index 0000000..54d2a6f Binary files /dev/null and b/resources/images/find.png differ diff --git a/resources/images/folder.png b/resources/images/folder.png new file mode 100755 index 0000000..c969ff4 Binary files /dev/null and b/resources/images/folder.png differ diff --git a/resources/images/graph/autolayout.png b/resources/images/graph/autolayout.png new file mode 100755 index 0000000..4470ace Binary files /dev/null and b/resources/images/graph/autolayout.png differ diff --git a/resources/images/graph/copy.png b/resources/images/graph/copy.png new file mode 100755 index 0000000..77b67a3 Binary files /dev/null and b/resources/images/graph/copy.png differ diff --git a/resources/images/graph/delete.png b/resources/images/graph/delete.png new file mode 100755 index 0000000..180fc21 Binary files /dev/null and b/resources/images/graph/delete.png differ diff --git a/resources/images/graph/edge.png b/resources/images/graph/edge.png new file mode 100755 index 0000000..12593ae Binary files /dev/null and b/resources/images/graph/edge.png differ diff --git a/resources/images/graph/history.png b/resources/images/graph/history.png new file mode 100755 index 0000000..f7defb1 Binary files /dev/null and b/resources/images/graph/history.png differ diff --git a/resources/images/graph/load.png b/resources/images/graph/load.png new file mode 100755 index 0000000..c969ff4 Binary files /dev/null and b/resources/images/graph/load.png differ diff --git a/resources/images/graph/newvertex.png b/resources/images/graph/newvertex.png new file mode 100755 index 0000000..324b65a Binary files /dev/null and b/resources/images/graph/newvertex.png differ diff --git a/resources/images/graph/newvertex_large.png b/resources/images/graph/newvertex_large.png new file mode 100755 index 0000000..aade756 Binary files /dev/null and b/resources/images/graph/newvertex_large.png differ diff --git a/resources/images/graph/print.png b/resources/images/graph/print.png new file mode 100755 index 0000000..f417d83 Binary files /dev/null and b/resources/images/graph/print.png differ diff --git a/resources/images/graph/resizepad.gif b/resources/images/graph/resizepad.gif new file mode 100755 index 0000000..0f1b5d6 Binary files /dev/null and b/resources/images/graph/resizepad.gif differ diff --git a/resources/images/graph/save.png b/resources/images/graph/save.png new file mode 100755 index 0000000..1c4f461 Binary files /dev/null and b/resources/images/graph/save.png differ diff --git a/resources/images/graph/selection.gif b/resources/images/graph/selection.gif new file mode 100755 index 0000000..92595c7 Binary files /dev/null and b/resources/images/graph/selection.gif differ diff --git a/resources/images/graph/start.png b/resources/images/graph/start.png new file mode 100755 index 0000000..b1212e2 Binary files /dev/null and b/resources/images/graph/start.png differ diff --git a/resources/images/graph/zoomout.png b/resources/images/graph/zoomout.png new file mode 100755 index 0000000..b65dcc1 Binary files /dev/null and b/resources/images/graph/zoomout.png differ diff --git a/resources/images/info.png b/resources/images/info.png new file mode 100755 index 0000000..7c98fba Binary files /dev/null and b/resources/images/info.png differ diff --git a/resources/images/leaf.png b/resources/images/leaf.png new file mode 100755 index 0000000..acbdea8 Binary files /dev/null and b/resources/images/leaf.png differ diff --git a/resources/images/loading.gif b/resources/images/loading.gif new file mode 100755 index 0000000..24f86d4 Binary files /dev/null and b/resources/images/loading.gif differ diff --git a/resources/images/next.png b/resources/images/next.png new file mode 100755 index 0000000..4be5f63 Binary files /dev/null and b/resources/images/next.png differ diff --git a/resources/images/reload.gif b/resources/images/reload.gif new file mode 100755 index 0000000..2739941 Binary files /dev/null and b/resources/images/reload.gif differ diff --git a/resources/images/typeicons/agent_16.png b/resources/images/typeicons/agent_16.png new file mode 100755 index 0000000..1820787 Binary files /dev/null and b/resources/images/typeicons/agent_16.png differ diff --git a/resources/images/typeicons/agent_32.png b/resources/images/typeicons/agent_32.png new file mode 100755 index 0000000..b69c918 Binary files /dev/null and b/resources/images/typeicons/agent_32.png differ diff --git a/resources/images/typeicons/compositeactivitydesc_16.png b/resources/images/typeicons/compositeactivitydesc_16.png new file mode 100755 index 0000000..14e0c55 Binary files /dev/null and b/resources/images/typeicons/compositeactivitydesc_16.png differ diff --git a/resources/images/typeicons/compositeactivitydesc_32.png b/resources/images/typeicons/compositeactivitydesc_32.png new file mode 100755 index 0000000..dec52db Binary files /dev/null and b/resources/images/typeicons/compositeactivitydesc_32.png differ diff --git a/resources/images/typeicons/elementaryactivitydesc_16.png b/resources/images/typeicons/elementaryactivitydesc_16.png new file mode 100755 index 0000000..4db99b3 Binary files /dev/null and b/resources/images/typeicons/elementaryactivitydesc_16.png differ diff --git a/resources/images/typeicons/elementaryactivitydesc_32.png b/resources/images/typeicons/elementaryactivitydesc_32.png new file mode 100755 index 0000000..def8c90 Binary files /dev/null and b/resources/images/typeicons/elementaryactivitydesc_32.png differ diff --git a/resources/images/typeicons/localobjectfactory_16.png b/resources/images/typeicons/localobjectfactory_16.png new file mode 100755 index 0000000..9979ee7 Binary files /dev/null and b/resources/images/typeicons/localobjectfactory_16.png differ diff --git a/resources/images/typeicons/localobjectfactory_32.png b/resources/images/typeicons/localobjectfactory_32.png new file mode 100755 index 0000000..f43f44f Binary files /dev/null and b/resources/images/typeicons/localobjectfactory_32.png 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 Binary files /dev/null and b/resources/images/typeicons/outcome_desc_32.png differ diff --git a/resources/images/typeicons/outcomedesc_16.png b/resources/images/typeicons/outcomedesc_16.png new file mode 100755 index 0000000..b5829ba Binary files /dev/null and b/resources/images/typeicons/outcomedesc_16.png differ diff --git a/resources/images/typeicons/outcomedesc_32.png b/resources/images/typeicons/outcomedesc_32.png new file mode 100755 index 0000000..0139f7e Binary files /dev/null and b/resources/images/typeicons/outcomedesc_32.png differ diff --git a/resources/images/typeicons/script_16.png b/resources/images/typeicons/script_16.png new file mode 100755 index 0000000..203e519 Binary files /dev/null and b/resources/images/typeicons/script_16.png differ diff --git a/resources/images/typeicons/script_32.png b/resources/images/typeicons/script_32.png new file mode 100755 index 0000000..a1e8d3a Binary files /dev/null and b/resources/images/typeicons/script_32.png differ diff --git a/resources/images/typeicons/server_16.png b/resources/images/typeicons/server_16.png new file mode 100755 index 0000000..b3ff15b Binary files /dev/null and b/resources/images/typeicons/server_16.png differ diff --git a/resources/images/typeicons/server_32.png b/resources/images/typeicons/server_32.png new file mode 100755 index 0000000..d7bf297 Binary files /dev/null and b/resources/images/typeicons/server_32.png 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ +

Cristal 2 Kernel

+Copyright (c) 2001-2004 The European Centre For Particle Physics Research. All Rights Reserved. +

Cristal Kernel utilizes the following software products: +

+

Third Party Licenses

+ \ 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 -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 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 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 + *

Each object will be stored as the path /clustertype/name in most cases. Exceptions are: + *

    + *
  • Outcomes - /Outcome/SchemaType/SchemaVersion/EventId + *
  • Viewpoints - /ViewPoint/SchemaType/Name + *
+ * + * @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 $ +*
+*                                ,.   '\'\    ,---.
+*                            .  | \\  l\\l_ //    |
+*        _              _       |  \\/ `/  `.|    |
+*      /~\\   \        //~\     | Y |   |   ||  Y |
+*      |  \\   \      //  |     |  \|   |   |\ /  |
+*      [   ||        ||   ]     \   |  o|o  | >  /
+*     ] Y  ||        ||  Y [     \___\_--_ /_/__/
+*     |  \_|l,------.l|_/  |     /.-\(____) /--.\
+*     |   >'          `<   |     `--(______)----'
+*     \  (/~`--____--'~\)  /         u// u / \
+*      `-_>-__________-<_-'          / \  / /|
+*          /(_#(__)#_)\             ( .) / / ]
+*          \___/__\___/              `.`' /   [
+*           /__`--'__\                |`-'    |
+*        /\(__,>-~~ __)               |       |_
+*     /\//\\(  `--~~ )               _l       |-:.
+*     '\/  <^\      /^>             |  `   (  <  \\
+*          _\ >-__-< /_           ,-\  ,-~~->. \  `:._,/
+*        (___\    /___)         (____/    (____)   `-'
+*             Kovax            and, paradoxically, Kovax
+* 
+***************************************************************************/ + +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 ""; + } + } + } + + /************************************************************************** + * 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 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 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"+e.getMessage()+""; + } + } + + 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 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 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 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= 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. + *

Shows 'Loading . . .' when the branch is opened, but a TreeExpansionListener attempts to fire this thread off in the first child node. + *
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= 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 - Creating ItemTabPane instance: " + + this.getClass().getPackage().getName() + ".tabs." + tabName + "Pane"); + componentToAdd = (EntityTabPane)myClass.newInstance(); + } catch (ClassNotFoundException e) { + Logger.msg(2, "ItemDetails. - No specialist tab found for " + tabName + ". Using default."); + } catch (InstantiationException e) { + Logger.msg(0, "ItemDetails. - Instantiation Error! " + e); + } catch (IllegalAccessException e) { + Logger.msg(0, "ItemDetails. - 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; + +/** + *

Title:

+ *

Description:

+ *

Copyright: Copyright (c) 2003

+ *

Company:

+ * @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.*; + +/** + *

Title:

+ *

Description:

+ *

Copyright: Copyright (c) 2003

+ *

Company:

+ * @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= 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 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 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. - 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. - 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. - "+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. - 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"); + 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 = "No help is available for this attribute"; + + + 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 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 -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 = ""+Language.translate("No help is available for this cell")+""; + + 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"+Language.translate("Help")+""; + + 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+"

"+title+"


"+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) { + xhtml = xhtml.substring(0,startPos)+xhtml.substring(endPos+2); + } + // remove slash in + 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 = ""+Language.translate("No help is available for this element")+""; + 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 + *
    + *
  1. if maxOccurs>1 then Dimension + *
  2. SimpleTypes are Fields + *
  3. No element children is a Field + *
  4. Everything else is a DataRecord + *
+ */ + 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 allItems = new ArrayList(); + + 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 -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 = ""; + 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 += ""; + 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() 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("")) + { + if (file.substring(i, i + 5).equals("")) + { + Logger.msg(7, ""); + 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("")) + { + Logger.msg(7, ""); + 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, ""); + } + 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 -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 "done"; + 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(""); + for (int i = 0; i < data.length; i++) + xmlData.append(""); + xmlData.append(""); + return xmlData.toString(); + } + } + // generic bundling of single parameter + static public String bundleData(String data) + { + return ""; + } + 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 ""; + } +} 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 -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 : /: + 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= '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) + 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: + *
    + *
  • Authentication - returning an AgentProxy object if a user has logged in + *
  • System key generation - through the NextKeyManager + *
  • Agent and Role lookup/modification - through the RoleManager + *
  • + * @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', ';', '/'}; + 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=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 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; i0) 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 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 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 -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 \n" + + " [-connect ] (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 ]"); + 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: + *
      + *
    • LDAPLookup - Provides access to the CRISTAL directory. Find or + * search for Items or Agents. + *
    • EntityProxyManager - Gives a local proxy object for Entities found + * in LDAP. Execute activities in Items, query or subscribe to Entity data. + *
    • TransactionManager - Access to the configured CRISTAL databases + *
    • CorbaServer - Manages the memory pool of active Entities + *
    • mORB - the Orbacus CORBA ORB + *
    + * + * @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 // + * 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 <path to item>?<path to kernel object>
    "+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;iParameterException without detail message. + */ + public ParameterException() { + } + + /** + * Constructs an ParameterException 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 = ""; + 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. + *
    • If there was no output class declared then null is returned + *
    • If a class was declared, but not named, then the object returned by the script is checked + * to be of that type, then returned. + *
    • 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. + *
    + * @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 ScriptParsingException without detail message. + */ + public ScriptParsingException() { + } + + + /** + * Constructs an ScriptParsingException 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 sciptingEngineException without detail message. + */ + public ScriptingEngineException() { + } + + /** + * Constructs an sciptingEngineException 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"; + 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("")) 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'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; +/** + *
    - 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);
    +*
    + */ +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= 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()+"
    "+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 ("" + + ""+code+"" + + "

    "+code+"

    " + + "

    "+desc+ + "


    Cristal Item HTTP server"); + } +} + 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. + * + *

     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.
    +    *
    + **************************************************************************/ + 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 + +#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 + +#pragma prefix "c2kernel.com" + +module entity +{ + /************************************************************************** + * ManageableEntity is an uniquely identifiable CORBA object. + * + * - 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 + { + + /** + *

    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") ). + *

    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. + * + *

    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!
    +    *
    + * + * @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__ -- cgit v1.2.3